diff --git a/.eslintrc.js b/.eslintrc.js index a301d47bc..1c43bfd51 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,6 +5,7 @@ module.exports = { env: { node: true, mocha: true, + es2020: true, }, extends: 'airbnb-base', rules: { @@ -24,7 +25,6 @@ module.exports = { 'no-console': [2, { allow: ['warn', 'error'] }], 'import/prefer-default-export': [0], 'lines-between-class-members': ['error', 'always', { exceptAfterSingleLine: true }], - 'multiline-comment-style': 'error', 'import/no-extraneous-dependencies': 'off' }, }; diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 86dd7758e..2fc579e16 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -3,44 +3,63 @@ ## To use this hook execute in the project root: ## git config --local core.hooksPath .githooks/ if npm run lint; then + ## force compile contracts npx hardhat compile --force + + ## contracts documentation npm run docgen + npm run docgen:0.8.17 git add docs - cp artifacts/contracts/PolygonZkEVMBridge.sol/PolygonZkEVMBridge.json compiled-contracts/ - cp artifacts/contracts/PolygonZkEVMGlobalExitRoot.sol/PolygonZkEVMGlobalExitRoot.json compiled-contracts/ + + ## copy contracts ABI to be exposed + ## V1 contracts cp artifacts/contracts/PolygonZkEVMGlobalExitRootL2.sol/PolygonZkEVMGlobalExitRootL2.json compiled-contracts/ cp artifacts/contracts/lib/TokenWrapped.sol/TokenWrapped.json compiled-contracts/ + cp artifacts/contracts/deployment/PolygonZkEVMDeployer.sol/PolygonZkEVMDeployer.json compiled-contracts/ + cp artifacts/contracts/PolygonZkEVMTimelock.sol/PolygonZkEVMTimelock.json compiled-contracts/ + + ## Mocks cp artifacts/contracts/mocks/PolygonZkEVMBridgeMock.sol/PolygonZkEVMBridgeMock.json compiled-contracts/ cp artifacts/contracts/mocks/ERC20PermitMock.sol/ERC20PermitMock.json compiled-contracts/ cp artifacts/contracts/mocks/PolygonZkEVMGlobalExitRootL2Mock.sol/PolygonZkEVMGlobalExitRootL2Mock.json compiled-contracts/ cp artifacts/contracts/mocks/PolygonZkEVMGlobalExitRootMock.sol/PolygonZkEVMGlobalExitRootMock.json compiled-contracts/ cp artifacts/contracts/mocks/PolygonZkEVMMock.sol/PolygonZkEVMMock.json compiled-contracts/ cp artifacts/contracts/mocks/VerifierRollupHelperMock.sol/VerifierRollupHelperMock.json compiled-contracts/ - cp artifacts/contracts/PolygonZkEVM.sol/PolygonZkEVM.json compiled-contracts/ + cp artifacts/contracts/v2/mocks/PolygonRollupManagerMock.sol/PolygonRollupManagerMock.json compiled-contracts/ + + ## Verifiers cp artifacts/contracts/verifiers/FflonkVerifier_10.sol/FflonkVerifier_10.json compiled-contracts/FflonkVerifier.json + cp artifacts/contracts/verifiers/v4.0.0-rc.3/SP1VerifierPlonk.sol/SP1VerifierPlonk.json compiled-contracts/SP1VerifierPlonk.json + + ## openzeppelin cp artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json compiled-contracts/ cp artifacts/@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol/TransparentUpgradeableProxy.json compiled-contracts/ - cp artifacts/contracts/deployment/PolygonZkEVMDeployer.sol/PolygonZkEVMDeployer.json compiled-contracts/ - cp artifacts/contracts/PolygonZkEVMTimelock.sol/PolygonZkEVMTimelock.json compiled-contracts/ + ## V2 General cp artifacts/contracts/v2/PolygonRollupManager.sol/PolygonRollupManager.json compiled-contracts/ - cp artifacts/contracts/v2/mocks/PolygonRollupManagerMock.sol/PolygonRollupManagerMock.json compiled-contracts/ - cp artifacts/contracts/v2/mocks/PolygonRollupManagerMockInternalTest.sol/PolygonRollupManagerMockInternalTest.json compiled-contracts/ - cp artifacts/contracts/v2/PolygonZkEVMBridgeV2.sol/PolygonZkEVMBridgeV2.json compiled-contracts/ cp artifacts/contracts/v2/PolygonZkEVMGlobalExitRootV2.sol/PolygonZkEVMGlobalExitRootV2.json compiled-contracts/ - cp artifacts/contracts/v2/PolygonZkEVMGlobalExitRootV2.sol/PolygonZkEVMGlobalExitRootV2.json compiled-contracts/ + + ## V2 Consensus cp artifacts/contracts/v2/consensus/zkEVM/PolygonZkEVMEtrog.sol/PolygonZkEVMEtrog.json compiled-contracts/ cp artifacts/contracts/v2/consensus/zkEVM/PolygonZkEVMExistentEtrog.sol/PolygonZkEVMExistentEtrog.json compiled-contracts/ - cp artifacts/contracts/v2/previousVersions/PolygonZkEVMEtrogPrevious.sol/PolygonZkEVMEtrogPrevious.json compiled-contracts/ - cp artifacts/contracts/v2/consensus/validium/PolygonValidiumEtrog.sol/PolygonValidiumEtrog.json compiled-contracts/ cp artifacts/contracts/v2/consensus/validium/PolygonDataCommittee.sol/PolygonDataCommittee.json compiled-contracts/ + cp artifacts/contracts/v2/consensus/pessimistic/PolygonPessimisticConsensus.sol/PolygonPessimisticConsensus.json compiled-contracts/ + ## V2 utils cp artifacts/contracts/v2/utils/ClaimCompressor.sol/ClaimCompressor.json compiled-contracts/ - git add compiled-contracts + + ## V2 Sovereign + cp artifacts/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol/BridgeL2SovereignChain.json compiled-contracts/ + cp artifacts/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol/GlobalExitRootManagerL2SovereignChain.json compiled-contracts/ + + ## generate forge selectors + forge selectors ls > docs/selectors.txt + git add docs/selectors.txt + exit 0 else exit 1 diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index 2a53e4c2f..ecea28d77 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - node-version: [18.x] + node-version: [20.x] steps: - name: Use Node.js ${{ matrix.node-version }} @@ -31,4 +31,4 @@ jobs: - name: Build docker run: npm run dockerv2:contracts - name: Test docker - run: npm run docker:tests \ No newline at end of file + run: npm run docker:tests diff --git a/.github/workflows/build-push-docker.yml b/.github/workflows/build-push-docker.yml new file mode 100644 index 000000000..de5067b47 --- /dev/null +++ b/.github/workflows/build-push-docker.yml @@ -0,0 +1,60 @@ +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Build-Docker image and push it + +on: + push: + branches: [main] +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [20.x] + + steps: + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + - name: Set int-bot SSH key + run: | + touch /tmp/ssh-key + echo "${{ secrets.INT_BOT_SSH_KEY }}" > /tmp/ssh-key + chmod 400 /tmp/ssh-key + eval "$(ssh-agent -s)" + ssh-add /tmp/ssh-key + - name: Checkout code + uses: actions/checkout@v3 + - name: setup + run: | + eval "$(ssh-agent -s)" + ssh-add /tmp/ssh-key + npm i + sudo curl -L "https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + sudo chmod +x /usr/local/bin/docker-compose + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build docker + run: npm run docker:contracts + - name: Push docker image + run: npm run push:docker:contracts + # Steps to push multi-platform image, it relies on the previous step: + # npm run docker:contracts + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - name: Build and push + uses: docker/build-push-action@v2 + with: + platforms: linux/amd64,linux/arm64 + push: true + tags: hermeznetwork/geth-zkevm-contracts:1.5-integration + file: docker/Dockerfile + context: . diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index d409b4d66..07b035cdf 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -5,9 +5,9 @@ name: Main CI on: push: - branches: [feature/ongoingPP] + branches: [main, develop, feature/ongoingPP] pull_request: - branches: [feature/ongoingPP] + branches: [main, develop, feature/ongoingPP] jobs: lint-and-test: @@ -15,7 +15,7 @@ jobs: strategy: matrix: - node-version: [18.x] + node-version: [20.x] steps: - name: Use Node.js ${{ matrix.node-version }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cb908ed7f..4d11b2e18 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,9 +5,9 @@ name: Main CI on: push: - branches: [main, develop] + branches: [main, develop, feature/ongoingPP] pull_request: - branches: [main, develop] + branches: [main, develop, feature/ongoingPP] jobs: lint-and-test: @@ -15,7 +15,7 @@ jobs: strategy: matrix: - node-version: [18.x] + node-version: [20.x] steps: - name: Use Node.js ${{ matrix.node-version }} diff --git a/.gitignore b/.gitignore index ca2367c8b..7f6fd160b 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,7 @@ typechain-types/ create_rollup_parameters.json docker/deploymentOutput + +.DS_Store + +tools/createSovereignGenesisWithHardhat/genesis-sovereign_hardhat.json diff --git a/audits/Sigma_Prime_Polygon_LXLY_Sovereign_Chains_Security_Assessment_Report_v2_0.pdf b/audits/Sigma_Prime_Polygon_LXLY_Sovereign_Chains_Security_Assessment_Report_v2_0.pdf new file mode 100644 index 000000000..4ee39fac2 Binary files /dev/null and b/audits/Sigma_Prime_Polygon_LXLY_Sovereign_Chains_Security_Assessment_Report_v2_0.pdf differ diff --git a/compiled-contracts/BridgeL2SovereignChain.json b/compiled-contracts/BridgeL2SovereignChain.json new file mode 100644 index 000000000..58e46256b --- /dev/null +++ b/compiled-contracts/BridgeL2SovereignChain.json @@ -0,0 +1,1397 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "BridgeL2SovereignChain", + "sourceName": "contracts/v2/sovereignChains/BridgeL2SovereignChain.sol", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AlreadyClaimed", + "type": "error" + }, + { + "inputs": [], + "name": "AmountDoesNotMatchMsgValue", + "type": "error" + }, + { + "inputs": [], + "name": "ClaimNotSet", + "type": "error" + }, + { + "inputs": [], + "name": "DestinationNetworkInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "EmergencyStateNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "EtherTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "FailedTokenWrappedDeployment", + "type": "error" + }, + { + "inputs": [], + "name": "GasTokenNetworkMustBeZeroOnEther", + "type": "error" + }, + { + "inputs": [], + "name": "GlobalExitRootInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "InputArraysLengthMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitializeFunction", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSmtProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidSovereignWETHAddressParams", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MerkleTreeFull", + "type": "error" + }, + { + "inputs": [], + "name": "MessageFailed", + "type": "error" + }, + { + "inputs": [], + "name": "MsgValueNotZero", + "type": "error" + }, + { + "inputs": [], + "name": "NativeTokenIsEther", + "type": "error" + }, + { + "inputs": [], + "name": "NoValueInMessagesOnGasTokenNetworks", + "type": "error" + }, + { + "inputs": [], + "name": "NotValidAmount", + "type": "error" + }, + { + "inputs": [], + "name": "NotValidOwner", + "type": "error" + }, + { + "inputs": [], + "name": "NotValidSignature", + "type": "error" + }, + { + "inputs": [], + "name": "NotValidSpender", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyBridgeManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyEmergencyState", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyNotEmergencyState", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyRollupManager", + "type": "error" + }, + { + "inputs": [], + "name": "OriginNetworkInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "TokenAlreadyMapped", + "type": "error" + }, + { + "inputs": [], + "name": "TokenAlreadyUpdated", + "type": "error" + }, + { + "inputs": [], + "name": "TokenNotMapped", + "type": "error" + }, + { + "inputs": [], + "name": "TokenNotRemapped", + "type": "error" + }, + { + "inputs": [], + "name": "WETHRemappingNotSupportedOnGasTokenNetworks", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "leafType", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "originAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "depositCount", + "type": "uint32" + } + ], + "name": "BridgeEvent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "globalIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "originAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ClaimEvent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EmergencyStateActivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "EmergencyStateDeactivated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "legacyTokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "updatedTokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MigrateLegacyToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "wrappedTokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "name": "NewWrappedToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "sovereignTokenAddress", + "type": "address" + } + ], + "name": "RemoveLegacySovereignTokenAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "bridgeManager", + "type": "address" + } + ], + "name": "SetBridgeManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "sovereignTokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isNotMintable", + "type": "bool" + } + ], + "name": "SetSovereignTokenAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "sovereignWETHTokenAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isNotMintable", + "type": "bool" + } + ], + "name": "SetSovereignWETHAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint32", + "name": "leafIndex", + "type": "uint32" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "sourceBridgeNetwork", + "type": "uint32" + } + ], + "name": "UnsetClaim", + "type": "event" + }, + { + "inputs": [], + "name": "BASE_INIT_BYTECODE_WRAPPED_TOKEN", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WETHToken", + "outputs": [ + { + "internalType": "contract TokenWrapped", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "activateEmergencyState", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "forceUpdateGlobalExitRoot", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "permitData", + "type": "bytes" + } + ], + "name": "bridgeAsset", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "bridgeManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "forceUpdateGlobalExitRoot", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "name": "bridgeMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountWETH", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "forceUpdateGlobalExitRoot", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "name": "bridgeMessageWETH", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "leafHash", + "type": "bytes32" + }, + { + "internalType": "bytes32[32]", + "name": "smtProof", + "type": "bytes32[32]" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + } + ], + "name": "calculateRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "calculateTokenWrapperAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[32]", + "name": "smtProofLocalExitRoot", + "type": "bytes32[32]" + }, + { + "internalType": "bytes32[32]", + "name": "smtProofRollupExitRoot", + "type": "bytes32[32]" + }, + { + "internalType": "uint256", + "name": "globalIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "mainnetExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "rollupExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "name": "claimAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[32]", + "name": "smtProofLocalExitRoot", + "type": "bytes32[32]" + }, + { + "internalType": "bytes32[32]", + "name": "smtProofRollupExitRoot", + "type": "bytes32[32]" + }, + { + "internalType": "uint256", + "name": "globalIndex", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "mainnetExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "rollupExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "name": "claimMessage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "claimedBitMap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deactivateEmergencyState", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "depositCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasTokenMetadata", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasTokenNetwork", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "leafType", + "type": "uint8" + }, + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "destinationNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "destinationAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "metadataHash", + "type": "bytes32" + } + ], + "name": "getLeafValue", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "getTokenMetadata", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + } + ], + "name": "getTokenWrappedAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalExitRootManager", + "outputs": [ + { + "internalType": "contract IBasePolygonZkEVMGlobalExitRoot", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_networkID", + "type": "uint32" + }, + { + "internalType": "address", + "name": "_gasTokenAddress", + "type": "address" + }, + { + "internalType": "uint32", + "name": "_gasTokenNetwork", + "type": "uint32" + }, + { + "internalType": "contract IBasePolygonZkEVMGlobalExitRoot", + "name": "_globalExitRootManager", + "type": "address" + }, + { + "internalType": "address", + "name": "_polygonRollupManager", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_gasTokenMetadata", + "type": "bytes" + }, + { + "internalType": "address", + "name": "_bridgeManager", + "type": "address" + }, + { + "internalType": "address", + "name": "_sovereignWETHAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "_sovereignWETHAddressIsNotMintable", + "type": "bool" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "contract IBasePolygonZkEVMGlobalExitRoot", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "leafIndex", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "sourceBridgeNetwork", + "type": "uint32" + } + ], + "name": "isClaimed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isEmergencyState", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastUpdatedDepositCount", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "legacyTokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "migrateLegacyToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "networkID", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "polygonRollupManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals", + "type": "uint8" + } + ], + "name": "precalculatedWrapperAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "legacySovereignTokenAddress", + "type": "address" + } + ], + "name": "removeLegacySovereignTokenAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_bridgeManager", + "type": "address" + } + ], + "name": "setBridgeManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32[]", + "name": "originNetworks", + "type": "uint32[]" + }, + { + "internalType": "address[]", + "name": "originTokenAddresses", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "sovereignTokenAddresses", + "type": "address[]" + }, + { + "internalType": "bool[]", + "name": "isNotMintable", + "type": "bool[]" + } + ], + "name": "setMultipleSovereignTokenAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sovereignWETHTokenAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "isNotMintable", + "type": "bool" + } + ], + "name": "setSovereignWETHAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "tokenInfoToWrappedToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32[]", + "name": "leafIndexes", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "sourceBridgeNetworks", + "type": "uint32[]" + } + ], + "name": "unsetMultipleClaimedBitmap", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateGlobalExitRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "leafHash", + "type": "bytes32" + }, + { + "internalType": "bytes32[32]", + "name": "smtProof", + "type": "bytes32[32]" + }, + { + "internalType": "uint32", + "name": "index", + "type": "uint32" + }, + { + "internalType": "bytes32", + "name": "root", + "type": "bytes32" + } + ], + "name": "verifyMerkleProof", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "wrappedAddress", + "type": "address" + } + ], + "name": "wrappedAddressIsNotMintable", + "outputs": [ + { + "internalType": "bool", + "name": "isNotMintable", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "wrappedTokenToTokenInfo", + "outputs": [ + { + "internalType": "uint32", + "name": "originNetwork", + "type": "uint32" + }, + { + "internalType": "address", + "name": "originTokenAddress", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x608060405234801562000010575f80fd5b506200001b6200002b565b620000256200002b565b620000ea565b5f54610100900460ff1615620000975760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff9081161015620000e8575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b615fd680620000f85f395ff3fe6080604052600436106101e4575f3560e01c80638c0dd470116101075780638c0dd470146104ba5780638ed7e3f2146104d95780639e76158f146104f8578063aaa13cc214610517578063b458696214610536578063b8b284d014610555578063bab161bf14610574578063be5831c714610595578063bf130d7f146105b8578063c00f14ab146105d7578063c0f49163146105f6578063cc46163214610624578063ccaa2d1114610643578063cd58657914610662578063d02103ca14610675578063dbc1697614610246578063eabd372a1461069b578063ee25560b146106ba578063f5efcd79146106e5578063f811bff714610704578063fb57083414610723575f80fd5b806314cc01a0146101e857806315064c961461021d5780632072f6c51461024657806322e95f2c1461025c578063240ff3781461027b57806327aef4e81461028e5780632dfdf0b5146102af578063318aee3d146102d25780633c351e10146103395780633cbc795b146103585780633e197043146103905780634b2f336d146103af57806357cfbee3146103ce5780635ca1e165146103ed5780637843298b1461040157806379e2cf971461042057806381b1c1741461043457806383c43a551461046857806383f244031461047c5780638781a5c51461049b575b5f80fd5b3480156101f3575f80fd5b5060a354610207906001600160a01b031681565b60405161021491906131df565b60405180910390f35b348015610228575f80fd5b506068546102369060ff1681565b6040519015158152602001610214565b348015610251575f80fd5b5061025a610742565b005b348015610267575f80fd5b5061020761027636600461321d565b61075b565b61025a6102893660046132a3565b6107a9565b348015610299575f80fd5b506102a2610819565b6040516102149190613364565b3480156102ba575f80fd5b506102c460535481565b604051908152602001610214565b3480156102dd575f80fd5b506103156102ec36600461337d565b606b6020525f908152604090205463ffffffff811690600160201b90046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201610214565b348015610344575f80fd5b50606d54610207906001600160a01b031681565b348015610363575f80fd5b50606d5461037b90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610214565b34801561039b575f80fd5b506102c46103aa3660046133a6565b6108a5565b3480156103ba575f80fd5b50606f54610207906001600160a01b031681565b3480156103d9575f80fd5b5061025a6103e8366004613556565b610931565b3480156103f8575f80fd5b506102c4610a27565b34801561040c575f80fd5b5061020761041b366004613655565b610b03565b34801561042b575f80fd5b5061025a610b2c565b34801561043f575f80fd5b5061020761044e36600461369b565b606a6020525f90815260409020546001600160a01b031681565b348015610473575f80fd5b506102a2610b4f565b348015610487575f80fd5b506102c46104963660046136c3565b610b6e565b3480156104a6575f80fd5b5061025a6104b53660046136ff565b610c43565b3480156104c5575f80fd5b5061025a6104d43660046137d1565b610cee565b3480156104e4575f80fd5b50606c54610207906001600160a01b031681565b348015610503575f80fd5b5061025a61051236600461389a565b610fcf565b348015610522575f80fd5b506102076105313660046138c4565b611107565b348015610541575f80fd5b5061025a61055036600461337d565b611207565b348015610560575f80fd5b5061025a61056f366004613959565b611368565b34801561057f575f80fd5b5060685461037b90610100900463ffffffff1681565b3480156105a0575f80fd5b5060685461037b90600160c81b900463ffffffff1681565b3480156105c3575f80fd5b5061025a6105d23660046139d6565b6113e1565b3480156105e2575f80fd5b506102a26105f136600461337d565b6114ab565b348015610601575f80fd5b5061023661061036600461337d565b60a26020525f908152604090205460ff1681565b34801561062f575f80fd5b5061023661063e366004613a02565b6114f0565b34801561064e575f80fd5b5061025a61065d366004613a33565b611540565b61025a610670366004613b16565b611924565b348015610680575f80fd5b5060685461020790600160281b90046001600160a01b031681565b3480156106a6575f80fd5b5061025a6106b536600461337d565b611cc4565b3480156106c5575f80fd5b506102c46106d436600461369b565b60696020525f908152604090205481565b3480156106f0575f80fd5b5061025a6106ff366004613a33565b611d46565b34801561070f575f80fd5b5061025a61071e366004613ba5565b611f8c565b34801561072e575f80fd5b5061023661073d366004613c34565b612031565b60405163441845b160e01b815260040160405180910390fd5b5f606a5f8484604051602001610772929190613c79565b60408051601f198184030181529181528151602092830120835290820192909252015f20546001600160a01b031690505b92915050565b60685460ff16156107cd57604051630bc011ff60e21b815260040160405180910390fd5b34158015906107e65750606f546001600160a01b031615155b15610804576040516301bd897160e61b815260040160405180910390fd5b610812858534868686612048565b5050505050565b606e805461082690613ca3565b80601f016020809104026020016040519081016040528092919081815260200182805461085290613ca3565b801561089d5780601f106108745761010080835404028352916020019161089d565b820191905f5260205f20905b81548152906001019060200180831161088057829003601f168201915b505050505081565b6040516001600160f81b031960f889901b1660208201526001600160e01b031960e088811b821660218401526001600160601b0319606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b60a3546001600160a01b0316331461095c576040516357b738d160e11b815260040160405180910390fd5b8251845114158061096f57508151845114155b8061097c57508051845114155b1561099a5760405163434f49f560e11b815260040160405180910390fd5b5f5b825181101561081257610a158582815181106109ba576109ba613cdb565b60200260200101518583815181106109d4576109d4613cdb565b60200260200101518584815181106109ee576109ee613cdb565b6020026020010151858581518110610a0857610a08613cdb565b6020026020010151612112565b80610a1f81613d03565b91505061099c565b6053545f90819081805b6020811015610afa578083901c600116600103610a8e5760338160208110610a5b57610a5b613cdb565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610abb565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080610af290613d03565b915050610a31565b50919392505050565b5f610b248484610b12856122c2565b610b1b8661237d565b61053187612431565b949350505050565b605354606854600160c81b900463ffffffff161015610b4d57610b4d6124e5565b565b60405180611ba00160405280611b66815260200161443b611b66913981565b5f83815b6020811015610c3a57600163ffffffff8516821c81169003610bdd57848160208110610ba057610ba0613cdb565b602002013582604051602001610bc0929190918252602082015260400190565b604051602081830303815290604052805190602001209150610c28565b81858260208110610bf057610bf0613cdb565b6020020135604051602001610c0f929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80610c3281613d03565b915050610b72565b50949350505050565b60a3546001600160a01b03163314610c6e576040516357b738d160e11b815260040160405180910390fd5b8051825114610c905760405163434f49f560e11b815260040160405180910390fd5b5f5b8251811015610ce957610cd7838281518110610cb057610cb0613cdb565b6020026020010151838381518110610cca57610cca613cdb565b6020026020010151612579565b80610ce181613d03565b915050610c92565b505050565b5f54610100900460ff1615808015610d0c57505f54600160ff909116105b80610d2c5750610d1b30612627565b158015610d2c57505f5460ff166001145b610d515760405162461bcd60e51b8152600401610d4890613d1b565b60405180910390fd5b5f805460ff191660011790558015610d72575f805461ff0019166101001790555b60688054610100600160c81b03191661010063ffffffff8d1602600160281b600160c81b03191617600160281b6001600160a01b038a81169190910291909117909155606c80546001600160a01b03199081168984161790915560a380549091168683161790558916610e3b5763ffffffff881615610e0457604051630d43a60960e11b815260040160405180910390fd5b6001600160a01b038316151580610e185750815b15610e3657604051630e6e237560e11b815260040160405180910390fd5b610f76565b606d805463ffffffff8a16600160a01b026001600160c01b03199091166001600160a01b038c1617179055606e610e728682613dae565b506001600160a01b038316610f3e57811515600103610ea457604051630e6e237560e11b815260040160405180910390fd5b610f195f801b6012604051602001610f0591906060808252600d908201526c2bb930b83832b21022ba3432b960991b608082015260a060208201819052600490820152630ae8aa8960e31b60c082015260ff91909116604082015260e00190565b604051602081830303815290604052612636565b606f80546001600160a01b0319166001600160a01b0392909216919091179055610f76565b606f80546001600160a01b0319166001600160a01b0385169081179091555f90815260a260205260409020805460ff19168315151790555b610f7e6126b0565b8015610fc3575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b6001600160a01b038083165f908152606b602090815260409182902082518084019093525463ffffffff81168352600160201b90049092169181018290529061102b5760405163828d566360e01b815260040160405180910390fd5b5f606a5f835f01518460200151604051602001611049929190613c79565b60408051601f198184030181529181528151602092830120835290820192909252015f20546001600160a01b0390811691508416810361109c5760405163e273c4a160e01b815260040160405180910390fd5b6110a684846126de565b6110b181338561276e565b604080513381526001600160a01b0386811660208301528316818301526060810185905290517fb7f8fd4d1faf9b2929dc269f59c53e3a2bccc44e9950f33a568fcbcb37eb69a99181900360800190a150505050565b5f80868660405160200161111c929190613c79565b6040516020818303038152906040528051906020012090505f60ff60f81b308360405180611ba00160405280611b66815260200161443b611b66913989898960405160200161116d93929190613e69565b60408051601f198184030181529082905261118b9291602001613ea1565b604051602081830303815290604052805190602001206040516020016111e394939291906001600160f81b031994909416845260609290921b6001600160601b03191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60a3546001600160a01b03163314611232576040516357b738d160e11b815260040160405180910390fd5b6001600160a01b038082165f908152606b6020908152604080832081518083018352905463ffffffff8116808352600160201b909104909516818401819052915190946112829390929101613c79565b60408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b031615806112d657505f818152606a60205260409020546001600160a01b038481169116145b156112f45760405163e0c897a760e01b815260040160405180910390fd5b6001600160a01b0383165f908152606b6020908152604080832080546001600160c01b031916905560a290915290819020805460ff19169055517fc2ae0bd0ec0fd0352bfe5bacac49637af342c1e40f1b80a7f74440dc7fe3f0639061135b9085906131df565b60405180910390a1505050565b60685460ff161561138c57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b03166113b55760405163dde3cda760e01b815260040160405180910390fd5b606f546113cb906001600160a01b0316856126de565b6113d9868686868686612048565b505050505050565b60a3546001600160a01b0316331461140c576040516357b738d160e11b815260040160405180910390fd5b606d546001600160a01b031661143557604051634cb4711360e11b815260040160405180910390fd5b606f80546001600160a01b0319166001600160a01b0384169081179091555f81815260a26020908152604091829020805460ff19168515159081179091558251938452908301527fc7318b7ed6ba4f2908a3de396d8ab49b1dadb55db5b55123247a401f29ff8d82910160405180910390a15050565b60606114b6826122c2565b6114bf8361237d565b6114c884612431565b6040516020016114da93929190613e69565b6040516020818303038152906040529050919050565b5f80611506600160201b63ffffffff8516613ecf565b6115169063ffffffff8616613ee6565b600881901c5f90815260696020526040902054600160ff9092169190911b90811614949350505050565b60685460ff161561156457604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614611594576040516302caf51760e11b815260040160405180910390fd5b6115c78c8c8c8c8c6115c25f8e8e8e8e8e8e8e6040516115b5929190613ef9565b60405180910390206108a5565b6127f9565b6001600160a01b0386166116ae57606f546001600160a01b0316611692575f6001600160a01b03851684825b6040519080825280601f01601f19166020018201604052801561161d576020820181803683370190505b5060405161162b9190613f08565b5f6040518083038185875af1925050503d805f8114611665576040519150601f19603f3d011682016040523d82523d5f602084013e61166a565b606091505b505090508061168c57604051630ce8f45160e31b815260040160405180910390fd5b506118d7565b606f546116a9906001600160a01b0316858561276e565b6118d7565b606d546001600160a01b0387811691161480156116dc5750606d5463ffffffff888116600160a01b90920416145b156116f3575f6001600160a01b03851684826115f3565b60685463ffffffff61010090910481169088160361171f576116a96001600160a01b0387168585612952565b5f8787604051602001611733929190613c79565b60408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b0316806118c9575f6117a88386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061263692505050565b90506117b581888861276e565b80606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a8388886040516118bb959493929190613f4b565b60405180910390a1506118d4565b6118d481878761276e565b50505b7f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d8a8888878760405161190e959493929190613f83565b60405180910390a1505050505050505050505050565b60685460ff161561194857604051630bc011ff60e21b815260040160405180910390fd5b6119506129a8565b60685463ffffffff610100909104811690881603611981576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b038816611a64578834146119b45760405163b89240f560e01b815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff169450906119e190613ca3565b80601f0160208091040260200160405190810160405280929190818152602001828054611a0d90613ca3565b8015611a585780601f10611a2f57610100808354040283529160200191611a58565b820191905f5260205f20905b815481529060010190602001808311611a3b57829003601f168201915b50505050509150611c3b565b3415611a835760405163798ee6f160e01b815260040160405180910390fd5b606f546001600160a01b0390811690891603611aa857611aa3888a6126de565b611c3b565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff81168352600160201b90049092169181018290529015611b0757611af6898b6126de565b602081015181519095509350611c2e565b8515611b1957611b19898b8989612a01565b6040516370a0823160e01b81525f906001600160a01b038b16906370a0823190611b479030906004016131df565b602060405180830381865afa158015611b62573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b869190613fb5565b9050611b9d6001600160a01b038b1633308e612cb2565b6040516370a0823160e01b81525f906001600160a01b038c16906370a0823190611bcb9030906004016131df565b602060405180830381865afa158015611be6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c0a9190613fb5565b9050611c168282613fcc565b6068548c9850610100900463ffffffff169650935050505b611c37896114ab565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e8688605354604051611c7a989796959493929190613fdf565b60405180910390a1611ca0611c9b5f85878f8f8789805190602001206108a5565b612cea565b8615611cae57611cae6124e5565b50505050611cbb60018055565b50505050505050565b60a3546001600160a01b03163314611cef576040516357b738d160e11b815260040160405180910390fd5b60a380546001600160a01b0319166001600160a01b0383169081179091556040517f32cf74f8a6d5f88593984d2cd52be5592bfa6884f5896175801a5069ef09cd6791611d3b916131df565b60405180910390a150565b60685460ff1615611d6a57604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614611d9a576040516302caf51760e11b815260040160405180910390fd5b611dbc8c8c8c8c8c6115c260018e8e8e8e8e8e8e6040516115b5929190613ef9565b606f545f906001600160a01b0316611e6f57846001600160a01b031684888a8686604051602401611df09493929190614049565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b17905251611e259190613f08565b5f6040518083038185875af1925050503d805f8114611e5f576040519150601f19603f3d011682016040523d82523d5f602084013e611e64565b606091505b505080915050611f20565b606f54611e86906001600160a01b0316868661276e565b846001600160a01b031687898585604051602401611ea79493929190614049565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b17905251611edc9190613f08565b5f604051808303815f865af19150503d805f8114611f15576040519150601f19603f3d011682016040523d82523d5f602084013e611f1a565b606091505b50909150505b80611f3e576040516337e391c360e01b815260040160405180910390fd5b7f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d8b89898888604051611f75959493929190613f83565b60405180910390a150505050505050505050505050565b5f54610100900460ff1615808015611faa57505f54600160ff909116105b80611fca5750611fb930612627565b158015611fca57505f5460ff166001145b611fe65760405162461bcd60e51b8152600401610d4890613d1b565b5f805460ff191660011790558015612007575f805461ff0019166101001790555b60405163f57ac68360e01b815260040160405180910390fd5b60405180910390a150505050505050565b5f8161203e868686610b6e565b1495945050505050565b60685463ffffffff610100909104811690871603612079576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff163389898988886053546040516120cd99989796959493929190614083565b60405180910390a1612104611c9b6001606860019054906101000a900463ffffffff16338a8a8a89896040516115b5929190613ef9565b82156113d9576113d96124e5565b6001600160a01b038316158061212f57506001600160a01b038216155b1561214d5760405163f6b2911f60e01b815260040160405180910390fd5b60685463ffffffff61010090910481169085160361217e5760405163658b23ad60e01b815260040160405180910390fd5b6001600160a01b038281165f908152606b6020526040902054600160201b900416156121bd576040516317abdeeb60e21b815260040160405180910390fd5b5f84846040516020016121d1929190613c79565b60408051808303601f1901815282825280516020918201205f818152606a835283812080546001600160a01b0319166001600160a01b038a8116918217909255868601865263ffffffff8c81168089528c8416878a01818152848752606b89528987209a518b54915194166001600160c01b031990911617600160201b93909516929092029390931790975560a2855291859020805460ff191689151590811790915585519182529381019590955292840192909252606083015291507fdbe8a5da6a7a916d9adfda9160167a0f8a3da415ee6610e810e753853597fce79060800160405180910390a15050505050565b60408051600481526024810182526020810180516001600160e01b03166306fdde0360e01b17905290516060915f9182916001600160a01b038616916123089190613f08565b5f60405180830381855afa9150503d805f8114612340576040519150601f19603f3d011682016040523d82523d5f602084013e612345565b606091505b50915091508161237457604051806040016040528060078152602001664e4f5f4e414d4560c81b815250610b24565b610b2481612dd2565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b17905290516060915f9182916001600160a01b038616916123c39190613f08565b5f60405180830381855afa9150503d805f81146123fb576040519150601f19603f3d011682016040523d82523d5f602084013e612400565b606091505b50915091508161237457604051806040016040528060098152602001681393d7d4d6535093d360ba1b815250610b24565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b17905290515f91829182916001600160a01b038616916124769190613f08565b5f60405180830381855afa9150503d805f81146124ae576040519150601f19603f3d011682016040523d82523d5f602084013e6124b3565b606091505b50915091508180156124c6575080516020145b6124d1576012610b24565b80806020019051810190610b2491906140ef565b6053546068805463ffffffff909216600160c81b0263ffffffff60c81b1990921691909117908190556001600160a01b03600160281b909104166333d6247d61252c610a27565b6040518263ffffffff1660e01b815260040161254a91815260200190565b5f604051808303815f87803b158015612561575f80fd5b505af1158015612573573d5f803e3d5ffd5b50505050565b5f61258e600160201b63ffffffff8416613ecf565b61259e9063ffffffff8516613ee6565b600881901c5f8181526069602052604090208054600160ff851690811b9182189283905593945091929190808216156125ea57604051630631b5f760e31b815260040160405180910390fd5b6040805163ffffffff808a168252881660208201527f4a402ac607e71571d0543be8fcccc358a4df62dcd019a1e7f7e98ca6175e8f2a9101612020565b6001600160a01b03163b151590565b5f8060405180611ba00160405280611b66815260200161443b611b66913983604051602001612666929190613ea1565b6040516020818303038152906040529050838151602083015ff591506001600160a01b0382166126a9576040516305f7d84960e51b815260040160405180910390fd5b5092915050565b5f54610100900460ff166126d65760405162461bcd60e51b8152600401610d489061410a565b610b4d612f5b565b6001600160a01b0382165f90815260a2602052604090205460ff1615612717576127136001600160a01b038316333084612cb2565b5050565b604051632770a7eb60e21b81526001600160a01b03831690639dc29fac906127459033908590600401614155565b5f604051808303815f87803b15801561275c575f80fd5b505af11580156113d9573d5f803e3d5ffd5b6001600160a01b0383165f90815260a2602052604090205460ff16156127a257610ce96001600160a01b0384168383612952565b6040516340c10f1960e01b81526001600160a01b038416906340c10f19906127d09085908590600401614155565b5f604051808303815f87803b1580156127e7575f80fd5b505af1158015611cbb573d5f803e3d5ffd5b606854604080516020808201879052818301869052825180830384018152606083019384905280519101206312bd9b1960e11b90925260648101919091525f91600160281b90046001600160a01b03169063257b3632906084016020604051808303815f875af115801561286f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128939190613fb5565b9050805f036128b457604051622f6fad60e01b815260040160405180910390fd5b5f80600160401b8716156128f3578691506128d1848a8489612031565b6128ee576040516338105f3b60e21b815260040160405180910390fd5b61293d565b602087901c61290381600161416e565b915087925061291e612916868c86610b6e565b8a8389612031565b61293b576040516338105f3b60e21b815260040160405180910390fd5b505b6129478282612f81565b505050505050505050565b610ce98363a9059cbb60e01b8484604051602401612971929190614155565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612ff3565b6002600154036129fa5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d48565b6002600155565b5f612a0f600482848661418b565b612a18916141b2565b9050632afa533160e01b6001600160e01b0319821601612b4c575f808080808080612a46896004818d61418b565b810190612a5391906141e2565b96509650965096509650965096508a8514612a81576040516303fffc4b60e01b815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b031663d505accf60e01b1790529151918e1691612aff9190613f08565b5f604051808303815f865af19150503d805f8114612b38576040519150601f19603f3d011682016040523d82523d5f602084013e612b3d565b606091505b50505050505050505050610812565b6001600160e01b031981166323f2ebc360e21b14612b7d57604051637141605d60e11b815260040160405180910390fd5b5f80808080808080612b928a6004818e61418b565b810190612b9f9190614231565b975097509750975097509750975097508c6001600160a01b0316638fcbaf0c60e01b8989898989898989604051602401612c249897969594939291906001600160a01b039889168152969097166020870152604086019490945260608501929092521515608084015260ff1660a083015260c082015260e08101919091526101000190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612c629190613f08565b5f604051808303815f865af19150503d805f8114612c9b576040519150601f19603f3d011682016040523d82523d5f602084013e612ca0565b606091505b50505050505050505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526125739085906323b872dd60e01b90608401612971565b806001612cf96020600261438f565b612d039190613fcc565b60535410612d24576040516377ae67b360e11b815260040160405180910390fd5b5f60535f8154612d3390613d03565b918290555090505f5b6020811015612dc3578082901c600116600103612d6f578260338260208110612d6757612d67613cdb565b015550505050565b60338160208110612d8257612d82613cdb565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092508080612dbb90613d03565b915050612d3c565b50610ce961439a565b60018055565b60606040825110612df157818060200190518101906107a391906143ae565b8151602003612f28575f5b602081108015612e2b5750828181518110612e1957612e19613cdb565b01602001516001600160f81b03191615155b15612e425780612e3a81613d03565b915050612dfc565b805f03612e795750506040805180820190915260128152714e4f545f56414c49445f454e434f44494e4760701b6020820152919050565b5f816001600160401b03811115612e9257612e92613420565b6040519080825280601f01601f191660200182016040528015612ebc576020820181803683370190505b5090505f5b82811015612f2057848181518110612edb57612edb613cdb565b602001015160f81c60f81b828281518110612ef857612ef8613cdb565b60200101906001600160f81b03191690815f1a90535080612f1881613d03565b915050612ec1565b509392505050565b50506040805180820190915260128152714e4f545f56414c49445f454e434f44494e4760701b602082015290565b919050565b5f54610100900460ff16612dcc5760405162461bcd60e51b8152600401610d489061410a565b5f612f96600160201b63ffffffff8416613ecf565b612fa69063ffffffff8516613ee6565b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055949550929392918183169003611cbb57604051630c8d9eab60e31b815260040160405180910390fd5b5f613047826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130c49092919063ffffffff16565b805190915015610ce95780806020019051810190613065919061441f565b610ce95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610d48565b6060610b2484845f85855f80866001600160a01b031685876040516130e99190613f08565b5f6040518083038185875af1925050503d805f8114613123576040519150601f19603f3d011682016040523d82523d5f602084013e613128565b606091505b509150915061313987838387613144565b979650505050505050565b606083156131b05782515f036131a95761315d85612627565b6131a95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d48565b5081610b24565b610b2483838151156131c55781518083602001fd5b8060405162461bcd60e51b8152600401610d489190613364565b6001600160a01b0391909116815260200190565b803563ffffffff81168114612f56575f80fd5b6001600160a01b038116811461321a575f80fd5b50565b5f806040838503121561322e575f80fd5b613237836131f3565b9150602083013561324781613206565b809150509250929050565b801515811461321a575f80fd5b5f8083601f84011261326f575f80fd5b5081356001600160401b03811115613285575f80fd5b60208301915083602082850101111561329c575f80fd5b9250929050565b5f805f805f608086880312156132b7575f80fd5b6132c0866131f3565b945060208601356132d081613206565b935060408601356132e081613252565b925060608601356001600160401b038111156132fa575f80fd5b6133068882890161325f565b969995985093965092949392505050565b5f5b83811015613331578181015183820152602001613319565b50505f910152565b5f8151808452613350816020860160208601613317565b601f01601f19169290920160200192915050565b602081525f6133766020830184613339565b9392505050565b5f6020828403121561338d575f80fd5b813561337681613206565b60ff8116811461321a575f80fd5b5f805f805f805f60e0888a0312156133bc575f80fd5b87356133c781613398565b96506133d5602089016131f3565b955060408801356133e581613206565b94506133f3606089016131f3565b9350608088013561340381613206565b9699959850939692959460a0840135945060c09093013592915050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561345c5761345c613420565b604052919050565b5f6001600160401b0382111561347c5761347c613420565b5060051b60200190565b5f82601f830112613495575f80fd5b813560206134aa6134a583613464565b613434565b82815260059290921b840181019181810190868411156134c8575f80fd5b8286015b848110156134ea576134dd816131f3565b83529183019183016134cc565b509695505050505050565b5f82601f830112613504575f80fd5b813560206135146134a583613464565b82815260059290921b84018101918181019086841115613532575f80fd5b8286015b848110156134ea57803561354981613206565b8352918301918301613536565b5f805f8060808587031215613569575f80fd5b84356001600160401b038082111561357f575f80fd5b61358b88838901613486565b95506020915081870135818111156135a1575f80fd5b6135ad89828a016134f5565b9550506040870135818111156135c1575f80fd5b6135cd89828a016134f5565b9450506060870135818111156135e1575f80fd5b87019050601f810188136135f3575f80fd5b80356136016134a582613464565b81815260059190911b8201830190838101908a83111561361f575f80fd5b928401925b8284101561364657833561363781613252565b82529284019290840190613624565b979a9699509497505050505050565b5f805f60608486031215613667575f80fd5b613670846131f3565b9250602084013561368081613206565b9150604084013561369081613206565b809150509250925092565b5f602082840312156136ab575f80fd5b5035919050565b8061040081018310156107a3575f80fd5b5f805f61044084860312156136d6575f80fd5b833592506136e785602086016136b2565b91506136f661042085016131f3565b90509250925092565b5f8060408385031215613710575f80fd5b82356001600160401b0380821115613726575f80fd5b61373286838701613486565b93506020850135915080821115613747575f80fd5b5061375485828601613486565b9150509250929050565b5f6001600160401b0382111561377657613776613420565b50601f01601f191660200190565b5f82601f830112613793575f80fd5b81356137a16134a58261375e565b8181528460208386010111156137b5575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f805f805f6101208a8c0312156137ea575f80fd5b6137f38a6131f3565b985060208a013561380381613206565b975061381160408b016131f3565b965060608a013561382181613206565b955060808a013561383181613206565b945060a08a01356001600160401b0381111561384b575f80fd5b6138578c828d01613784565b94505060c08a013561386881613206565b925060e08a013561387881613206565b91506101008a013561388981613252565b809150509295985092959850929598565b5f80604083850312156138ab575f80fd5b82356138b681613206565b946020939093013593505050565b5f805f805f60a086880312156138d8575f80fd5b6138e1866131f3565b945060208601356138f181613206565b935060408601356001600160401b038082111561390c575f80fd5b61391889838a01613784565b9450606088013591508082111561392d575f80fd5b5061393a88828901613784565b925050608086013561394b81613398565b809150509295509295909350565b5f805f805f8060a0878903121561396e575f80fd5b613977876131f3565b9550602087013561398781613206565b945060408701359350606087013561399e81613252565b925060808701356001600160401b038111156139b8575f80fd5b6139c489828a0161325f565b979a9699509497509295939492505050565b5f80604083850312156139e7575f80fd5b82356139f281613206565b9150602083013561324781613252565b5f8060408385031215613a13575f80fd5b613a1c836131f3565b9150613a2a602084016131f3565b90509250929050565b5f805f805f805f805f805f806109208d8f031215613a4f575f80fd5b613a598e8e6136b2565b9b50613a698e6104008f016136b2565b9a506108008d013599506108208d013598506108408d01359750613a906108608e016131f3565b9650613aa06108808e0135613206565b6108808d01359550613ab56108a08e016131f3565b9450613ac56108c08e0135613206565b6108c08d013593506108e08d013592506001600160401b036109008e01351115613aed575f80fd5b613afe8e6109008f01358f0161325f565b81935080925050509295989b509295989b509295989b565b5f805f805f805f60c0888a031215613b2c575f80fd5b613b35886131f3565b96506020880135613b4581613206565b9550604088013594506060880135613b5c81613206565b93506080880135613b6c81613252565b925060a08801356001600160401b03811115613b86575f80fd5b613b928a828b0161325f565b989b979a50959850939692959293505050565b5f805f805f8060c08789031215613bba575f80fd5b613bc3876131f3565b95506020870135613bd381613206565b9450613be1604088016131f3565b93506060870135613bf181613206565b92506080870135613c0181613206565b915060a08701356001600160401b03811115613c1b575f80fd5b613c2789828a01613784565b9150509295509295509295565b5f805f806104608587031215613c48575f80fd5b84359350613c5986602087016136b2565b9250613c6861042086016131f3565b939692955092936104400135925050565b60e09290921b6001600160e01b031916825260601b6001600160601b031916600482015260180190565b600181811c90821680613cb757607f821691505b602082108103613cd557634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f60018201613d1457613d14613cef565b5060010190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b601f821115610ce9575f81815260208120601f850160051c81016020861015613d8f5750805b601f850160051c820191505b818110156113d957828155600101613d9b565b81516001600160401b03811115613dc757613dc7613420565b613ddb81613dd58454613ca3565b84613d69565b602080601f831160018114613e0e575f8415613df75750858301515b5f19600386901b1c1916600185901b1785556113d9565b5f85815260208120601f198616915b82811015613e3c57888601518255948401946001909101908401613e1d565b5085821015613e5957878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f613e7b6060830186613339565b8281036020840152613e8d8186613339565b91505060ff83166040830152949350505050565b5f8351613eb2818460208801613317565b835190830190613ec6818360208801613317565b01949350505050565b80820281158282048414176107a3576107a3613cef565b808201808211156107a3576107a3613cef565b818382375f9101908152919050565b5f8251613f19818460208701613317565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681526001600160a01b038581166020830152841660408201526080606082018190525f906131399083018486613f23565b94855263ffffffff9390931660208501526001600160a01b039182166040850152166060830152608082015260a00190565b5f60208284031215613fc5575f80fd5b5051919050565b818103818111156107a3576107a3613cef565b60ff8916815263ffffffff88811660208301526001600160a01b03888116604084015287821660608401528616608083015260a0820185905261010060c083018190525f9161403084830187613339565b925080851660e085015250509998505050505050505050565b6001600160a01b038516815263ffffffff841660208201526060604082018190525f906140799083018486613f23565b9695505050505050565b60ff8a16815263ffffffff89811660208301526001600160a01b03898116604084015288821660608401528716608083015260a0820186905261010060c083018190525f916140d58483018789613f23565b925080851660e085015250509a9950505050505050505050565b5f602082840312156140ff575f80fd5b815161337681613398565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b03929092168252602082015260400190565b63ffffffff8181168382160190808211156126a9576126a9613cef565b5f8085851115614199575f80fd5b838611156141a5575f80fd5b5050820193919092039150565b6001600160e01b031981358181169160048510156141da5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a0312156141f8575f80fd5b873561420381613206565b9650602088013561421381613206565b95506040880135945060608801359350608088013561340381613398565b5f805f805f805f80610100898b031215614249575f80fd5b883561425481613206565b9750602089013561426481613206565b96506040890135955060608901359450608089013561428281613252565b935060a089013561429281613398565b979a969950949793969295929450505060c08201359160e0013590565b600181815b808511156142e957815f19048211156142cf576142cf613cef565b808516156142dc57918102915b93841c93908002906142b4565b509250929050565b5f826142ff575060016107a3565b8161430b57505f6107a3565b8160018114614321576002811461432b57614347565b60019150506107a3565b60ff84111561433c5761433c613cef565b50506001821b6107a3565b5060208310610133831016604e8410600b841016171561436a575081810a6107a3565b61437483836142af565b805f190482111561438757614387613cef565b029392505050565b5f61337683836142f1565b634e487b7160e01b5f52600160045260245ffd5b5f602082840312156143be575f80fd5b81516001600160401b038111156143d3575f80fd5b8201601f810184136143e3575f80fd5b80516143f16134a58261375e565b818152856020838501011115614405575f80fd5b614416826020830160208601613317565b95945050505050565b5f6020828403121561442f575f80fd5b81516133768161325256fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220ca7a7fd14ec73edf6b3d053ef2133e4a8110a83daf9abb364c35f9d9eb2a083564736f6c63430008140033", + "deployedBytecode": "0x6080604052600436106101e4575f3560e01c80638c0dd470116101075780638c0dd470146104ba5780638ed7e3f2146104d95780639e76158f146104f8578063aaa13cc214610517578063b458696214610536578063b8b284d014610555578063bab161bf14610574578063be5831c714610595578063bf130d7f146105b8578063c00f14ab146105d7578063c0f49163146105f6578063cc46163214610624578063ccaa2d1114610643578063cd58657914610662578063d02103ca14610675578063dbc1697614610246578063eabd372a1461069b578063ee25560b146106ba578063f5efcd79146106e5578063f811bff714610704578063fb57083414610723575f80fd5b806314cc01a0146101e857806315064c961461021d5780632072f6c51461024657806322e95f2c1461025c578063240ff3781461027b57806327aef4e81461028e5780632dfdf0b5146102af578063318aee3d146102d25780633c351e10146103395780633cbc795b146103585780633e197043146103905780634b2f336d146103af57806357cfbee3146103ce5780635ca1e165146103ed5780637843298b1461040157806379e2cf971461042057806381b1c1741461043457806383c43a551461046857806383f244031461047c5780638781a5c51461049b575b5f80fd5b3480156101f3575f80fd5b5060a354610207906001600160a01b031681565b60405161021491906131df565b60405180910390f35b348015610228575f80fd5b506068546102369060ff1681565b6040519015158152602001610214565b348015610251575f80fd5b5061025a610742565b005b348015610267575f80fd5b5061020761027636600461321d565b61075b565b61025a6102893660046132a3565b6107a9565b348015610299575f80fd5b506102a2610819565b6040516102149190613364565b3480156102ba575f80fd5b506102c460535481565b604051908152602001610214565b3480156102dd575f80fd5b506103156102ec36600461337d565b606b6020525f908152604090205463ffffffff811690600160201b90046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201610214565b348015610344575f80fd5b50606d54610207906001600160a01b031681565b348015610363575f80fd5b50606d5461037b90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610214565b34801561039b575f80fd5b506102c46103aa3660046133a6565b6108a5565b3480156103ba575f80fd5b50606f54610207906001600160a01b031681565b3480156103d9575f80fd5b5061025a6103e8366004613556565b610931565b3480156103f8575f80fd5b506102c4610a27565b34801561040c575f80fd5b5061020761041b366004613655565b610b03565b34801561042b575f80fd5b5061025a610b2c565b34801561043f575f80fd5b5061020761044e36600461369b565b606a6020525f90815260409020546001600160a01b031681565b348015610473575f80fd5b506102a2610b4f565b348015610487575f80fd5b506102c46104963660046136c3565b610b6e565b3480156104a6575f80fd5b5061025a6104b53660046136ff565b610c43565b3480156104c5575f80fd5b5061025a6104d43660046137d1565b610cee565b3480156104e4575f80fd5b50606c54610207906001600160a01b031681565b348015610503575f80fd5b5061025a61051236600461389a565b610fcf565b348015610522575f80fd5b506102076105313660046138c4565b611107565b348015610541575f80fd5b5061025a61055036600461337d565b611207565b348015610560575f80fd5b5061025a61056f366004613959565b611368565b34801561057f575f80fd5b5060685461037b90610100900463ffffffff1681565b3480156105a0575f80fd5b5060685461037b90600160c81b900463ffffffff1681565b3480156105c3575f80fd5b5061025a6105d23660046139d6565b6113e1565b3480156105e2575f80fd5b506102a26105f136600461337d565b6114ab565b348015610601575f80fd5b5061023661061036600461337d565b60a26020525f908152604090205460ff1681565b34801561062f575f80fd5b5061023661063e366004613a02565b6114f0565b34801561064e575f80fd5b5061025a61065d366004613a33565b611540565b61025a610670366004613b16565b611924565b348015610680575f80fd5b5060685461020790600160281b90046001600160a01b031681565b3480156106a6575f80fd5b5061025a6106b536600461337d565b611cc4565b3480156106c5575f80fd5b506102c46106d436600461369b565b60696020525f908152604090205481565b3480156106f0575f80fd5b5061025a6106ff366004613a33565b611d46565b34801561070f575f80fd5b5061025a61071e366004613ba5565b611f8c565b34801561072e575f80fd5b5061023661073d366004613c34565b612031565b60405163441845b160e01b815260040160405180910390fd5b5f606a5f8484604051602001610772929190613c79565b60408051601f198184030181529181528151602092830120835290820192909252015f20546001600160a01b031690505b92915050565b60685460ff16156107cd57604051630bc011ff60e21b815260040160405180910390fd5b34158015906107e65750606f546001600160a01b031615155b15610804576040516301bd897160e61b815260040160405180910390fd5b610812858534868686612048565b5050505050565b606e805461082690613ca3565b80601f016020809104026020016040519081016040528092919081815260200182805461085290613ca3565b801561089d5780601f106108745761010080835404028352916020019161089d565b820191905f5260205f20905b81548152906001019060200180831161088057829003601f168201915b505050505081565b6040516001600160f81b031960f889901b1660208201526001600160e01b031960e088811b821660218401526001600160601b0319606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b60a3546001600160a01b0316331461095c576040516357b738d160e11b815260040160405180910390fd5b8251845114158061096f57508151845114155b8061097c57508051845114155b1561099a5760405163434f49f560e11b815260040160405180910390fd5b5f5b825181101561081257610a158582815181106109ba576109ba613cdb565b60200260200101518583815181106109d4576109d4613cdb565b60200260200101518584815181106109ee576109ee613cdb565b6020026020010151858581518110610a0857610a08613cdb565b6020026020010151612112565b80610a1f81613d03565b91505061099c565b6053545f90819081805b6020811015610afa578083901c600116600103610a8e5760338160208110610a5b57610a5b613cdb565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610abb565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080610af290613d03565b915050610a31565b50919392505050565b5f610b248484610b12856122c2565b610b1b8661237d565b61053187612431565b949350505050565b605354606854600160c81b900463ffffffff161015610b4d57610b4d6124e5565b565b60405180611ba00160405280611b66815260200161443b611b66913981565b5f83815b6020811015610c3a57600163ffffffff8516821c81169003610bdd57848160208110610ba057610ba0613cdb565b602002013582604051602001610bc0929190918252602082015260400190565b604051602081830303815290604052805190602001209150610c28565b81858260208110610bf057610bf0613cdb565b6020020135604051602001610c0f929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80610c3281613d03565b915050610b72565b50949350505050565b60a3546001600160a01b03163314610c6e576040516357b738d160e11b815260040160405180910390fd5b8051825114610c905760405163434f49f560e11b815260040160405180910390fd5b5f5b8251811015610ce957610cd7838281518110610cb057610cb0613cdb565b6020026020010151838381518110610cca57610cca613cdb565b6020026020010151612579565b80610ce181613d03565b915050610c92565b505050565b5f54610100900460ff1615808015610d0c57505f54600160ff909116105b80610d2c5750610d1b30612627565b158015610d2c57505f5460ff166001145b610d515760405162461bcd60e51b8152600401610d4890613d1b565b60405180910390fd5b5f805460ff191660011790558015610d72575f805461ff0019166101001790555b60688054610100600160c81b03191661010063ffffffff8d1602600160281b600160c81b03191617600160281b6001600160a01b038a81169190910291909117909155606c80546001600160a01b03199081168984161790915560a380549091168683161790558916610e3b5763ffffffff881615610e0457604051630d43a60960e11b815260040160405180910390fd5b6001600160a01b038316151580610e185750815b15610e3657604051630e6e237560e11b815260040160405180910390fd5b610f76565b606d805463ffffffff8a16600160a01b026001600160c01b03199091166001600160a01b038c1617179055606e610e728682613dae565b506001600160a01b038316610f3e57811515600103610ea457604051630e6e237560e11b815260040160405180910390fd5b610f195f801b6012604051602001610f0591906060808252600d908201526c2bb930b83832b21022ba3432b960991b608082015260a060208201819052600490820152630ae8aa8960e31b60c082015260ff91909116604082015260e00190565b604051602081830303815290604052612636565b606f80546001600160a01b0319166001600160a01b0392909216919091179055610f76565b606f80546001600160a01b0319166001600160a01b0385169081179091555f90815260a260205260409020805460ff19168315151790555b610f7e6126b0565b8015610fc3575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050505050565b6001600160a01b038083165f908152606b602090815260409182902082518084019093525463ffffffff81168352600160201b90049092169181018290529061102b5760405163828d566360e01b815260040160405180910390fd5b5f606a5f835f01518460200151604051602001611049929190613c79565b60408051601f198184030181529181528151602092830120835290820192909252015f20546001600160a01b0390811691508416810361109c5760405163e273c4a160e01b815260040160405180910390fd5b6110a684846126de565b6110b181338561276e565b604080513381526001600160a01b0386811660208301528316818301526060810185905290517fb7f8fd4d1faf9b2929dc269f59c53e3a2bccc44e9950f33a568fcbcb37eb69a99181900360800190a150505050565b5f80868660405160200161111c929190613c79565b6040516020818303038152906040528051906020012090505f60ff60f81b308360405180611ba00160405280611b66815260200161443b611b66913989898960405160200161116d93929190613e69565b60408051601f198184030181529082905261118b9291602001613ea1565b604051602081830303815290604052805190602001206040516020016111e394939291906001600160f81b031994909416845260609290921b6001600160601b03191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60a3546001600160a01b03163314611232576040516357b738d160e11b815260040160405180910390fd5b6001600160a01b038082165f908152606b6020908152604080832081518083018352905463ffffffff8116808352600160201b909104909516818401819052915190946112829390929101613c79565b60408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b031615806112d657505f818152606a60205260409020546001600160a01b038481169116145b156112f45760405163e0c897a760e01b815260040160405180910390fd5b6001600160a01b0383165f908152606b6020908152604080832080546001600160c01b031916905560a290915290819020805460ff19169055517fc2ae0bd0ec0fd0352bfe5bacac49637af342c1e40f1b80a7f74440dc7fe3f0639061135b9085906131df565b60405180910390a1505050565b60685460ff161561138c57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b03166113b55760405163dde3cda760e01b815260040160405180910390fd5b606f546113cb906001600160a01b0316856126de565b6113d9868686868686612048565b505050505050565b60a3546001600160a01b0316331461140c576040516357b738d160e11b815260040160405180910390fd5b606d546001600160a01b031661143557604051634cb4711360e11b815260040160405180910390fd5b606f80546001600160a01b0319166001600160a01b0384169081179091555f81815260a26020908152604091829020805460ff19168515159081179091558251938452908301527fc7318b7ed6ba4f2908a3de396d8ab49b1dadb55db5b55123247a401f29ff8d82910160405180910390a15050565b60606114b6826122c2565b6114bf8361237d565b6114c884612431565b6040516020016114da93929190613e69565b6040516020818303038152906040529050919050565b5f80611506600160201b63ffffffff8516613ecf565b6115169063ffffffff8616613ee6565b600881901c5f90815260696020526040902054600160ff9092169190911b90811614949350505050565b60685460ff161561156457604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614611594576040516302caf51760e11b815260040160405180910390fd5b6115c78c8c8c8c8c6115c25f8e8e8e8e8e8e8e6040516115b5929190613ef9565b60405180910390206108a5565b6127f9565b6001600160a01b0386166116ae57606f546001600160a01b0316611692575f6001600160a01b03851684825b6040519080825280601f01601f19166020018201604052801561161d576020820181803683370190505b5060405161162b9190613f08565b5f6040518083038185875af1925050503d805f8114611665576040519150601f19603f3d011682016040523d82523d5f602084013e61166a565b606091505b505090508061168c57604051630ce8f45160e31b815260040160405180910390fd5b506118d7565b606f546116a9906001600160a01b0316858561276e565b6118d7565b606d546001600160a01b0387811691161480156116dc5750606d5463ffffffff888116600160a01b90920416145b156116f3575f6001600160a01b03851684826115f3565b60685463ffffffff61010090910481169088160361171f576116a96001600160a01b0387168585612952565b5f8787604051602001611733929190613c79565b60408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b0316806118c9575f6117a88386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061263692505050565b90506117b581888861276e565b80606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a8388886040516118bb959493929190613f4b565b60405180910390a1506118d4565b6118d481878761276e565b50505b7f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d8a8888878760405161190e959493929190613f83565b60405180910390a1505050505050505050505050565b60685460ff161561194857604051630bc011ff60e21b815260040160405180910390fd5b6119506129a8565b60685463ffffffff610100909104811690881603611981576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b038816611a64578834146119b45760405163b89240f560e01b815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff169450906119e190613ca3565b80601f0160208091040260200160405190810160405280929190818152602001828054611a0d90613ca3565b8015611a585780601f10611a2f57610100808354040283529160200191611a58565b820191905f5260205f20905b815481529060010190602001808311611a3b57829003601f168201915b50505050509150611c3b565b3415611a835760405163798ee6f160e01b815260040160405180910390fd5b606f546001600160a01b0390811690891603611aa857611aa3888a6126de565b611c3b565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff81168352600160201b90049092169181018290529015611b0757611af6898b6126de565b602081015181519095509350611c2e565b8515611b1957611b19898b8989612a01565b6040516370a0823160e01b81525f906001600160a01b038b16906370a0823190611b479030906004016131df565b602060405180830381865afa158015611b62573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b869190613fb5565b9050611b9d6001600160a01b038b1633308e612cb2565b6040516370a0823160e01b81525f906001600160a01b038c16906370a0823190611bcb9030906004016131df565b602060405180830381865afa158015611be6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c0a9190613fb5565b9050611c168282613fcc565b6068548c9850610100900463ffffffff169650935050505b611c37896114ab565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e8688605354604051611c7a989796959493929190613fdf565b60405180910390a1611ca0611c9b5f85878f8f8789805190602001206108a5565b612cea565b8615611cae57611cae6124e5565b50505050611cbb60018055565b50505050505050565b60a3546001600160a01b03163314611cef576040516357b738d160e11b815260040160405180910390fd5b60a380546001600160a01b0319166001600160a01b0383169081179091556040517f32cf74f8a6d5f88593984d2cd52be5592bfa6884f5896175801a5069ef09cd6791611d3b916131df565b60405180910390a150565b60685460ff1615611d6a57604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614611d9a576040516302caf51760e11b815260040160405180910390fd5b611dbc8c8c8c8c8c6115c260018e8e8e8e8e8e8e6040516115b5929190613ef9565b606f545f906001600160a01b0316611e6f57846001600160a01b031684888a8686604051602401611df09493929190614049565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b17905251611e259190613f08565b5f6040518083038185875af1925050503d805f8114611e5f576040519150601f19603f3d011682016040523d82523d5f602084013e611e64565b606091505b505080915050611f20565b606f54611e86906001600160a01b0316868661276e565b846001600160a01b031687898585604051602401611ea79493929190614049565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b17905251611edc9190613f08565b5f604051808303815f865af19150503d805f8114611f15576040519150601f19603f3d011682016040523d82523d5f602084013e611f1a565b606091505b50909150505b80611f3e576040516337e391c360e01b815260040160405180910390fd5b7f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d8b89898888604051611f75959493929190613f83565b60405180910390a150505050505050505050505050565b5f54610100900460ff1615808015611faa57505f54600160ff909116105b80611fca5750611fb930612627565b158015611fca57505f5460ff166001145b611fe65760405162461bcd60e51b8152600401610d4890613d1b565b5f805460ff191660011790558015612007575f805461ff0019166101001790555b60405163f57ac68360e01b815260040160405180910390fd5b60405180910390a150505050505050565b5f8161203e868686610b6e565b1495945050505050565b60685463ffffffff610100909104811690871603612079576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff163389898988886053546040516120cd99989796959493929190614083565b60405180910390a1612104611c9b6001606860019054906101000a900463ffffffff16338a8a8a89896040516115b5929190613ef9565b82156113d9576113d96124e5565b6001600160a01b038316158061212f57506001600160a01b038216155b1561214d5760405163f6b2911f60e01b815260040160405180910390fd5b60685463ffffffff61010090910481169085160361217e5760405163658b23ad60e01b815260040160405180910390fd5b6001600160a01b038281165f908152606b6020526040902054600160201b900416156121bd576040516317abdeeb60e21b815260040160405180910390fd5b5f84846040516020016121d1929190613c79565b60408051808303601f1901815282825280516020918201205f818152606a835283812080546001600160a01b0319166001600160a01b038a8116918217909255868601865263ffffffff8c81168089528c8416878a01818152848752606b89528987209a518b54915194166001600160c01b031990911617600160201b93909516929092029390931790975560a2855291859020805460ff191689151590811790915585519182529381019590955292840192909252606083015291507fdbe8a5da6a7a916d9adfda9160167a0f8a3da415ee6610e810e753853597fce79060800160405180910390a15050505050565b60408051600481526024810182526020810180516001600160e01b03166306fdde0360e01b17905290516060915f9182916001600160a01b038616916123089190613f08565b5f60405180830381855afa9150503d805f8114612340576040519150601f19603f3d011682016040523d82523d5f602084013e612345565b606091505b50915091508161237457604051806040016040528060078152602001664e4f5f4e414d4560c81b815250610b24565b610b2481612dd2565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b17905290516060915f9182916001600160a01b038616916123c39190613f08565b5f60405180830381855afa9150503d805f81146123fb576040519150601f19603f3d011682016040523d82523d5f602084013e612400565b606091505b50915091508161237457604051806040016040528060098152602001681393d7d4d6535093d360ba1b815250610b24565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b17905290515f91829182916001600160a01b038616916124769190613f08565b5f60405180830381855afa9150503d805f81146124ae576040519150601f19603f3d011682016040523d82523d5f602084013e6124b3565b606091505b50915091508180156124c6575080516020145b6124d1576012610b24565b80806020019051810190610b2491906140ef565b6053546068805463ffffffff909216600160c81b0263ffffffff60c81b1990921691909117908190556001600160a01b03600160281b909104166333d6247d61252c610a27565b6040518263ffffffff1660e01b815260040161254a91815260200190565b5f604051808303815f87803b158015612561575f80fd5b505af1158015612573573d5f803e3d5ffd5b50505050565b5f61258e600160201b63ffffffff8416613ecf565b61259e9063ffffffff8516613ee6565b600881901c5f8181526069602052604090208054600160ff851690811b9182189283905593945091929190808216156125ea57604051630631b5f760e31b815260040160405180910390fd5b6040805163ffffffff808a168252881660208201527f4a402ac607e71571d0543be8fcccc358a4df62dcd019a1e7f7e98ca6175e8f2a9101612020565b6001600160a01b03163b151590565b5f8060405180611ba00160405280611b66815260200161443b611b66913983604051602001612666929190613ea1565b6040516020818303038152906040529050838151602083015ff591506001600160a01b0382166126a9576040516305f7d84960e51b815260040160405180910390fd5b5092915050565b5f54610100900460ff166126d65760405162461bcd60e51b8152600401610d489061410a565b610b4d612f5b565b6001600160a01b0382165f90815260a2602052604090205460ff1615612717576127136001600160a01b038316333084612cb2565b5050565b604051632770a7eb60e21b81526001600160a01b03831690639dc29fac906127459033908590600401614155565b5f604051808303815f87803b15801561275c575f80fd5b505af11580156113d9573d5f803e3d5ffd5b6001600160a01b0383165f90815260a2602052604090205460ff16156127a257610ce96001600160a01b0384168383612952565b6040516340c10f1960e01b81526001600160a01b038416906340c10f19906127d09085908590600401614155565b5f604051808303815f87803b1580156127e7575f80fd5b505af1158015611cbb573d5f803e3d5ffd5b606854604080516020808201879052818301869052825180830384018152606083019384905280519101206312bd9b1960e11b90925260648101919091525f91600160281b90046001600160a01b03169063257b3632906084016020604051808303815f875af115801561286f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128939190613fb5565b9050805f036128b457604051622f6fad60e01b815260040160405180910390fd5b5f80600160401b8716156128f3578691506128d1848a8489612031565b6128ee576040516338105f3b60e21b815260040160405180910390fd5b61293d565b602087901c61290381600161416e565b915087925061291e612916868c86610b6e565b8a8389612031565b61293b576040516338105f3b60e21b815260040160405180910390fd5b505b6129478282612f81565b505050505050505050565b610ce98363a9059cbb60e01b8484604051602401612971929190614155565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612ff3565b6002600154036129fa5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610d48565b6002600155565b5f612a0f600482848661418b565b612a18916141b2565b9050632afa533160e01b6001600160e01b0319821601612b4c575f808080808080612a46896004818d61418b565b810190612a5391906141e2565b96509650965096509650965096508a8514612a81576040516303fffc4b60e01b815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b031663d505accf60e01b1790529151918e1691612aff9190613f08565b5f604051808303815f865af19150503d805f8114612b38576040519150601f19603f3d011682016040523d82523d5f602084013e612b3d565b606091505b50505050505050505050610812565b6001600160e01b031981166323f2ebc360e21b14612b7d57604051637141605d60e11b815260040160405180910390fd5b5f80808080808080612b928a6004818e61418b565b810190612b9f9190614231565b975097509750975097509750975097508c6001600160a01b0316638fcbaf0c60e01b8989898989898989604051602401612c249897969594939291906001600160a01b039889168152969097166020870152604086019490945260608501929092521515608084015260ff1660a083015260c082015260e08101919091526101000190565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612c629190613f08565b5f604051808303815f865af19150503d805f8114612c9b576040519150601f19603f3d011682016040523d82523d5f602084013e612ca0565b606091505b50505050505050505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526125739085906323b872dd60e01b90608401612971565b806001612cf96020600261438f565b612d039190613fcc565b60535410612d24576040516377ae67b360e11b815260040160405180910390fd5b5f60535f8154612d3390613d03565b918290555090505f5b6020811015612dc3578082901c600116600103612d6f578260338260208110612d6757612d67613cdb565b015550505050565b60338160208110612d8257612d82613cdb565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092508080612dbb90613d03565b915050612d3c565b50610ce961439a565b60018055565b60606040825110612df157818060200190518101906107a391906143ae565b8151602003612f28575f5b602081108015612e2b5750828181518110612e1957612e19613cdb565b01602001516001600160f81b03191615155b15612e425780612e3a81613d03565b915050612dfc565b805f03612e795750506040805180820190915260128152714e4f545f56414c49445f454e434f44494e4760701b6020820152919050565b5f816001600160401b03811115612e9257612e92613420565b6040519080825280601f01601f191660200182016040528015612ebc576020820181803683370190505b5090505f5b82811015612f2057848181518110612edb57612edb613cdb565b602001015160f81c60f81b828281518110612ef857612ef8613cdb565b60200101906001600160f81b03191690815f1a90535080612f1881613d03565b915050612ec1565b509392505050565b50506040805180820190915260128152714e4f545f56414c49445f454e434f44494e4760701b602082015290565b919050565b5f54610100900460ff16612dcc5760405162461bcd60e51b8152600401610d489061410a565b5f612f96600160201b63ffffffff8416613ecf565b612fa69063ffffffff8516613ee6565b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055949550929392918183169003611cbb57604051630c8d9eab60e31b815260040160405180910390fd5b5f613047826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130c49092919063ffffffff16565b805190915015610ce95780806020019051810190613065919061441f565b610ce95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610d48565b6060610b2484845f85855f80866001600160a01b031685876040516130e99190613f08565b5f6040518083038185875af1925050503d805f8114613123576040519150601f19603f3d011682016040523d82523d5f602084013e613128565b606091505b509150915061313987838387613144565b979650505050505050565b606083156131b05782515f036131a95761315d85612627565b6131a95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d48565b5081610b24565b610b2483838151156131c55781518083602001fd5b8060405162461bcd60e51b8152600401610d489190613364565b6001600160a01b0391909116815260200190565b803563ffffffff81168114612f56575f80fd5b6001600160a01b038116811461321a575f80fd5b50565b5f806040838503121561322e575f80fd5b613237836131f3565b9150602083013561324781613206565b809150509250929050565b801515811461321a575f80fd5b5f8083601f84011261326f575f80fd5b5081356001600160401b03811115613285575f80fd5b60208301915083602082850101111561329c575f80fd5b9250929050565b5f805f805f608086880312156132b7575f80fd5b6132c0866131f3565b945060208601356132d081613206565b935060408601356132e081613252565b925060608601356001600160401b038111156132fa575f80fd5b6133068882890161325f565b969995985093965092949392505050565b5f5b83811015613331578181015183820152602001613319565b50505f910152565b5f8151808452613350816020860160208601613317565b601f01601f19169290920160200192915050565b602081525f6133766020830184613339565b9392505050565b5f6020828403121561338d575f80fd5b813561337681613206565b60ff8116811461321a575f80fd5b5f805f805f805f60e0888a0312156133bc575f80fd5b87356133c781613398565b96506133d5602089016131f3565b955060408801356133e581613206565b94506133f3606089016131f3565b9350608088013561340381613206565b9699959850939692959460a0840135945060c09093013592915050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561345c5761345c613420565b604052919050565b5f6001600160401b0382111561347c5761347c613420565b5060051b60200190565b5f82601f830112613495575f80fd5b813560206134aa6134a583613464565b613434565b82815260059290921b840181019181810190868411156134c8575f80fd5b8286015b848110156134ea576134dd816131f3565b83529183019183016134cc565b509695505050505050565b5f82601f830112613504575f80fd5b813560206135146134a583613464565b82815260059290921b84018101918181019086841115613532575f80fd5b8286015b848110156134ea57803561354981613206565b8352918301918301613536565b5f805f8060808587031215613569575f80fd5b84356001600160401b038082111561357f575f80fd5b61358b88838901613486565b95506020915081870135818111156135a1575f80fd5b6135ad89828a016134f5565b9550506040870135818111156135c1575f80fd5b6135cd89828a016134f5565b9450506060870135818111156135e1575f80fd5b87019050601f810188136135f3575f80fd5b80356136016134a582613464565b81815260059190911b8201830190838101908a83111561361f575f80fd5b928401925b8284101561364657833561363781613252565b82529284019290840190613624565b979a9699509497505050505050565b5f805f60608486031215613667575f80fd5b613670846131f3565b9250602084013561368081613206565b9150604084013561369081613206565b809150509250925092565b5f602082840312156136ab575f80fd5b5035919050565b8061040081018310156107a3575f80fd5b5f805f61044084860312156136d6575f80fd5b833592506136e785602086016136b2565b91506136f661042085016131f3565b90509250925092565b5f8060408385031215613710575f80fd5b82356001600160401b0380821115613726575f80fd5b61373286838701613486565b93506020850135915080821115613747575f80fd5b5061375485828601613486565b9150509250929050565b5f6001600160401b0382111561377657613776613420565b50601f01601f191660200190565b5f82601f830112613793575f80fd5b81356137a16134a58261375e565b8181528460208386010111156137b5575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f805f805f6101208a8c0312156137ea575f80fd5b6137f38a6131f3565b985060208a013561380381613206565b975061381160408b016131f3565b965060608a013561382181613206565b955060808a013561383181613206565b945060a08a01356001600160401b0381111561384b575f80fd5b6138578c828d01613784565b94505060c08a013561386881613206565b925060e08a013561387881613206565b91506101008a013561388981613252565b809150509295985092959850929598565b5f80604083850312156138ab575f80fd5b82356138b681613206565b946020939093013593505050565b5f805f805f60a086880312156138d8575f80fd5b6138e1866131f3565b945060208601356138f181613206565b935060408601356001600160401b038082111561390c575f80fd5b61391889838a01613784565b9450606088013591508082111561392d575f80fd5b5061393a88828901613784565b925050608086013561394b81613398565b809150509295509295909350565b5f805f805f8060a0878903121561396e575f80fd5b613977876131f3565b9550602087013561398781613206565b945060408701359350606087013561399e81613252565b925060808701356001600160401b038111156139b8575f80fd5b6139c489828a0161325f565b979a9699509497509295939492505050565b5f80604083850312156139e7575f80fd5b82356139f281613206565b9150602083013561324781613252565b5f8060408385031215613a13575f80fd5b613a1c836131f3565b9150613a2a602084016131f3565b90509250929050565b5f805f805f805f805f805f806109208d8f031215613a4f575f80fd5b613a598e8e6136b2565b9b50613a698e6104008f016136b2565b9a506108008d013599506108208d013598506108408d01359750613a906108608e016131f3565b9650613aa06108808e0135613206565b6108808d01359550613ab56108a08e016131f3565b9450613ac56108c08e0135613206565b6108c08d013593506108e08d013592506001600160401b036109008e01351115613aed575f80fd5b613afe8e6109008f01358f0161325f565b81935080925050509295989b509295989b509295989b565b5f805f805f805f60c0888a031215613b2c575f80fd5b613b35886131f3565b96506020880135613b4581613206565b9550604088013594506060880135613b5c81613206565b93506080880135613b6c81613252565b925060a08801356001600160401b03811115613b86575f80fd5b613b928a828b0161325f565b989b979a50959850939692959293505050565b5f805f805f8060c08789031215613bba575f80fd5b613bc3876131f3565b95506020870135613bd381613206565b9450613be1604088016131f3565b93506060870135613bf181613206565b92506080870135613c0181613206565b915060a08701356001600160401b03811115613c1b575f80fd5b613c2789828a01613784565b9150509295509295509295565b5f805f806104608587031215613c48575f80fd5b84359350613c5986602087016136b2565b9250613c6861042086016131f3565b939692955092936104400135925050565b60e09290921b6001600160e01b031916825260601b6001600160601b031916600482015260180190565b600181811c90821680613cb757607f821691505b602082108103613cd557634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f60018201613d1457613d14613cef565b5060010190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b601f821115610ce9575f81815260208120601f850160051c81016020861015613d8f5750805b601f850160051c820191505b818110156113d957828155600101613d9b565b81516001600160401b03811115613dc757613dc7613420565b613ddb81613dd58454613ca3565b84613d69565b602080601f831160018114613e0e575f8415613df75750858301515b5f19600386901b1c1916600185901b1785556113d9565b5f85815260208120601f198616915b82811015613e3c57888601518255948401946001909101908401613e1d565b5085821015613e5957878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f613e7b6060830186613339565b8281036020840152613e8d8186613339565b91505060ff83166040830152949350505050565b5f8351613eb2818460208801613317565b835190830190613ec6818360208801613317565b01949350505050565b80820281158282048414176107a3576107a3613cef565b808201808211156107a3576107a3613cef565b818382375f9101908152919050565b5f8251613f19818460208701613317565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681526001600160a01b038581166020830152841660408201526080606082018190525f906131399083018486613f23565b94855263ffffffff9390931660208501526001600160a01b039182166040850152166060830152608082015260a00190565b5f60208284031215613fc5575f80fd5b5051919050565b818103818111156107a3576107a3613cef565b60ff8916815263ffffffff88811660208301526001600160a01b03888116604084015287821660608401528616608083015260a0820185905261010060c083018190525f9161403084830187613339565b925080851660e085015250509998505050505050505050565b6001600160a01b038516815263ffffffff841660208201526060604082018190525f906140799083018486613f23565b9695505050505050565b60ff8a16815263ffffffff89811660208301526001600160a01b03898116604084015288821660608401528716608083015260a0820186905261010060c083018190525f916140d58483018789613f23565b925080851660e085015250509a9950505050505050505050565b5f602082840312156140ff575f80fd5b815161337681613398565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b03929092168252602082015260400190565b63ffffffff8181168382160190808211156126a9576126a9613cef565b5f8085851115614199575f80fd5b838611156141a5575f80fd5b5050820193919092039150565b6001600160e01b031981358181169160048510156141da5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a0312156141f8575f80fd5b873561420381613206565b9650602088013561421381613206565b95506040880135945060608801359350608088013561340381613398565b5f805f805f805f80610100898b031215614249575f80fd5b883561425481613206565b9750602089013561426481613206565b96506040890135955060608901359450608089013561428281613252565b935060a089013561429281613398565b979a969950949793969295929450505060c08201359160e0013590565b600181815b808511156142e957815f19048211156142cf576142cf613cef565b808516156142dc57918102915b93841c93908002906142b4565b509250929050565b5f826142ff575060016107a3565b8161430b57505f6107a3565b8160018114614321576002811461432b57614347565b60019150506107a3565b60ff84111561433c5761433c613cef565b50506001821b6107a3565b5060208310610133831016604e8410600b841016171561436a575081810a6107a3565b61437483836142af565b805f190482111561438757614387613cef565b029392505050565b5f61337683836142f1565b634e487b7160e01b5f52600160045260245ffd5b5f602082840312156143be575f80fd5b81516001600160401b038111156143d3575f80fd5b8201601f810184136143e3575f80fd5b80516143f16134a58261375e565b818152856020838501011115614405575f80fd5b614416826020830160208601613317565b95945050505050565b5f6020828403121561442f575f80fd5b81516133768161325256fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220ca7a7fd14ec73edf6b3d053ef2133e4a8110a83daf9abb364c35f9d9eb2a083564736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/compiled-contracts/ClaimCompressor.json b/compiled-contracts/ClaimCompressor.json index 602172e0b..ae111a23e 100644 --- a/compiled-contracts/ClaimCompressor.json +++ b/compiled-contracts/ClaimCompressor.json @@ -109,8 +109,8 @@ "type": "function" } ], - "bytecode": "0x60c060405234801561000f575f80fd5b50604051610dec380380610dec83398101604081905261002e9161004a565b6001600160a01b0390911660805263ffffffff1660a052610095565b5f806040838503121561005b575f80fd5b82516001600160a01b0381168114610071575f80fd5b602084015190925063ffffffff8116811461008a575f80fd5b809150509250929050565b60805160a051610d366100b65f395f61043601525f6104580152610d365ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806304e5557b1461003857806397b1410f14610061575b5f80fd5b61004b610046366004610600565b610076565b604051610058919061069e565b60405180910390f35b61007461006f3660046106ee565b61042f565b005b60605f8585604051602001610095929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905290505f805b84811015610423575f8686838181106100e3576100e361075a565b90506020028101906100f59190610787565b6100fe90610976565b90505f825f03610110575060206101a0565b5f5b602081101561019e578888610128600187610a6c565b8181106101375761013761075a565b90506020028101906101499190610787565b816020811061015a5761015a61075a565b6020020135835f015182602081106101745761017461075a565b60200201511461018c57610189816001610a85565b91505b8061019681610a98565b915050610112565b505b6040805160f883901b7fff000000000000000000000000000000000000000000000000000000000000001660208201528151600181830301815260219091019091525f5b8281101561023b578351829082602081106102015761020161075a565b6020020151604051602001610217929190610aea565b6040516020818303038152906040529150808061023390610a98565b9150506101e4565b5060208301516103e001515f92501561030157831580610259575084155b1561026757602091506102fc565b5f5b60208110156102fa57898961027f600188610a6c565b81811061028e5761028e61075a565b90506020028101906102a09190610787565b6104000181602081106102b5576102b561075a565b6020020135846020015182602081106102d0576102d061075a565b6020020151146102e8576102e5816001610a85565b92505b806102f281610a98565b915050610269565b505b600194505b8082604051602001610314929190610b0b565b60405160208183030381529060405290505f5b828110156103805781846020015182602081106103465761034661075a565b602002015160405160200161035c929190610aea565b6040516020818303038152906040529150808061037890610a98565b915050610327565b505f836101000151610392575f610395565b60015b6040858101516060870151608088015160a089015160c08a015160e08b0151805187516103d799988c989081901c979096909590949093909291602001610b54565b604051602081830303815290604052905086816040516020016103fb929190610cd2565b604051602081830303815290604052965050505050808061041b90610a98565b9150506100c8565b50909695505050505050565b63ffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000063ccaa2d1163f5efcd798585602082610824376020828101610844376108a486905261092061090452604082015b8183018110156105f557803560f81c80156104c757600181146104e4576104fd565b856003538560081c6002538560101c6001538560181c5f536104fd565b846003538460081c6002538460101c6001538460181c5f535b5060028101906004906001013560f81c60200280838337909101600181019161040001906020903560f81c02808383379190910190610400810190823560f81c9061041701536001820191506008826018830137600882019150606081019050600482601c830137600482019150602081019050601482600c83013760149182019160408201918390604c01376014820191506020810190506020828237602082013560e01c60408201819052602490920191606090910190808383375f9181019190915290810190601f808216602003160161094401622625a05a10156105e3575f80fd5b5f80825f808b621e8480f150506104a5565b505050505050505050565b5f805f8060608587031215610613575f80fd5b8435935060208501359250604085013567ffffffffffffffff80821115610638575f80fd5b818701915087601f83011261064b575f80fd5b813581811115610659575f80fd5b8860208260051b850101111561066d575f80fd5b95989497505060200194505050565b5f5b8381101561069657818101518382015260200161067e565b50505f910152565b602081525f82518060208401526106bc81604085016020870161067c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b5f80602083850312156106ff575f80fd5b823567ffffffffffffffff80821115610716575f80fd5b818501915085601f830112610729575f80fd5b813581811115610737575f80fd5b866020828501011115610748575f80fd5b60209290920196919550909350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7218336030181126107b9575f80fd5b9190910192915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051610120810167ffffffffffffffff81118282101715610814576108146107c3565b60405290565b5f82601f830112610829575f80fd5b60405161040080820182811067ffffffffffffffff8211171561084e5761084e6107c3565b60405283018185821115610860575f80fd5b845b8281101561087a578035825260209182019101610862565b509195945050505050565b803563ffffffff81168114610898575f80fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610898575f80fd5b5f82601f8301126108cf575f80fd5b813567ffffffffffffffff808211156108ea576108ea6107c3565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610930576109306107c3565b81604052838152866020858801011115610948575f80fd5b836020870160208301375f602085830101528094505050505092915050565b80358015158114610898575f80fd5b5f6108e08236031215610987575f80fd5b61098f6107f0565b610999368461081a565b81526109a936610400850161081a565b602082015261080083013560408201526109c66108208401610885565b60608201526109d8610840840161089d565b60808201526109ea610860840161089d565b60a082015261088083013560c08201526108a083013567ffffffffffffffff811115610a14575f80fd5b610a20368286016108c0565b60e083015250610a336108c08401610967565b61010082015292915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810381811115610a7f57610a7f610a3f565b92915050565b80820180821115610a7f57610a7f610a3f565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610ac857610ac8610a3f565b5060010190565b5f8151610ae081856020860161067c565b9290920192915050565b5f8351610afb81846020880161067c565b9190910191825250602001919050565b5f8351610b1c81846020880161067c565b60f89390931b7fff00000000000000000000000000000000000000000000000000000000000000169190920190815260010192915050565b7fff000000000000000000000000000000000000000000000000000000000000008b60f81b1681525f8a51610b90816001850160208f0161067c565b7fff000000000000000000000000000000000000000000000000000000000000008b60f81b16600182850101527fffffffffffffffff0000000000000000000000000000000000000000000000008a60c01b16600282850101527fffffffff000000000000000000000000000000000000000000000000000000008960e01b16600a82850101527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b16600e8285010152610c776022828501018860601b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169052565b8560368285010152610cb26056828501018660e01b7fffffffff00000000000000000000000000000000000000000000000000000000169052565b610cc1605a8285010185610acf565b9d9c50505050505050505050505050565b5f8351610ce381846020880161067c565b835190830190610cf781836020880161067c565b0194935050505056fea2646970667358221220431d4b4962f6e0fedc7eff37b6b46383dff32ef58340bfd8486915afedccad0564736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610034575f3560e01c806304e5557b1461003857806397b1410f14610061575b5f80fd5b61004b610046366004610600565b610076565b604051610058919061069e565b60405180910390f35b61007461006f3660046106ee565b61042f565b005b60605f8585604051602001610095929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905290505f805b84811015610423575f8686838181106100e3576100e361075a565b90506020028101906100f59190610787565b6100fe90610976565b90505f825f03610110575060206101a0565b5f5b602081101561019e578888610128600187610a6c565b8181106101375761013761075a565b90506020028101906101499190610787565b816020811061015a5761015a61075a565b6020020135835f015182602081106101745761017461075a565b60200201511461018c57610189816001610a85565b91505b8061019681610a98565b915050610112565b505b6040805160f883901b7fff000000000000000000000000000000000000000000000000000000000000001660208201528151600181830301815260219091019091525f5b8281101561023b578351829082602081106102015761020161075a565b6020020151604051602001610217929190610aea565b6040516020818303038152906040529150808061023390610a98565b9150506101e4565b5060208301516103e001515f92501561030157831580610259575084155b1561026757602091506102fc565b5f5b60208110156102fa57898961027f600188610a6c565b81811061028e5761028e61075a565b90506020028101906102a09190610787565b6104000181602081106102b5576102b561075a565b6020020135846020015182602081106102d0576102d061075a565b6020020151146102e8576102e5816001610a85565b92505b806102f281610a98565b915050610269565b505b600194505b8082604051602001610314929190610b0b565b60405160208183030381529060405290505f5b828110156103805781846020015182602081106103465761034661075a565b602002015160405160200161035c929190610aea565b6040516020818303038152906040529150808061037890610a98565b915050610327565b505f836101000151610392575f610395565b60015b6040858101516060870151608088015160a089015160c08a015160e08b0151805187516103d799988c989081901c979096909590949093909291602001610b54565b604051602081830303815290604052905086816040516020016103fb929190610cd2565b604051602081830303815290604052965050505050808061041b90610a98565b9150506100c8565b50909695505050505050565b63ffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000063ccaa2d1163f5efcd798585602082610824376020828101610844376108a486905261092061090452604082015b8183018110156105f557803560f81c80156104c757600181146104e4576104fd565b856003538560081c6002538560101c6001538560181c5f536104fd565b846003538460081c6002538460101c6001538460181c5f535b5060028101906004906001013560f81c60200280838337909101600181019161040001906020903560f81c02808383379190910190610400810190823560f81c9061041701536001820191506008826018830137600882019150606081019050600482601c830137600482019150602081019050601482600c83013760149182019160408201918390604c01376014820191506020810190506020828237602082013560e01c60408201819052602490920191606090910190808383375f9181019190915290810190601f808216602003160161094401622625a05a10156105e3575f80fd5b5f80825f808b621e8480f150506104a5565b505050505050505050565b5f805f8060608587031215610613575f80fd5b8435935060208501359250604085013567ffffffffffffffff80821115610638575f80fd5b818701915087601f83011261064b575f80fd5b813581811115610659575f80fd5b8860208260051b850101111561066d575f80fd5b95989497505060200194505050565b5f5b8381101561069657818101518382015260200161067e565b50505f910152565b602081525f82518060208401526106bc81604085016020870161067c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b5f80602083850312156106ff575f80fd5b823567ffffffffffffffff80821115610716575f80fd5b818501915085601f830112610729575f80fd5b813581811115610737575f80fd5b866020828501011115610748575f80fd5b60209290920196919550909350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7218336030181126107b9575f80fd5b9190910192915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051610120810167ffffffffffffffff81118282101715610814576108146107c3565b60405290565b5f82601f830112610829575f80fd5b60405161040080820182811067ffffffffffffffff8211171561084e5761084e6107c3565b60405283018185821115610860575f80fd5b845b8281101561087a578035825260209182019101610862565b509195945050505050565b803563ffffffff81168114610898575f80fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610898575f80fd5b5f82601f8301126108cf575f80fd5b813567ffffffffffffffff808211156108ea576108ea6107c3565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610930576109306107c3565b81604052838152866020858801011115610948575f80fd5b836020870160208301375f602085830101528094505050505092915050565b80358015158114610898575f80fd5b5f6108e08236031215610987575f80fd5b61098f6107f0565b610999368461081a565b81526109a936610400850161081a565b602082015261080083013560408201526109c66108208401610885565b60608201526109d8610840840161089d565b60808201526109ea610860840161089d565b60a082015261088083013560c08201526108a083013567ffffffffffffffff811115610a14575f80fd5b610a20368286016108c0565b60e083015250610a336108c08401610967565b61010082015292915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810381811115610a7f57610a7f610a3f565b92915050565b80820180821115610a7f57610a7f610a3f565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610ac857610ac8610a3f565b5060010190565b5f8151610ae081856020860161067c565b9290920192915050565b5f8351610afb81846020880161067c565b9190910191825250602001919050565b5f8351610b1c81846020880161067c565b60f89390931b7fff00000000000000000000000000000000000000000000000000000000000000169190920190815260010192915050565b7fff000000000000000000000000000000000000000000000000000000000000008b60f81b1681525f8a51610b90816001850160208f0161067c565b7fff000000000000000000000000000000000000000000000000000000000000008b60f81b16600182850101527fffffffffffffffff0000000000000000000000000000000000000000000000008a60c01b16600282850101527fffffffff000000000000000000000000000000000000000000000000000000008960e01b16600a82850101527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b16600e8285010152610c776022828501018860601b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169052565b8560368285010152610cb26056828501018660e01b7fffffffff00000000000000000000000000000000000000000000000000000000169052565b610cc1605a8285010185610acf565b9d9c50505050505050505050505050565b5f8351610ce381846020880161067c565b835190830190610cf781836020880161067c565b0194935050505056fea2646970667358221220431d4b4962f6e0fedc7eff37b6b46383dff32ef58340bfd8486915afedccad0564736f6c63430008140033", + "bytecode": "0x60c060405234801561000f575f80fd5b50604051610dec380380610dec83398101604081905261002e9161004a565b6001600160a01b0390911660805263ffffffff1660a052610095565b5f806040838503121561005b575f80fd5b82516001600160a01b0381168114610071575f80fd5b602084015190925063ffffffff8116811461008a575f80fd5b809150509250929050565b60805160a051610d366100b65f395f61043601525f6104580152610d365ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806304e5557b1461003857806397b1410f14610061575b5f80fd5b61004b610046366004610600565b610076565b604051610058919061069e565b60405180910390f35b61007461006f3660046106ee565b61042f565b005b60605f8585604051602001610095929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905290505f805b84811015610423575f8686838181106100e3576100e361075a565b90506020028101906100f59190610787565b6100fe90610976565b90505f825f03610110575060206101a0565b5f5b602081101561019e578888610128600187610a6c565b8181106101375761013761075a565b90506020028101906101499190610787565b816020811061015a5761015a61075a565b6020020135835f015182602081106101745761017461075a565b60200201511461018c57610189816001610a85565b91505b8061019681610a98565b915050610112565b505b6040805160f883901b7fff000000000000000000000000000000000000000000000000000000000000001660208201528151600181830301815260219091019091525f5b8281101561023b578351829082602081106102015761020161075a565b6020020151604051602001610217929190610aea565b6040516020818303038152906040529150808061023390610a98565b9150506101e4565b5060208301516103e001515f92501561030157831580610259575084155b1561026757602091506102fc565b5f5b60208110156102fa57898961027f600188610a6c565b81811061028e5761028e61075a565b90506020028101906102a09190610787565b6104000181602081106102b5576102b561075a565b6020020135846020015182602081106102d0576102d061075a565b6020020151146102e8576102e5816001610a85565b92505b806102f281610a98565b915050610269565b505b600194505b8082604051602001610314929190610b0b565b60405160208183030381529060405290505f5b828110156103805781846020015182602081106103465761034661075a565b602002015160405160200161035c929190610aea565b6040516020818303038152906040529150808061037890610a98565b915050610327565b505f836101000151610392575f610395565b60015b6040858101516060870151608088015160a089015160c08a015160e08b0151805187516103d799988c989081901c979096909590949093909291602001610b54565b604051602081830303815290604052905086816040516020016103fb929190610cd2565b604051602081830303815290604052965050505050808061041b90610a98565b9150506100c8565b50909695505050505050565b63ffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000063ccaa2d1163f5efcd798585602082610824376020828101610844376108a486905261092061090452604082015b8183018110156105f557803560f81c80156104c757600181146104e4576104fd565b856003538560081c6002538560101c6001538560181c5f536104fd565b846003538460081c6002538460101c6001538460181c5f535b5060028101906004906001013560f81c60200280838337909101600181019161040001906020903560f81c02808383379190910190610400810190823560f81c9061041701536001820191506008826018830137600882019150606081019050600482601c830137600482019150602081019050601482600c83013760149182019160408201918390604c01376014820191506020810190506020828237602082013560e01c60408201819052602490920191606090910190808383375f9181019190915290810190601f808216602003160161094401622625a05a10156105e3575f80fd5b5f80825f808b621e8480f150506104a5565b505050505050505050565b5f805f8060608587031215610613575f80fd5b8435935060208501359250604085013567ffffffffffffffff80821115610638575f80fd5b818701915087601f83011261064b575f80fd5b813581811115610659575f80fd5b8860208260051b850101111561066d575f80fd5b95989497505060200194505050565b5f5b8381101561069657818101518382015260200161067e565b50505f910152565b602081525f82518060208401526106bc81604085016020870161067c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b5f80602083850312156106ff575f80fd5b823567ffffffffffffffff80821115610716575f80fd5b818501915085601f830112610729575f80fd5b813581811115610737575f80fd5b866020828501011115610748575f80fd5b60209290920196919550909350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7218336030181126107b9575f80fd5b9190910192915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051610120810167ffffffffffffffff81118282101715610814576108146107c3565b60405290565b5f82601f830112610829575f80fd5b60405161040080820182811067ffffffffffffffff8211171561084e5761084e6107c3565b60405283018185821115610860575f80fd5b845b8281101561087a578035825260209182019101610862565b509195945050505050565b803563ffffffff81168114610898575f80fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610898575f80fd5b5f82601f8301126108cf575f80fd5b813567ffffffffffffffff808211156108ea576108ea6107c3565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610930576109306107c3565b81604052838152866020858801011115610948575f80fd5b836020870160208301375f602085830101528094505050505092915050565b80358015158114610898575f80fd5b5f6108e08236031215610987575f80fd5b61098f6107f0565b610999368461081a565b81526109a936610400850161081a565b602082015261080083013560408201526109c66108208401610885565b60608201526109d8610840840161089d565b60808201526109ea610860840161089d565b60a082015261088083013560c08201526108a083013567ffffffffffffffff811115610a14575f80fd5b610a20368286016108c0565b60e083015250610a336108c08401610967565b61010082015292915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810381811115610a7f57610a7f610a3f565b92915050565b80820180821115610a7f57610a7f610a3f565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610ac857610ac8610a3f565b5060010190565b5f8151610ae081856020860161067c565b9290920192915050565b5f8351610afb81846020880161067c565b9190910191825250602001919050565b5f8351610b1c81846020880161067c565b60f89390931b7fff00000000000000000000000000000000000000000000000000000000000000169190920190815260010192915050565b7fff000000000000000000000000000000000000000000000000000000000000008b60f81b1681525f8a51610b90816001850160208f0161067c565b7fff000000000000000000000000000000000000000000000000000000000000008b60f81b16600182850101527fffffffffffffffff0000000000000000000000000000000000000000000000008a60c01b16600282850101527fffffffff000000000000000000000000000000000000000000000000000000008960e01b16600a82850101527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b16600e8285010152610c776022828501018860601b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169052565b8560368285010152610cb26056828501018660e01b7fffffffff00000000000000000000000000000000000000000000000000000000169052565b610cc1605a8285010185610acf565b9d9c50505050505050505050505050565b5f8351610ce381846020880161067c565b835190830190610cf781836020880161067c565b0194935050505056fea26469706673582212208db60002eaedca6cd565e219fe415e1a9fb774ac0cf074924c07a3fcee9fb16964736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610034575f3560e01c806304e5557b1461003857806397b1410f14610061575b5f80fd5b61004b610046366004610600565b610076565b604051610058919061069e565b60405180910390f35b61007461006f3660046106ee565b61042f565b005b60605f8585604051602001610095929190918252602082015260400190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905290505f805b84811015610423575f8686838181106100e3576100e361075a565b90506020028101906100f59190610787565b6100fe90610976565b90505f825f03610110575060206101a0565b5f5b602081101561019e578888610128600187610a6c565b8181106101375761013761075a565b90506020028101906101499190610787565b816020811061015a5761015a61075a565b6020020135835f015182602081106101745761017461075a565b60200201511461018c57610189816001610a85565b91505b8061019681610a98565b915050610112565b505b6040805160f883901b7fff000000000000000000000000000000000000000000000000000000000000001660208201528151600181830301815260219091019091525f5b8281101561023b578351829082602081106102015761020161075a565b6020020151604051602001610217929190610aea565b6040516020818303038152906040529150808061023390610a98565b9150506101e4565b5060208301516103e001515f92501561030157831580610259575084155b1561026757602091506102fc565b5f5b60208110156102fa57898961027f600188610a6c565b81811061028e5761028e61075a565b90506020028101906102a09190610787565b6104000181602081106102b5576102b561075a565b6020020135846020015182602081106102d0576102d061075a565b6020020151146102e8576102e5816001610a85565b92505b806102f281610a98565b915050610269565b505b600194505b8082604051602001610314929190610b0b565b60405160208183030381529060405290505f5b828110156103805781846020015182602081106103465761034661075a565b602002015160405160200161035c929190610aea565b6040516020818303038152906040529150808061037890610a98565b915050610327565b505f836101000151610392575f610395565b60015b6040858101516060870151608088015160a089015160c08a015160e08b0151805187516103d799988c989081901c979096909590949093909291602001610b54565b604051602081830303815290604052905086816040516020016103fb929190610cd2565b604051602081830303815290604052965050505050808061041b90610a98565b9150506100c8565b50909695505050505050565b63ffffffff7f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000063ccaa2d1163f5efcd798585602082610824376020828101610844376108a486905261092061090452604082015b8183018110156105f557803560f81c80156104c757600181146104e4576104fd565b856003538560081c6002538560101c6001538560181c5f536104fd565b846003538460081c6002538460101c6001538460181c5f535b5060028101906004906001013560f81c60200280838337909101600181019161040001906020903560f81c02808383379190910190610400810190823560f81c9061041701536001820191506008826018830137600882019150606081019050600482601c830137600482019150602081019050601482600c83013760149182019160408201918390604c01376014820191506020810190506020828237602082013560e01c60408201819052602490920191606090910190808383375f9181019190915290810190601f808216602003160161094401622625a05a10156105e3575f80fd5b5f80825f808b621e8480f150506104a5565b505050505050505050565b5f805f8060608587031215610613575f80fd5b8435935060208501359250604085013567ffffffffffffffff80821115610638575f80fd5b818701915087601f83011261064b575f80fd5b813581811115610659575f80fd5b8860208260051b850101111561066d575f80fd5b95989497505060200194505050565b5f5b8381101561069657818101518382015260200161067e565b50505f910152565b602081525f82518060208401526106bc81604085016020870161067c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b5f80602083850312156106ff575f80fd5b823567ffffffffffffffff80821115610716575f80fd5b818501915085601f830112610729575f80fd5b813581811115610737575f80fd5b866020828501011115610748575f80fd5b60209290920196919550909350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7218336030181126107b9575f80fd5b9190910192915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051610120810167ffffffffffffffff81118282101715610814576108146107c3565b60405290565b5f82601f830112610829575f80fd5b60405161040080820182811067ffffffffffffffff8211171561084e5761084e6107c3565b60405283018185821115610860575f80fd5b845b8281101561087a578035825260209182019101610862565b509195945050505050565b803563ffffffff81168114610898575f80fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610898575f80fd5b5f82601f8301126108cf575f80fd5b813567ffffffffffffffff808211156108ea576108ea6107c3565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610930576109306107c3565b81604052838152866020858801011115610948575f80fd5b836020870160208301375f602085830101528094505050505092915050565b80358015158114610898575f80fd5b5f6108e08236031215610987575f80fd5b61098f6107f0565b610999368461081a565b81526109a936610400850161081a565b602082015261080083013560408201526109c66108208401610885565b60608201526109d8610840840161089d565b60808201526109ea610860840161089d565b60a082015261088083013560c08201526108a083013567ffffffffffffffff811115610a14575f80fd5b610a20368286016108c0565b60e083015250610a336108c08401610967565b61010082015292915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810381811115610a7f57610a7f610a3f565b92915050565b80820180821115610a7f57610a7f610a3f565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610ac857610ac8610a3f565b5060010190565b5f8151610ae081856020860161067c565b9290920192915050565b5f8351610afb81846020880161067c565b9190910191825250602001919050565b5f8351610b1c81846020880161067c565b60f89390931b7fff00000000000000000000000000000000000000000000000000000000000000169190920190815260010192915050565b7fff000000000000000000000000000000000000000000000000000000000000008b60f81b1681525f8a51610b90816001850160208f0161067c565b7fff000000000000000000000000000000000000000000000000000000000000008b60f81b16600182850101527fffffffffffffffff0000000000000000000000000000000000000000000000008a60c01b16600282850101527fffffffff000000000000000000000000000000000000000000000000000000008960e01b16600a82850101527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b16600e8285010152610c776022828501018860601b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169052565b8560368285010152610cb26056828501018660e01b7fffffffff00000000000000000000000000000000000000000000000000000000169052565b610cc1605a8285010185610acf565b9d9c50505050505050505050505050565b5f8351610ce381846020880161067c565b835190830190610cf781836020880161067c565b0194935050505056fea26469706673582212208db60002eaedca6cd565e219fe415e1a9fb774ac0cf074924c07a3fcee9fb16964736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/GlobalExitRootManagerL2SovereignChain.json b/compiled-contracts/GlobalExitRootManagerL2SovereignChain.json new file mode 100644 index 000000000..1bd52c6dc --- /dev/null +++ b/compiled-contracts/GlobalExitRootManagerL2SovereignChain.json @@ -0,0 +1,284 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "GlobalExitRootManagerL2SovereignChain", + "sourceName": "contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bridgeAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "GlobalExitRootAlreadySet", + "type": "error" + }, + { + "inputs": [], + "name": "NotEnoughGlobalExitRootsInserted", + "type": "error" + }, + { + "inputs": [], + "name": "NotLastInsertedGlobalExitRoot", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyAllowedContracts", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyGlobalExitRootRemover", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyGlobalExitRootUpdater", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "newGlobalExitRoot", + "type": "bytes32" + } + ], + "name": "InsertGlobalExitRoot", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "removedGlobalExitRoot", + "type": "bytes32" + } + ], + "name": "RemoveLastGlobalExitRoot", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newGlobalExitRootRemover", + "type": "address" + } + ], + "name": "SetGlobalExitRootRemover", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "newGlobalExitRootUpdater", + "type": "address" + } + ], + "name": "SetGlobalExitRootUpdater", + "type": "event" + }, + { + "inputs": [], + "name": "bridgeAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "globalExitRootMap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalExitRootRemover", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalExitRootUpdater", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_globalExitRootUpdater", + "type": "address" + }, + { + "internalType": "address", + "name": "_globalExitRootRemover", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_newRoot", + "type": "bytes32" + } + ], + "name": "insertGlobalExitRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "insertedGERCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastRollupExitRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "gersToRemove", + "type": "bytes32[]" + } + ], + "name": "removeLastGlobalExitRoots", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_globalExitRootRemover", + "type": "address" + } + ], + "name": "setGlobalExitRootRemover", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_globalExitRootUpdater", + "type": "address" + } + ], + "name": "setGlobalExitRootUpdater", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "newRoot", + "type": "bytes32" + } + ], + "name": "updateExitRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x60a060405234801561000f575f80fd5b50604051610c89380380610c8983398101604081905261002e91610109565b6001600160a01b038116608052610043610049565b50610136565b603454610100900460ff16156100b55760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60345460ff9081161015610107576034805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b5f60208284031215610119575f80fd5b81516001600160a01b038116811461012f575f80fd5b9392505050565b608051610b346101555f395f81816101e801526103820152610b345ff3fe608060405234801561000f575f80fd5b50600436106100cf575f3560e01c80636da0e4ab1161007d57806391eb796d1161005857806391eb796d146101c3578063a3c573eb146101e3578063d0267f391461020a575f80fd5b80636da0e4ab1461015c5780637c314ce31461016f5780638bd0eb1c146101ba575f80fd5b806333d6247d116100ad57806333d6247d14610123578063485cc9551461013657806357dfb57214610149575f80fd5b806301fd9044146100d357806312da06b2146100ef578063257b363214610104575b5f80fd5b6100dc60015481565b6040519081526020015b60405180910390f35b6101026100fd36600461093a565b61021d565b005b6100dc61011236600461093a565b5f6020819052908152604090205481565b61010261013136600461093a565b61036a565b610102610144366004610979565b6103de565b6101026101573660046109aa565b6105ea565b61010261016a366004610a19565b61074e565b6034546101959062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e6565b6100dc60365481565b6035546101959073ffffffffffffffffffffffffffffffffffffffff1681565b6101957f000000000000000000000000000000000000000000000000000000000000000081565b610102610218366004610a19565b61087c565b60345462010000900473ffffffffffffffffffffffffffffffffffffffff1661027e57413314610279576040517fc758fc1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6102d5565b60345462010000900473ffffffffffffffffffffffffffffffffffffffff1633146102d5576040517fc758fc1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8181526020819052604081205490036103385760365f81546102f790610a66565b91829055505f8281526020819052604080822092909255905182917fb1b866fe5fac68e8f1a4ab2520c7a6b493a954934bbd0f054bd91d6674a4c0d591a250565b6040517f1f97a58200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146103d9576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b603454610100900460ff16158080156103fe5750603454600160ff909116105b806104185750303b158015610418575060345460ff166001145b6104a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b603480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561050657603480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603480547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155603580547fffffffffffffffffffffffff00000000000000000000000000000000000000001691841691909117905580156105e557603480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60355473ffffffffffffffffffffffffffffffffffffffff16331461063b576040517fa34ddeb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60365480821115610678576040517f56feb4f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b82811015610746575f84848381811061069557610695610a9d565b9050602002013590505f805f8381526020019081526020015f205490508381146106eb576040517fae765ff600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f828152602081905260408120558361070381610aca565b6040519095508391507f605764d0b65b62ecf05dc90f674a00a2e2531fabaf120fdde65790e407fcb7a2905f90a25050808061073e90610a66565b91505061067a565b506036555050565b60345462010000900473ffffffffffffffffffffffffffffffffffffffff166107af574133146107aa576040517fc758fc1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610806565b60345462010000900473ffffffffffffffffffffffffffffffffffffffff163314610806576040517fc758fc1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603480547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040517f992b80814dbc3fba903486d81daddb07d1d5b20483742458c8b0540e3a37e37c905f90a250565b60355473ffffffffffffffffffffffffffffffffffffffff1633146108cd576040517fa34ddeb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517eb4672b6135d1dfbd4e9520e01abb14ea5eac645990b0d24dfda00ae999b758905f90a250565b5f6020828403121561094a575f80fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610974575f80fd5b919050565b5f806040838503121561098a575f80fd5b61099383610951565b91506109a160208401610951565b90509250929050565b5f80602083850312156109bb575f80fd5b823567ffffffffffffffff808211156109d2575f80fd5b818501915085601f8301126109e5575f80fd5b8135818111156109f3575f80fd5b8660208260051b8501011115610a07575f80fd5b60209290920196919550909350505050565b5f60208284031215610a29575f80fd5b610a3282610951565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610a9657610a96610a39565b5060010190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f81610ad857610ad8610a39565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220eaeb96edcd68aaace0b150250759e33e52bda31e20946c3877825cec6f50572564736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106100cf575f3560e01c80636da0e4ab1161007d57806391eb796d1161005857806391eb796d146101c3578063a3c573eb146101e3578063d0267f391461020a575f80fd5b80636da0e4ab1461015c5780637c314ce31461016f5780638bd0eb1c146101ba575f80fd5b806333d6247d116100ad57806333d6247d14610123578063485cc9551461013657806357dfb57214610149575f80fd5b806301fd9044146100d357806312da06b2146100ef578063257b363214610104575b5f80fd5b6100dc60015481565b6040519081526020015b60405180910390f35b6101026100fd36600461093a565b61021d565b005b6100dc61011236600461093a565b5f6020819052908152604090205481565b61010261013136600461093a565b61036a565b610102610144366004610979565b6103de565b6101026101573660046109aa565b6105ea565b61010261016a366004610a19565b61074e565b6034546101959062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e6565b6100dc60365481565b6035546101959073ffffffffffffffffffffffffffffffffffffffff1681565b6101957f000000000000000000000000000000000000000000000000000000000000000081565b610102610218366004610a19565b61087c565b60345462010000900473ffffffffffffffffffffffffffffffffffffffff1661027e57413314610279576040517fc758fc1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6102d5565b60345462010000900473ffffffffffffffffffffffffffffffffffffffff1633146102d5576040517fc758fc1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8181526020819052604081205490036103385760365f81546102f790610a66565b91829055505f8281526020819052604080822092909255905182917fb1b866fe5fac68e8f1a4ab2520c7a6b493a954934bbd0f054bd91d6674a4c0d591a250565b6040517f1f97a58200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146103d9576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b603454610100900460ff16158080156103fe5750603454600160ff909116105b806104185750303b158015610418575060345460ff166001145b6104a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b603480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561050657603480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b603480547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155603580547fffffffffffffffffffffffff00000000000000000000000000000000000000001691841691909117905580156105e557603480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050565b60355473ffffffffffffffffffffffffffffffffffffffff16331461063b576040517fa34ddeb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60365480821115610678576040517f56feb4f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f5b82811015610746575f84848381811061069557610695610a9d565b9050602002013590505f805f8381526020019081526020015f205490508381146106eb576040517fae765ff600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f828152602081905260408120558361070381610aca565b6040519095508391507f605764d0b65b62ecf05dc90f674a00a2e2531fabaf120fdde65790e407fcb7a2905f90a25050808061073e90610a66565b91505061067a565b506036555050565b60345462010000900473ffffffffffffffffffffffffffffffffffffffff166107af574133146107aa576040517fc758fc1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610806565b60345462010000900473ffffffffffffffffffffffffffffffffffffffff163314610806576040517fc758fc1a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603480547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040517f992b80814dbc3fba903486d81daddb07d1d5b20483742458c8b0540e3a37e37c905f90a250565b60355473ffffffffffffffffffffffffffffffffffffffff1633146108cd576040517fa34ddeb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040517eb4672b6135d1dfbd4e9520e01abb14ea5eac645990b0d24dfda00ae999b758905f90a250565b5f6020828403121561094a575f80fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610974575f80fd5b919050565b5f806040838503121561098a575f80fd5b61099383610951565b91506109a160208401610951565b90509250929050565b5f80602083850312156109bb575f80fd5b823567ffffffffffffffff808211156109d2575f80fd5b818501915085601f8301126109e5575f80fd5b8135818111156109f3575f80fd5b8660208260051b8501011115610a07575f80fd5b60209290920196919550909350505050565b5f60208284031215610a29575f80fd5b610a3282610951565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610a9657610a96610a39565b5060010190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f81610ad857610ad8610a39565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220eaeb96edcd68aaace0b150250759e33e52bda31e20946c3877825cec6f50572564736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/compiled-contracts/PolygonPessimisticConsensus.json b/compiled-contracts/PolygonPessimisticConsensus.json new file mode 100644 index 000000000..7bd077919 --- /dev/null +++ b/compiled-contracts/PolygonPessimisticConsensus.json @@ -0,0 +1,704 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "PolygonPessimisticConsensus", + "sourceName": "contracts/v2/consensus/pessimistic/PolygonPessimisticConsensus.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IPolygonZkEVMGlobalExitRootV2", + "name": "_globalExitRootManager", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "_pol", + "type": "address" + }, + { + "internalType": "contract IPolygonZkEVMBridgeV2", + "name": "_bridgeAddress", + "type": "address" + }, + { + "internalType": "contract PolygonRollupManager", + "name": "_rollupManager", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "BatchAlreadyVerified", + "type": "error" + }, + { + "inputs": [], + "name": "BatchNotSequencedOrNotSequenceEnd", + "type": "error" + }, + { + "inputs": [], + "name": "ExceedMaxVerifyBatches", + "type": "error" + }, + { + "inputs": [], + "name": "FinalAccInputHashDoesNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "FinalNumBatchBelowLastVerifiedBatch", + "type": "error" + }, + { + "inputs": [], + "name": "FinalNumBatchDoesNotMatchPendingState", + "type": "error" + }, + { + "inputs": [], + "name": "FinalPendingStateNumInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "ForceBatchNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ForceBatchTimeoutNotExpired", + "type": "error" + }, + { + "inputs": [], + "name": "ForceBatchesAlreadyActive", + "type": "error" + }, + { + "inputs": [], + "name": "ForceBatchesDecentralized", + "type": "error" + }, + { + "inputs": [], + "name": "ForceBatchesNotAllowedOnEmergencyState", + "type": "error" + }, + { + "inputs": [], + "name": "ForceBatchesOverflow", + "type": "error" + }, + { + "inputs": [], + "name": "ForcedDataDoesNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "GasTokenNetworkMustBeZeroOnEther", + "type": "error" + }, + { + "inputs": [], + "name": "GlobalExitRootNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "HaltTimeoutNotExpired", + "type": "error" + }, + { + "inputs": [], + "name": "HaltTimeoutNotExpiredAfterEmergencyState", + "type": "error" + }, + { + "inputs": [], + "name": "HugeTokenMetadataNotSupported", + "type": "error" + }, + { + "inputs": [], + "name": "InitNumBatchAboveLastVerifiedBatch", + "type": "error" + }, + { + "inputs": [], + "name": "InitNumBatchDoesNotMatchPendingState", + "type": "error" + }, + { + "inputs": [], + "name": "InitSequencedBatchDoesNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidInitializeTransaction", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidProof", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRangeBatchTimeTarget", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRangeForceBatchTimeout", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRangeMultiplierBatchFee", + "type": "error" + }, + { + "inputs": [], + "name": "L1InfoTreeLeafCountInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "MaxTimestampSequenceInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "NewAccInputHashDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "NewPendingStateTimeoutMustBeLower", + "type": "error" + }, + { + "inputs": [], + "name": "NewStateRootNotInsidePrime", + "type": "error" + }, + { + "inputs": [], + "name": "NewTrustedAggregatorTimeoutMustBeLower", + "type": "error" + }, + { + "inputs": [], + "name": "NotEnoughMaticAmount", + "type": "error" + }, + { + "inputs": [], + "name": "NotEnoughPOLAmount", + "type": "error" + }, + { + "inputs": [], + "name": "OldAccInputHashDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "OldStateRootDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyPendingAdmin", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyRollupManager", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyTrustedAggregator", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyTrustedSequencer", + "type": "error" + }, + { + "inputs": [], + "name": "PendingStateDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "PendingStateInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "PendingStateNotConsolidable", + "type": "error" + }, + { + "inputs": [], + "name": "PendingStateTimeoutExceedHaltAggregationTimeout", + "type": "error" + }, + { + "inputs": [], + "name": "SequenceZeroBatches", + "type": "error" + }, + { + "inputs": [], + "name": "SequencedTimestampBelowForcedTimestamp", + "type": "error" + }, + { + "inputs": [], + "name": "SequencedTimestampInvalid", + "type": "error" + }, + { + "inputs": [], + "name": "StoredRootMustBeDifferentThanNewRoot", + "type": "error" + }, + { + "inputs": [], + "name": "TransactionsLengthAboveMax", + "type": "error" + }, + { + "inputs": [], + "name": "TrustedAggregatorTimeoutExceedHaltAggregationTimeout", + "type": "error" + }, + { + "inputs": [], + "name": "TrustedAggregatorTimeoutNotExpired", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AcceptAdminRole", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newTrustedSequencer", + "type": "address" + } + ], + "name": "SetTrustedSequencer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "newTrustedSequencerURL", + "type": "string" + } + ], + "name": "SetTrustedSequencerURL", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "TransferAdminRole", + "type": "event" + }, + { + "inputs": [], + "name": "CONSENSUS_TYPE", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptAdminRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bridgeAddress", + "outputs": [ + { + "internalType": "contract IPolygonZkEVMBridgeV2", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "forceBatchAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "forceBatchTimeout", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "name": "forcedBatches", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gasTokenNetwork", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConsensusHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "globalExitRootManager", + "outputs": [ + { + "internalType": "contract IPolygonZkEVMGlobalExitRootV2", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + }, + { + "internalType": "address", + "name": "sequencer", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + }, + { + "internalType": "address", + "name": "_gasTokenAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "sequencerURL", + "type": "string" + }, + { + "internalType": "string", + "name": "_networkName", + "type": "string" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "lastAccInputHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastForceBatch", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastForceBatchSequenced", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "networkName", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pol", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rollupManager", + "outputs": [ + { + "internalType": "contract PolygonRollupManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTrustedSequencer", + "type": "address" + } + ], + "name": "setTrustedSequencer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "newTrustedSequencerURL", + "type": "string" + } + ], + "name": "setTrustedSequencerURL", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "transferAdminRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "trustedSequencer", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "trustedSequencerURL", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x61010060405234801562000011575f80fd5b506040516200118638038062001186833981016040819052620000349162000146565b6001600160a01b0380851660a05280841660805280831660c052811660e05283838383620000616200006f565b5050505050505050620001ab565b5f54610100900460ff1615620000db5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811610156200012c575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b038116811462000143575f80fd5b50565b5f805f80608085870312156200015a575f80fd5b845162000167816200012e565b60208601519094506200017a816200012e565b60408601519093506200018d816200012e565b6060860151909250620001a0816200012e565b939692955090935050565b60805160a05160c05160e051610fa0620001e65f395f81816102b1015261062b01525f61034601525f61043e01525f6104650152610fa05ff3fe608060405234801561000f575f80fd5b506004361061018f575f3560e01c80638c3d7301116100dd578063cea5a4c011610088578063e46761c411610063578063e46761c414610460578063e7a7ed0214610487578063f851a4401461049b575f80fd5b8063cea5a4c014610412578063cfa8ed4714610419578063d02103ca14610439575f80fd5b8063ada8f919116100b8578063ada8f919146103c4578063c754c7ed146103d7578063c89e42df146103ff575f80fd5b80638c3d730114610339578063a3c573eb14610341578063ad1edf3414610368575f80fd5b806349b7b8021161013d5780636e05d2cd116101185780636e05d2cd146103085780636ff512cc146103115780637125702214610326575f80fd5b806349b7b802146102ac578063542028d5146102d35780636b8616ce146102db575f80fd5b80633c351e101161016d5780633c351e10146102165780633cbc795b146102365780634560526714610273575f80fd5b8063107bf28c1461019357806326782247146101b15780632c111c06146101f6575b5f80fd5b61019b6104c0565b6040516101a89190610b24565b60405180910390f35b6001546101d19073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a8565b6008546101d19073ffffffffffffffffffffffffffffffffffffffff1681565b6009546101d19073ffffffffffffffffffffffffffffffffffffffff1681565b60095461025e9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016101a8565b6007546102939068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101a8565b6101d17f000000000000000000000000000000000000000000000000000000000000000081565b61019b61054c565b6102fa6102e9366004610b8d565b60066020525f908152604090205481565b6040519081526020016101a8565b6102fa60055481565b61032461031f366004610be3565b610559565b005b610324610334366004610cd0565b610629565b6103246108fb565b6101d17f000000000000000000000000000000000000000000000000000000000000000081565b6102fa6002546040515f6020820181905260609290921b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602482015260380160405160208183030381529060405280519060200120905090565b6103246103d2366004610be3565b6109cd565b60075461029390700100000000000000000000000000000000900467ffffffffffffffff1681565b61032461040d366004610d79565b610a96565b61025e5f81565b6002546101d19073ffffffffffffffffffffffffffffffffffffffff1681565b6101d17f000000000000000000000000000000000000000000000000000000000000000081565b6101d17f000000000000000000000000000000000000000000000000000000000000000081565b6007546102939067ffffffffffffffff1681565b5f546101d19062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b600480546104cd90610db3565b80601f01602080910402602001604051908101604052809291908181526020018280546104f990610db3565b80156105445780601f1061051b57610100808354040283529160200191610544565b820191905f5260205f20905b81548152906001019060200180831161052757829003601f168201915b505050505081565b600380546104cd90610db3565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146105af576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0906020015b60405180910390a150565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610698576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff16158080156106b657505f54600160ff909116105b806106cf5750303b1580156106cf57505f5460ff166001145b61075f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156107bb575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff8a81169190910291909117909155600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001691881691909117905560036108428482610e52565b50600461084f8382610e52565b50600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861617905580156108f2575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461094c576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610a23576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce69060200161061e565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610aec576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003610af88282610e52565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b208160405161061e91905b5f6020808352835180828501525f5b81811015610b4f57858101830151858201604001528201610b33565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b5f60208284031215610b9d575f80fd5b813567ffffffffffffffff81168114610bb4575f80fd5b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610bde575f80fd5b919050565b5f60208284031215610bf3575f80fd5b610bb482610bbb565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f830112610c38575f80fd5b813567ffffffffffffffff80821115610c5357610c53610bfc565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610c9957610c99610bfc565b81604052838152866020858801011115610cb1575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f805f8060c08789031215610ce5575f80fd5b610cee87610bbb565b9550610cfc60208801610bbb565b9450604087013563ffffffff81168114610d14575f80fd5b9350610d2260608801610bbb565b9250608087013567ffffffffffffffff80821115610d3e575f80fd5b610d4a8a838b01610c29565b935060a0890135915080821115610d5f575f80fd5b50610d6c89828a01610c29565b9150509295509295509295565b5f60208284031215610d89575f80fd5b813567ffffffffffffffff811115610d9f575f80fd5b610dab84828501610c29565b949350505050565b600181811c90821680610dc757607f821691505b602082108103610dfe577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b601f821115610e4d575f81815260208120601f850160051c81016020861015610e2a5750805b601f850160051c820191505b81811015610e4957828155600101610e36565b5050505b505050565b815167ffffffffffffffff811115610e6c57610e6c610bfc565b610e8081610e7a8454610db3565b84610e04565b602080601f831160018114610ed2575f8415610e9c5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610e49565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015610f1e57888601518255948401946001909101908401610eff565b5085821015610f5a57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea2646970667358221220ad794faf9e0b5c82ead50a6f1b5e27f7ada7ec4545266c0d28c66461e04b1b3e64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061018f575f3560e01c80638c3d7301116100dd578063cea5a4c011610088578063e46761c411610063578063e46761c414610460578063e7a7ed0214610487578063f851a4401461049b575f80fd5b8063cea5a4c014610412578063cfa8ed4714610419578063d02103ca14610439575f80fd5b8063ada8f919116100b8578063ada8f919146103c4578063c754c7ed146103d7578063c89e42df146103ff575f80fd5b80638c3d730114610339578063a3c573eb14610341578063ad1edf3414610368575f80fd5b806349b7b8021161013d5780636e05d2cd116101185780636e05d2cd146103085780636ff512cc146103115780637125702214610326575f80fd5b806349b7b802146102ac578063542028d5146102d35780636b8616ce146102db575f80fd5b80633c351e101161016d5780633c351e10146102165780633cbc795b146102365780634560526714610273575f80fd5b8063107bf28c1461019357806326782247146101b15780632c111c06146101f6575b5f80fd5b61019b6104c0565b6040516101a89190610b24565b60405180910390f35b6001546101d19073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101a8565b6008546101d19073ffffffffffffffffffffffffffffffffffffffff1681565b6009546101d19073ffffffffffffffffffffffffffffffffffffffff1681565b60095461025e9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016101a8565b6007546102939068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016101a8565b6101d17f000000000000000000000000000000000000000000000000000000000000000081565b61019b61054c565b6102fa6102e9366004610b8d565b60066020525f908152604090205481565b6040519081526020016101a8565b6102fa60055481565b61032461031f366004610be3565b610559565b005b610324610334366004610cd0565b610629565b6103246108fb565b6101d17f000000000000000000000000000000000000000000000000000000000000000081565b6102fa6002546040515f6020820181905260609290921b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602482015260380160405160208183030381529060405280519060200120905090565b6103246103d2366004610be3565b6109cd565b60075461029390700100000000000000000000000000000000900467ffffffffffffffff1681565b61032461040d366004610d79565b610a96565b61025e5f81565b6002546101d19073ffffffffffffffffffffffffffffffffffffffff1681565b6101d17f000000000000000000000000000000000000000000000000000000000000000081565b6101d17f000000000000000000000000000000000000000000000000000000000000000081565b6007546102939067ffffffffffffffff1681565b5f546101d19062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b600480546104cd90610db3565b80601f01602080910402602001604051908101604052809291908181526020018280546104f990610db3565b80156105445780601f1061051b57610100808354040283529160200191610544565b820191905f5260205f20905b81548152906001019060200180831161052757829003601f168201915b505050505081565b600380546104cd90610db3565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146105af576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0906020015b60405180910390a150565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610698576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff16158080156106b657505f54600160ff909116105b806106cf5750303b1580156106cf57505f5460ff166001145b61075f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156107bb575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff166201000073ffffffffffffffffffffffffffffffffffffffff8a81169190910291909117909155600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001691881691909117905560036108428482610e52565b50600461084f8382610e52565b50600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861617905580156108f2575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461094c576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610a23576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce69060200161061e565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610aec576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003610af88282610e52565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b208160405161061e91905b5f6020808352835180828501525f5b81811015610b4f57858101830151858201604001528201610b33565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b5f60208284031215610b9d575f80fd5b813567ffffffffffffffff81168114610bb4575f80fd5b9392505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610bde575f80fd5b919050565b5f60208284031215610bf3575f80fd5b610bb482610bbb565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f830112610c38575f80fd5b813567ffffffffffffffff80821115610c5357610c53610bfc565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715610c9957610c99610bfc565b81604052838152866020858801011115610cb1575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f805f8060c08789031215610ce5575f80fd5b610cee87610bbb565b9550610cfc60208801610bbb565b9450604087013563ffffffff81168114610d14575f80fd5b9350610d2260608801610bbb565b9250608087013567ffffffffffffffff80821115610d3e575f80fd5b610d4a8a838b01610c29565b935060a0890135915080821115610d5f575f80fd5b50610d6c89828a01610c29565b9150509295509295509295565b5f60208284031215610d89575f80fd5b813567ffffffffffffffff811115610d9f575f80fd5b610dab84828501610c29565b949350505050565b600181811c90821680610dc757607f821691505b602082108103610dfe577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b601f821115610e4d575f81815260208120601f850160051c81016020861015610e2a5750805b601f850160051c820191505b81811015610e4957828155600101610e36565b5050505b505050565b815167ffffffffffffffff811115610e6c57610e6c610bfc565b610e8081610e7a8454610db3565b84610e04565b602080601f831160018114610ed2575f8415610e9c5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610e49565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015610f1e57888601518255948401946001909101908401610eff565b5085821015610f5a57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea2646970667358221220ad794faf9e0b5c82ead50a6f1b5e27f7ada7ec4545266c0d28c66461e04b1b3e64736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/compiled-contracts/PolygonRollupManager.json b/compiled-contracts/PolygonRollupManager.json index b721e8ab8..51ffd6dd3 100644 --- a/compiled-contracts/PolygonRollupManager.json +++ b/compiled-contracts/PolygonRollupManager.json @@ -134,6 +134,11 @@ "name": "InitSequenceNumDoesNotMatchPendingState", "type": "error" }, + { + "inputs": [], + "name": "InvalidPessimisticProof", + "type": "error" + }, { "inputs": [], "name": "InvalidProof", @@ -159,6 +164,26 @@ "name": "InvalidRangeSequenceTimeTarget", "type": "error" }, + { + "inputs": [], + "name": "InvalidRollup", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRollupType", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidVerifierType", + "type": "error" + }, + { + "inputs": [], + "name": "L1InfoTreeLeafCountInvalid", + "type": "error" + }, { "inputs": [], "name": "MustSequenceSomeBatch", @@ -204,6 +229,11 @@ "name": "OldStateRootDoesNotExist", "type": "error" }, + { + "inputs": [], + "name": "OnlyChainsWithPessimisticProofs", + "type": "error" + }, { "inputs": [], "name": "OnlyEmergencyState", @@ -219,6 +249,11 @@ "name": "OnlyRollupAdmin", "type": "error" }, + { + "inputs": [], + "name": "OnlyStateTransitionChains", + "type": "error" + }, { "inputs": [], "name": "PendingStateDoesNotExist", @@ -234,6 +269,11 @@ "name": "PendingStateNotConsolidable", "type": "error" }, + { + "inputs": [], + "name": "PendingStateNumExist", + "type": "error" + }, { "inputs": [], "name": "RollbackBatchIsNotEndOfSequence", @@ -333,8 +373,8 @@ }, { "indexed": false, - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" }, { @@ -342,6 +382,12 @@ "internalType": "uint64", "name": "lastVerifiedBatchBeforeUpgrade", "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" } ], "name": "AddExistingRollup", @@ -376,8 +422,8 @@ }, { "indexed": false, - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" }, { @@ -391,46 +437,15 @@ "internalType": "string", "name": "description", "type": "string" - } - ], - "name": "AddNewRollupType", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" }, { "indexed": false, "internalType": "bytes32", - "name": "exitRoot", + "name": "programVKey", "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "pendingStateNum", - "type": "uint64" } ], - "name": "ConsolidatePendingState", + "name": "AddNewRollupType", "type": "event" }, { @@ -527,62 +542,6 @@ "name": "OnSequenceBatches", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "exitRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "OverridePendingState", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "storedStateRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "provedStateRoot", - "type": "bytes32" - } - ], - "name": "ProveNonDeterministicPendingState", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -696,32 +655,6 @@ "name": "SetBatchFee", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "newMultiplierBatchFee", - "type": "uint16" - } - ], - "name": "SetMultiplierBatchFee", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "newPendingStateTimeout", - "type": "uint64" - } - ], - "name": "SetPendingStateTimeout", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -735,32 +668,6 @@ "name": "SetTrustedAggregator", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "newTrustedAggregatorTimeout", - "type": "uint64" - } - ], - "name": "SetTrustedAggregatorTimeout", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "newVerifyBatchTimeTarget", - "type": "uint64" - } - ], - "name": "SetVerifyBatchTimeTarget", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -789,38 +696,14 @@ { "anonymous": false, "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" - }, { "indexed": false, - "internalType": "bytes32", - "name": "exitRoot", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "aggregator", - "type": "address" + "internalType": "string", + "name": "rollupManagerVersion", + "type": "string" } ], - "name": "VerifyBatches", + "name": "UpdateRollupManagerVersion", "type": "event" }, { @@ -873,6 +756,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "ROLLUP_MANAGER_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "activateEmergencyState", @@ -888,7 +784,7 @@ "type": "address" }, { - "internalType": "contract IVerifierRollup", + "internalType": "address", "name": "verifier", "type": "address" }, @@ -904,13 +800,18 @@ }, { "internalType": "bytes32", - "name": "genesis", + "name": "initRoot", "type": "bytes32" }, { - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" } ], "name": "addExistingRollup", @@ -926,7 +827,7 @@ "type": "address" }, { - "internalType": "contract IVerifierRollup", + "internalType": "address", "name": "verifier", "type": "address" }, @@ -936,8 +837,8 @@ "type": "uint64" }, { - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" }, { @@ -949,6 +850,11 @@ "internalType": "string", "name": "description", "type": "string" + }, + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" } ], "name": "addNewRollupType", @@ -1001,24 +907,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "pendingStateNum", - "type": "uint64" - } - ], - "name": "consolidatePendingState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1102,33 +990,23 @@ "name": "rollupID", "type": "uint32" }, - { - "internalType": "uint64", - "name": "initNumBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalNewBatch", - "type": "uint64" - }, { "internalType": "bytes32", - "name": "newLocalExitRoot", + "name": "l1InfoTreeRoot", "type": "bytes32" }, { "internalType": "bytes32", - "name": "oldStateRoot", + "name": "newLocalExitRoot", "type": "bytes32" }, { "internalType": "bytes32", - "name": "newStateRoot", + "name": "newPessimisticRoot", "type": "bytes32" } ], - "name": "getInputSnarkBytes", + "name": "getInputPessimisticBytes", "outputs": [ { "internalType": "bytes", @@ -1145,10 +1023,54 @@ "internalType": "uint32", "name": "rollupID", "type": "uint32" - } - ], - "name": "getLastVerifiedBatch", - "outputs": [ + }, + { + "internalType": "uint64", + "name": "initNumBatch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "finalNewBatch", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "newLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "oldStateRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newStateRoot", + "type": "bytes32" + } + ], + "name": "getInputSnarkBytes", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "rollupID", + "type": "uint32" + } + ], + "name": "getLastVerifiedBatch", + "outputs": [ { "internalType": "uint64", "name": "", @@ -1214,52 +1136,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "batchNum", - "type": "uint64" - } - ], - "name": "getRollupPendingStateTransitions", - "outputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastVerifiedBatch", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "exitRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" - } - ], - "internalType": "struct LegacyZKEVMStateVariables.PendingState", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1358,31 +1234,14 @@ }, { "inputs": [], - "name": "isEmergencyState", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "pendingStateNum", - "type": "uint64" - } - ], - "name": "isPendingStateConsolidable", + "inputs": [], + "name": "isEmergencyState", "outputs": [ { "internalType": "bool", @@ -1419,19 +1278,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "multiplierBatchFee", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1469,67 +1315,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "initPendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalPendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initNumBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalNewBatch", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "newLocalExitRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newStateRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[24]", - "name": "proof", - "type": "bytes32[24]" - } - ], - "name": "overridePendingState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pendingStateTimeout", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "pol", @@ -1543,54 +1328,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "initPendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalPendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initNumBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalNewBatch", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "newLocalExitRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newStateRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[24]", - "name": "proof", - "type": "bytes32[24]" - } - ], - "name": "proveNonDeterministicPendingState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1688,64 +1425,152 @@ "name": "rollupIDToRollupData", "outputs": [ { - "internalType": "contract IPolygonRollupBase", - "name": "rollupContract", - "type": "address" - }, - { - "internalType": "uint64", - "name": "chainID", - "type": "uint64" - }, - { - "internalType": "contract IVerifierRollup", - "name": "verifier", - "type": "address" - }, - { - "internalType": "uint64", - "name": "forkID", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "lastLocalExitRoot", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "lastBatchSequenced", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastVerifiedBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastPendingState", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastPendingStateConsolidated", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastVerifiedBatchBeforeUpgrade", - "type": "uint64" - }, + "components": [ + { + "internalType": "contract IPolygonRollupBase", + "name": "rollupContract", + "type": "address" + }, + { + "internalType": "uint64", + "name": "chainID", + "type": "uint64" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint64", + "name": "forkID", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "lastLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "lastBatchSequenced", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "_legacyLastPendingState", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "_legacyLastPendingStateConsolidated", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatchBeforeUpgrade", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rollupTypeID", + "type": "uint64" + }, + { + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", + "type": "uint8" + } + ], + "internalType": "struct PolygonRollupManager.RollupDataReturn", + "name": "rollupData", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { - "internalType": "uint64", - "name": "rollupTypeID", - "type": "uint64" - }, + "internalType": "uint32", + "name": "rollupID", + "type": "uint32" + } + ], + "name": "rollupIDToRollupDataV2", + "outputs": [ { - "internalType": "uint8", - "name": "rollupCompatibilityID", - "type": "uint8" + "components": [ + { + "internalType": "address", + "name": "rollupContract", + "type": "address" + }, + { + "internalType": "uint64", + "name": "chainID", + "type": "uint64" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint64", + "name": "forkID", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "lastLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "lastBatchSequenced", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatchBeforeUpgrade", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rollupTypeID", + "type": "uint64" + }, + { + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "lastPessimisticRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" + } + ], + "internalType": "struct PolygonRollupManager.RollupDataReturnV2", + "name": "rollupData", + "type": "tuple" } ], "stateMutability": "view", @@ -1780,7 +1605,7 @@ "type": "address" }, { - "internalType": "contract IVerifierRollup", + "internalType": "address", "name": "verifier", "type": "address" }, @@ -1790,8 +1615,8 @@ "type": "uint64" }, { - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" }, { @@ -1803,6 +1628,11 @@ "internalType": "bytes32", "name": "genesis", "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" } ], "stateMutability": "view", @@ -1821,58 +1651,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "newMultiplierBatchFee", - "type": "uint16" - } - ], - "name": "setMultiplierBatchFee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "newPendingStateTimeout", - "type": "uint64" - } - ], - "name": "setPendingStateTimeout", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "newTrustedAggregatorTimeout", - "type": "uint64" - } - ], - "name": "setTrustedAggregatorTimeout", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "newVerifyBatchTimeTarget", - "type": "uint64" - } - ], - "name": "setVerifyBatchTimeTarget", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "totalSequencedBatches", @@ -1899,19 +1677,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "trustedAggregatorTimeout", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1953,19 +1718,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "verifyBatchTimeTarget", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -2009,7 +1761,7 @@ "type": "bytes32[24]" } ], - "name": "verifyBatches", + "name": "verifyBatchesTrustedAggregator", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -2022,19 +1774,9 @@ "type": "uint32" }, { - "internalType": "uint64", - "name": "pendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initNumBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalNewBatch", - "type": "uint64" + "internalType": "uint32", + "name": "l1InfoTreeLeafCount", + "type": "uint32" }, { "internalType": "bytes32", @@ -2043,28 +1785,23 @@ }, { "internalType": "bytes32", - "name": "newStateRoot", + "name": "newPessimisticRoot", "type": "bytes32" }, { - "internalType": "address", - "name": "beneficiary", - "type": "address" - }, - { - "internalType": "bytes32[24]", + "internalType": "bytes", "name": "proof", - "type": "bytes32[24]" + "type": "bytes" } ], - "name": "verifyBatchesTrustedAggregator", + "name": "verifyPessimisticTrustedAggregator", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ], - "bytecode": "0x60e060405234801562000010575f80fd5b5060405162005db638038062005db6833981016040819052620000339162000136565b6001600160a01b0380841660805282811660c052811660a052620000566200005f565b50505062000187565b5f54610100900460ff1615620000cb5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811610156200011c575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b038116811462000133575f80fd5b50565b5f805f6060848603121562000149575f80fd5b835162000156816200011e565b602085015190935062000169816200011e565b60408501519092506200017c816200011e565b809150509250925092565b60805160a05160c051615bcc620001ea5f395f8181610ae30152818161212e015261365801525f818161088701528181612a55015261395c01525f8181610a2601528181610d4701528181610f0201528181611a9c01526138510152615bcc5ff3fe608060405234801562000010575f80fd5b506004361062000398575f3560e01c80638bd4f07111620001e3578063c4c928c21162000113578063dde0ff7711620000ab578063e46761c41162000083578063e46761c41462000add578063f34eb8eb1462000b05578063f4e926751462000b1c578063f9c4c2ae1462000b2d575f80fd5b8063dde0ff771462000a94578063dfdb8c5e1462000aaf578063e0bfd3d21462000ac6575f80fd5b8063d5073f6f11620000eb578063d5073f6f1462000a48578063d547741f1462000a5f578063d939b3151462000a76578063dbc169761462000a8a575f80fd5b8063c4c928c214620009e1578063ceee281d14620009f8578063d02103ca1462000a20575f80fd5b8063a066215c1162000187578063a3c573eb116200015f578063a3c573eb1462000881578063afd23cbe14620008c2578063b99d0ad714620008ec578063c1acbc3414620009c6575f80fd5b8063a066215c1462000858578063a217fddf146200086f578063a2967d991462000877575f80fd5b806399f5634e11620001bb57806399f5634e14620008205780639a908e73146200082a5780639c9f3dfe1462000841575f80fd5b80638bd4f07114620007b75780638fd88cc214620007ce57806391d1485414620007e5575f80fd5b80632f2ff15d11620002cb57806365c0504d11620002635780637975fcfe116200023b5780637975fcfe14620007375780637fb6e76a146200075d578063841b24d7146200078557806387c20c0114620007a0575f80fd5b806365c0504d146200065b5780637222020f1462000709578063727885e91462000720575f80fd5b8063394218e911620002a3578063394218e914620005ee578063477fa270146200060557806355a71ee0146200060e578063604691691462000651575f80fd5b80632f2ff15d14620005ac57806330c27dde14620005c357806336568abe14620005d7575f80fd5b806315064c96116200033f5780631816b7e511620003175780631816b7e514620004a35780632072f6c514620004ba578063248a9ca314620004c45780632528016914620004f8575f80fd5b806315064c9614620004575780631608859c14620004655780631796a1ae146200047c575f80fd5b806311f6b287116200037357806311f6b287146200041057806312b86e1914620004275780631489ed101462000440575f80fd5b8063066ec012146200039c578063080b311114620003cd5780630a0d9fbe14620003f5575b5f80fd5b608454620003b0906001600160401b031681565b6040516001600160401b0390911681526020015b60405180910390f35b620003e4620003de3660046200489b565b62000c43565b6040519015158152602001620003c4565b608554620003b090600160401b90046001600160401b031681565b620003b062000421366004620048d1565b62000c6c565b6200043e62000438366004620048ff565b62000c8b565b005b6200043e62000451366004620049a6565b62000e46565b606f54620003e49060ff1681565b6200043e620004763660046200489b565b62000fe7565b607e546200048d9063ffffffff1681565b60405163ffffffff9091168152602001620003c4565b6200043e620004b436600462004a2b565b62001091565b6200043e6200115b565b620004e9620004d536600462004a55565b5f9081526034602052604090206001015490565b604051908152602001620003c4565b62000578620005093660046200489b565b60408051606080820183525f808352602080840182905292840181905263ffffffff959095168552608182528285206001600160401b03948516865260030182529382902082519485018352805485526001015480841691850191909152600160401b90049091169082015290565b60408051825181526020808401516001600160401b03908116918301919091529282015190921690820152606001620003c4565b6200043e620005bd36600462004a6d565b62001237565b608754620003b0906001600160401b031681565b6200043e620005e836600462004a6d565b6200125f565b6200043e620005ff36600462004a9e565b62001299565b608654620004e9565b620004e96200061f3660046200489b565b63ffffffff82165f9081526081602090815260408083206001600160401b038516845260020190915290205492915050565b620004e96200135e565b620006bf6200066c366004620048d1565b607f6020525f90815260409020805460018201546002909201546001600160a01b0391821692918216916001600160401b03600160a01b8204169160ff600160e01b8304811692600160e81b9004169086565b604080516001600160a01b0397881681529690951660208701526001600160401b039093169385019390935260ff166060840152901515608083015260a082015260c001620003c4565b6200043e6200071a366004620048d1565b62001375565b6200043e6200073136600462004b68565b6200146f565b6200074e6200074836600462004c2e565b620018fb565b604051620003c4919062004ce1565b6200048d6200076e36600462004a9e565b60836020525f908152604090205463ffffffff1681565b608454620003b090600160c01b90046001600160401b031681565b6200043e620007b1366004620049a6565b6200192d565b6200043e620007c8366004620048ff565b62001c58565b6200043e620007df36600462004cf5565b62001d0f565b620003e4620007f636600462004a6d565b5f9182526034602090815260408084206001600160a01b0393909316845291905290205460ff1690565b620004e96200210d565b620003b06200083b36600462004d14565b620021ee565b6200043e6200085236600462004a9e565b620023c3565b6200043e6200086936600462004a9e565b6200247a565b620004e95f81565b620004e962002530565b620008a97f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001620003c4565b608554620008d890600160801b900461ffff1681565b60405161ffff9091168152602001620003c4565b62000981620008fd3660046200489b565b60408051608080820183525f8083526020808401829052838501829052606093840182905263ffffffff969096168152608186528381206001600160401b03958616825260040186528390208351918201845280548086168352600160401b9004909416948101949094526001830154918401919091526002909101549082015290565b604051620003c491905f6080820190506001600160401b0380845116835280602085015116602084015250604083015160408301526060830151606083015292915050565b608454620003b090600160801b90046001600160401b031681565b6200043e620009f236600462004d3f565b620028f8565b6200048d62000a0936600462004db6565b60826020525f908152604090205463ffffffff1681565b620008a97f000000000000000000000000000000000000000000000000000000000000000081565b6200043e62000a5936600462004a55565b62002937565b6200043e62000a7036600462004a6d565b620029d3565b608554620003b0906001600160401b031681565b6200043e620029fb565b608454620003b090600160401b90046001600160401b031681565b6200043e62000ac036600462004dd4565b62002ac7565b6200043e62000ad736600462004e14565b62002c18565b620008a97f000000000000000000000000000000000000000000000000000000000000000081565b6200043e62000b1636600462004e8c565b62002d1a565b6080546200048d9063ffffffff1681565b62000bc362000b3e366004620048d1565b60816020525f9081526040902080546001820154600583015460068401546007909401546001600160a01b0380851695600160a01b958690046001600160401b039081169692861695929092048216939282821692600160401b808404821693600160801b808204841694600160c01b90920484169380831693830416910460ff168c565b604080516001600160a01b039d8e1681526001600160401b039c8d1660208201529c909a16998c019990995296891660608b015260808a019590955292871660a089015290861660c0880152851660e0870152841661010086015283166101208501529190911661014083015260ff1661016082015261018001620003c4565b63ffffffff82165f90815260816020526040812062000c63908362002f0e565b90505b92915050565b63ffffffff81165f90815260816020526040812062000c669062002f52565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd462000cb78162002fc1565b63ffffffff89165f90815260816020526040902062000cdd818a8a8a8a8a8a8a62002fcd565b60068101805467ffffffffffffffff60401b1916600160401b6001600160401b038981169182029290921783555f9081526002840160205260409020869055600583018790559054600160801b9004161562000d45576006810180546001600160801b031690555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62000d7e62002530565b6040518263ffffffff1660e01b815260040162000d9d91815260200190565b5f604051808303815f87803b15801562000db5575f80fd5b505af115801562000dc8573d5f803e3d5ffd5b5050608480546001600160c01b031661127560c71b1790555050604080516001600160401b03881681526020810186905290810186905233606082015263ffffffff8b16907f3182bd6e6f74fc1fdc88b60f3a4f4c7f79db6ae6f5b88a1b3f5a1e28ec210d5e9060800160405180910390a250505050505050505050565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd462000e728162002fc1565b63ffffffff89165f90815260816020526040902062000e98818a8a8a8a8a8a8a6200335b565b60068101805467ffffffffffffffff60401b1916600160401b6001600160401b038a81169182029290921783555f9081526002840160205260409020879055600583018890559054600160801b9004161562000f00576006810180546001600160801b031690555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62000f3962002530565b6040518263ffffffff1660e01b815260040162000f5891815260200190565b5f604051808303815f87803b15801562000f70575f80fd5b505af115801562000f83573d5f803e3d5ffd5b5050604080516001600160401b038b1681526020810189905290810189905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d39060600160405180910390a350505050505050505050565b63ffffffff82165f9081526081602090815260408083203384527fc17b14a573f65366cdad721c7c0a0f76536bb4a86b935cdac44610e4f010b52a9092529091205460ff166200108057606f5460ff16156200105657604051630bc011ff60e21b815260040160405180910390fd5b62001062818362002f0e565b6200108057604051630674f25160e11b815260040160405180910390fd5b6200108c81836200376e565b505050565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620010bd8162002fc1565b6103e88261ffff161080620010d757506103ff8261ffff16115b15620010f657604051630984a67960e31b815260040160405180910390fd5b6085805471ffff000000000000000000000000000000001916600160801b61ffff8516908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a15050565b335f9081527f8875b94af5657a2903def9906d67a3f42d8a836d24b5602c00f00fc855339fcd602052604090205460ff166200122b57608454600160801b90046001600160401b03161580620011dc57506084544290620011d19062093a8090600160801b90046001600160401b031662004f32565b6001600160401b0316115b806200120c57506087544290620012019062093a80906001600160401b031662004f32565b6001600160401b0316115b156200122b5760405163692baaad60e11b815260040160405180910390fd5b620012356200395a565b565b5f82815260346020526040902060010154620012538162002fc1565b6200108c8383620039d4565b6001600160a01b03811633146200128957604051630b4ad1cd60e31b815260040160405180910390fd5b62001295828262003a58565b5050565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620012c58162002fc1565b606f5460ff1662001307576084546001600160401b03600160c01b909104811690831610620013075760405163401636df60e01b815260040160405180910390fd5b608480546001600160c01b0316600160c01b6001600160401b038516908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a1906020016200114f565b5f608654606462001370919062004f5c565b905090565b7fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd620013a18162002fc1565b63ffffffff82161580620013c05750607e5463ffffffff908116908316115b15620013df57604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff82165f908152607f60205260409020600180820154600160e81b900460ff16151590036200142557604051633b8d3d9960e01b815260040160405180910390fd5b60018101805460ff60e81b1916600160e81b17905560405163ffffffff8416907f4710d2ee567ef1ed6eb2f651dde4589524bcf7cebc62147a99b281cc836e7e44905f90a2505050565b7fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd086200149b8162002fc1565b63ffffffff88161580620014ba5750607e5463ffffffff908116908916115b15620014d957604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff88165f908152607f60205260409020600180820154600160e81b900460ff16151590036200151f57604051633b8d3d9960e01b815260040160405180910390fd5b63ffffffff6001600160401b03891611156200154e57604051634c753f5760e01b815260040160405180910390fd5b6001600160401b0388165f9081526083602052604090205463ffffffff16156200158b576040516337c8fe0960e11b815260040160405180910390fd5b608080545f91908290620015a59063ffffffff1662004f76565b825463ffffffff8281166101009490940a93840293021916919091179091558254604080515f80825260208201928390529394506001600160a01b03909216913091620015f29062004862565b620016009392919062004f9b565b604051809103905ff0801580156200161a573d5f803e3d5ffd5b5090508160835f8c6001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508160825f836001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8463ffffffff1663ffffffff1681526020019081526020015f20905081815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508360010160149054906101000a90046001600160401b03168160010160146101000a8154816001600160401b0302191690836001600160401b03160217905550836001015f9054906101000a90046001600160a01b0316816001015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508a815f0160146101000a8154816001600160401b0302191690836001600160401b031602179055508360020154816002015f806001600160401b031681526020019081526020015f20819055508b63ffffffff168160070160086101000a8154816001600160401b0302191690836001600160401b0316021790555083600101601c9054906101000a900460ff168160070160106101000a81548160ff021916908360ff1602179055508263ffffffff167f194c983456df6701c6a50830b90fe80e72b823411d0d524970c9590dc277a6418d848e8c6040516200187e949392919063ffffffff9490941684526001600160a01b0392831660208501526001600160401b0391909116604084015216606082015260800190565b60405180910390a2604051633892b81160e11b81526001600160a01b03831690637125702290620018be908d908d9088908e908e908e9060040162004fd1565b5f604051808303815f87803b158015620018d6575f80fd5b505af1158015620018e9573d5f803e3d5ffd5b50505050505050505050505050505050565b63ffffffff86165f9081526081602052604090206060906200192290878787878762003ada565b979650505050505050565b606f5460ff16156200195257604051630bc011ff60e21b815260040160405180910390fd5b63ffffffff88165f9081526081602090815260408083206084546001600160401b038a811686526003830190945291909320600101544292620019a092600160c01b90048116911662004f32565b6001600160401b03161115620019c957604051638a0704d360e01b815260040160405180910390fd5b6103e8620019d8888862005033565b6001600160401b0316111562001a0157604051635acfba9d60e11b815260040160405180910390fd5b62001a1381898989898989896200335b565b62001a1f818762003c31565b6085546001600160401b03165f0362001b275760068101805467ffffffffffffffff60401b1916600160401b6001600160401b038981169182029290921783555f9081526002840160205260409020869055600583018790559054600160801b9004161562001a9a576006810180546001600160801b031690555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62001ad362002530565b6040518263ffffffff1660e01b815260040162001af291815260200190565b5f604051808303815f87803b15801562001b0a575f80fd5b505af115801562001b1d573d5f803e3d5ffd5b5050505062001bf9565b62001b328162003e28565b600681018054600160801b90046001600160401b031690601062001b568362005056565b82546001600160401b039182166101009390930a92830292820219169190911790915560408051608081018252428316815289831660208083019182528284018b8152606084018b81526006890154600160801b900487165f90815260048a01909352949091209251835492518616600160401b026fffffffffffffffffffffffffffffffff199093169516949094171781559151600183015551600290910155505b604080516001600160401b038816815260208101869052908101869052339063ffffffff8b16907faac1e7a157b259544ebacd6e8a82ae5d6c8f174e12aa48696277bcc9a661f0b49060600160405180910390a3505050505050505050565b606f5460ff161562001c7d57604051630bc011ff60e21b815260040160405180910390fd5b63ffffffff88165f90815260816020526040902062001ca3818989898989898962002fcd565b6001600160401b0387165f9081526004820160209081526040918290206002015482519081529081018590527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a162001d046200395a565b505050505050505050565b335f9081527ff14f5a8ad59d90593602e905b358229bff5ceea677d5bf0f5a1701793550a9a6602052604090205460ff1615801562001dc35750336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562001d91573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001db7919062005074565b6001600160a01b031614155b1562001de257604051630d03687f60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526082602052604081205463ffffffff169081900362001e22576040516374a086a360e01b815260040160405180910390fd5b63ffffffff81165f90815260816020526040902060068101546001600160401b039081169084168111158062001e6f575060068201546001600160401b03600160401b9091048116908516105b1562001e8e5760405163cb23ebdf60e01b815260040160405180910390fd5b805b846001600160401b0316816001600160401b03161462001f32576001600160401b038082165f908152600385016020526040902060010154600160401b9004811690861681101562001ef557604051639753965f60e01b815260040160405180910390fd5b6001600160401b039091165f908152600384016020526040812090815560010180546fffffffffffffffffffffffffffffffff1916905562001e90565b60068301805467ffffffffffffffff19166001600160401b03871617905562001f5c858362005033565b608480545f9062001f789084906001600160401b031662005033565b82546101009290920a6001600160401b038181021990931691831602179091556006850154600160801b90041615905062002037575f62001fb98462002f52565b600685015490915062001fdd90600160401b90046001600160401b03168262005033565b6084805460089062002001908490600160401b90046001600160401b031662005033565b82546001600160401b039182166101009390930a928302919092021990911617905550506006830180546001600160801b031690555b6001600160401b0385165f8181526003850160205260409081902054905163334d6f6760e11b8152600481019290925260248201526001600160a01b0387169063669adece906044015f604051808303815f87803b15801562002098575f80fd5b505af1158015620020ab573d5f803e3d5ffd5b505050506001600160401b0385165f81815260038501602090815260409182902054915191825263ffffffff8716917f80a6d395a55aed8126079cb8247f0a6848b1440ca2cdca3b4386f250c3529402910160405180910390a3505050505050565b6040516370a0823160e01b81523060048201525f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801562002174573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200219a919062005092565b6084549091505f90620021c0906001600160401b03600160401b82048116911662005033565b6001600160401b03169050805f03620021db575f9250505090565b620021e78183620050be565b9250505090565b606f545f9060ff16156200221557604051630bc011ff60e21b815260040160405180910390fd5b335f9081526082602052604081205463ffffffff16908190036200224c576040516371653c1560e01b815260040160405180910390fd5b836001600160401b03165f036200227657604051632590ccf960e01b815260040160405180910390fd5b63ffffffff81165f9081526081602052604081206084805491928792620022a89084906001600160401b031662004f32565b82546101009290920a6001600160401b0381810219909316918316021790915560068301541690505f620022dd878362004f32565b6006840180546001600160401b0380841667ffffffffffffffff199092168217909255604080516060810182528a815242841660208083019182528886168385019081525f95865260038b0190915292909320905181559151600192909201805491518416600160401b026fffffffffffffffffffffffffffffffff1990921692909316919091171790559050620023758362003e28565b6040516001600160401b038216815263ffffffff8516907f1d9f30260051d51d70339da239ea7b080021adcaabfa71c9b0ea339a20cf9a259060200160405180910390a29695505050505050565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620023ef8162002fc1565b606f5460ff166200242a576085546001600160401b03908116908316106200242a5760405163048a05a960e41b815260040160405180910390fd5b6085805467ffffffffffffffff19166001600160401b0384169081179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c75906020016200114f565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620024a68162002fc1565b62015180826001600160401b03161115620024d457604051631c0cfbfd60e31b815260040160405180910390fd5b6085805467ffffffffffffffff60401b1916600160401b6001600160401b038516908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c28906020016200114f565b6080545f9063ffffffff168082036200254a57505f919050565b5f816001600160401b0381111562002566576200256662004aba565b60405190808252806020026020018201604052801562002590578160200160208202803683370190505b5090505f5b82811015620026005760815f620025ae836001620050d4565b63ffffffff1663ffffffff1681526020019081526020015f2060050154828281518110620025e057620025e0620050ea565b602090810291909101015280620025f781620050fe565b91505062002595565b505f60205b8360011462002858575f6200261c60028662005119565b62002629600287620050be565b620026359190620050d4565b90505f816001600160401b0381111562002653576200265362004aba565b6040519080825280602002602001820160405280156200267d578160200160208202803683370190505b5090505f5b828110156200280457620026986001846200512f565b81148015620026b35750620026af60028862005119565b6001145b156200273b5785620026c782600262004f5c565b81518110620026da57620026da620050ea565b602002602001015185604051602001620026fe929190918252602082015260400190565b60405160208183030381529060405280519060200120828281518110620027295762002729620050ea565b602002602001018181525050620027ef565b856200274982600262004f5c565b815181106200275c576200275c620050ea565b60200260200101518682600262002774919062004f5c565b62002781906001620050d4565b81518110620027945762002794620050ea565b6020026020010151604051602001620027b7929190918252602082015260400190565b60405160208183030381529060405280519060200120828281518110620027e257620027e2620050ea565b6020026020010181815250505b80620027fb81620050fe565b91505062002682565b50809450819550838460405160200162002828929190918252602082015260400190565b60405160208183030381529060405280519060200120935082806200284d9062005145565b935050505062002605565b5f835f815181106200286e576200286e620050ea565b602002602001015190505f5b82811015620028ee57604080516020810184905290810185905260600160408051601f19818403018152828252805160209182012090830187905290820186905292506060016040516020818303038152906040528051906020012093508080620028e590620050fe565b9150506200287a565b5095945050505050565b7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac620029248162002fc1565b6200293184848462003ef1565b50505050565b7f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb620029638162002fc1565b683635c9adc5dea000008211806200297e5750633b9aca0082105b156200299d57604051638586952560e01b815260040160405180910390fd5b60868290556040518281527ffb383653f53ee079978d0c9aff7aeff04a10166ce244cca9c9f9d8d96bed45b2906020016200114f565b5f82815260346020526040902060010154620029ef8162002fc1565b6200108c838362003a58565b7f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f462002a278162002fc1565b6087805467ffffffffffffffff1916426001600160401b031617905560408051636de0b4bb60e11b815290517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163dbc16976916004808301925f92919082900301818387803b15801562002aa3575f80fd5b505af115801562002ab6573d5f803e3d5ffd5b5050505062002ac4620041f6565b50565b336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562002b0f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002b35919062005074565b6001600160a01b03161462002b5d5760405163696072e960e01b815260040160405180910390fd5b6001600160a01b0382165f9081526082602090815260408083205463ffffffff1683526081909152902060068101546001600160401b03808216600160401b909204161462002bbf5760405163664316a560e11b815260040160405180910390fd5b600781015463ffffffff8316600160401b9091046001600160401b03161062002bfb57604051633e37e23360e01b815260040160405180910390fd5b604080515f8152602081019091526200108c908490849062003ef1565b7f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e62002c448162002fc1565b6001600160401b0384165f9081526083602052604090205463ffffffff161562002c81576040516337c8fe0960e11b815260040160405180910390fd5b63ffffffff6001600160401b038516111562002cb057604051634c753f5760e01b815260040160405180910390fd5b6001600160a01b0387165f9081526082602052604090205463ffffffff161562002ced57604051630d409b9360e41b815260040160405180910390fd5b5f62002cfd88888888876200424e565b5f8080526002909101602052604090209390935550505050505050565b7fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f59062002d468162002fc1565b607e80545f9190829062002d609063ffffffff1662004f76565b91906101000a81548163ffffffff021916908363ffffffff160217905590506040518060c00160405280896001600160a01b03168152602001886001600160a01b03168152602001876001600160401b031681526020018660ff1681526020015f1515815260200185815250607f5f8363ffffffff1663ffffffff1681526020019081526020015f205f820151815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160146101000a8154816001600160401b0302191690836001600160401b03160217905550606082015181600101601c6101000a81548160ff021916908360ff160217905550608082015181600101601d6101000a81548160ff02191690831515021790555060a082015181600201559050508063ffffffff167fa2970448b3bd66ba7e524e7b2a5b9cf94fa29e32488fb942afdfe70dd4b77b5289898989898960405162002efc969594939291906200515d565b60405180910390a25050505050505050565b6085546001600160401b038281165f9081526004850160205260408120549092429262002f4092918116911662004f32565b6001600160401b031611159392505050565b60068101545f90600160801b90046001600160401b03161562002fa4575060068101546001600160401b03600160801b90910481165f9081526004909201602052604090912054600160401b90041690565b5060060154600160401b90046001600160401b031690565b919050565b62002ac481336200446e565b60078801545f906001600160401b039081169087161015620030025760405163ead1340b60e01b815260040160405180910390fd5b6001600160401b03881615620030a25760068901546001600160401b03600160801b909104811690891611156200304c5760405163bb14c20560e01b815260040160405180910390fd5b506001600160401b038088165f90815260048a0160205260409020600281015481549092888116600160401b90920416146200309b57604051632bd2e3e760e01b815260040160405180910390fd5b5062003116565b506001600160401b0385165f90815260028901602052604090205480620030dc576040516324cbdcc360e11b815260040160405180910390fd5b60068901546001600160401b03600160401b909104811690871611156200311657604051630f2b74f160e11b815260040160405180910390fd5b60068901546001600160401b03600160801b909104811690881611806200314f5750876001600160401b0316876001600160401b031611155b8062003173575060068901546001600160401b03600160c01b909104811690881611155b15620031925760405163bfa7079f60e01b815260040160405180910390fd5b6001600160401b038781165f90815260048b016020526040902054600160401b9004811690861614620031d8576040516332a2a77f60e01b815260040160405180910390fd5b5f620031e98a888888868962003ada565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516200321f9190620051b4565b602060405180830381855afa1580156200323b573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019062003260919062005092565b6200326c919062005119565b60018c0154604080516020810182528381529051634890ed4560e11b81529293506001600160a01b0390911691639121da8a91620032b091889190600401620051d1565b602060405180830381865afa158015620032cc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620032f291906200520d565b62003310576040516309bde33960e01b815260040160405180910390fd5b6001600160401b0389165f90815260048c0160205260409020600201548590036200334e5760405163a47276bd60e01b815260040160405180910390fd5b5050505050505050505050565b5f80620033688a62002f52565b60078b01549091506001600160401b0390811690891610156200339e5760405163ead1340b60e01b815260040160405180910390fd5b6001600160401b03891615620034405760068a01546001600160401b03600160801b9091048116908a161115620033e85760405163bb14c20560e01b815260040160405180910390fd5b6001600160401b03808a165f90815260048c01602052604090206002810154815490945090918a8116600160401b90920416146200343957604051632bd2e3e760e01b815260040160405180910390fd5b50620034af565b6001600160401b0388165f90815260028b0160205260409020549150816200347b576040516324cbdcc360e11b815260040160405180910390fd5b806001600160401b0316886001600160401b03161115620034af57604051630f2b74f160e11b815260040160405180910390fd5b806001600160401b0316876001600160401b031611620034e25760405163b9b18f5760e01b815260040160405180910390fd5b5f620034f38b8a8a8a878b62003ada565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051620035299190620051b4565b602060405180830381855afa15801562003545573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906200356a919062005092565b62003576919062005119565b60018d0154604080516020810182528381529051634890ed4560e11b81529293506001600160a01b0390911691639121da8a91620035ba91899190600401620051d1565b602060405180830381865afa158015620035d6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620035fc91906200520d565b6200361a576040516309bde33960e01b815260040160405180910390fd5b5f62003627848b62005033565b90506200368087826001600160401b0316620036426200210d565b6200364e919062004f5c565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190620044b1565b80608460088282829054906101000a90046001600160401b0316620036a6919062004f32565b82546101009290920a6001600160401b03818102199093169183160217909155608480547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b428416021790558e546040516332c2d15360e01b8152918d166004830152602482018b90523360448301526001600160a01b031691506332c2d153906064015f604051808303815f87803b15801562003748575f80fd5b505af11580156200375b573d5f803e3d5ffd5b5050505050505050505050505050505050565b60068201546001600160401b03600160c01b9091048116908216111580620037ad575060068201546001600160401b03600160801b9091048116908216115b15620037cc5760405163d086b70b60e01b815260040160405180910390fd5b6001600160401b038181165f8181526004850160209081526040808320805460068901805467ffffffffffffffff60401b1916600160401b92839004909816918202979097178755600280830154828752908a0190945291909320919091556001820154600587015583546001600160c01b0316600160c01b909302929092179092557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d6200388862002530565b6040518263ffffffff1660e01b8152600401620038a791815260200190565b5f604051808303815f87803b158015620038bf575f80fd5b505af1158015620038d2573d5f803e3d5ffd5b505085546001600160a01b03165f90815260826020908152604091829020546002870154600188015484516001600160401b03898116825294810192909252818501529188166060830152915163ffffffff90921693507f581910eb7a27738945c2f00a91f2284b2d6de9d4e472b12f901c2b0df045e21b925081900360800190a250505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b158015620039b3575f80fd5b505af1158015620039c6573d5f803e3d5ffd5b50505050620012356200451a565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff1662001295575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff161562001295575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001600160401b038086165f818152600389016020526040808220549388168252902054606092911580159062003b0f575081155b1562003b2e5760405163340c614f60e11b815260040160405180910390fd5b8062003b4d576040516366385b5160e01b815260040160405180910390fd5b62003b588462004576565b62003b76576040516305dae44f60e21b815260040160405180910390fd5b885460018a01546040516bffffffffffffffffffffffff193360601b16602082015260348101889052605481018590527fffffffffffffffff00000000000000000000000000000000000000000000000060c08c811b82166074840152600160a01b94859004811b8216607c84015293909204831b82166084820152608c810187905260ac810184905260cc81018990529189901b1660ec82015260f401604051602081830303815290604052925050509695505050505050565b5f62003c3d8362002f52565b9050815f8062003c4e848462005033565b6085546001600160401b0391821692505f9162003c7491600160401b900416426200512f565b90505b846001600160401b0316846001600160401b03161462003cfd576001600160401b038085165f9081526003890160205260409020600181015490911682101562003cd8576001810154600160401b90046001600160401b0316945062003cf6565b62003ce4868662005033565b6001600160401b031693505062003cfd565b5062003c77565b5f62003d0a84846200512f565b90508381101562003d6857808403600c811162003d28578062003d2b565b600c5b9050806103e80a81608560109054906101000a900461ffff1661ffff160a608654028162003d5d5762003d5d620050aa565b046086555062003ddf565b838103600c811162003d7b578062003d7e565b600c5b90505f816103e80a82608560109054906101000a900461ffff1661ffff160a670de0b6b3a7640000028162003db75762003db7620050aa565b04905080608654670de0b6b3a7640000028162003dd85762003dd8620050aa565b0460865550505b683635c9adc5dea00000608654111562003e0657683635c9adc5dea0000060865562003e1e565b633b9aca00608654101562003e1e57633b9aca006086555b5050505050505050565b60068101546001600160401b03600160c01b82048116600160801b90920416111562002ac45760068101545f9062003e7290600160c01b90046001600160401b0316600162004f32565b905062003e80828262002f0e565b15620012955760068201545f9060029062003ead908490600160801b90046001600160401b031662005033565b62003eb991906200522e565b62003ec5908362004f32565b905062003ed3838262002f0e565b1562003ee5576200108c83826200376e565b6200108c83836200376e565b63ffffffff8216158062003f105750607e5463ffffffff908116908316115b1562003f2f57604051637512e5cb60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526082602052604081205463ffffffff169081900362003f6f576040516374a086a360e01b815260040160405180910390fd5b63ffffffff8181165f908152608160205260409020600781015490918516600160401b9091046001600160401b03160362003fbd57604051634f61d51960e01b815260040160405180910390fd5b63ffffffff84165f908152607f60205260409020600180820154600160e81b900460ff16151590036200400357604051633b8d3d9960e01b815260040160405180910390fd5b60018101546007830154600160801b900460ff908116600160e01b90920416146200404157604051635aa0d5f160e11b815260040160405180910390fd5b6001818101805491840180546001600160a01b0390931673ffffffffffffffffffffffffffffffffffffffff1984168117825591547fffffffff00000000000000000000000000000000000000000000000000000000909316909117600160a01b928390046001600160401b0390811690930217905560078301805467ffffffffffffffff60401b191663ffffffff8816600160401b021790556006830154600160c01b81048216600160801b909104909116146200411357604051639d59507b60e01b815260040160405180910390fd5b5f6200411f8462000c6c565b60078401805467ffffffffffffffff19166001600160401b038316179055825460405163278f794360e11b81529192506001600160a01b0389811692634f1ef2869262004173921690899060040162005256565b5f604051808303815f87803b1580156200418b575f80fd5b505af11580156200419e573d5f803e3d5ffd5b50506040805163ffffffff8a811682526001600160401b0386166020830152881693507ff585e04c05d396901170247783d3e5f0ee9c1df23072985b50af089f5e48b19d92500160405180910390a250505050505050565b606f5460ff166200421a57604051635386698160e01b815260040160405180910390fd5b606f805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b608080545f9182918290620042699063ffffffff1662004f76565b91906101000a81548163ffffffff021916908363ffffffff160217905590508060835f866001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508060825f896001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff16021790555060815f8263ffffffff1663ffffffff1681526020019081526020015f20915086825f015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550848260010160146101000a8154816001600160401b0302191690836001600160401b0316021790555085826001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555083825f0160146101000a8154816001600160401b0302191690836001600160401b03160217905550828260070160106101000a81548160ff021916908360ff1602179055508063ffffffff167fadfc7d56f7e39b08b321534f14bfb135ad27698f7d2f5ad0edc2356ea9a3f850868987875f6040516200445c9594939291906001600160401b0395861681526001600160a01b03949094166020850152918416604084015260ff166060830152909116608082015260a00190565b60405180910390a25095945050505050565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff166200129557604051637615be1f60e11b815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b1790526200108c908490620045fa565b606f5460ff16156200453f57604051630bc011ff60e21b815260040160405180910390fd5b606f805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b5f67ffffffff000000016001600160401b038316108015620045ac575067ffffffff00000001604083901c6001600160401b0316105b8015620045cd575067ffffffff00000001608083901c6001600160401b0316105b8015620045e5575067ffffffff0000000160c083901c105b15620045f357506001919050565b505f919050565b5f62004650826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620046d69092919063ffffffff16565b8051909150156200108c57808060200190518101906200467191906200520d565b6200108c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084015b60405180910390fd5b6060620046e684845f85620046ee565b949350505050565b606082471015620047515760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620046cd565b5f80866001600160a01b031685876040516200476e9190620051b4565b5f6040518083038185875af1925050503d805f8114620047aa576040519150601f19603f3d011682016040523d82523d5f602084013e620047af565b606091505b50915091506200192287838387606083156200482f5782515f0362004827576001600160a01b0385163b620048275760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620046cd565b5081620046e6565b620046e68383815115620048465781518083602001fd5b8060405162461bcd60e51b8152600401620046cd919062004ce1565b61091d806200527a83390190565b803563ffffffff8116811462002fbc575f80fd5b80356001600160401b038116811462002fbc575f80fd5b5f8060408385031215620048ad575f80fd5b620048b88362004870565b9150620048c86020840162004884565b90509250929050565b5f60208284031215620048e2575f80fd5b62000c638262004870565b80610300810183101562000c66575f80fd5b5f805f805f805f806103e0898b03121562004918575f80fd5b620049238962004870565b97506200493360208a0162004884565b96506200494360408a0162004884565b95506200495360608a0162004884565b94506200496360808a0162004884565b935060a0890135925060c08901359150620049828a60e08b01620048ed565b90509295985092959890939650565b6001600160a01b038116811462002ac4575f80fd5b5f805f805f805f806103e0898b031215620049bf575f80fd5b620049ca8962004870565b9750620049da60208a0162004884565b9650620049ea60408a0162004884565b9550620049fa60608a0162004884565b94506080890135935060a0890135925060c089013562004a1a8162004991565b9150620049828a60e08b01620048ed565b5f6020828403121562004a3c575f80fd5b813561ffff8116811462004a4e575f80fd5b9392505050565b5f6020828403121562004a66575f80fd5b5035919050565b5f806040838503121562004a7f575f80fd5b82359150602083013562004a938162004991565b809150509250929050565b5f6020828403121562004aaf575f80fd5b62000c638262004884565b634e487b7160e01b5f52604160045260245ffd5b5f6001600160401b038084111562004aea5762004aea62004aba565b604051601f8501601f19908116603f0116810190828211818310171562004b155762004b1562004aba565b8160405280935085815286868601111562004b2e575f80fd5b858560208301375f602087830101525050509392505050565b5f82601f83011262004b57575f80fd5b62000c638383356020850162004ace565b5f805f805f805f60e0888a03121562004b7f575f80fd5b62004b8a8862004870565b965062004b9a6020890162004884565b9550604088013562004bac8162004991565b9450606088013562004bbe8162004991565b9350608088013562004bd08162004991565b925060a08801356001600160401b038082111562004bec575f80fd5b62004bfa8b838c0162004b47565b935060c08a013591508082111562004c10575f80fd5b5062004c1f8a828b0162004b47565b91505092959891949750929550565b5f805f805f8060c0878903121562004c44575f80fd5b62004c4f8762004870565b955062004c5f6020880162004884565b945062004c6f6040880162004884565b9350606087013592506080870135915060a087013590509295509295509295565b5f5b8381101562004cac57818101518382015260200162004c92565b50505f910152565b5f815180845262004ccd81602086016020860162004c90565b601f01601f19169290920160200192915050565b602081525f62000c63602083018462004cb4565b5f806040838503121562004d07575f80fd5b8235620048b88162004991565b5f806040838503121562004d26575f80fd5b62004d318362004884565b946020939093013593505050565b5f805f6060848603121562004d52575f80fd5b833562004d5f8162004991565b925062004d6f6020850162004870565b915060408401356001600160401b0381111562004d8a575f80fd5b8401601f8101861362004d9b575f80fd5b62004dac8682356020840162004ace565b9150509250925092565b5f6020828403121562004dc7575f80fd5b813562004a4e8162004991565b5f806040838503121562004de6575f80fd5b823562004df38162004991565b9150620048c86020840162004870565b803560ff8116811462002fbc575f80fd5b5f805f805f8060c0878903121562004e2a575f80fd5b863562004e378162004991565b9550602087013562004e498162004991565b945062004e596040880162004884565b935062004e696060880162004884565b92506080870135915062004e8060a0880162004e03565b90509295509295509295565b5f805f805f8060c0878903121562004ea2575f80fd5b863562004eaf8162004991565b9550602087013562004ec18162004991565b945062004ed16040880162004884565b935062004ee16060880162004e03565b92506080870135915060a08701356001600160401b0381111562004f03575f80fd5b62004f1189828a0162004b47565b9150509295509295509295565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b0381811683821601908082111562004f555762004f5562004f1e565b5092915050565b808202811582820484141762000c665762000c6662004f1e565b5f63ffffffff80831681810362004f915762004f9162004f1e565b6001019392505050565b5f6001600160a01b0380861683528085166020840152506060604083015262004fc8606083018462004cb4565b95945050505050565b5f6001600160a01b038089168352808816602084015263ffffffff8716604084015280861660608401525060c060808301526200501260c083018562004cb4565b82810360a084015262005026818562004cb4565b9998505050505050505050565b6001600160401b0382811682821603908082111562004f555762004f5562004f1e565b5f6001600160401b0380831681810362004f915762004f9162004f1e565b5f6020828403121562005085575f80fd5b815162004a4e8162004991565b5f60208284031215620050a3575f80fd5b5051919050565b634e487b7160e01b5f52601260045260245ffd5b5f82620050cf57620050cf620050aa565b500490565b8082018082111562000c665762000c6662004f1e565b634e487b7160e01b5f52603260045260245ffd5b5f6001820162005112576200511262004f1e565b5060010190565b5f826200512a576200512a620050aa565b500690565b8181038181111562000c665762000c6662004f1e565b5f8162005156576200515662004f1e565b505f190190565b5f6001600160a01b0380891683528088166020840152506001600160401b038616604083015260ff8516606083015283608083015260c060a0830152620051a860c083018462004cb4565b98975050505050505050565b5f8251620051c781846020870162004c90565b9190910192915050565b6103208101610300808584378201835f5b600181101562005203578151835260209283019290910190600101620051e2565b5050509392505050565b5f602082840312156200521e575f80fd5b8151801515811462004a4e575f80fd5b5f6001600160401b03808416806200524a576200524a620050aa565b92169190910492915050565b6001600160a01b0383168152604060208201525f620046e6604083018462004cb456fe60a06040526040516200091d3803806200091d833981016040819052620000269162000375565b828162000034828262000060565b50506001600160a01b038216608052620000576200005160805190565b620000c5565b5050506200046c565b6200006b8262000136565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000b757620000b28282620001b5565b505050565b620000c16200022e565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620001065f80516020620008fd833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001338162000250565b50565b806001600160a01b03163b5f036200017157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b031684604051620001d391906200044f565b5f60405180830381855af49150503d805f81146200020d576040519150601f19603f3d011682016040523d82523d5f602084013e62000212565b606091505b5090925090506200022585838362000291565b95945050505050565b34156200024e5760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b0381166200027b57604051633173bdd160e11b81525f600482015260240162000168565b805f80516020620008fd83398151915262000194565b606082620002aa57620002a482620002f7565b620002f0565b8151158015620002c257506001600160a01b0384163b155b15620002ed57604051639996b31560e01b81526001600160a01b038516600482015260240162000168565b50805b9392505050565b805115620003085780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811462000338575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b838110156200036d57818101518382015260200162000353565b50505f910152565b5f805f6060848603121562000388575f80fd5b620003938462000321565b9250620003a36020850162000321565b60408501519092506001600160401b0380821115620003c0575f80fd5b818601915086601f830112620003d4575f80fd5b815181811115620003e957620003e96200033d565b604051601f8201601f19908116603f011681019083821181831017156200041457620004146200033d565b816040528281528960208487010111156200042d575f80fd5b6200044083602083016020880162000351565b80955050505050509250925092565b5f82516200046281846020870162000351565b9190910192915050565b608051610479620004845f395f601001526104795ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610081575f357fffffffff000000000000000000000000000000000000000000000000000000001663278f794360e11b1461007957610077610085565b565b610077610095565b6100775b6100776100906100c3565b6100fa565b5f806100a43660048184610313565b8101906100b1919061034e565b915091506100bf8282610118565b5050565b5f6100f57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e808015610114573d5ff35b3d5ffd5b61012182610172565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561016a5761016582826101fa565b505050565b6100bf61026c565b806001600160a01b03163b5f036101ac57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516102169190610417565b5f60405180830381855af49150503d805f811461024e576040519150601f19603f3d011682016040523d82523d5f602084013e610253565b606091505b509150915061026385838361028b565b95945050505050565b34156100775760405163b398979f60e01b815260040160405180910390fd5b6060826102a05761029b826102ea565b6102e3565b81511580156102b757506001600160a01b0384163b155b156102e057604051639996b31560e01b81526001600160a01b03851660048201526024016101a3565b50805b9392505050565b8051156102fa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f8085851115610321575f80fd5b8386111561032d575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561035f575f80fd5b82356001600160a01b0381168114610375575f80fd5b9150602083013567ffffffffffffffff80821115610391575f80fd5b818501915085601f8301126103a4575f80fd5b8135818111156103b6576103b661033a565b604051601f8201601f19908116603f011681019083821181831017156103de576103de61033a565b816040528281528860208487010111156103f6575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610436576020818601810151858301520161041c565b505f92019182525091905056fea26469706673582212201862559c7a1a6f6ad5955fa13172986128c855ab779db998ecea424bd4dfebf064736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103a2646970667358221220f7c2380164dc44ad0ccfb54de8868b9fa4ea4c441164d6c2b61465340c34086064736f6c63430008140033", - "deployedBytecode": "0x608060405234801562000010575f80fd5b506004361062000398575f3560e01c80638bd4f07111620001e3578063c4c928c21162000113578063dde0ff7711620000ab578063e46761c41162000083578063e46761c41462000add578063f34eb8eb1462000b05578063f4e926751462000b1c578063f9c4c2ae1462000b2d575f80fd5b8063dde0ff771462000a94578063dfdb8c5e1462000aaf578063e0bfd3d21462000ac6575f80fd5b8063d5073f6f11620000eb578063d5073f6f1462000a48578063d547741f1462000a5f578063d939b3151462000a76578063dbc169761462000a8a575f80fd5b8063c4c928c214620009e1578063ceee281d14620009f8578063d02103ca1462000a20575f80fd5b8063a066215c1162000187578063a3c573eb116200015f578063a3c573eb1462000881578063afd23cbe14620008c2578063b99d0ad714620008ec578063c1acbc3414620009c6575f80fd5b8063a066215c1462000858578063a217fddf146200086f578063a2967d991462000877575f80fd5b806399f5634e11620001bb57806399f5634e14620008205780639a908e73146200082a5780639c9f3dfe1462000841575f80fd5b80638bd4f07114620007b75780638fd88cc214620007ce57806391d1485414620007e5575f80fd5b80632f2ff15d11620002cb57806365c0504d11620002635780637975fcfe116200023b5780637975fcfe14620007375780637fb6e76a146200075d578063841b24d7146200078557806387c20c0114620007a0575f80fd5b806365c0504d146200065b5780637222020f1462000709578063727885e91462000720575f80fd5b8063394218e911620002a3578063394218e914620005ee578063477fa270146200060557806355a71ee0146200060e578063604691691462000651575f80fd5b80632f2ff15d14620005ac57806330c27dde14620005c357806336568abe14620005d7575f80fd5b806315064c96116200033f5780631816b7e511620003175780631816b7e514620004a35780632072f6c514620004ba578063248a9ca314620004c45780632528016914620004f8575f80fd5b806315064c9614620004575780631608859c14620004655780631796a1ae146200047c575f80fd5b806311f6b287116200037357806311f6b287146200041057806312b86e1914620004275780631489ed101462000440575f80fd5b8063066ec012146200039c578063080b311114620003cd5780630a0d9fbe14620003f5575b5f80fd5b608454620003b0906001600160401b031681565b6040516001600160401b0390911681526020015b60405180910390f35b620003e4620003de3660046200489b565b62000c43565b6040519015158152602001620003c4565b608554620003b090600160401b90046001600160401b031681565b620003b062000421366004620048d1565b62000c6c565b6200043e62000438366004620048ff565b62000c8b565b005b6200043e62000451366004620049a6565b62000e46565b606f54620003e49060ff1681565b6200043e620004763660046200489b565b62000fe7565b607e546200048d9063ffffffff1681565b60405163ffffffff9091168152602001620003c4565b6200043e620004b436600462004a2b565b62001091565b6200043e6200115b565b620004e9620004d536600462004a55565b5f9081526034602052604090206001015490565b604051908152602001620003c4565b62000578620005093660046200489b565b60408051606080820183525f808352602080840182905292840181905263ffffffff959095168552608182528285206001600160401b03948516865260030182529382902082519485018352805485526001015480841691850191909152600160401b90049091169082015290565b60408051825181526020808401516001600160401b03908116918301919091529282015190921690820152606001620003c4565b6200043e620005bd36600462004a6d565b62001237565b608754620003b0906001600160401b031681565b6200043e620005e836600462004a6d565b6200125f565b6200043e620005ff36600462004a9e565b62001299565b608654620004e9565b620004e96200061f3660046200489b565b63ffffffff82165f9081526081602090815260408083206001600160401b038516845260020190915290205492915050565b620004e96200135e565b620006bf6200066c366004620048d1565b607f6020525f90815260409020805460018201546002909201546001600160a01b0391821692918216916001600160401b03600160a01b8204169160ff600160e01b8304811692600160e81b9004169086565b604080516001600160a01b0397881681529690951660208701526001600160401b039093169385019390935260ff166060840152901515608083015260a082015260c001620003c4565b6200043e6200071a366004620048d1565b62001375565b6200043e6200073136600462004b68565b6200146f565b6200074e6200074836600462004c2e565b620018fb565b604051620003c4919062004ce1565b6200048d6200076e36600462004a9e565b60836020525f908152604090205463ffffffff1681565b608454620003b090600160c01b90046001600160401b031681565b6200043e620007b1366004620049a6565b6200192d565b6200043e620007c8366004620048ff565b62001c58565b6200043e620007df36600462004cf5565b62001d0f565b620003e4620007f636600462004a6d565b5f9182526034602090815260408084206001600160a01b0393909316845291905290205460ff1690565b620004e96200210d565b620003b06200083b36600462004d14565b620021ee565b6200043e6200085236600462004a9e565b620023c3565b6200043e6200086936600462004a9e565b6200247a565b620004e95f81565b620004e962002530565b620008a97f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001620003c4565b608554620008d890600160801b900461ffff1681565b60405161ffff9091168152602001620003c4565b62000981620008fd3660046200489b565b60408051608080820183525f8083526020808401829052838501829052606093840182905263ffffffff969096168152608186528381206001600160401b03958616825260040186528390208351918201845280548086168352600160401b9004909416948101949094526001830154918401919091526002909101549082015290565b604051620003c491905f6080820190506001600160401b0380845116835280602085015116602084015250604083015160408301526060830151606083015292915050565b608454620003b090600160801b90046001600160401b031681565b6200043e620009f236600462004d3f565b620028f8565b6200048d62000a0936600462004db6565b60826020525f908152604090205463ffffffff1681565b620008a97f000000000000000000000000000000000000000000000000000000000000000081565b6200043e62000a5936600462004a55565b62002937565b6200043e62000a7036600462004a6d565b620029d3565b608554620003b0906001600160401b031681565b6200043e620029fb565b608454620003b090600160401b90046001600160401b031681565b6200043e62000ac036600462004dd4565b62002ac7565b6200043e62000ad736600462004e14565b62002c18565b620008a97f000000000000000000000000000000000000000000000000000000000000000081565b6200043e62000b1636600462004e8c565b62002d1a565b6080546200048d9063ffffffff1681565b62000bc362000b3e366004620048d1565b60816020525f9081526040902080546001820154600583015460068401546007909401546001600160a01b0380851695600160a01b958690046001600160401b039081169692861695929092048216939282821692600160401b808404821693600160801b808204841694600160c01b90920484169380831693830416910460ff168c565b604080516001600160a01b039d8e1681526001600160401b039c8d1660208201529c909a16998c019990995296891660608b015260808a019590955292871660a089015290861660c0880152851660e0870152841661010086015283166101208501529190911661014083015260ff1661016082015261018001620003c4565b63ffffffff82165f90815260816020526040812062000c63908362002f0e565b90505b92915050565b63ffffffff81165f90815260816020526040812062000c669062002f52565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd462000cb78162002fc1565b63ffffffff89165f90815260816020526040902062000cdd818a8a8a8a8a8a8a62002fcd565b60068101805467ffffffffffffffff60401b1916600160401b6001600160401b038981169182029290921783555f9081526002840160205260409020869055600583018790559054600160801b9004161562000d45576006810180546001600160801b031690555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62000d7e62002530565b6040518263ffffffff1660e01b815260040162000d9d91815260200190565b5f604051808303815f87803b15801562000db5575f80fd5b505af115801562000dc8573d5f803e3d5ffd5b5050608480546001600160c01b031661127560c71b1790555050604080516001600160401b03881681526020810186905290810186905233606082015263ffffffff8b16907f3182bd6e6f74fc1fdc88b60f3a4f4c7f79db6ae6f5b88a1b3f5a1e28ec210d5e9060800160405180910390a250505050505050505050565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd462000e728162002fc1565b63ffffffff89165f90815260816020526040902062000e98818a8a8a8a8a8a8a6200335b565b60068101805467ffffffffffffffff60401b1916600160401b6001600160401b038a81169182029290921783555f9081526002840160205260409020879055600583018890559054600160801b9004161562000f00576006810180546001600160801b031690555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62000f3962002530565b6040518263ffffffff1660e01b815260040162000f5891815260200190565b5f604051808303815f87803b15801562000f70575f80fd5b505af115801562000f83573d5f803e3d5ffd5b5050604080516001600160401b038b1681526020810189905290810189905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d39060600160405180910390a350505050505050505050565b63ffffffff82165f9081526081602090815260408083203384527fc17b14a573f65366cdad721c7c0a0f76536bb4a86b935cdac44610e4f010b52a9092529091205460ff166200108057606f5460ff16156200105657604051630bc011ff60e21b815260040160405180910390fd5b62001062818362002f0e565b6200108057604051630674f25160e11b815260040160405180910390fd5b6200108c81836200376e565b505050565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620010bd8162002fc1565b6103e88261ffff161080620010d757506103ff8261ffff16115b15620010f657604051630984a67960e31b815260040160405180910390fd5b6085805471ffff000000000000000000000000000000001916600160801b61ffff8516908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a15050565b335f9081527f8875b94af5657a2903def9906d67a3f42d8a836d24b5602c00f00fc855339fcd602052604090205460ff166200122b57608454600160801b90046001600160401b03161580620011dc57506084544290620011d19062093a8090600160801b90046001600160401b031662004f32565b6001600160401b0316115b806200120c57506087544290620012019062093a80906001600160401b031662004f32565b6001600160401b0316115b156200122b5760405163692baaad60e11b815260040160405180910390fd5b620012356200395a565b565b5f82815260346020526040902060010154620012538162002fc1565b6200108c8383620039d4565b6001600160a01b03811633146200128957604051630b4ad1cd60e31b815260040160405180910390fd5b62001295828262003a58565b5050565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620012c58162002fc1565b606f5460ff1662001307576084546001600160401b03600160c01b909104811690831610620013075760405163401636df60e01b815260040160405180910390fd5b608480546001600160c01b0316600160c01b6001600160401b038516908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a1906020016200114f565b5f608654606462001370919062004f5c565b905090565b7fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd620013a18162002fc1565b63ffffffff82161580620013c05750607e5463ffffffff908116908316115b15620013df57604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff82165f908152607f60205260409020600180820154600160e81b900460ff16151590036200142557604051633b8d3d9960e01b815260040160405180910390fd5b60018101805460ff60e81b1916600160e81b17905560405163ffffffff8416907f4710d2ee567ef1ed6eb2f651dde4589524bcf7cebc62147a99b281cc836e7e44905f90a2505050565b7fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd086200149b8162002fc1565b63ffffffff88161580620014ba5750607e5463ffffffff908116908916115b15620014d957604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff88165f908152607f60205260409020600180820154600160e81b900460ff16151590036200151f57604051633b8d3d9960e01b815260040160405180910390fd5b63ffffffff6001600160401b03891611156200154e57604051634c753f5760e01b815260040160405180910390fd5b6001600160401b0388165f9081526083602052604090205463ffffffff16156200158b576040516337c8fe0960e11b815260040160405180910390fd5b608080545f91908290620015a59063ffffffff1662004f76565b825463ffffffff8281166101009490940a93840293021916919091179091558254604080515f80825260208201928390529394506001600160a01b03909216913091620015f29062004862565b620016009392919062004f9b565b604051809103905ff0801580156200161a573d5f803e3d5ffd5b5090508160835f8c6001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508160825f836001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8463ffffffff1663ffffffff1681526020019081526020015f20905081815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508360010160149054906101000a90046001600160401b03168160010160146101000a8154816001600160401b0302191690836001600160401b03160217905550836001015f9054906101000a90046001600160a01b0316816001015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508a815f0160146101000a8154816001600160401b0302191690836001600160401b031602179055508360020154816002015f806001600160401b031681526020019081526020015f20819055508b63ffffffff168160070160086101000a8154816001600160401b0302191690836001600160401b0316021790555083600101601c9054906101000a900460ff168160070160106101000a81548160ff021916908360ff1602179055508263ffffffff167f194c983456df6701c6a50830b90fe80e72b823411d0d524970c9590dc277a6418d848e8c6040516200187e949392919063ffffffff9490941684526001600160a01b0392831660208501526001600160401b0391909116604084015216606082015260800190565b60405180910390a2604051633892b81160e11b81526001600160a01b03831690637125702290620018be908d908d9088908e908e908e9060040162004fd1565b5f604051808303815f87803b158015620018d6575f80fd5b505af1158015620018e9573d5f803e3d5ffd5b50505050505050505050505050505050565b63ffffffff86165f9081526081602052604090206060906200192290878787878762003ada565b979650505050505050565b606f5460ff16156200195257604051630bc011ff60e21b815260040160405180910390fd5b63ffffffff88165f9081526081602090815260408083206084546001600160401b038a811686526003830190945291909320600101544292620019a092600160c01b90048116911662004f32565b6001600160401b03161115620019c957604051638a0704d360e01b815260040160405180910390fd5b6103e8620019d8888862005033565b6001600160401b0316111562001a0157604051635acfba9d60e11b815260040160405180910390fd5b62001a1381898989898989896200335b565b62001a1f818762003c31565b6085546001600160401b03165f0362001b275760068101805467ffffffffffffffff60401b1916600160401b6001600160401b038981169182029290921783555f9081526002840160205260409020869055600583018790559054600160801b9004161562001a9a576006810180546001600160801b031690555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62001ad362002530565b6040518263ffffffff1660e01b815260040162001af291815260200190565b5f604051808303815f87803b15801562001b0a575f80fd5b505af115801562001b1d573d5f803e3d5ffd5b5050505062001bf9565b62001b328162003e28565b600681018054600160801b90046001600160401b031690601062001b568362005056565b82546001600160401b039182166101009390930a92830292820219169190911790915560408051608081018252428316815289831660208083019182528284018b8152606084018b81526006890154600160801b900487165f90815260048a01909352949091209251835492518616600160401b026fffffffffffffffffffffffffffffffff199093169516949094171781559151600183015551600290910155505b604080516001600160401b038816815260208101869052908101869052339063ffffffff8b16907faac1e7a157b259544ebacd6e8a82ae5d6c8f174e12aa48696277bcc9a661f0b49060600160405180910390a3505050505050505050565b606f5460ff161562001c7d57604051630bc011ff60e21b815260040160405180910390fd5b63ffffffff88165f90815260816020526040902062001ca3818989898989898962002fcd565b6001600160401b0387165f9081526004820160209081526040918290206002015482519081529081018590527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a162001d046200395a565b505050505050505050565b335f9081527ff14f5a8ad59d90593602e905b358229bff5ceea677d5bf0f5a1701793550a9a6602052604090205460ff1615801562001dc35750336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562001d91573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001db7919062005074565b6001600160a01b031614155b1562001de257604051630d03687f60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526082602052604081205463ffffffff169081900362001e22576040516374a086a360e01b815260040160405180910390fd5b63ffffffff81165f90815260816020526040902060068101546001600160401b039081169084168111158062001e6f575060068201546001600160401b03600160401b9091048116908516105b1562001e8e5760405163cb23ebdf60e01b815260040160405180910390fd5b805b846001600160401b0316816001600160401b03161462001f32576001600160401b038082165f908152600385016020526040902060010154600160401b9004811690861681101562001ef557604051639753965f60e01b815260040160405180910390fd5b6001600160401b039091165f908152600384016020526040812090815560010180546fffffffffffffffffffffffffffffffff1916905562001e90565b60068301805467ffffffffffffffff19166001600160401b03871617905562001f5c858362005033565b608480545f9062001f789084906001600160401b031662005033565b82546101009290920a6001600160401b038181021990931691831602179091556006850154600160801b90041615905062002037575f62001fb98462002f52565b600685015490915062001fdd90600160401b90046001600160401b03168262005033565b6084805460089062002001908490600160401b90046001600160401b031662005033565b82546001600160401b039182166101009390930a928302919092021990911617905550506006830180546001600160801b031690555b6001600160401b0385165f8181526003850160205260409081902054905163334d6f6760e11b8152600481019290925260248201526001600160a01b0387169063669adece906044015f604051808303815f87803b15801562002098575f80fd5b505af1158015620020ab573d5f803e3d5ffd5b505050506001600160401b0385165f81815260038501602090815260409182902054915191825263ffffffff8716917f80a6d395a55aed8126079cb8247f0a6848b1440ca2cdca3b4386f250c3529402910160405180910390a3505050505050565b6040516370a0823160e01b81523060048201525f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801562002174573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200219a919062005092565b6084549091505f90620021c0906001600160401b03600160401b82048116911662005033565b6001600160401b03169050805f03620021db575f9250505090565b620021e78183620050be565b9250505090565b606f545f9060ff16156200221557604051630bc011ff60e21b815260040160405180910390fd5b335f9081526082602052604081205463ffffffff16908190036200224c576040516371653c1560e01b815260040160405180910390fd5b836001600160401b03165f036200227657604051632590ccf960e01b815260040160405180910390fd5b63ffffffff81165f9081526081602052604081206084805491928792620022a89084906001600160401b031662004f32565b82546101009290920a6001600160401b0381810219909316918316021790915560068301541690505f620022dd878362004f32565b6006840180546001600160401b0380841667ffffffffffffffff199092168217909255604080516060810182528a815242841660208083019182528886168385019081525f95865260038b0190915292909320905181559151600192909201805491518416600160401b026fffffffffffffffffffffffffffffffff1990921692909316919091171790559050620023758362003e28565b6040516001600160401b038216815263ffffffff8516907f1d9f30260051d51d70339da239ea7b080021adcaabfa71c9b0ea339a20cf9a259060200160405180910390a29695505050505050565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620023ef8162002fc1565b606f5460ff166200242a576085546001600160401b03908116908316106200242a5760405163048a05a960e41b815260040160405180910390fd5b6085805467ffffffffffffffff19166001600160401b0384169081179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c75906020016200114f565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620024a68162002fc1565b62015180826001600160401b03161115620024d457604051631c0cfbfd60e31b815260040160405180910390fd5b6085805467ffffffffffffffff60401b1916600160401b6001600160401b038516908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c28906020016200114f565b6080545f9063ffffffff168082036200254a57505f919050565b5f816001600160401b0381111562002566576200256662004aba565b60405190808252806020026020018201604052801562002590578160200160208202803683370190505b5090505f5b82811015620026005760815f620025ae836001620050d4565b63ffffffff1663ffffffff1681526020019081526020015f2060050154828281518110620025e057620025e0620050ea565b602090810291909101015280620025f781620050fe565b91505062002595565b505f60205b8360011462002858575f6200261c60028662005119565b62002629600287620050be565b620026359190620050d4565b90505f816001600160401b0381111562002653576200265362004aba565b6040519080825280602002602001820160405280156200267d578160200160208202803683370190505b5090505f5b828110156200280457620026986001846200512f565b81148015620026b35750620026af60028862005119565b6001145b156200273b5785620026c782600262004f5c565b81518110620026da57620026da620050ea565b602002602001015185604051602001620026fe929190918252602082015260400190565b60405160208183030381529060405280519060200120828281518110620027295762002729620050ea565b602002602001018181525050620027ef565b856200274982600262004f5c565b815181106200275c576200275c620050ea565b60200260200101518682600262002774919062004f5c565b62002781906001620050d4565b81518110620027945762002794620050ea565b6020026020010151604051602001620027b7929190918252602082015260400190565b60405160208183030381529060405280519060200120828281518110620027e257620027e2620050ea565b6020026020010181815250505b80620027fb81620050fe565b91505062002682565b50809450819550838460405160200162002828929190918252602082015260400190565b60405160208183030381529060405280519060200120935082806200284d9062005145565b935050505062002605565b5f835f815181106200286e576200286e620050ea565b602002602001015190505f5b82811015620028ee57604080516020810184905290810185905260600160408051601f19818403018152828252805160209182012090830187905290820186905292506060016040516020818303038152906040528051906020012093508080620028e590620050fe565b9150506200287a565b5095945050505050565b7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac620029248162002fc1565b6200293184848462003ef1565b50505050565b7f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb620029638162002fc1565b683635c9adc5dea000008211806200297e5750633b9aca0082105b156200299d57604051638586952560e01b815260040160405180910390fd5b60868290556040518281527ffb383653f53ee079978d0c9aff7aeff04a10166ce244cca9c9f9d8d96bed45b2906020016200114f565b5f82815260346020526040902060010154620029ef8162002fc1565b6200108c838362003a58565b7f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f462002a278162002fc1565b6087805467ffffffffffffffff1916426001600160401b031617905560408051636de0b4bb60e11b815290517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163dbc16976916004808301925f92919082900301818387803b15801562002aa3575f80fd5b505af115801562002ab6573d5f803e3d5ffd5b5050505062002ac4620041f6565b50565b336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562002b0f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002b35919062005074565b6001600160a01b03161462002b5d5760405163696072e960e01b815260040160405180910390fd5b6001600160a01b0382165f9081526082602090815260408083205463ffffffff1683526081909152902060068101546001600160401b03808216600160401b909204161462002bbf5760405163664316a560e11b815260040160405180910390fd5b600781015463ffffffff8316600160401b9091046001600160401b03161062002bfb57604051633e37e23360e01b815260040160405180910390fd5b604080515f8152602081019091526200108c908490849062003ef1565b7f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e62002c448162002fc1565b6001600160401b0384165f9081526083602052604090205463ffffffff161562002c81576040516337c8fe0960e11b815260040160405180910390fd5b63ffffffff6001600160401b038516111562002cb057604051634c753f5760e01b815260040160405180910390fd5b6001600160a01b0387165f9081526082602052604090205463ffffffff161562002ced57604051630d409b9360e41b815260040160405180910390fd5b5f62002cfd88888888876200424e565b5f8080526002909101602052604090209390935550505050505050565b7fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f59062002d468162002fc1565b607e80545f9190829062002d609063ffffffff1662004f76565b91906101000a81548163ffffffff021916908363ffffffff160217905590506040518060c00160405280896001600160a01b03168152602001886001600160a01b03168152602001876001600160401b031681526020018660ff1681526020015f1515815260200185815250607f5f8363ffffffff1663ffffffff1681526020019081526020015f205f820151815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160146101000a8154816001600160401b0302191690836001600160401b03160217905550606082015181600101601c6101000a81548160ff021916908360ff160217905550608082015181600101601d6101000a81548160ff02191690831515021790555060a082015181600201559050508063ffffffff167fa2970448b3bd66ba7e524e7b2a5b9cf94fa29e32488fb942afdfe70dd4b77b5289898989898960405162002efc969594939291906200515d565b60405180910390a25050505050505050565b6085546001600160401b038281165f9081526004850160205260408120549092429262002f4092918116911662004f32565b6001600160401b031611159392505050565b60068101545f90600160801b90046001600160401b03161562002fa4575060068101546001600160401b03600160801b90910481165f9081526004909201602052604090912054600160401b90041690565b5060060154600160401b90046001600160401b031690565b919050565b62002ac481336200446e565b60078801545f906001600160401b039081169087161015620030025760405163ead1340b60e01b815260040160405180910390fd5b6001600160401b03881615620030a25760068901546001600160401b03600160801b909104811690891611156200304c5760405163bb14c20560e01b815260040160405180910390fd5b506001600160401b038088165f90815260048a0160205260409020600281015481549092888116600160401b90920416146200309b57604051632bd2e3e760e01b815260040160405180910390fd5b5062003116565b506001600160401b0385165f90815260028901602052604090205480620030dc576040516324cbdcc360e11b815260040160405180910390fd5b60068901546001600160401b03600160401b909104811690871611156200311657604051630f2b74f160e11b815260040160405180910390fd5b60068901546001600160401b03600160801b909104811690881611806200314f5750876001600160401b0316876001600160401b031611155b8062003173575060068901546001600160401b03600160c01b909104811690881611155b15620031925760405163bfa7079f60e01b815260040160405180910390fd5b6001600160401b038781165f90815260048b016020526040902054600160401b9004811690861614620031d8576040516332a2a77f60e01b815260040160405180910390fd5b5f620031e98a888888868962003ada565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516200321f9190620051b4565b602060405180830381855afa1580156200323b573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019062003260919062005092565b6200326c919062005119565b60018c0154604080516020810182528381529051634890ed4560e11b81529293506001600160a01b0390911691639121da8a91620032b091889190600401620051d1565b602060405180830381865afa158015620032cc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620032f291906200520d565b62003310576040516309bde33960e01b815260040160405180910390fd5b6001600160401b0389165f90815260048c0160205260409020600201548590036200334e5760405163a47276bd60e01b815260040160405180910390fd5b5050505050505050505050565b5f80620033688a62002f52565b60078b01549091506001600160401b0390811690891610156200339e5760405163ead1340b60e01b815260040160405180910390fd5b6001600160401b03891615620034405760068a01546001600160401b03600160801b9091048116908a161115620033e85760405163bb14c20560e01b815260040160405180910390fd5b6001600160401b03808a165f90815260048c01602052604090206002810154815490945090918a8116600160401b90920416146200343957604051632bd2e3e760e01b815260040160405180910390fd5b50620034af565b6001600160401b0388165f90815260028b0160205260409020549150816200347b576040516324cbdcc360e11b815260040160405180910390fd5b806001600160401b0316886001600160401b03161115620034af57604051630f2b74f160e11b815260040160405180910390fd5b806001600160401b0316876001600160401b031611620034e25760405163b9b18f5760e01b815260040160405180910390fd5b5f620034f38b8a8a8a878b62003ada565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051620035299190620051b4565b602060405180830381855afa15801562003545573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906200356a919062005092565b62003576919062005119565b60018d0154604080516020810182528381529051634890ed4560e11b81529293506001600160a01b0390911691639121da8a91620035ba91899190600401620051d1565b602060405180830381865afa158015620035d6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620035fc91906200520d565b6200361a576040516309bde33960e01b815260040160405180910390fd5b5f62003627848b62005033565b90506200368087826001600160401b0316620036426200210d565b6200364e919062004f5c565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190620044b1565b80608460088282829054906101000a90046001600160401b0316620036a6919062004f32565b82546101009290920a6001600160401b03818102199093169183160217909155608480547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b428416021790558e546040516332c2d15360e01b8152918d166004830152602482018b90523360448301526001600160a01b031691506332c2d153906064015f604051808303815f87803b15801562003748575f80fd5b505af11580156200375b573d5f803e3d5ffd5b5050505050505050505050505050505050565b60068201546001600160401b03600160c01b9091048116908216111580620037ad575060068201546001600160401b03600160801b9091048116908216115b15620037cc5760405163d086b70b60e01b815260040160405180910390fd5b6001600160401b038181165f8181526004850160209081526040808320805460068901805467ffffffffffffffff60401b1916600160401b92839004909816918202979097178755600280830154828752908a0190945291909320919091556001820154600587015583546001600160c01b0316600160c01b909302929092179092557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d6200388862002530565b6040518263ffffffff1660e01b8152600401620038a791815260200190565b5f604051808303815f87803b158015620038bf575f80fd5b505af1158015620038d2573d5f803e3d5ffd5b505085546001600160a01b03165f90815260826020908152604091829020546002870154600188015484516001600160401b03898116825294810192909252818501529188166060830152915163ffffffff90921693507f581910eb7a27738945c2f00a91f2284b2d6de9d4e472b12f901c2b0df045e21b925081900360800190a250505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b158015620039b3575f80fd5b505af1158015620039c6573d5f803e3d5ffd5b50505050620012356200451a565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff1662001295575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff161562001295575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001600160401b038086165f818152600389016020526040808220549388168252902054606092911580159062003b0f575081155b1562003b2e5760405163340c614f60e11b815260040160405180910390fd5b8062003b4d576040516366385b5160e01b815260040160405180910390fd5b62003b588462004576565b62003b76576040516305dae44f60e21b815260040160405180910390fd5b885460018a01546040516bffffffffffffffffffffffff193360601b16602082015260348101889052605481018590527fffffffffffffffff00000000000000000000000000000000000000000000000060c08c811b82166074840152600160a01b94859004811b8216607c84015293909204831b82166084820152608c810187905260ac810184905260cc81018990529189901b1660ec82015260f401604051602081830303815290604052925050509695505050505050565b5f62003c3d8362002f52565b9050815f8062003c4e848462005033565b6085546001600160401b0391821692505f9162003c7491600160401b900416426200512f565b90505b846001600160401b0316846001600160401b03161462003cfd576001600160401b038085165f9081526003890160205260409020600181015490911682101562003cd8576001810154600160401b90046001600160401b0316945062003cf6565b62003ce4868662005033565b6001600160401b031693505062003cfd565b5062003c77565b5f62003d0a84846200512f565b90508381101562003d6857808403600c811162003d28578062003d2b565b600c5b9050806103e80a81608560109054906101000a900461ffff1661ffff160a608654028162003d5d5762003d5d620050aa565b046086555062003ddf565b838103600c811162003d7b578062003d7e565b600c5b90505f816103e80a82608560109054906101000a900461ffff1661ffff160a670de0b6b3a7640000028162003db75762003db7620050aa565b04905080608654670de0b6b3a7640000028162003dd85762003dd8620050aa565b0460865550505b683635c9adc5dea00000608654111562003e0657683635c9adc5dea0000060865562003e1e565b633b9aca00608654101562003e1e57633b9aca006086555b5050505050505050565b60068101546001600160401b03600160c01b82048116600160801b90920416111562002ac45760068101545f9062003e7290600160c01b90046001600160401b0316600162004f32565b905062003e80828262002f0e565b15620012955760068201545f9060029062003ead908490600160801b90046001600160401b031662005033565b62003eb991906200522e565b62003ec5908362004f32565b905062003ed3838262002f0e565b1562003ee5576200108c83826200376e565b6200108c83836200376e565b63ffffffff8216158062003f105750607e5463ffffffff908116908316115b1562003f2f57604051637512e5cb60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526082602052604081205463ffffffff169081900362003f6f576040516374a086a360e01b815260040160405180910390fd5b63ffffffff8181165f908152608160205260409020600781015490918516600160401b9091046001600160401b03160362003fbd57604051634f61d51960e01b815260040160405180910390fd5b63ffffffff84165f908152607f60205260409020600180820154600160e81b900460ff16151590036200400357604051633b8d3d9960e01b815260040160405180910390fd5b60018101546007830154600160801b900460ff908116600160e01b90920416146200404157604051635aa0d5f160e11b815260040160405180910390fd5b6001818101805491840180546001600160a01b0390931673ffffffffffffffffffffffffffffffffffffffff1984168117825591547fffffffff00000000000000000000000000000000000000000000000000000000909316909117600160a01b928390046001600160401b0390811690930217905560078301805467ffffffffffffffff60401b191663ffffffff8816600160401b021790556006830154600160c01b81048216600160801b909104909116146200411357604051639d59507b60e01b815260040160405180910390fd5b5f6200411f8462000c6c565b60078401805467ffffffffffffffff19166001600160401b038316179055825460405163278f794360e11b81529192506001600160a01b0389811692634f1ef2869262004173921690899060040162005256565b5f604051808303815f87803b1580156200418b575f80fd5b505af11580156200419e573d5f803e3d5ffd5b50506040805163ffffffff8a811682526001600160401b0386166020830152881693507ff585e04c05d396901170247783d3e5f0ee9c1df23072985b50af089f5e48b19d92500160405180910390a250505050505050565b606f5460ff166200421a57604051635386698160e01b815260040160405180910390fd5b606f805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b608080545f9182918290620042699063ffffffff1662004f76565b91906101000a81548163ffffffff021916908363ffffffff160217905590508060835f866001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508060825f896001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff16021790555060815f8263ffffffff1663ffffffff1681526020019081526020015f20915086825f015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550848260010160146101000a8154816001600160401b0302191690836001600160401b0316021790555085826001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555083825f0160146101000a8154816001600160401b0302191690836001600160401b03160217905550828260070160106101000a81548160ff021916908360ff1602179055508063ffffffff167fadfc7d56f7e39b08b321534f14bfb135ad27698f7d2f5ad0edc2356ea9a3f850868987875f6040516200445c9594939291906001600160401b0395861681526001600160a01b03949094166020850152918416604084015260ff166060830152909116608082015260a00190565b60405180910390a25095945050505050565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff166200129557604051637615be1f60e11b815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b1790526200108c908490620045fa565b606f5460ff16156200453f57604051630bc011ff60e21b815260040160405180910390fd5b606f805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b5f67ffffffff000000016001600160401b038316108015620045ac575067ffffffff00000001604083901c6001600160401b0316105b8015620045cd575067ffffffff00000001608083901c6001600160401b0316105b8015620045e5575067ffffffff0000000160c083901c105b15620045f357506001919050565b505f919050565b5f62004650826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620046d69092919063ffffffff16565b8051909150156200108c57808060200190518101906200467191906200520d565b6200108c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084015b60405180910390fd5b6060620046e684845f85620046ee565b949350505050565b606082471015620047515760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401620046cd565b5f80866001600160a01b031685876040516200476e9190620051b4565b5f6040518083038185875af1925050503d805f8114620047aa576040519150601f19603f3d011682016040523d82523d5f602084013e620047af565b606091505b50915091506200192287838387606083156200482f5782515f0362004827576001600160a01b0385163b620048275760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620046cd565b5081620046e6565b620046e68383815115620048465781518083602001fd5b8060405162461bcd60e51b8152600401620046cd919062004ce1565b61091d806200527a83390190565b803563ffffffff8116811462002fbc575f80fd5b80356001600160401b038116811462002fbc575f80fd5b5f8060408385031215620048ad575f80fd5b620048b88362004870565b9150620048c86020840162004884565b90509250929050565b5f60208284031215620048e2575f80fd5b62000c638262004870565b80610300810183101562000c66575f80fd5b5f805f805f805f806103e0898b03121562004918575f80fd5b620049238962004870565b97506200493360208a0162004884565b96506200494360408a0162004884565b95506200495360608a0162004884565b94506200496360808a0162004884565b935060a0890135925060c08901359150620049828a60e08b01620048ed565b90509295985092959890939650565b6001600160a01b038116811462002ac4575f80fd5b5f805f805f805f806103e0898b031215620049bf575f80fd5b620049ca8962004870565b9750620049da60208a0162004884565b9650620049ea60408a0162004884565b9550620049fa60608a0162004884565b94506080890135935060a0890135925060c089013562004a1a8162004991565b9150620049828a60e08b01620048ed565b5f6020828403121562004a3c575f80fd5b813561ffff8116811462004a4e575f80fd5b9392505050565b5f6020828403121562004a66575f80fd5b5035919050565b5f806040838503121562004a7f575f80fd5b82359150602083013562004a938162004991565b809150509250929050565b5f6020828403121562004aaf575f80fd5b62000c638262004884565b634e487b7160e01b5f52604160045260245ffd5b5f6001600160401b038084111562004aea5762004aea62004aba565b604051601f8501601f19908116603f0116810190828211818310171562004b155762004b1562004aba565b8160405280935085815286868601111562004b2e575f80fd5b858560208301375f602087830101525050509392505050565b5f82601f83011262004b57575f80fd5b62000c638383356020850162004ace565b5f805f805f805f60e0888a03121562004b7f575f80fd5b62004b8a8862004870565b965062004b9a6020890162004884565b9550604088013562004bac8162004991565b9450606088013562004bbe8162004991565b9350608088013562004bd08162004991565b925060a08801356001600160401b038082111562004bec575f80fd5b62004bfa8b838c0162004b47565b935060c08a013591508082111562004c10575f80fd5b5062004c1f8a828b0162004b47565b91505092959891949750929550565b5f805f805f8060c0878903121562004c44575f80fd5b62004c4f8762004870565b955062004c5f6020880162004884565b945062004c6f6040880162004884565b9350606087013592506080870135915060a087013590509295509295509295565b5f5b8381101562004cac57818101518382015260200162004c92565b50505f910152565b5f815180845262004ccd81602086016020860162004c90565b601f01601f19169290920160200192915050565b602081525f62000c63602083018462004cb4565b5f806040838503121562004d07575f80fd5b8235620048b88162004991565b5f806040838503121562004d26575f80fd5b62004d318362004884565b946020939093013593505050565b5f805f6060848603121562004d52575f80fd5b833562004d5f8162004991565b925062004d6f6020850162004870565b915060408401356001600160401b0381111562004d8a575f80fd5b8401601f8101861362004d9b575f80fd5b62004dac8682356020840162004ace565b9150509250925092565b5f6020828403121562004dc7575f80fd5b813562004a4e8162004991565b5f806040838503121562004de6575f80fd5b823562004df38162004991565b9150620048c86020840162004870565b803560ff8116811462002fbc575f80fd5b5f805f805f8060c0878903121562004e2a575f80fd5b863562004e378162004991565b9550602087013562004e498162004991565b945062004e596040880162004884565b935062004e696060880162004884565b92506080870135915062004e8060a0880162004e03565b90509295509295509295565b5f805f805f8060c0878903121562004ea2575f80fd5b863562004eaf8162004991565b9550602087013562004ec18162004991565b945062004ed16040880162004884565b935062004ee16060880162004e03565b92506080870135915060a08701356001600160401b0381111562004f03575f80fd5b62004f1189828a0162004b47565b9150509295509295509295565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b0381811683821601908082111562004f555762004f5562004f1e565b5092915050565b808202811582820484141762000c665762000c6662004f1e565b5f63ffffffff80831681810362004f915762004f9162004f1e565b6001019392505050565b5f6001600160a01b0380861683528085166020840152506060604083015262004fc8606083018462004cb4565b95945050505050565b5f6001600160a01b038089168352808816602084015263ffffffff8716604084015280861660608401525060c060808301526200501260c083018562004cb4565b82810360a084015262005026818562004cb4565b9998505050505050505050565b6001600160401b0382811682821603908082111562004f555762004f5562004f1e565b5f6001600160401b0380831681810362004f915762004f9162004f1e565b5f6020828403121562005085575f80fd5b815162004a4e8162004991565b5f60208284031215620050a3575f80fd5b5051919050565b634e487b7160e01b5f52601260045260245ffd5b5f82620050cf57620050cf620050aa565b500490565b8082018082111562000c665762000c6662004f1e565b634e487b7160e01b5f52603260045260245ffd5b5f6001820162005112576200511262004f1e565b5060010190565b5f826200512a576200512a620050aa565b500690565b8181038181111562000c665762000c6662004f1e565b5f8162005156576200515662004f1e565b505f190190565b5f6001600160a01b0380891683528088166020840152506001600160401b038616604083015260ff8516606083015283608083015260c060a0830152620051a860c083018462004cb4565b98975050505050505050565b5f8251620051c781846020870162004c90565b9190910192915050565b6103208101610300808584378201835f5b600181101562005203578151835260209283019290910190600101620051e2565b5050509392505050565b5f602082840312156200521e575f80fd5b8151801515811462004a4e575f80fd5b5f6001600160401b03808416806200524a576200524a620050aa565b92169190910492915050565b6001600160a01b0383168152604060208201525f620046e6604083018462004cb456fe60a06040526040516200091d3803806200091d833981016040819052620000269162000375565b828162000034828262000060565b50506001600160a01b038216608052620000576200005160805190565b620000c5565b5050506200046c565b6200006b8262000136565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000b757620000b28282620001b5565b505050565b620000c16200022e565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620001065f80516020620008fd833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001338162000250565b50565b806001600160a01b03163b5f036200017157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b031684604051620001d391906200044f565b5f60405180830381855af49150503d805f81146200020d576040519150601f19603f3d011682016040523d82523d5f602084013e62000212565b606091505b5090925090506200022585838362000291565b95945050505050565b34156200024e5760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b0381166200027b57604051633173bdd160e11b81525f600482015260240162000168565b805f80516020620008fd83398151915262000194565b606082620002aa57620002a482620002f7565b620002f0565b8151158015620002c257506001600160a01b0384163b155b15620002ed57604051639996b31560e01b81526001600160a01b038516600482015260240162000168565b50805b9392505050565b805115620003085780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811462000338575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b838110156200036d57818101518382015260200162000353565b50505f910152565b5f805f6060848603121562000388575f80fd5b620003938462000321565b9250620003a36020850162000321565b60408501519092506001600160401b0380821115620003c0575f80fd5b818601915086601f830112620003d4575f80fd5b815181811115620003e957620003e96200033d565b604051601f8201601f19908116603f011681019083821181831017156200041457620004146200033d565b816040528281528960208487010111156200042d575f80fd5b6200044083602083016020880162000351565b80955050505050509250925092565b5f82516200046281846020870162000351565b9190910192915050565b608051610479620004845f395f601001526104795ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610081575f357fffffffff000000000000000000000000000000000000000000000000000000001663278f794360e11b1461007957610077610085565b565b610077610095565b6100775b6100776100906100c3565b6100fa565b5f806100a43660048184610313565b8101906100b1919061034e565b915091506100bf8282610118565b5050565b5f6100f57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e808015610114573d5ff35b3d5ffd5b61012182610172565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561016a5761016582826101fa565b505050565b6100bf61026c565b806001600160a01b03163b5f036101ac57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516102169190610417565b5f60405180830381855af49150503d805f811461024e576040519150601f19603f3d011682016040523d82523d5f602084013e610253565b606091505b509150915061026385838361028b565b95945050505050565b34156100775760405163b398979f60e01b815260040160405180910390fd5b6060826102a05761029b826102ea565b6102e3565b81511580156102b757506001600160a01b0384163b155b156102e057604051639996b31560e01b81526001600160a01b03851660048201526024016101a3565b50805b9392505050565b8051156102fa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f8085851115610321575f80fd5b8386111561032d575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561035f575f80fd5b82356001600160a01b0381168114610375575f80fd5b9150602083013567ffffffffffffffff80821115610391575f80fd5b818501915085601f8301126103a4575f80fd5b8135818111156103b6576103b661033a565b604051601f8201601f19908116603f011681019083821181831017156103de576103de61033a565b816040528281528860208487010111156103f6575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610436576020818601810151858301520161041c565b505f92019182525091905056fea26469706673582212201862559c7a1a6f6ad5955fa13172986128c855ab779db998ecea424bd4dfebf064736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103a2646970667358221220f7c2380164dc44ad0ccfb54de8868b9fa4ea4c441164d6c2b61465340c34086064736f6c63430008140033", + "bytecode": "0x60e060405234801562000010575f80fd5b506040516200523038038062005230833981016040819052620000339162000136565b6001600160a01b0380841660805282811660c052811660a052620000566200005f565b50505062000187565b5f54610100900460ff1615620000cb5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811610156200011c575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b038116811462000133575f80fd5b50565b5f805f6060848603121562000149575f80fd5b835162000156816200011e565b602085015190935062000169816200011e565b60408501519092506200017c816200011e565b809150509250925092565b60805160a05160c05161504d620001e35f395f818161089c01528181611e260152612e5a01525f818161072d015281816128bf0152612f2601525f81816107df01528181610a2e0152818161153e0152611686015261504d5ff3fe608060405234801562000010575f80fd5b5060043610620002fc575f3560e01c80638fd88cc211620001a3578063c4c928c211620000fb578063dbc16976116200009f578063e46761c41162000077578063e46761c41462000896578063f4e9267514620008be578063f9c4c2ae14620008cf575f80fd5b8063dbc16976146200085a578063dde0ff771462000864578063dfdb8c5e146200087f575f80fd5b8063d5073f6f11620000d3578063d5073f6f1462000801578063d547741f1462000818578063d8905812146200082f575f80fd5b8063c4c928c2146200079a578063ceee281d14620007b1578063d02103ca14620007d9575f80fd5b80639e36c5651162000163578063a3c573eb116200013b578063a3c573eb1462000727578063abcb51981462000768578063c1acbc34146200077f575f80fd5b80639e36c56514620006fe578063a217fddf1462000715578063a2967d99146200071d575f80fd5b80638fd88cc2146200067457806391d14854146200068b57806397bf07e814620006c657806399f5634e14620006dd5780639a908e7314620006e7575f80fd5b8063477fa2701162000257578063727885e911620002175780637fb6e76a11620001ef5780637fb6e76a146200062b5780638129fc1c14620006535780638875f03c146200065d575f80fd5b8063727885e914620005c857806374d9c24414620005df5780637975fcfe1462000605575f80fd5b8063477fa27014620004db57806355a71ee014620004e457806360469169146200052757806365c0504d14620005315780637222020f14620005b1575f80fd5b80632072f6c511620002bf5780632f2ff15d11620002975780632f2ff15d146200049957806330c27dde14620004b057806336568abe14620004c4575f80fd5b80632072f6c514620003a7578063248a9ca314620003b15780632528016914620003e5575f80fd5b8063066ec012146200030057806311f6b28714620003315780631489ed10146200034857806315064c9614620003615780631796a1ae1462000380575b5f80fd5b60845462000314906001600160401b031681565b6040516001600160401b0390911681526020015b60405180910390f35b6200031462000342366004620039c5565b620008f5565b6200035f6200035936600462003a14565b62000924565b005b606f546200036f9060ff1681565b604051901515815260200162000328565b607e54620003919063ffffffff1681565b60405163ffffffff909116815260200162000328565b6200035f62000b14565b620003d6620003c236600462003aae565b5f9081526034602052604090206001015490565b60405190815260200162000328565b62000465620003f636600462003ac6565b60408051606080820183525f808352602080840182905292840181905263ffffffff959095168552608182528285206001600160401b03948516865260030182529382902082519485018352805485526001015480841691850191909152600160401b90049091169082015290565b60408051825181526020808401516001600160401b0390811691830191909152928201519092169082015260600162000328565b6200035f620004aa36600462003afc565b62000bf0565b60875462000314906001600160401b031681565b6200035f620004d536600462003afc565b62000c1d565b608654620003d6565b620003d6620004f536600462003ac6565b63ffffffff82165f9081526081602090815260408083206001600160401b038516845260020190915290205492915050565b620003d662000c57565b6200059c62000542366004620039c5565b607f6020525f908152604090208054600182015460028301546003909301546001600160a01b0392831693928216926001600160401b03600160a01b8404169260ff600160e01b8204811693600160e81b90920416919087565b60405162000328979695949392919062003b62565b6200035f620005c2366004620039c5565b62000c6e565b6200035f620005d936600462003c64565b62000d64565b620005f6620005f0366004620039c5565b620011f2565b60405162000328919062003d2a565b6200061c6200061636600462003e36565b62001324565b60405162000328919062003ee9565b620003916200063c36600462003efd565b60836020525f908152604090205463ffffffff1681565b6200035f62001356565b6200035f6200066e36600462003f19565b6200149d565b6200035f6200068536600462003fbf565b62001753565b6200036f6200069c36600462003afc565b5f9182526034602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6200035f620006d736600462003fed565b62001aed565b620003d662001e05565b62000314620006f83660046200406f565b62001ee6565b6200061c6200070f3660046200409a565b620020e7565b620003d65f81565b620003d662002119565b6200074f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200162000328565b6200035f62000779366004620040d3565b620024e1565b6084546200031490600160801b90046001600160401b031681565b6200035f620007ab3660046200416f565b6200275c565b62000391620007c2366004620041e6565b60826020525f908152604090205463ffffffff1681565b6200074f7f000000000000000000000000000000000000000000000000000000000000000081565b6200035f6200081236600462003aae565b6200279b565b6200035f6200082936600462003afc565b6200283d565b6200061c6040518060400160405280600b81526020016a70657373696d697374696360a81b81525081565b6200035f62002865565b6084546200031490600160401b90046001600160401b031681565b6200035f6200089036600462004204565b62002931565b6200074f7f000000000000000000000000000000000000000000000000000000000000000081565b608054620003919063ffffffff1681565b620008e6620008e0366004620039c5565b62002a81565b60405162000328919062004233565b63ffffffff81165f90815260816020526040812060060154600160401b90046001600160401b03165b92915050565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4620009508162002be1565b6001600160401b03881615620009795760405163306dfc5760e11b815260040160405180910390fd5b63ffffffff89165f908152608160205260408120906007820154600160801b900460ff166001811115620009b157620009b162003b2d565b14620009d0576040516390db0d0760e01b815260040160405180910390fd5b620009e18189898989898962002bed565b6006810180546fffffffffffffffff00000000000000001916600160401b6001600160401b038a16908102919091179091555f9081526002820160205260409020859055600581018690557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62000a6562002119565b6040518263ffffffff1660e01b815260040162000a8491815260200190565b5f604051808303815f87803b15801562000a9c575f80fd5b505af115801562000aaf573d5f803e3d5ffd5b5050604080516001600160401b038b1681526020810189905290810189905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d3906060015b60405180910390a350505050505050505050565b335f9081527f8875b94af5657a2903def9906d67a3f42d8a836d24b5602c00f00fc855339fcd602052604090205460ff1662000be457608454600160801b90046001600160401b0316158062000b955750608454429062000b8a9062093a8090600160801b90046001600160401b03166200435c565b6001600160401b0316115b8062000bc55750608754429062000bba9062093a80906001600160401b03166200435c565b6001600160401b0316115b1562000be45760405163692baaad60e11b815260040160405180910390fd5b62000bee62002f24565b565b5f8281526034602052604090206001015462000c0c8162002be1565b62000c18838362002f9e565b505050565b6001600160a01b038116331462000c4757604051630b4ad1cd60e31b815260040160405180910390fd5b62000c53828262003022565b5050565b5f608654606462000c69919062004386565b905090565b7fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd62000c9a8162002be1565b63ffffffff8216158062000cb95750607e5463ffffffff908116908316115b1562000cd857604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff82165f908152607f602052604090206001810154600160e81b900460ff161562000d1a57604051633b8d3d9960e01b815260040160405180910390fd5b60018101805460ff60e81b1916600160e81b17905560405163ffffffff8416907f4710d2ee567ef1ed6eb2f651dde4589524bcf7cebc62147a99b281cc836e7e44905f90a2505050565b7fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd0862000d908162002be1565b63ffffffff8816158062000daf5750607e5463ffffffff908116908916115b1562000dce57604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff88165f908152607f602052604090206001810154600160e81b900460ff161562000e1057604051633b8d3d9960e01b815260040160405180910390fd5b63ffffffff6001600160401b038916111562000e3f57604051634c753f5760e01b815260040160405180910390fd5b6001600160401b0388165f9081526083602052604090205463ffffffff161562000e7c576040516337c8fe0960e11b815260040160405180910390fd5b608080545f9190829062000e969063ffffffff16620043a0565b825463ffffffff8281166101009490940a93840293021916919091179091558254604080515f80825260208201928390529394506001600160a01b0390921691309162000ee390620039a3565b62000ef193929190620043c5565b604051809103905ff08015801562000f0b573d5f803e3d5ffd5b5090508160835f8c6001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508160825f836001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8463ffffffff1663ffffffff1681526020019081526020015f20905081815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508360010160149054906101000a90046001600160401b03168160010160146101000a8154816001600160401b0302191690836001600160401b03160217905550836001015f9054906101000a90046001600160a01b0316816001015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508a815f0160146101000a8154816001600160401b0302191690836001600160401b031602179055508360020154816002015f806001600160401b031681526020019081526020015f20819055508b63ffffffff168160070160086101000a8154816001600160401b0302191690836001600160401b0316021790555083600101601c9054906101000a900460ff168160070160106101000a81548160ff021916908360018111156200110b576200110b62003b2d565b0217905550600384015460098201556040805163ffffffff8e811682526001600160a01b0385811660208401526001600160401b038f16838501528b1660608301529151918516917f194c983456df6701c6a50830b90fe80e72b823411d0d524970c9590dc277a6419181900360800190a2604051633892b81160e11b81526001600160a01b03831690637125702290620011b5908d908d9088908e908e908e90600401620043f2565b5f604051808303815f87803b158015620011cd575f80fd5b505af1158015620011e0573d5f803e3d5ffd5b50505050505050505050505050505050565b60408051610180810182525f8082526020808301828152838501838152606085018481526080860185815260a0870186815260c0880187815260e089018881526101008a018981526101208b018a81526101408c018b90526101608c018b905263ffffffff8e168b5260819099529a90982080546001600160a01b038082168c52600160a01b918290046001600160401b0390811690995260018084015491821690985204871690945260058401549092526006830154808616909152600160401b9081900485169091526007820154808516909652850490921690955292939091600160801b900460ff1690811115620012f157620012f162003b2d565b9081600181111562001307576200130762003b2d565b905250600881015461014083015260090154610160820152919050565b63ffffffff86165f9081526081602052604090206060906200134b908787878787620030a4565b979650505050505050565b5f54600390610100900460ff161580156200137757505f5460ff8083169116105b620013ef5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805461ffff191660ff831617610100179055604080518082018252600b81526a70657373696d697374696360a81b602082015290517f50cadc0c001f05dd4b81db1e92b98d77e718fd2f103fb7b77293e867d329a4c291620014529162003ee9565b60405180910390a15f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4620014c98162002be1565b63ffffffff87165f90815260816020526040902060016007820154600160801b900460ff16600181111562001502576200150262003b2d565b146200152157604051633a64d97360e01b815260040160405180910390fd5b60405163ef4eeb3560e01b815263ffffffff881660048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef4eeb3590602401602060405180830381865afa1580156200158c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620015b2919062004454565b905080620015d35760405163a60721e160e01b815260040160405180910390fd5b5f620015e38a84848b8b620031fb565b6001840154600985015460405163020a49e360e51b81529293506001600160a01b03909116916341493c6091620016239185908b908b906004016200446c565b5f6040518083038186803b1580156200163a575f80fd5b505afa1580156200164d573d5f803e3d5ffd5b50506084805467ffffffffffffffff60801b1916600160801b426001600160401b031602179055505060058301889055600883018790557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d620016bd62002119565b6040518263ffffffff1660e01b8152600401620016dc91815260200190565b5f604051808303815f87803b158015620016f4575f80fd5b505af115801562001707573d5f803e3d5ffd5b5050604080515f80825260208201529081018b905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d39060600162000b00565b335f9081527ff14f5a8ad59d90593602e905b358229bff5ceea677d5bf0f5a1701793550a9a6602052604090205460ff16158015620018065750336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015620017d4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620017fa9190620044b9565b6001600160a01b031614155b156200182557604051630d03687f60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526082602052604081205463ffffffff169081900362001865576040516374a086a360e01b815260040160405180910390fd5b63ffffffff81165f908152608160205260408120906007820154600160801b900460ff1660018111156200189d576200189d62003b2d565b14620018bc576040516390db0d0760e01b815260040160405180910390fd5b60068101546001600160401b0390811690841681111580620018f5575060068201546001600160401b03600160401b9091048116908516105b15620019145760405163cb23ebdf60e01b815260040160405180910390fd5b805b846001600160401b0316816001600160401b031614620019b8576001600160401b038082165f908152600385016020526040902060010154600160401b900481169086168110156200197b57604051639753965f60e01b815260040160405180910390fd5b6001600160401b039091165f908152600384016020526040812090815560010180546fffffffffffffffffffffffffffffffff1916905562001916565b60068301805467ffffffffffffffff19166001600160401b038716179055620019e28583620044d7565b608480545f90620019fe9084906001600160401b0316620044d7565b82546101009290920a6001600160401b0381810219909316918316021790915586165f8181526003860160205260409081902054905163334d6f6760e11b8152600481019290925260248201526001600160a01b038816915063669adece906044015f604051808303815f87803b15801562001a78575f80fd5b505af115801562001a8b573d5f803e3d5ffd5b505050506001600160401b0385165f81815260038501602090815260409182902054915191825263ffffffff8716917f80a6d395a55aed8126079cb8247f0a6848b1440ca2cdca3b4386f250c3529402910160405180910390a3505050505050565b7f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e62001b198162002be1565b6001600160401b0385165f9081526083602052604090205463ffffffff161562001b56576040516337c8fe0960e11b815260040160405180910390fd5b63ffffffff6001600160401b038616111562001b8557604051634c753f5760e01b815260040160405180910390fd5b6001600160a01b0388165f9081526082602052604090205463ffffffff161562001bc257604051630d409b9360e41b815260040160405180910390fd5b608080545f9190829062001bdc9063ffffffff16620043a0565b91906101000a81548163ffffffff021916908363ffffffff160217905590508060835f886001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508060825f8b6001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8363ffffffff1663ffffffff1681526020019081526020015f20905089815f015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550878160010160146101000a8154816001600160401b0302191690836001600160401b0316021790555088816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555086815f0160146101000a8154816001600160401b0302191690836001600160401b03160217905550848160070160106101000a81548160ff0219169083600181111562001d665762001d6662003b2d565b0217905550600185600181111562001d825762001d8262003b2d565b0362001d9c57600981018490556005810186905562001daf565b5f80805260028201602052604090208690555b8163ffffffff167fd490df184152edba8455dac3228134939c71f8cb4c8f310c3145dec9037147ac898c8a895f8a60405162001df196959493929190620044fa565b60405180910390a250505050505050505050565b6040516370a0823160e01b81523060048201525f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801562001e6c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001e92919062004454565b6084549091505f9062001eb8906001600160401b03600160401b820481169116620044d7565b6001600160401b03169050805f0362001ed3575f9250505090565b62001edf81836200455b565b9250505090565b606f545f9060ff161562001f0d57604051630bc011ff60e21b815260040160405180910390fd5b335f9081526082602052604081205463ffffffff169081900362001f44576040516371653c1560e01b815260040160405180910390fd5b836001600160401b03165f0362001f6e57604051632590ccf960e01b815260040160405180910390fd5b63ffffffff81165f908152608160205260408120906007820154600160801b900460ff16600181111562001fa65762001fa662003b2d565b1462001fc5576040516390db0d0760e01b815260040160405180910390fd5b608480548691905f9062001fe49084906001600160401b03166200435c565b82546101009290920a6001600160401b0381810219909316918316021790915560068301541690505f6200201987836200435c565b6006840180546001600160401b0383811667ffffffffffffffff199092168217909255604080516060810182528a815242841660208083019182528886168385019081525f86815260038c018352859020935184559151600193909301805492518716600160401b026fffffffffffffffffffffffffffffffff199093169390961692909217179093555190815291925063ffffffff8616917f1d9f30260051d51d70339da239ea7b080021adcaabfa71c9b0ea339a20cf9a25910160405180910390a29695505050505050565b63ffffffff84165f9081526081602052604090206060906200210e908690868686620031fb565b90505b949350505050565b6080545f9063ffffffff168082036200213357505f919050565b5f816001600160401b038111156200214f576200214f62003bb6565b60405190808252806020026020018201604052801562002179578160200160208202803683370190505b5090505f5b82811015620021e95760815f6200219783600162004571565b63ffffffff1663ffffffff1681526020019081526020015f2060050154828281518110620021c957620021c962004587565b602090810291909101015280620021e0816200459b565b9150506200217e565b505f60205b8360011462002441575f62002205600286620045b6565b620022126002876200455b565b6200221e919062004571565b90505f816001600160401b038111156200223c576200223c62003bb6565b60405190808252806020026020018201604052801562002266578160200160208202803683370190505b5090505f5b82811015620023ed5762002281600184620045cc565b811480156200229c575062002298600288620045b6565b6001145b15620023245785620022b082600262004386565b81518110620022c357620022c362004587565b602002602001015185604051602001620022e7929190918252602082015260400190565b6040516020818303038152906040528051906020012082828151811062002312576200231262004587565b602002602001018181525050620023d8565b856200233282600262004386565b8151811062002345576200234562004587565b6020026020010151868260026200235d919062004386565b6200236a90600162004571565b815181106200237d576200237d62004587565b6020026020010151604051602001620023a0929190918252602082015260400190565b60405160208183030381529060405280519060200120828281518110620023cb57620023cb62004587565b6020026020010181815250505b80620023e4816200459b565b9150506200226b565b50809450819550838460405160200162002411929190918252602082015260400190565b60405160208183030381529060405280519060200120935082806200243690620045e2565b9350505050620021ee565b5f835f8151811062002457576200245762004587565b602002602001015190505f5b82811015620024d757604080516020810184905290810185905260600160408051601f19818403018152828252805160209182012090830187905290820186905292506060016040516020818303038152906040528051906020012093508080620024ce906200459b565b91505062002463565b5095945050505050565b7fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f5906200250d8162002be1565b607e80545f91908290620025279063ffffffff16620043a0565b91906101000a81548163ffffffff021916908363ffffffff160217905590506001808111156200255b576200255b62003b2d565b86600181111562002570576200257062003b2d565b036200259c57841562002596576040516363d722e760e01b815260040160405180910390fd5b620025bc565b8215620025bc576040516363d722e760e01b815260040160405180910390fd5b6040518060e001604052808a6001600160a01b03168152602001896001600160a01b03168152602001886001600160401b0316815260200187600181111562002609576200260962003b2d565b81525f602080830182905260408084018a9052606093840188905263ffffffff86168352607f825291829020845181546001600160a01b0391821673ffffffffffffffffffffffffffffffffffffffff199091161782559185015160018281018054958801516001600160401b0316600160a01b026001600160e01b0319909616929094169190911793909317808355938501519093909260ff60e01b1990911690600160e01b908490811115620026c557620026c562003b2d565b02179055506080820151600182018054911515600160e81b0260ff60e81b1990921691909117905560a0820151600282015560c09091015160039091015560405163ffffffff8216907f9eaf2ecbddb14889c9e141a63175c55ac25e0cd7cdea312cdfbd0397976b383a9062002749908c908c908c908c908c908c908c90620045fa565b60405180910390a2505050505050505050565b7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac620027888162002be1565b62002795848484620032e0565b50505050565b7f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb620027c78162002be1565b683635c9adc5dea00000821180620027e25750633b9aca0082105b156200280157604051638586952560e01b815260040160405180910390fd5b60868290556040518281527ffb383653f53ee079978d0c9aff7aeff04a10166ce244cca9c9f9d8d96bed45b29060200160405180910390a15050565b5f82815260346020526040902060010154620028598162002be1565b62000c18838362003022565b7f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f4620028918162002be1565b6087805467ffffffffffffffff1916426001600160401b031617905560408051636de0b4bb60e11b815290517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163dbc16976916004808301925f92919082900301818387803b1580156200290d575f80fd5b505af115801562002920573d5f803e3d5ffd5b505050506200292e620035c6565b50565b336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002978573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200299e9190620044b9565b6001600160a01b031614620029c65760405163696072e960e01b815260040160405180910390fd5b6001600160a01b0382165f9081526082602090815260408083205463ffffffff1683526081909152902060068101546001600160401b03808216600160401b909204161462002a285760405163664316a560e11b815260040160405180910390fd5b600781015463ffffffff8316600160401b9091046001600160401b03161062002a6457604051633e37e23360e01b815260040160405180910390fd5b604080515f81526020810190915262000c189084908490620032e0565b62002ae660408051610180810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290529061016082015290565b63ffffffff82165f9081526081602090815260409182902080546001600160a01b038082168652600160a01b918290046001600160401b039081169487019490945260018084015491821695870195909552048216606085015260058101546080850152600681015480831660a0860152600160401b808204841660c0870152600160801b808304851660e0880152600160c01b9092048416610100870152600783015480851661012088015290810490931661014086015290926101608501929190910460ff169081111562002bc15762002bc162003b2d565b9081600181111562002bd75762002bd762003b2d565b8152505050919050565b6200292e81336200361e565b5f8062002c0c89600601546001600160401b03600160401b9091041690565b60078a01549091506001600160401b03908116908916101562002c425760405163ead1340b60e01b815260040160405180910390fd5b6001600160401b0388165f90815260028a01602052604090205491508162002c7d576040516324cbdcc360e11b815260040160405180910390fd5b806001600160401b0316886001600160401b0316111562002cb157604051630f2b74f160e11b815260040160405180910390fd5b806001600160401b0316876001600160401b03161162002ce45760405163b9b18f5760e01b815260040160405180910390fd5b5f62002cf58a8a8a8a878b620030a4565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028360405162002d2b91906200465d565b602060405180830381855afa15801562002d47573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019062002d6c919062004454565b62002d789190620045b6565b60018c0154604080516020810182528381529051634890ed4560e11b81529293506001600160a01b0390911691639121da8a9162002dbc918991906004016200467a565b602060405180830381865afa15801562002dd8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002dfe9190620046b6565b62002e1c576040516309bde33960e01b815260040160405180910390fd5b5f62002e29848b620044d7565b905062002e8287826001600160401b031662002e4462001e05565b62002e50919062004386565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016919062003661565b80608460088282829054906101000a90046001600160401b031662002ea891906200435c565b82546101009290920a6001600160401b038181021990931691831602179091556084805467ffffffffffffffff60801b1916600160801b428416021790558d546040516332c2d15360e01b8152918d166004830152602482018b90523360448301526001600160a01b031691506332c2d15390606401620011b5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562002f7d575f80fd5b505af115801562002f90573d5f803e3d5ffd5b5050505062000bee620036ca565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff1662000c53575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff161562000c53575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001600160401b038086165f8181526003890160205260408082205493881682529020546060929115801590620030d9575081155b15620030f85760405163340c614f60e11b815260040160405180910390fd5b8062003117576040516366385b5160e01b815260040160405180910390fd5b620031228462003726565b62003140576040516305dae44f60e21b815260040160405180910390fd5b885460018a01546040516bffffffffffffffffffffffff193360601b16602082015260348101889052605481018590527fffffffffffffffff00000000000000000000000000000000000000000000000060c08c811b82166074840152600160a01b94859004811b8216607c84015293909204831b82166084820152608c810187905260ac810184905260cc81018990529189901b1660ec82015260f401604051602081830303815290604052925050509695505050505050565b60605f855f015f9054906101000a90046001600160a01b03166001600160a01b031663ad1edf346040518163ffffffff1660e01b8152600401602060405180830381865afa15801562003250573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062003276919062004454565b60058701546008880154604080516020810193909352820152606081018790526001600160e01b031960e08a901b1660808201526084810182905260a4810186905260c4810185905290915060e40160405160208183030381529060405291505095945050505050565b63ffffffff82161580620032ff5750607e5463ffffffff908116908316115b156200331e57604051637512e5cb60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526082602052604081205463ffffffff16908190036200335e576040516374a086a360e01b815260040160405180910390fd5b63ffffffff8181165f908152608160205260409020600781015490918516600160401b9091046001600160401b031603620033ac57604051634f61d51960e01b815260040160405180910390fd5b63ffffffff84165f908152607f602052604090206001810154600160e81b900460ff1615620033ee57604051633b8d3d9960e01b815260040160405180910390fd5b600181810154600160e01b900460ff169081111562003411576200341162003b2d565b6007830154600160801b900460ff16600181111562003434576200343462003b2d565b146200345357604051635aa0d5f160e11b815260040160405180910390fd5b60018082018054918401805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03909416938417825591546001600160401b03600160a01b9182900416026001600160e01b031990921690921717905560038101546009830155600782018054600160401b63ffffffff8816026fffffffffffffffff0000000000000000199091161790555f620034ef84620008f5565b60078401805467ffffffffffffffff19166001600160401b038316179055825460405163278f794360e11b81529192506001600160a01b0389811692634f1ef28692620035439216908990600401620046d7565b5f604051808303815f87803b1580156200355b575f80fd5b505af11580156200356e573d5f803e3d5ffd5b50506040805163ffffffff8a811682526001600160401b0386166020830152881693507ff585e04c05d396901170247783d3e5f0ee9c1df23072985b50af089f5e48b19d92500160405180910390a250505050505050565b606f5460ff16620035ea57604051635386698160e01b815260040160405180910390fd5b606f805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff1662000c5357604051637615be1f60e11b815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b17905262000c18908490620037af565b606f5460ff1615620036ef57604051630bc011ff60e21b815260040160405180910390fd5b606f805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b5f67ffffffff000000016001600160401b0383161080156200375c575067ffffffff00000001604083901c6001600160401b0316105b80156200377d575067ffffffff00000001608083901c6001600160401b0316105b801562003795575067ffffffff0000000160c083901c105b15620037a357506001919050565b505f919050565b919050565b5f62003805826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620038879092919063ffffffff16565b80519091501562000c185780806020019051810190620038269190620046b6565b62000c185760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620013e6565b60606200211184845f85855f80866001600160a01b03168587604051620038af91906200465d565b5f6040518083038185875af1925050503d805f8114620038eb576040519150601f19603f3d011682016040523d82523d5f602084013e620038f0565b606091505b50915091506200134b8783838760608315620039705782515f0362003968576001600160a01b0385163b620039685760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620013e6565b508162002111565b620021118383815115620039875781518083602001fd5b8060405162461bcd60e51b8152600401620013e6919062003ee9565b61091d80620046fb83390190565b803563ffffffff81168114620037aa575f80fd5b5f60208284031215620039d6575f80fd5b620039e182620039b1565b9392505050565b80356001600160401b0381168114620037aa575f80fd5b6001600160a01b03811681146200292e575f80fd5b5f805f805f805f806103e0808a8c03121562003a2e575f80fd5b62003a398a620039b1565b985062003a4960208b01620039e8565b975062003a5960408b01620039e8565b965062003a6960608b01620039e8565b955060808a0135945060a08a0135935060c08a013562003a8981620039ff565b92508981018b101562003a9a575f80fd5b5060e0890190509295985092959890939650565b5f6020828403121562003abf575f80fd5b5035919050565b5f806040838503121562003ad8575f80fd5b62003ae383620039b1565b915062003af360208401620039e8565b90509250929050565b5f806040838503121562003b0e575f80fd5b82359150602083013562003b2281620039ff565b809150509250929050565b634e487b7160e01b5f52602160045260245ffd5b6002811062003b5e57634e487b7160e01b5f52602160045260245ffd5b9052565b6001600160a01b038881168252871660208201526001600160401b038616604082015260e0810162003b98606083018762003b41565b931515608082015260a081019290925260c090910152949350505050565b634e487b7160e01b5f52604160045260245ffd5b5f6001600160401b038084111562003be65762003be662003bb6565b604051601f8501601f19908116603f0116810190828211818310171562003c115762003c1162003bb6565b8160405280935085815286868601111562003c2a575f80fd5b858560208301375f602087830101525050509392505050565b5f82601f83011262003c53575f80fd5b620039e18383356020850162003bca565b5f805f805f805f60e0888a03121562003c7b575f80fd5b62003c8688620039b1565b965062003c9660208901620039e8565b9550604088013562003ca881620039ff565b9450606088013562003cba81620039ff565b9350608088013562003ccc81620039ff565b925060a08801356001600160401b038082111562003ce8575f80fd5b62003cf68b838c0162003c43565b935060c08a013591508082111562003d0c575f80fd5b5062003d1b8a828b0162003c43565b91505092959891949750929550565b81516001600160a01b031681526101808101602083015162003d5760208401826001600160401b03169052565b50604083015162003d7360408401826001600160a01b03169052565b50606083015162003d8f60608401826001600160401b03169052565b506080830151608083015260a083015162003db560a08401826001600160401b03169052565b5060c083015162003dd160c08401826001600160401b03169052565b5060e083015162003ded60e08401826001600160401b03169052565b50610100838101516001600160401b0316908301526101208084015162003e178285018262003b41565b5050610140838101519083015261016092830151929091019190915290565b5f805f805f8060c0878903121562003e4c575f80fd5b62003e5787620039b1565b955062003e6760208801620039e8565b945062003e7760408801620039e8565b9350606087013592506080870135915060a087013590509295509295509295565b5f5b8381101562003eb457818101518382015260200162003e9a565b50505f910152565b5f815180845262003ed581602086016020860162003e98565b601f01601f19169290920160200192915050565b602081525f620039e1602083018462003ebc565b5f6020828403121562003f0e575f80fd5b620039e182620039e8565b5f805f805f8060a0878903121562003f2f575f80fd5b62003f3a87620039b1565b955062003f4a60208801620039b1565b9450604087013593506060870135925060808701356001600160401b038082111562003f74575f80fd5b818901915089601f83011262003f88575f80fd5b81358181111562003f97575f80fd5b8a602082850101111562003fa9575f80fd5b6020830194508093505050509295509295509295565b5f806040838503121562003fd1575f80fd5b823562003ae381620039ff565b803560028110620037aa575f80fd5b5f805f805f805f60e0888a03121562004004575f80fd5b87356200401181620039ff565b965060208801356200402381620039ff565b95506200403360408901620039e8565b94506200404360608901620039e8565b9350608088013592506200405a60a0890162003fde565b915060c0880135905092959891949750929550565b5f806040838503121562004081575f80fd5b6200408c83620039e8565b946020939093013593505050565b5f805f8060808587031215620040ae575f80fd5b620040b985620039b1565b966020860135965060408601359560600135945092505050565b5f805f805f805f60e0888a031215620040ea575f80fd5b8735620040f781620039ff565b965060208801356200410981620039ff565b95506200411960408901620039e8565b9450620041296060890162003fde565b93506080880135925060a08801356001600160401b038111156200414b575f80fd5b620041598a828b0162003c43565b92505060c0880135905092959891949750929550565b5f805f6060848603121562004182575f80fd5b83356200418f81620039ff565b92506200419f60208501620039b1565b915060408401356001600160401b03811115620041ba575f80fd5b8401601f81018613620041cb575f80fd5b620041dc8682356020840162003bca565b9150509250925092565b5f60208284031215620041f7575f80fd5b8135620039e181620039ff565b5f806040838503121562004216575f80fd5b82356200422381620039ff565b915062003af360208401620039b1565b81516001600160a01b03168152610180810160208301516200426060208401826001600160401b03169052565b5060408301516200427c60408401826001600160a01b03169052565b5060608301516200429860608401826001600160401b03169052565b506080830151608083015260a0830151620042be60a08401826001600160401b03169052565b5060c0830151620042da60c08401826001600160401b03169052565b5060e0830151620042f660e08401826001600160401b03169052565b50610100838101516001600160401b039081169184019190915261012080850151821690840152610140808501519091169083015261016080840151620043408285018262003b41565b505092915050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b038181168382160190808211156200437f576200437f62004348565b5092915050565b80820281158282048414176200091e576200091e62004348565b5f63ffffffff808316818103620043bb57620043bb62004348565b6001019392505050565b5f6001600160a01b038086168352808516602084015250606060408301526200210e606083018462003ebc565b5f6001600160a01b038089168352808816602084015263ffffffff8716604084015280861660608401525060c060808301526200443360c083018562003ebc565b82810360a084015262004447818562003ebc565b9998505050505050505050565b5f6020828403121562004465575f80fd5b5051919050565b848152606060208201525f62004486606083018662003ebc565b8281036040840152838152838560208301375f602085830101526020601f19601f86011682010191505095945050505050565b5f60208284031215620044ca575f80fd5b8151620039e181620039ff565b6001600160401b038281168282160390808211156200437f576200437f62004348565b6001600160401b0387811682526001600160a01b0387166020830152858116604083015260c082019062004532606084018762003b41565b93909316608082015260a00152949350505050565b634e487b7160e01b5f52601260045260245ffd5b5f826200456c576200456c62004547565b500490565b808201808211156200091e576200091e62004348565b634e487b7160e01b5f52603260045260245ffd5b5f60018201620045af57620045af62004348565b5060010190565b5f82620045c757620045c762004547565b500690565b818103818111156200091e576200091e62004348565b5f81620045f357620045f362004348565b505f190190565b6001600160a01b038881168252871660208201526001600160401b03861660408201525f6200462d606083018762003b41565b84608083015260e060a08301526200464960e083018562003ebc565b90508260c083015298975050505050505050565b5f82516200467081846020870162003e98565b9190910192915050565b6103208101610300808584378201835f5b6001811015620046ac5781518352602092830192909101906001016200468b565b5050509392505050565b5f60208284031215620046c7575f80fd5b81518015158114620039e1575f80fd5b6001600160a01b0383168152604060208201525f62002111604083018462003ebc56fe60a06040526040516200091d3803806200091d833981016040819052620000269162000375565b828162000034828262000060565b50506001600160a01b038216608052620000576200005160805190565b620000c5565b5050506200046c565b6200006b8262000136565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000b757620000b28282620001b5565b505050565b620000c16200022e565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620001065f80516020620008fd833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001338162000250565b50565b806001600160a01b03163b5f036200017157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b031684604051620001d391906200044f565b5f60405180830381855af49150503d805f81146200020d576040519150601f19603f3d011682016040523d82523d5f602084013e62000212565b606091505b5090925090506200022585838362000291565b95945050505050565b34156200024e5760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b0381166200027b57604051633173bdd160e11b81525f600482015260240162000168565b805f80516020620008fd83398151915262000194565b606082620002aa57620002a482620002f7565b620002f0565b8151158015620002c257506001600160a01b0384163b155b15620002ed57604051639996b31560e01b81526001600160a01b038516600482015260240162000168565b50805b9392505050565b805115620003085780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811462000338575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b838110156200036d57818101518382015260200162000353565b50505f910152565b5f805f6060848603121562000388575f80fd5b620003938462000321565b9250620003a36020850162000321565b60408501519092506001600160401b0380821115620003c0575f80fd5b818601915086601f830112620003d4575f80fd5b815181811115620003e957620003e96200033d565b604051601f8201601f19908116603f011681019083821181831017156200041457620004146200033d565b816040528281528960208487010111156200042d575f80fd5b6200044083602083016020880162000351565b80955050505050509250925092565b5f82516200046281846020870162000351565b9190910192915050565b608051610479620004845f395f601001526104795ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610081575f357fffffffff000000000000000000000000000000000000000000000000000000001663278f794360e11b1461007957610077610085565b565b610077610095565b6100775b6100776100906100c3565b6100fa565b5f806100a43660048184610313565b8101906100b1919061034e565b915091506100bf8282610118565b5050565b5f6100f57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e808015610114573d5ff35b3d5ffd5b61012182610172565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561016a5761016582826101fa565b505050565b6100bf61026c565b806001600160a01b03163b5f036101ac57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516102169190610417565b5f60405180830381855af49150503d805f811461024e576040519150601f19603f3d011682016040523d82523d5f602084013e610253565b606091505b509150915061026385838361028b565b95945050505050565b34156100775760405163b398979f60e01b815260040160405180910390fd5b6060826102a05761029b826102ea565b6102e3565b81511580156102b757506001600160a01b0384163b155b156102e057604051639996b31560e01b81526001600160a01b03851660048201526024016101a3565b50805b9392505050565b8051156102fa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f8085851115610321575f80fd5b8386111561032d575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561035f575f80fd5b82356001600160a01b0381168114610375575f80fd5b9150602083013567ffffffffffffffff80821115610391575f80fd5b818501915085601f8301126103a4575f80fd5b8135818111156103b6576103b661033a565b604051601f8201601f19908116603f011681019083821181831017156103de576103de61033a565b816040528281528860208487010111156103f6575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610436576020818601810151858301520161041c565b505f92019182525091905056fea264697066735822122021e23b4641727aa4aa8fd2d3ef7960a43cab420d4c8632503bedc3eb2d30690764736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103a2646970667358221220214b2666bb6e2771614820f1fc68d70cdf88a8640c33fd376a6a976c4ac5a78a64736f6c63430008140033", + "deployedBytecode": "0x608060405234801562000010575f80fd5b5060043610620002fc575f3560e01c80638fd88cc211620001a3578063c4c928c211620000fb578063dbc16976116200009f578063e46761c41162000077578063e46761c41462000896578063f4e9267514620008be578063f9c4c2ae14620008cf575f80fd5b8063dbc16976146200085a578063dde0ff771462000864578063dfdb8c5e146200087f575f80fd5b8063d5073f6f11620000d3578063d5073f6f1462000801578063d547741f1462000818578063d8905812146200082f575f80fd5b8063c4c928c2146200079a578063ceee281d14620007b1578063d02103ca14620007d9575f80fd5b80639e36c5651162000163578063a3c573eb116200013b578063a3c573eb1462000727578063abcb51981462000768578063c1acbc34146200077f575f80fd5b80639e36c56514620006fe578063a217fddf1462000715578063a2967d99146200071d575f80fd5b80638fd88cc2146200067457806391d14854146200068b57806397bf07e814620006c657806399f5634e14620006dd5780639a908e7314620006e7575f80fd5b8063477fa2701162000257578063727885e911620002175780637fb6e76a11620001ef5780637fb6e76a146200062b5780638129fc1c14620006535780638875f03c146200065d575f80fd5b8063727885e914620005c857806374d9c24414620005df5780637975fcfe1462000605575f80fd5b8063477fa27014620004db57806355a71ee014620004e457806360469169146200052757806365c0504d14620005315780637222020f14620005b1575f80fd5b80632072f6c511620002bf5780632f2ff15d11620002975780632f2ff15d146200049957806330c27dde14620004b057806336568abe14620004c4575f80fd5b80632072f6c514620003a7578063248a9ca314620003b15780632528016914620003e5575f80fd5b8063066ec012146200030057806311f6b28714620003315780631489ed10146200034857806315064c9614620003615780631796a1ae1462000380575b5f80fd5b60845462000314906001600160401b031681565b6040516001600160401b0390911681526020015b60405180910390f35b6200031462000342366004620039c5565b620008f5565b6200035f6200035936600462003a14565b62000924565b005b606f546200036f9060ff1681565b604051901515815260200162000328565b607e54620003919063ffffffff1681565b60405163ffffffff909116815260200162000328565b6200035f62000b14565b620003d6620003c236600462003aae565b5f9081526034602052604090206001015490565b60405190815260200162000328565b62000465620003f636600462003ac6565b60408051606080820183525f808352602080840182905292840181905263ffffffff959095168552608182528285206001600160401b03948516865260030182529382902082519485018352805485526001015480841691850191909152600160401b90049091169082015290565b60408051825181526020808401516001600160401b0390811691830191909152928201519092169082015260600162000328565b6200035f620004aa36600462003afc565b62000bf0565b60875462000314906001600160401b031681565b6200035f620004d536600462003afc565b62000c1d565b608654620003d6565b620003d6620004f536600462003ac6565b63ffffffff82165f9081526081602090815260408083206001600160401b038516845260020190915290205492915050565b620003d662000c57565b6200059c62000542366004620039c5565b607f6020525f908152604090208054600182015460028301546003909301546001600160a01b0392831693928216926001600160401b03600160a01b8404169260ff600160e01b8204811693600160e81b90920416919087565b60405162000328979695949392919062003b62565b6200035f620005c2366004620039c5565b62000c6e565b6200035f620005d936600462003c64565b62000d64565b620005f6620005f0366004620039c5565b620011f2565b60405162000328919062003d2a565b6200061c6200061636600462003e36565b62001324565b60405162000328919062003ee9565b620003916200063c36600462003efd565b60836020525f908152604090205463ffffffff1681565b6200035f62001356565b6200035f6200066e36600462003f19565b6200149d565b6200035f6200068536600462003fbf565b62001753565b6200036f6200069c36600462003afc565b5f9182526034602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6200035f620006d736600462003fed565b62001aed565b620003d662001e05565b62000314620006f83660046200406f565b62001ee6565b6200061c6200070f3660046200409a565b620020e7565b620003d65f81565b620003d662002119565b6200074f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200162000328565b6200035f62000779366004620040d3565b620024e1565b6084546200031490600160801b90046001600160401b031681565b6200035f620007ab3660046200416f565b6200275c565b62000391620007c2366004620041e6565b60826020525f908152604090205463ffffffff1681565b6200074f7f000000000000000000000000000000000000000000000000000000000000000081565b6200035f6200081236600462003aae565b6200279b565b6200035f6200082936600462003afc565b6200283d565b6200061c6040518060400160405280600b81526020016a70657373696d697374696360a81b81525081565b6200035f62002865565b6084546200031490600160401b90046001600160401b031681565b6200035f6200089036600462004204565b62002931565b6200074f7f000000000000000000000000000000000000000000000000000000000000000081565b608054620003919063ffffffff1681565b620008e6620008e0366004620039c5565b62002a81565b60405162000328919062004233565b63ffffffff81165f90815260816020526040812060060154600160401b90046001600160401b03165b92915050565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4620009508162002be1565b6001600160401b03881615620009795760405163306dfc5760e11b815260040160405180910390fd5b63ffffffff89165f908152608160205260408120906007820154600160801b900460ff166001811115620009b157620009b162003b2d565b14620009d0576040516390db0d0760e01b815260040160405180910390fd5b620009e18189898989898962002bed565b6006810180546fffffffffffffffff00000000000000001916600160401b6001600160401b038a16908102919091179091555f9081526002820160205260409020859055600581018690557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62000a6562002119565b6040518263ffffffff1660e01b815260040162000a8491815260200190565b5f604051808303815f87803b15801562000a9c575f80fd5b505af115801562000aaf573d5f803e3d5ffd5b5050604080516001600160401b038b1681526020810189905290810189905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d3906060015b60405180910390a350505050505050505050565b335f9081527f8875b94af5657a2903def9906d67a3f42d8a836d24b5602c00f00fc855339fcd602052604090205460ff1662000be457608454600160801b90046001600160401b0316158062000b955750608454429062000b8a9062093a8090600160801b90046001600160401b03166200435c565b6001600160401b0316115b8062000bc55750608754429062000bba9062093a80906001600160401b03166200435c565b6001600160401b0316115b1562000be45760405163692baaad60e11b815260040160405180910390fd5b62000bee62002f24565b565b5f8281526034602052604090206001015462000c0c8162002be1565b62000c18838362002f9e565b505050565b6001600160a01b038116331462000c4757604051630b4ad1cd60e31b815260040160405180910390fd5b62000c53828262003022565b5050565b5f608654606462000c69919062004386565b905090565b7fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd62000c9a8162002be1565b63ffffffff8216158062000cb95750607e5463ffffffff908116908316115b1562000cd857604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff82165f908152607f602052604090206001810154600160e81b900460ff161562000d1a57604051633b8d3d9960e01b815260040160405180910390fd5b60018101805460ff60e81b1916600160e81b17905560405163ffffffff8416907f4710d2ee567ef1ed6eb2f651dde4589524bcf7cebc62147a99b281cc836e7e44905f90a2505050565b7fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd0862000d908162002be1565b63ffffffff8816158062000daf5750607e5463ffffffff908116908916115b1562000dce57604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff88165f908152607f602052604090206001810154600160e81b900460ff161562000e1057604051633b8d3d9960e01b815260040160405180910390fd5b63ffffffff6001600160401b038916111562000e3f57604051634c753f5760e01b815260040160405180910390fd5b6001600160401b0388165f9081526083602052604090205463ffffffff161562000e7c576040516337c8fe0960e11b815260040160405180910390fd5b608080545f9190829062000e969063ffffffff16620043a0565b825463ffffffff8281166101009490940a93840293021916919091179091558254604080515f80825260208201928390529394506001600160a01b0390921691309162000ee390620039a3565b62000ef193929190620043c5565b604051809103905ff08015801562000f0b573d5f803e3d5ffd5b5090508160835f8c6001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508160825f836001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8463ffffffff1663ffffffff1681526020019081526020015f20905081815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508360010160149054906101000a90046001600160401b03168160010160146101000a8154816001600160401b0302191690836001600160401b03160217905550836001015f9054906101000a90046001600160a01b0316816001015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508a815f0160146101000a8154816001600160401b0302191690836001600160401b031602179055508360020154816002015f806001600160401b031681526020019081526020015f20819055508b63ffffffff168160070160086101000a8154816001600160401b0302191690836001600160401b0316021790555083600101601c9054906101000a900460ff168160070160106101000a81548160ff021916908360018111156200110b576200110b62003b2d565b0217905550600384015460098201556040805163ffffffff8e811682526001600160a01b0385811660208401526001600160401b038f16838501528b1660608301529151918516917f194c983456df6701c6a50830b90fe80e72b823411d0d524970c9590dc277a6419181900360800190a2604051633892b81160e11b81526001600160a01b03831690637125702290620011b5908d908d9088908e908e908e90600401620043f2565b5f604051808303815f87803b158015620011cd575f80fd5b505af1158015620011e0573d5f803e3d5ffd5b50505050505050505050505050505050565b60408051610180810182525f8082526020808301828152838501838152606085018481526080860185815260a0870186815260c0880187815260e089018881526101008a018981526101208b018a81526101408c018b90526101608c018b905263ffffffff8e168b5260819099529a90982080546001600160a01b038082168c52600160a01b918290046001600160401b0390811690995260018084015491821690985204871690945260058401549092526006830154808616909152600160401b9081900485169091526007820154808516909652850490921690955292939091600160801b900460ff1690811115620012f157620012f162003b2d565b9081600181111562001307576200130762003b2d565b905250600881015461014083015260090154610160820152919050565b63ffffffff86165f9081526081602052604090206060906200134b908787878787620030a4565b979650505050505050565b5f54600390610100900460ff161580156200137757505f5460ff8083169116105b620013ef5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805461ffff191660ff831617610100179055604080518082018252600b81526a70657373696d697374696360a81b602082015290517f50cadc0c001f05dd4b81db1e92b98d77e718fd2f103fb7b77293e867d329a4c291620014529162003ee9565b60405180910390a15f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4620014c98162002be1565b63ffffffff87165f90815260816020526040902060016007820154600160801b900460ff16600181111562001502576200150262003b2d565b146200152157604051633a64d97360e01b815260040160405180910390fd5b60405163ef4eeb3560e01b815263ffffffff881660048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef4eeb3590602401602060405180830381865afa1580156200158c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620015b2919062004454565b905080620015d35760405163a60721e160e01b815260040160405180910390fd5b5f620015e38a84848b8b620031fb565b6001840154600985015460405163020a49e360e51b81529293506001600160a01b03909116916341493c6091620016239185908b908b906004016200446c565b5f6040518083038186803b1580156200163a575f80fd5b505afa1580156200164d573d5f803e3d5ffd5b50506084805467ffffffffffffffff60801b1916600160801b426001600160401b031602179055505060058301889055600883018790557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d620016bd62002119565b6040518263ffffffff1660e01b8152600401620016dc91815260200190565b5f604051808303815f87803b158015620016f4575f80fd5b505af115801562001707573d5f803e3d5ffd5b5050604080515f80825260208201529081018b905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d39060600162000b00565b335f9081527ff14f5a8ad59d90593602e905b358229bff5ceea677d5bf0f5a1701793550a9a6602052604090205460ff16158015620018065750336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015620017d4573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620017fa9190620044b9565b6001600160a01b031614155b156200182557604051630d03687f60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526082602052604081205463ffffffff169081900362001865576040516374a086a360e01b815260040160405180910390fd5b63ffffffff81165f908152608160205260408120906007820154600160801b900460ff1660018111156200189d576200189d62003b2d565b14620018bc576040516390db0d0760e01b815260040160405180910390fd5b60068101546001600160401b0390811690841681111580620018f5575060068201546001600160401b03600160401b9091048116908516105b15620019145760405163cb23ebdf60e01b815260040160405180910390fd5b805b846001600160401b0316816001600160401b031614620019b8576001600160401b038082165f908152600385016020526040902060010154600160401b900481169086168110156200197b57604051639753965f60e01b815260040160405180910390fd5b6001600160401b039091165f908152600384016020526040812090815560010180546fffffffffffffffffffffffffffffffff1916905562001916565b60068301805467ffffffffffffffff19166001600160401b038716179055620019e28583620044d7565b608480545f90620019fe9084906001600160401b0316620044d7565b82546101009290920a6001600160401b0381810219909316918316021790915586165f8181526003860160205260409081902054905163334d6f6760e11b8152600481019290925260248201526001600160a01b038816915063669adece906044015f604051808303815f87803b15801562001a78575f80fd5b505af115801562001a8b573d5f803e3d5ffd5b505050506001600160401b0385165f81815260038501602090815260409182902054915191825263ffffffff8716917f80a6d395a55aed8126079cb8247f0a6848b1440ca2cdca3b4386f250c3529402910160405180910390a3505050505050565b7f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e62001b198162002be1565b6001600160401b0385165f9081526083602052604090205463ffffffff161562001b56576040516337c8fe0960e11b815260040160405180910390fd5b63ffffffff6001600160401b038616111562001b8557604051634c753f5760e01b815260040160405180910390fd5b6001600160a01b0388165f9081526082602052604090205463ffffffff161562001bc257604051630d409b9360e41b815260040160405180910390fd5b608080545f9190829062001bdc9063ffffffff16620043a0565b91906101000a81548163ffffffff021916908363ffffffff160217905590508060835f886001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508060825f8b6001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8363ffffffff1663ffffffff1681526020019081526020015f20905089815f015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550878160010160146101000a8154816001600160401b0302191690836001600160401b0316021790555088816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555086815f0160146101000a8154816001600160401b0302191690836001600160401b03160217905550848160070160106101000a81548160ff0219169083600181111562001d665762001d6662003b2d565b0217905550600185600181111562001d825762001d8262003b2d565b0362001d9c57600981018490556005810186905562001daf565b5f80805260028201602052604090208690555b8163ffffffff167fd490df184152edba8455dac3228134939c71f8cb4c8f310c3145dec9037147ac898c8a895f8a60405162001df196959493929190620044fa565b60405180910390a250505050505050505050565b6040516370a0823160e01b81523060048201525f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801562001e6c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001e92919062004454565b6084549091505f9062001eb8906001600160401b03600160401b820481169116620044d7565b6001600160401b03169050805f0362001ed3575f9250505090565b62001edf81836200455b565b9250505090565b606f545f9060ff161562001f0d57604051630bc011ff60e21b815260040160405180910390fd5b335f9081526082602052604081205463ffffffff169081900362001f44576040516371653c1560e01b815260040160405180910390fd5b836001600160401b03165f0362001f6e57604051632590ccf960e01b815260040160405180910390fd5b63ffffffff81165f908152608160205260408120906007820154600160801b900460ff16600181111562001fa65762001fa662003b2d565b1462001fc5576040516390db0d0760e01b815260040160405180910390fd5b608480548691905f9062001fe49084906001600160401b03166200435c565b82546101009290920a6001600160401b0381810219909316918316021790915560068301541690505f6200201987836200435c565b6006840180546001600160401b0383811667ffffffffffffffff199092168217909255604080516060810182528a815242841660208083019182528886168385019081525f86815260038c018352859020935184559151600193909301805492518716600160401b026fffffffffffffffffffffffffffffffff199093169390961692909217179093555190815291925063ffffffff8616917f1d9f30260051d51d70339da239ea7b080021adcaabfa71c9b0ea339a20cf9a25910160405180910390a29695505050505050565b63ffffffff84165f9081526081602052604090206060906200210e908690868686620031fb565b90505b949350505050565b6080545f9063ffffffff168082036200213357505f919050565b5f816001600160401b038111156200214f576200214f62003bb6565b60405190808252806020026020018201604052801562002179578160200160208202803683370190505b5090505f5b82811015620021e95760815f6200219783600162004571565b63ffffffff1663ffffffff1681526020019081526020015f2060050154828281518110620021c957620021c962004587565b602090810291909101015280620021e0816200459b565b9150506200217e565b505f60205b8360011462002441575f62002205600286620045b6565b620022126002876200455b565b6200221e919062004571565b90505f816001600160401b038111156200223c576200223c62003bb6565b60405190808252806020026020018201604052801562002266578160200160208202803683370190505b5090505f5b82811015620023ed5762002281600184620045cc565b811480156200229c575062002298600288620045b6565b6001145b15620023245785620022b082600262004386565b81518110620022c357620022c362004587565b602002602001015185604051602001620022e7929190918252602082015260400190565b6040516020818303038152906040528051906020012082828151811062002312576200231262004587565b602002602001018181525050620023d8565b856200233282600262004386565b8151811062002345576200234562004587565b6020026020010151868260026200235d919062004386565b6200236a90600162004571565b815181106200237d576200237d62004587565b6020026020010151604051602001620023a0929190918252602082015260400190565b60405160208183030381529060405280519060200120828281518110620023cb57620023cb62004587565b6020026020010181815250505b80620023e4816200459b565b9150506200226b565b50809450819550838460405160200162002411929190918252602082015260400190565b60405160208183030381529060405280519060200120935082806200243690620045e2565b9350505050620021ee565b5f835f8151811062002457576200245762004587565b602002602001015190505f5b82811015620024d757604080516020810184905290810185905260600160408051601f19818403018152828252805160209182012090830187905290820186905292506060016040516020818303038152906040528051906020012093508080620024ce906200459b565b91505062002463565b5095945050505050565b7fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f5906200250d8162002be1565b607e80545f91908290620025279063ffffffff16620043a0565b91906101000a81548163ffffffff021916908363ffffffff160217905590506001808111156200255b576200255b62003b2d565b86600181111562002570576200257062003b2d565b036200259c57841562002596576040516363d722e760e01b815260040160405180910390fd5b620025bc565b8215620025bc576040516363d722e760e01b815260040160405180910390fd5b6040518060e001604052808a6001600160a01b03168152602001896001600160a01b03168152602001886001600160401b0316815260200187600181111562002609576200260962003b2d565b81525f602080830182905260408084018a9052606093840188905263ffffffff86168352607f825291829020845181546001600160a01b0391821673ffffffffffffffffffffffffffffffffffffffff199091161782559185015160018281018054958801516001600160401b0316600160a01b026001600160e01b0319909616929094169190911793909317808355938501519093909260ff60e01b1990911690600160e01b908490811115620026c557620026c562003b2d565b02179055506080820151600182018054911515600160e81b0260ff60e81b1990921691909117905560a0820151600282015560c09091015160039091015560405163ffffffff8216907f9eaf2ecbddb14889c9e141a63175c55ac25e0cd7cdea312cdfbd0397976b383a9062002749908c908c908c908c908c908c908c90620045fa565b60405180910390a2505050505050505050565b7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac620027888162002be1565b62002795848484620032e0565b50505050565b7f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb620027c78162002be1565b683635c9adc5dea00000821180620027e25750633b9aca0082105b156200280157604051638586952560e01b815260040160405180910390fd5b60868290556040518281527ffb383653f53ee079978d0c9aff7aeff04a10166ce244cca9c9f9d8d96bed45b29060200160405180910390a15050565b5f82815260346020526040902060010154620028598162002be1565b62000c18838362003022565b7f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f4620028918162002be1565b6087805467ffffffffffffffff1916426001600160401b031617905560408051636de0b4bb60e11b815290517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163dbc16976916004808301925f92919082900301818387803b1580156200290d575f80fd5b505af115801562002920573d5f803e3d5ffd5b505050506200292e620035c6565b50565b336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002978573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200299e9190620044b9565b6001600160a01b031614620029c65760405163696072e960e01b815260040160405180910390fd5b6001600160a01b0382165f9081526082602090815260408083205463ffffffff1683526081909152902060068101546001600160401b03808216600160401b909204161462002a285760405163664316a560e11b815260040160405180910390fd5b600781015463ffffffff8316600160401b9091046001600160401b03161062002a6457604051633e37e23360e01b815260040160405180910390fd5b604080515f81526020810190915262000c189084908490620032e0565b62002ae660408051610180810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290529061016082015290565b63ffffffff82165f9081526081602090815260409182902080546001600160a01b038082168652600160a01b918290046001600160401b039081169487019490945260018084015491821695870195909552048216606085015260058101546080850152600681015480831660a0860152600160401b808204841660c0870152600160801b808304851660e0880152600160c01b9092048416610100870152600783015480851661012088015290810490931661014086015290926101608501929190910460ff169081111562002bc15762002bc162003b2d565b9081600181111562002bd75762002bd762003b2d565b8152505050919050565b6200292e81336200361e565b5f8062002c0c89600601546001600160401b03600160401b9091041690565b60078a01549091506001600160401b03908116908916101562002c425760405163ead1340b60e01b815260040160405180910390fd5b6001600160401b0388165f90815260028a01602052604090205491508162002c7d576040516324cbdcc360e11b815260040160405180910390fd5b806001600160401b0316886001600160401b0316111562002cb157604051630f2b74f160e11b815260040160405180910390fd5b806001600160401b0316876001600160401b03161162002ce45760405163b9b18f5760e01b815260040160405180910390fd5b5f62002cf58a8a8a8a878b620030a4565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028360405162002d2b91906200465d565b602060405180830381855afa15801562002d47573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019062002d6c919062004454565b62002d789190620045b6565b60018c0154604080516020810182528381529051634890ed4560e11b81529293506001600160a01b0390911691639121da8a9162002dbc918991906004016200467a565b602060405180830381865afa15801562002dd8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002dfe9190620046b6565b62002e1c576040516309bde33960e01b815260040160405180910390fd5b5f62002e29848b620044d7565b905062002e8287826001600160401b031662002e4462001e05565b62002e50919062004386565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016919062003661565b80608460088282829054906101000a90046001600160401b031662002ea891906200435c565b82546101009290920a6001600160401b038181021990931691831602179091556084805467ffffffffffffffff60801b1916600160801b428416021790558d546040516332c2d15360e01b8152918d166004830152602482018b90523360448301526001600160a01b031691506332c2d15390606401620011b5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562002f7d575f80fd5b505af115801562002f90573d5f803e3d5ffd5b5050505062000bee620036ca565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff1662000c53575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff161562000c53575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001600160401b038086165f8181526003890160205260408082205493881682529020546060929115801590620030d9575081155b15620030f85760405163340c614f60e11b815260040160405180910390fd5b8062003117576040516366385b5160e01b815260040160405180910390fd5b620031228462003726565b62003140576040516305dae44f60e21b815260040160405180910390fd5b885460018a01546040516bffffffffffffffffffffffff193360601b16602082015260348101889052605481018590527fffffffffffffffff00000000000000000000000000000000000000000000000060c08c811b82166074840152600160a01b94859004811b8216607c84015293909204831b82166084820152608c810187905260ac810184905260cc81018990529189901b1660ec82015260f401604051602081830303815290604052925050509695505050505050565b60605f855f015f9054906101000a90046001600160a01b03166001600160a01b031663ad1edf346040518163ffffffff1660e01b8152600401602060405180830381865afa15801562003250573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062003276919062004454565b60058701546008880154604080516020810193909352820152606081018790526001600160e01b031960e08a901b1660808201526084810182905260a4810186905260c4810185905290915060e40160405160208183030381529060405291505095945050505050565b63ffffffff82161580620032ff5750607e5463ffffffff908116908316115b156200331e57604051637512e5cb60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526082602052604081205463ffffffff16908190036200335e576040516374a086a360e01b815260040160405180910390fd5b63ffffffff8181165f908152608160205260409020600781015490918516600160401b9091046001600160401b031603620033ac57604051634f61d51960e01b815260040160405180910390fd5b63ffffffff84165f908152607f602052604090206001810154600160e81b900460ff1615620033ee57604051633b8d3d9960e01b815260040160405180910390fd5b600181810154600160e01b900460ff169081111562003411576200341162003b2d565b6007830154600160801b900460ff16600181111562003434576200343462003b2d565b146200345357604051635aa0d5f160e11b815260040160405180910390fd5b60018082018054918401805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03909416938417825591546001600160401b03600160a01b9182900416026001600160e01b031990921690921717905560038101546009830155600782018054600160401b63ffffffff8816026fffffffffffffffff0000000000000000199091161790555f620034ef84620008f5565b60078401805467ffffffffffffffff19166001600160401b038316179055825460405163278f794360e11b81529192506001600160a01b0389811692634f1ef28692620035439216908990600401620046d7565b5f604051808303815f87803b1580156200355b575f80fd5b505af11580156200356e573d5f803e3d5ffd5b50506040805163ffffffff8a811682526001600160401b0386166020830152881693507ff585e04c05d396901170247783d3e5f0ee9c1df23072985b50af089f5e48b19d92500160405180910390a250505050505050565b606f5460ff16620035ea57604051635386698160e01b815260040160405180910390fd5b606f805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff1662000c5357604051637615be1f60e11b815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b17905262000c18908490620037af565b606f5460ff1615620036ef57604051630bc011ff60e21b815260040160405180910390fd5b606f805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b5f67ffffffff000000016001600160401b0383161080156200375c575067ffffffff00000001604083901c6001600160401b0316105b80156200377d575067ffffffff00000001608083901c6001600160401b0316105b801562003795575067ffffffff0000000160c083901c105b15620037a357506001919050565b505f919050565b919050565b5f62003805826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620038879092919063ffffffff16565b80519091501562000c185780806020019051810190620038269190620046b6565b62000c185760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620013e6565b60606200211184845f85855f80866001600160a01b03168587604051620038af91906200465d565b5f6040518083038185875af1925050503d805f8114620038eb576040519150601f19603f3d011682016040523d82523d5f602084013e620038f0565b606091505b50915091506200134b8783838760608315620039705782515f0362003968576001600160a01b0385163b620039685760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620013e6565b508162002111565b620021118383815115620039875781518083602001fd5b8060405162461bcd60e51b8152600401620013e6919062003ee9565b61091d80620046fb83390190565b803563ffffffff81168114620037aa575f80fd5b5f60208284031215620039d6575f80fd5b620039e182620039b1565b9392505050565b80356001600160401b0381168114620037aa575f80fd5b6001600160a01b03811681146200292e575f80fd5b5f805f805f805f806103e0808a8c03121562003a2e575f80fd5b62003a398a620039b1565b985062003a4960208b01620039e8565b975062003a5960408b01620039e8565b965062003a6960608b01620039e8565b955060808a0135945060a08a0135935060c08a013562003a8981620039ff565b92508981018b101562003a9a575f80fd5b5060e0890190509295985092959890939650565b5f6020828403121562003abf575f80fd5b5035919050565b5f806040838503121562003ad8575f80fd5b62003ae383620039b1565b915062003af360208401620039e8565b90509250929050565b5f806040838503121562003b0e575f80fd5b82359150602083013562003b2281620039ff565b809150509250929050565b634e487b7160e01b5f52602160045260245ffd5b6002811062003b5e57634e487b7160e01b5f52602160045260245ffd5b9052565b6001600160a01b038881168252871660208201526001600160401b038616604082015260e0810162003b98606083018762003b41565b931515608082015260a081019290925260c090910152949350505050565b634e487b7160e01b5f52604160045260245ffd5b5f6001600160401b038084111562003be65762003be662003bb6565b604051601f8501601f19908116603f0116810190828211818310171562003c115762003c1162003bb6565b8160405280935085815286868601111562003c2a575f80fd5b858560208301375f602087830101525050509392505050565b5f82601f83011262003c53575f80fd5b620039e18383356020850162003bca565b5f805f805f805f60e0888a03121562003c7b575f80fd5b62003c8688620039b1565b965062003c9660208901620039e8565b9550604088013562003ca881620039ff565b9450606088013562003cba81620039ff565b9350608088013562003ccc81620039ff565b925060a08801356001600160401b038082111562003ce8575f80fd5b62003cf68b838c0162003c43565b935060c08a013591508082111562003d0c575f80fd5b5062003d1b8a828b0162003c43565b91505092959891949750929550565b81516001600160a01b031681526101808101602083015162003d5760208401826001600160401b03169052565b50604083015162003d7360408401826001600160a01b03169052565b50606083015162003d8f60608401826001600160401b03169052565b506080830151608083015260a083015162003db560a08401826001600160401b03169052565b5060c083015162003dd160c08401826001600160401b03169052565b5060e083015162003ded60e08401826001600160401b03169052565b50610100838101516001600160401b0316908301526101208084015162003e178285018262003b41565b5050610140838101519083015261016092830151929091019190915290565b5f805f805f8060c0878903121562003e4c575f80fd5b62003e5787620039b1565b955062003e6760208801620039e8565b945062003e7760408801620039e8565b9350606087013592506080870135915060a087013590509295509295509295565b5f5b8381101562003eb457818101518382015260200162003e9a565b50505f910152565b5f815180845262003ed581602086016020860162003e98565b601f01601f19169290920160200192915050565b602081525f620039e1602083018462003ebc565b5f6020828403121562003f0e575f80fd5b620039e182620039e8565b5f805f805f8060a0878903121562003f2f575f80fd5b62003f3a87620039b1565b955062003f4a60208801620039b1565b9450604087013593506060870135925060808701356001600160401b038082111562003f74575f80fd5b818901915089601f83011262003f88575f80fd5b81358181111562003f97575f80fd5b8a602082850101111562003fa9575f80fd5b6020830194508093505050509295509295509295565b5f806040838503121562003fd1575f80fd5b823562003ae381620039ff565b803560028110620037aa575f80fd5b5f805f805f805f60e0888a03121562004004575f80fd5b87356200401181620039ff565b965060208801356200402381620039ff565b95506200403360408901620039e8565b94506200404360608901620039e8565b9350608088013592506200405a60a0890162003fde565b915060c0880135905092959891949750929550565b5f806040838503121562004081575f80fd5b6200408c83620039e8565b946020939093013593505050565b5f805f8060808587031215620040ae575f80fd5b620040b985620039b1565b966020860135965060408601359560600135945092505050565b5f805f805f805f60e0888a031215620040ea575f80fd5b8735620040f781620039ff565b965060208801356200410981620039ff565b95506200411960408901620039e8565b9450620041296060890162003fde565b93506080880135925060a08801356001600160401b038111156200414b575f80fd5b620041598a828b0162003c43565b92505060c0880135905092959891949750929550565b5f805f6060848603121562004182575f80fd5b83356200418f81620039ff565b92506200419f60208501620039b1565b915060408401356001600160401b03811115620041ba575f80fd5b8401601f81018613620041cb575f80fd5b620041dc8682356020840162003bca565b9150509250925092565b5f60208284031215620041f7575f80fd5b8135620039e181620039ff565b5f806040838503121562004216575f80fd5b82356200422381620039ff565b915062003af360208401620039b1565b81516001600160a01b03168152610180810160208301516200426060208401826001600160401b03169052565b5060408301516200427c60408401826001600160a01b03169052565b5060608301516200429860608401826001600160401b03169052565b506080830151608083015260a0830151620042be60a08401826001600160401b03169052565b5060c0830151620042da60c08401826001600160401b03169052565b5060e0830151620042f660e08401826001600160401b03169052565b50610100838101516001600160401b039081169184019190915261012080850151821690840152610140808501519091169083015261016080840151620043408285018262003b41565b505092915050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b038181168382160190808211156200437f576200437f62004348565b5092915050565b80820281158282048414176200091e576200091e62004348565b5f63ffffffff808316818103620043bb57620043bb62004348565b6001019392505050565b5f6001600160a01b038086168352808516602084015250606060408301526200210e606083018462003ebc565b5f6001600160a01b038089168352808816602084015263ffffffff8716604084015280861660608401525060c060808301526200443360c083018562003ebc565b82810360a084015262004447818562003ebc565b9998505050505050505050565b5f6020828403121562004465575f80fd5b5051919050565b848152606060208201525f62004486606083018662003ebc565b8281036040840152838152838560208301375f602085830101526020601f19601f86011682010191505095945050505050565b5f60208284031215620044ca575f80fd5b8151620039e181620039ff565b6001600160401b038281168282160390808211156200437f576200437f62004348565b6001600160401b0387811682526001600160a01b0387166020830152858116604083015260c082019062004532606084018762003b41565b93909316608082015260a00152949350505050565b634e487b7160e01b5f52601260045260245ffd5b5f826200456c576200456c62004547565b500490565b808201808211156200091e576200091e62004348565b634e487b7160e01b5f52603260045260245ffd5b5f60018201620045af57620045af62004348565b5060010190565b5f82620045c757620045c762004547565b500690565b818103818111156200091e576200091e62004348565b5f81620045f357620045f362004348565b505f190190565b6001600160a01b038881168252871660208201526001600160401b03861660408201525f6200462d606083018762003b41565b84608083015260e060a08301526200464960e083018562003ebc565b90508260c083015298975050505050505050565b5f82516200467081846020870162003e98565b9190910192915050565b6103208101610300808584378201835f5b6001811015620046ac5781518352602092830192909101906001016200468b565b5050509392505050565b5f60208284031215620046c7575f80fd5b81518015158114620039e1575f80fd5b6001600160a01b0383168152604060208201525f62002111604083018462003ebc56fe60a06040526040516200091d3803806200091d833981016040819052620000269162000375565b828162000034828262000060565b50506001600160a01b038216608052620000576200005160805190565b620000c5565b5050506200046c565b6200006b8262000136565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000b757620000b28282620001b5565b505050565b620000c16200022e565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620001065f80516020620008fd833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001338162000250565b50565b806001600160a01b03163b5f036200017157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b031684604051620001d391906200044f565b5f60405180830381855af49150503d805f81146200020d576040519150601f19603f3d011682016040523d82523d5f602084013e62000212565b606091505b5090925090506200022585838362000291565b95945050505050565b34156200024e5760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b0381166200027b57604051633173bdd160e11b81525f600482015260240162000168565b805f80516020620008fd83398151915262000194565b606082620002aa57620002a482620002f7565b620002f0565b8151158015620002c257506001600160a01b0384163b155b15620002ed57604051639996b31560e01b81526001600160a01b038516600482015260240162000168565b50805b9392505050565b805115620003085780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811462000338575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b838110156200036d57818101518382015260200162000353565b50505f910152565b5f805f6060848603121562000388575f80fd5b620003938462000321565b9250620003a36020850162000321565b60408501519092506001600160401b0380821115620003c0575f80fd5b818601915086601f830112620003d4575f80fd5b815181811115620003e957620003e96200033d565b604051601f8201601f19908116603f011681019083821181831017156200041457620004146200033d565b816040528281528960208487010111156200042d575f80fd5b6200044083602083016020880162000351565b80955050505050509250925092565b5f82516200046281846020870162000351565b9190910192915050565b608051610479620004845f395f601001526104795ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610081575f357fffffffff000000000000000000000000000000000000000000000000000000001663278f794360e11b1461007957610077610085565b565b610077610095565b6100775b6100776100906100c3565b6100fa565b5f806100a43660048184610313565b8101906100b1919061034e565b915091506100bf8282610118565b5050565b5f6100f57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e808015610114573d5ff35b3d5ffd5b61012182610172565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561016a5761016582826101fa565b505050565b6100bf61026c565b806001600160a01b03163b5f036101ac57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516102169190610417565b5f60405180830381855af49150503d805f811461024e576040519150601f19603f3d011682016040523d82523d5f602084013e610253565b606091505b509150915061026385838361028b565b95945050505050565b34156100775760405163b398979f60e01b815260040160405180910390fd5b6060826102a05761029b826102ea565b6102e3565b81511580156102b757506001600160a01b0384163b155b156102e057604051639996b31560e01b81526001600160a01b03851660048201526024016101a3565b50805b9392505050565b8051156102fa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f8085851115610321575f80fd5b8386111561032d575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561035f575f80fd5b82356001600160a01b0381168114610375575f80fd5b9150602083013567ffffffffffffffff80821115610391575f80fd5b818501915085601f8301126103a4575f80fd5b8135818111156103b6576103b661033a565b604051601f8201601f19908116603f011681019083821181831017156103de576103de61033a565b816040528281528860208487010111156103f6575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610436576020818601810151858301520161041c565b505f92019182525091905056fea264697066735822122021e23b4641727aa4aa8fd2d3ef7960a43cab420d4c8632503bedc3eb2d30690764736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103a2646970667358221220214b2666bb6e2771614820f1fc68d70cdf88a8640c33fd376a6a976c4ac5a78a64736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonRollupManagerMock.json b/compiled-contracts/PolygonRollupManagerMock.json index 08e59b604..f765c8320 100644 --- a/compiled-contracts/PolygonRollupManagerMock.json +++ b/compiled-contracts/PolygonRollupManagerMock.json @@ -134,6 +134,11 @@ "name": "InitSequenceNumDoesNotMatchPendingState", "type": "error" }, + { + "inputs": [], + "name": "InvalidPessimisticProof", + "type": "error" + }, { "inputs": [], "name": "InvalidProof", @@ -159,6 +164,26 @@ "name": "InvalidRangeSequenceTimeTarget", "type": "error" }, + { + "inputs": [], + "name": "InvalidRollup", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRollupType", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidVerifierType", + "type": "error" + }, + { + "inputs": [], + "name": "L1InfoTreeLeafCountInvalid", + "type": "error" + }, { "inputs": [], "name": "MustSequenceSomeBatch", @@ -204,6 +229,11 @@ "name": "OldStateRootDoesNotExist", "type": "error" }, + { + "inputs": [], + "name": "OnlyChainsWithPessimisticProofs", + "type": "error" + }, { "inputs": [], "name": "OnlyEmergencyState", @@ -219,6 +249,11 @@ "name": "OnlyRollupAdmin", "type": "error" }, + { + "inputs": [], + "name": "OnlyStateTransitionChains", + "type": "error" + }, { "inputs": [], "name": "PendingStateDoesNotExist", @@ -234,6 +269,11 @@ "name": "PendingStateNotConsolidable", "type": "error" }, + { + "inputs": [], + "name": "PendingStateNumExist", + "type": "error" + }, { "inputs": [], "name": "RollbackBatchIsNotEndOfSequence", @@ -333,8 +373,8 @@ }, { "indexed": false, - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" }, { @@ -342,6 +382,12 @@ "internalType": "uint64", "name": "lastVerifiedBatchBeforeUpgrade", "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" } ], "name": "AddExistingRollup", @@ -376,8 +422,8 @@ }, { "indexed": false, - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" }, { @@ -391,46 +437,15 @@ "internalType": "string", "name": "description", "type": "string" - } - ], - "name": "AddNewRollupType", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" }, { "indexed": false, "internalType": "bytes32", - "name": "exitRoot", + "name": "programVKey", "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "pendingStateNum", - "type": "uint64" } ], - "name": "ConsolidatePendingState", + "name": "AddNewRollupType", "type": "event" }, { @@ -527,62 +542,6 @@ "name": "OnSequenceBatches", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "exitRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "OverridePendingState", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "storedStateRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "provedStateRoot", - "type": "bytes32" - } - ], - "name": "ProveNonDeterministicPendingState", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -696,32 +655,6 @@ "name": "SetBatchFee", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "newMultiplierBatchFee", - "type": "uint16" - } - ], - "name": "SetMultiplierBatchFee", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "newPendingStateTimeout", - "type": "uint64" - } - ], - "name": "SetPendingStateTimeout", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -735,32 +668,6 @@ "name": "SetTrustedAggregator", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "newTrustedAggregatorTimeout", - "type": "uint64" - } - ], - "name": "SetTrustedAggregatorTimeout", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "newVerifyBatchTimeTarget", - "type": "uint64" - } - ], - "name": "SetVerifyBatchTimeTarget", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -789,38 +696,14 @@ { "anonymous": false, "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" - }, { "indexed": false, - "internalType": "bytes32", - "name": "exitRoot", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "aggregator", - "type": "address" + "internalType": "string", + "name": "rollupManagerVersion", + "type": "string" } ], - "name": "VerifyBatches", + "name": "UpdateRollupManagerVersion", "type": "event" }, { @@ -873,6 +756,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "ROLLUP_MANAGER_VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "activateEmergencyState", @@ -888,7 +784,7 @@ "type": "address" }, { - "internalType": "contract IVerifierRollup", + "internalType": "address", "name": "verifier", "type": "address" }, @@ -904,13 +800,18 @@ }, { "internalType": "bytes32", - "name": "genesis", + "name": "initRoot", "type": "bytes32" }, { - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" } ], "name": "addExistingRollup", @@ -926,7 +827,7 @@ "type": "address" }, { - "internalType": "contract IVerifierRollup", + "internalType": "address", "name": "verifier", "type": "address" }, @@ -936,8 +837,8 @@ "type": "uint64" }, { - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" }, { @@ -949,6 +850,11 @@ "internalType": "string", "name": "description", "type": "string" + }, + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" } ], "name": "addNewRollupType", @@ -1001,24 +907,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "pendingStateNum", - "type": "uint64" - } - ], - "name": "consolidatePendingState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1069,6 +957,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newStateRoot", + "type": "uint256" + } + ], + "name": "exposed_checkStateRootInsidePrime", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, { "inputs": [], "name": "getBatchFee", @@ -1103,8 +1010,42 @@ "type": "uint32" }, { - "internalType": "uint64", - "name": "initNumBatch", + "internalType": "bytes32", + "name": "l1InfoTreeRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newPessimisticRoot", + "type": "bytes32" + } + ], + "name": "getInputPessimisticBytes", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "rollupID", + "type": "uint32" + }, + { + "internalType": "uint64", + "name": "initNumBatch", "type": "uint64" }, { @@ -1214,52 +1155,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "batchNum", - "type": "uint64" - } - ], - "name": "getRollupPendingStateTransitions", - "outputs": [ - { - "components": [ - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastVerifiedBatch", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "exitRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" - } - ], - "internalType": "struct LegacyZKEVMStateVariables.PendingState", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1356,6 +1251,13 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -1407,30 +1309,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "pendingStateNum", - "type": "uint64" - } - ], - "name": "isPendingStateConsolidable", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "lastAggregationTimestamp", @@ -1457,19 +1335,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "multiplierBatchFee", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1507,67 +1372,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "initPendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalPendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initNumBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalNewBatch", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "newLocalExitRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newStateRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[24]", - "name": "proof", - "type": "bytes32[24]" - } - ], - "name": "overridePendingState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pendingStateTimeout", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "pol", @@ -1594,54 +1398,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "initPendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalPendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initNumBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalNewBatch", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "newLocalExitRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newStateRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[24]", - "name": "proof", - "type": "bytes32[24]" - } - ], - "name": "proveNonDeterministicPendingState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1739,64 +1495,152 @@ "name": "rollupIDToRollupData", "outputs": [ { - "internalType": "contract IPolygonRollupBase", - "name": "rollupContract", - "type": "address" - }, - { - "internalType": "uint64", - "name": "chainID", - "type": "uint64" - }, - { - "internalType": "contract IVerifierRollup", - "name": "verifier", - "type": "address" - }, - { - "internalType": "uint64", - "name": "forkID", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "lastLocalExitRoot", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "lastBatchSequenced", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastVerifiedBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastPendingState", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastPendingStateConsolidated", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastVerifiedBatchBeforeUpgrade", - "type": "uint64" - }, + "components": [ + { + "internalType": "contract IPolygonRollupBase", + "name": "rollupContract", + "type": "address" + }, + { + "internalType": "uint64", + "name": "chainID", + "type": "uint64" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint64", + "name": "forkID", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "lastLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "lastBatchSequenced", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "_legacyLastPendingState", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "_legacyLastPendingStateConsolidated", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatchBeforeUpgrade", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rollupTypeID", + "type": "uint64" + }, + { + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", + "type": "uint8" + } + ], + "internalType": "struct PolygonRollupManager.RollupDataReturn", + "name": "rollupData", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { - "internalType": "uint64", - "name": "rollupTypeID", - "type": "uint64" - }, + "internalType": "uint32", + "name": "rollupID", + "type": "uint32" + } + ], + "name": "rollupIDToRollupDataV2", + "outputs": [ { - "internalType": "uint8", - "name": "rollupCompatibilityID", - "type": "uint8" + "components": [ + { + "internalType": "address", + "name": "rollupContract", + "type": "address" + }, + { + "internalType": "uint64", + "name": "chainID", + "type": "uint64" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint64", + "name": "forkID", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "lastLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "lastBatchSequenced", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatchBeforeUpgrade", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rollupTypeID", + "type": "uint64" + }, + { + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "lastPessimisticRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" + } + ], + "internalType": "struct PolygonRollupManager.RollupDataReturnV2", + "name": "rollupData", + "type": "tuple" } ], "stateMutability": "view", @@ -1831,7 +1675,7 @@ "type": "address" }, { - "internalType": "contract IVerifierRollup", + "internalType": "address", "name": "verifier", "type": "address" }, @@ -1841,8 +1685,8 @@ "type": "uint64" }, { - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" }, { @@ -1854,6 +1698,11 @@ "internalType": "bytes32", "name": "genesis", "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" } ], "stateMutability": "view", @@ -1875,51 +1724,22 @@ { "inputs": [ { - "internalType": "uint16", - "name": "newMultiplierBatchFee", - "type": "uint16" - } - ], - "name": "setMultiplierBatchFee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "newPendingStateTimeout", - "type": "uint64" - } - ], - "name": "setPendingStateTimeout", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + "internalType": "uint32", + "name": "rollupID", + "type": "uint32" + }, { - "internalType": "uint64", - "name": "newTrustedAggregatorTimeout", - "type": "uint64" - } - ], - "name": "setTrustedAggregatorTimeout", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ + "internalType": "bytes32", + "name": "lastLocalExitRoot", + "type": "bytes32" + }, { - "internalType": "uint64", - "name": "newVerifyBatchTimeTarget", - "type": "uint64" + "internalType": "bytes32", + "name": "lastPessimisticRoot", + "type": "bytes32" } ], - "name": "setVerifyBatchTimeTarget", + "name": "setRollupData", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -1950,19 +1770,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "trustedAggregatorTimeout", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -2004,19 +1811,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "verifyBatchTimeTarget", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -2060,7 +1854,7 @@ "type": "bytes32[24]" } ], - "name": "verifyBatches", + "name": "verifyBatchesTrustedAggregator", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -2073,19 +1867,9 @@ "type": "uint32" }, { - "internalType": "uint64", - "name": "pendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initNumBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalNewBatch", - "type": "uint64" + "internalType": "uint32", + "name": "l1InfoTreeLeafCount", + "type": "uint32" }, { "internalType": "bytes32", @@ -2094,28 +1878,23 @@ }, { "internalType": "bytes32", - "name": "newStateRoot", + "name": "newPessimisticRoot", "type": "bytes32" }, { - "internalType": "address", - "name": "beneficiary", - "type": "address" - }, - { - "internalType": "bytes32[24]", + "internalType": "bytes", "name": "proof", - "type": "bytes32[24]" + "type": "bytes" } ], - "name": "verifyBatchesTrustedAggregator", + "name": "verifyPessimisticTrustedAggregator", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ], - "bytecode": "0x60e060405234801562000010575f80fd5b50604051620061ae380380620061ae83398101604081905262000033916200013c565b6001600160a01b0380841660805280831660c052811660a0528282826200005962000065565b5050505050506200018d565b5f54610100900460ff1615620000d15760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116101562000122575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b038116811462000139575f80fd5b50565b5f805f606084860312156200014f575f80fd5b83516200015c8162000124565b60208501519093506200016f8162000124565b6040850151909250620001828162000124565b809150509250925092565b60805160a05160c051615fbe620001f05f395f81816109f5015281816122ed015261383101525f81816107a601528181612bab0152613b1f01525f818161093801528181610f39015281816110e101528181611bfa0152613a140152615fbe5ff3fe608060405234801562000010575f80fd5b5060043610620002c0575f3560e01c8063066ec01214620002c4578063080b311114620002f05780630a0d9fbe14620003185780630e36f582146200033357806311f6b287146200034c57806312b86e1914620003635780631489ed10146200037a57806315064c9614620003915780631608859c146200039f5780631796a1ae14620003b65780631816b7e514620003dd5780632072f6c514620003f4578063248a9ca314620003fe5780632528016914620004245780632f2ff15d14620004d857806330c27dde14620004ef57806336568abe1462000503578063394218e9146200051a578063477fa270146200053157806355a71ee0146200053a57806360469169146200057d57806365c0504d14620005875780637222020f1462000635578063727885e9146200064c5780637975fcfe14620006635780637fb6e76a1462000689578063841b24d714620006b157806387c20c0114620006cc5780638bd4f07114620006e35780638f698ec514620006fa5780638fd88cc2146200071157806391d14854146200072857806399f5634e146200073f5780639a908e7314620007495780639c9f3dfe1462000760578063a066215c1462000777578063a217fddf146200078e578063a2967d991462000796578063a3c573eb14620007a0578063afd23cbe14620007d7578063b99d0ad71462000801578063c1acbc3414620008d8578063c4c928c214620008f3578063ceee281d146200090a578063d02103ca1462000932578063d5073f6f146200095a578063d547741f1462000971578063d939b3151462000988578063dbc16976146200099c578063dde0ff7714620009a6578063dfdb8c5e14620009c1578063e0bfd3d214620009d8578063e46761c414620009ef578063f34eb8eb1462000a17578063f4e926751462000a2e578063f9c4c2ae1462000a3f575b5f80fd5b608454620002d8906001600160401b031681565b604051620002e791906200498b565b60405180910390f35b6200030762000301366004620049ca565b62000b55565b6040519015158152602001620002e7565b608554620002d890600160401b90046001600160401b031681565b6200034a6200034436600462004a15565b62000b7e565b005b620002d86200035d36600462004a9c565b62000e71565b6200034a6200037436600462004aca565b62000e90565b6200034a6200038b36600462004b5c565b62001038565b606f54620003079060ff1681565b6200034a620003b0366004620049ca565b620011c0565b607e54620003c79063ffffffff1681565b60405163ffffffff9091168152602001620002e7565b6200034a620003ee36600462004be1565b62001253565b6200034a620012fe565b620004156200040f36600462004c0b565b620013c3565b604051908152602001620002e7565b620004a462000435366004620049ca565b60408051606080820183525f808352602080840182905292840181905263ffffffff959095168552608182528285206001600160401b03948516865260030182529382902082519485018352805485526001015480841691850191909152600160401b90049091169082015290565b60408051825181526020808401516001600160401b03908116918301919091529282015190921690820152606001620002e7565b6200034a620004e936600462004c23565b620013d7565b608754620002d8906001600160401b031681565b6200034a6200051436600462004c23565b620013f9565b6200034a6200052b36600462004c54565b62001433565b60865462000415565b620004156200054b366004620049ca565b63ffffffff82165f9081526081602090815260408083206001600160401b038516845260020190915290205492915050565b62000415620014e1565b620005eb6200059836600462004a9c565b607f6020525f90815260409020805460018201546002909201546001600160a01b0391821692918216916001600160401b03600160a01b8204169160ff600160e01b8304811692600160e81b9004169086565b604080516001600160a01b0397881681529690951660208701526001600160401b039093169385019390935260ff166060840152901515608083015260a082015260c001620002e7565b6200034a6200064636600462004a9c565b620014f8565b6200034a6200065d36600462004d32565b620015e0565b6200067a6200067436600462004df8565b62001a5a565b604051620002e7919062004eab565b620003c76200069a36600462004c54565b60836020525f908152604090205463ffffffff1681565b608454620002d890600160c01b90046001600160401b031681565b6200034a620006dd36600462004b5c565b62001a8c565b6200034a620006f436600462004aca565b62001da7565b6200034a6200070b36600462004ebf565b62001e5e565b6200034a6200072236600462004f6a565b62001ee2565b620003076200073936600462004c23565b620022bf565b62000415620022e9565b620002d86200075a36600462004f89565b620023cf565b6200034a6200077136600462004c54565b62002596565b6200034a6200078836600462004c54565b62002638565b620004155f81565b62000415620026d6565b620007c87f000000000000000000000000000000000000000000000000000000000000000081565b604051620002e7919062004fb4565b608554620007ed90600160801b900461ffff1681565b60405161ffff9091168152602001620002e7565b6200089662000812366004620049ca565b60408051608080820183525f8083526020808401829052838501829052606093840182905263ffffffff969096168152608186528381206001600160401b03958616825260040186528390208351918201845280548086168352600160401b9004909416948101949094526001830154918401919091526002909101549082015290565b604051620002e7919081516001600160401b03908116825260208084015190911690820152604082810151908201526060918201519181019190915260800190565b608454620002d890600160801b90046001600160401b031681565b6200034a6200090436600462004fc8565b62002a8b565b620003c76200091b3660046200503f565b60826020525f908152604090205463ffffffff1681565b620007c87f000000000000000000000000000000000000000000000000000000000000000081565b6200034a6200096b36600462004c0b565b62002ab8565b6200034a6200098236600462004c23565b62002b42565b608554620002d8906001600160401b031681565b6200034a62002b64565b608454620002d890600160401b90046001600160401b031681565b6200034a620009d23660046200505d565b62002c1d565b6200034a620009e93660046200509d565b62002d6e565b620007c87f000000000000000000000000000000000000000000000000000000000000000081565b6200034a62000a2836600462005115565b62002e5e565b608054620003c79063ffffffff1681565b62000ad562000a5036600462004a9c565b60816020525f9081526040902080546001820154600583015460068401546007909401546001600160a01b0380851695600160a01b958690046001600160401b039081169692861695929092048216939282821692600160401b808404821693600160801b808204841694600160c01b90920484169380831693830416910460ff168c565b604080516001600160a01b039d8e1681526001600160401b039c8d1660208201529c909a16998c019990995296891660608b015260808a019590955292871660a089015290861660c0880152851660e0870152841661010086015283166101208501529190911661014083015260ff1661016082015261018001620002e7565b63ffffffff82165f90815260816020526040812062000b75908362003040565b90505b92915050565b5f54600290610100900460ff1615801562000b9f57505f5460ff8083169116105b62000c085760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805461010060ff841661ffff199092169190911717905560858054608480546001600160c01b0316600160c01b6001600160401b038a8116919091029190911790915567016345785d8a000060865588166001600160801b03199091161760e160431b1761ffff60801b19166101f560811b17905562000c8862003084565b62000ca25f8051602062005f6983398151915288620030f0565b62000cae5f84620030f0565b62000cc85f8051602062005e6983398151915284620030f0565b62000ce25f8051602062005ec983398151915284620030f0565b62000cfc5f8051602062005e0983398151915284620030f0565b62000d165f8051602062005e4983398151915285620030f0565b62000d305f8051602062005f4983398151915285620030f0565b62000d4a5f8051602062005e8983398151915285620030f0565b62000d645f8051602062005ee983398151915285620030f0565b62000d8c5f8051602062005f698339815191525f8051602062005de9833981519152620030fc565b62000da65f8051602062005de983398151915285620030f0565b62000dc05f8051602062005e2983398151915285620030f0565b62000de85f8051602062005f298339815191525f8051602062005f09833981519152620030fc565b62000e025f8051602062005f2983398151915283620030f0565b62000e1c5f8051602062005f0983398151915283620030f0565b62000e285f33620030f0565b5f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b63ffffffff81165f90815260816020526040812062000b78906200314f565b5f8051602062005f6983398151915262000eaa81620031be565b63ffffffff89165f90815260816020526040902062000ed0818a8a8a8a8a8a8a620031ca565b600681018054600160401b600160801b031916600160401b6001600160401b038981169182029290921783555f9081526002840160205260409020869055600583018790559054600160801b9004161562000f37576006810180546001600160801b031690555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62000f70620026d6565b6040518263ffffffff1660e01b815260040162000f8f91815260200190565b5f604051808303815f87803b15801562000fa7575f80fd5b505af115801562000fba573d5f803e3d5ffd5b5050608480546001600160c01b031661127560c71b1790555050604080516001600160401b03881681526020810186905290810186905233606082015263ffffffff8b16907f3182bd6e6f74fc1fdc88b60f3a4f4c7f79db6ae6f5b88a1b3f5a1e28ec210d5e9060800160405180910390a250505050505050505050565b5f8051602062005f698339815191526200105281620031be565b63ffffffff89165f90815260816020526040902062001078818a8a8a8a8a8a8a62003546565b600681018054600160401b600160801b031916600160401b6001600160401b038a81169182029290921783555f9081526002840160205260409020879055600583018890559054600160801b90041615620010df576006810180546001600160801b031690555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62001118620026d6565b6040518263ffffffff1660e01b81526004016200113791815260200190565b5f604051808303815f87803b1580156200114f575f80fd5b505af115801562001162573d5f803e3d5ffd5b50505050336001600160a01b03168a63ffffffff167fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d389888a604051620011ac93929190620051a7565b60405180910390a350505050505050505050565b63ffffffff82165f908152608160205260409020620011ee5f8051602062005f6983398151915233620022bf565b6200124257606f5460ff16156200121857604051630bc011ff60e21b815260040160405180910390fd5b62001224818362003040565b6200124257604051630674f25160e11b815260040160405180910390fd5b6200124e818362003932565b505050565b5f8051602062005ee98339815191526200126d81620031be565b6103e88261ffff1610806200128757506103ff8261ffff16115b15620012a657604051630984a67960e31b815260040160405180910390fd5b6085805461ffff60801b1916600160801b61ffff8516908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a15050565b620013185f8051602062005f2983398151915233620022bf565b620013b757608454600160801b90046001600160401b0316158062001368575060845442906200135d9062093a8090600160801b90046001600160401b0316620051dc565b6001600160401b0316115b8062001398575060875442906200138d9062093a80906001600160401b0316620051dc565b6001600160401b0316115b15620013b75760405163692baaad60e11b815260040160405180910390fd5b620013c162003b1d565b565b5f9081526034602052604090206001015490565b620013e282620013c3565b620013ed81620031be565b6200124e838362003b97565b6001600160a01b03811633146200142357604051630b4ad1cd60e31b815260040160405180910390fd5b6200142f828262003c02565b5050565b5f8051602062005ee98339815191526200144d81620031be565b606f5460ff166200148f576084546001600160401b03600160c01b9091048116908316106200148f5760405163401636df60e01b815260040160405180910390fd5b608480546001600160c01b0316600160c01b6001600160401b038516021790556040517f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a190620012f29084906200498b565b5f6086546064620014f3919062005206565b905090565b5f8051602062005e498339815191526200151281620031be565b63ffffffff82161580620015315750607e5463ffffffff908116908316115b156200155057604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff82165f908152607f60205260409020600180820154600160e81b900460ff16151590036200159657604051633b8d3d9960e01b815260040160405180910390fd5b60018101805460ff60e81b1916600160e81b17905560405163ffffffff8416907f4710d2ee567ef1ed6eb2f651dde4589524bcf7cebc62147a99b281cc836e7e44905f90a2505050565b5f8051602062005f49833981519152620015fa81620031be565b63ffffffff88161580620016195750607e5463ffffffff908116908916115b156200163857604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff88165f908152607f60205260409020600180820154600160e81b900460ff16151590036200167e57604051633b8d3d9960e01b815260040160405180910390fd5b63ffffffff6001600160401b0389161115620016ad57604051634c753f5760e01b815260040160405180910390fd5b6001600160401b0388165f9081526083602052604090205463ffffffff1615620016ea576040516337c8fe0960e11b815260040160405180910390fd5b608080545f91908290620017049063ffffffff1662005220565b825463ffffffff8281166101009490940a93840293021916919091179091558254604080515f80825260208201928390529394506001600160a01b0390921691309162001751906200497d565b6200175f9392919062005245565b604051809103905ff08015801562001779573d5f803e3d5ffd5b5090508160835f8c6001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508160825f836001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8463ffffffff1663ffffffff1681526020019081526020015f20905081815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508360010160149054906101000a90046001600160401b03168160010160146101000a8154816001600160401b0302191690836001600160401b03160217905550836001015f9054906101000a90046001600160a01b0316816001015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508a815f0160146101000a8154816001600160401b0302191690836001600160401b031602179055508360020154816002015f806001600160401b031681526020019081526020015f20819055508b63ffffffff168160070160086101000a8154816001600160401b0302191690836001600160401b0316021790555083600101601c9054906101000a900460ff168160070160106101000a81548160ff021916908360ff1602179055508263ffffffff167f194c983456df6701c6a50830b90fe80e72b823411d0d524970c9590dc277a6418d848e8c604051620019dd949392919063ffffffff9490941684526001600160a01b0392831660208501526001600160401b0391909116604084015216606082015260800190565b60405180910390a2604051633892b81160e11b81526001600160a01b0383169063712570229062001a1d908d908d9088908e908e908e906004016200527b565b5f604051808303815f87803b15801562001a35575f80fd5b505af115801562001a48573d5f803e3d5ffd5b50505050505050505050505050505050565b63ffffffff86165f90815260816020526040902060609062001a8190878787878762003c6b565b979650505050505050565b606f5460ff161562001ab157604051630bc011ff60e21b815260040160405180910390fd5b63ffffffff88165f9081526081602090815260408083206084546001600160401b038a81168652600383019094529190932060010154429262001aff92600160c01b900481169116620051dc565b6001600160401b0316111562001b2857604051638a0704d360e01b815260040160405180910390fd5b6103e862001b378888620052dd565b6001600160401b0316111562001b6057604051635acfba9d60e11b815260040160405180910390fd5b62001b72818989898989898962003546565b62001b7e818762003da5565b6085546001600160401b03165f0362001c8557600681018054600160401b600160801b031916600160401b6001600160401b038981169182029290921783555f9081526002840160205260409020869055600583018790559054600160801b9004161562001bf8576006810180546001600160801b031690555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62001c31620026d6565b6040518263ffffffff1660e01b815260040162001c5091815260200190565b5f604051808303815f87803b15801562001c68575f80fd5b505af115801562001c7b573d5f803e3d5ffd5b5050505062001d4e565b62001c908162003f9c565b600681018054600160801b90046001600160401b031690601062001cb48362005300565b82546001600160401b039182166101009390930a92830292820219169190911790915560408051608081018252428316815289831660208083019182528284018b8152606084018b81526006890154600160801b900487165f90815260048a01909352949091209251835492518616600160401b026001600160801b03199093169516949094171781559151600183015551600290910155505b336001600160a01b03168963ffffffff167faac1e7a157b259544ebacd6e8a82ae5d6c8f174e12aa48696277bcc9a661f0b488878960405162001d9493929190620051a7565b60405180910390a3505050505050505050565b606f5460ff161562001dcc57604051630bc011ff60e21b815260040160405180910390fd5b63ffffffff88165f90815260816020526040902062001df28189898989898989620031ca565b6001600160401b0387165f9081526004820160209081526040918290206002015482519081529081018590527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a162001e5362003b1d565b505050505050505050565b80516080805463ffffffff191663ffffffff9092169190911790555f5b81518110156200142f5781818151811062001e9a5762001e9a62005326565b602002602001015160815f83600162001eb491906200533a565b63ffffffff16815260208101919091526040015f20600501558062001ed98162005350565b91505062001e7b565b62001efc5f8051602062005e0983398151915233620022bf565b15801562001f7f5750336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562001f4d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001f7391906200536b565b6001600160a01b031614155b1562001f9e57604051630d03687f60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526082602052604081205463ffffffff169081900362001fde576040516374a086a360e01b815260040160405180910390fd5b63ffffffff81165f90815260816020526040902060068101546001600160401b03908116908416811115806200202b575060068201546001600160401b03600160401b9091048116908516105b156200204a5760405163cb23ebdf60e01b815260040160405180910390fd5b805b846001600160401b0316816001600160401b031614620020e5576001600160401b038082165f908152600385016020526040902060010154600160401b90048116908616811015620020b157604051639753965f60e01b815260040160405180910390fd5b6001600160401b039091165f908152600384016020526040812090815560010180546001600160801b03191690556200204c565b6006830180546001600160401b0319166001600160401b0387161790556200210e8583620052dd565b608480545f906200212a9084906001600160401b0316620052dd565b82546101009290920a6001600160401b038181021990931691831602179091556006850154600160801b900416159050620021e9575f6200216b846200314f565b60068501549091506200218f90600160401b90046001600160401b031682620052dd565b60848054600890620021b3908490600160401b90046001600160401b0316620052dd565b82546001600160401b039182166101009390930a928302919092021990911617905550506006830180546001600160801b031690555b6001600160401b0385165f8181526003850160205260409081902054905163334d6f6760e11b8152600481019290925260248201526001600160a01b0387169063669adece906044015f604051808303815f87803b1580156200224a575f80fd5b505af11580156200225d573d5f803e3d5ffd5b505050506001600160401b0385165f81815260038501602090815260409182902054915191825263ffffffff8716917f80a6d395a55aed8126079cb8247f0a6848b1440ca2cdca3b4386f250c3529402910160405180910390a3505050505050565b5f9182526034602090815260408084206001600160a01b0393909316845291905290205460ff1690565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040162002339919062004fb4565b602060405180830381865afa15801562002355573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200237b919062005389565b6084549091505f90620023a1906001600160401b03600160401b820481169116620052dd565b6001600160401b03169050805f03620023bc575f9250505090565b620023c88183620053b5565b9250505090565b606f545f9060ff1615620023f657604051630bc011ff60e21b815260040160405180910390fd5b335f9081526082602052604081205463ffffffff16908190036200242d576040516371653c1560e01b815260040160405180910390fd5b836001600160401b03165f036200245757604051632590ccf960e01b815260040160405180910390fd5b63ffffffff81165f9081526081602052604081206084805491928792620024899084906001600160401b0316620051dc565b82546101009290920a6001600160401b0381810219909316918316021790915560068301541690505f620024be8783620051dc565b6006840180546001600160401b038084166001600160401b03199092168217909255604080516060810182528a815242841660208083019182528886168385019081525f95865260038b0190915292909320905181559151600192909201805491518416600160401b026001600160801b0319909216929093169190911717905590506200254c8362003f9c565b8363ffffffff167f1d9f30260051d51d70339da239ea7b080021adcaabfa71c9b0ea339a20cf9a25826040516200258491906200498b565b60405180910390a29695505050505050565b5f8051602062005ee9833981519152620025b081620031be565b606f5460ff16620025eb576085546001600160401b0390811690831610620025eb5760405163048a05a960e41b815260040160405180910390fd5b608580546001600160401b0319166001600160401b0384161790556040517fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c7590620012f29084906200498b565b5f8051602062005ee98339815191526200265281620031be565b62015180826001600160401b031611156200268057604051631c0cfbfd60e31b815260040160405180910390fd5b60858054600160401b600160801b031916600160401b6001600160401b038516021790556040517f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c2890620012f29084906200498b565b6080545f9063ffffffff16808203620026f057505f919050565b5f816001600160401b038111156200270c576200270c62004c70565b60405190808252806020026020018201604052801562002736578160200160208202803683370190505b5090505f5b82811015620027a65760815f620027548360016200533a565b63ffffffff1663ffffffff1681526020019081526020015f206005015482828151811062002786576200278662005326565b6020908102919091010152806200279d8162005350565b9150506200273b565b505f60205b83600114620029e6575f620027c2600286620053cb565b620027cf600287620053b5565b620027db91906200533a565b90505f816001600160401b03811115620027f957620027f962004c70565b60405190808252806020026020018201604052801562002823578160200160208202803683370190505b5090505f5b828110156200299a576200283e600184620053e1565b8114801562002859575062002855600288620053cb565b6001145b15620028d957856200286d82600262005206565b8151811062002880576200288062005326565b6020026020010151856040516020016200289c929190620053f7565b60405160208183030381529060405280519060200120828281518110620028c757620028c762005326565b60200260200101818152505062002985565b85620028e782600262005206565b81518110620028fa57620028fa62005326565b60200260200101518682600262002912919062005206565b6200291f9060016200533a565b8151811062002932576200293262005326565b60200260200101516040516020016200294d929190620053f7565b6040516020818303038152906040528051906020012082828151811062002978576200297862005326565b6020026020010181815250505b80620029918162005350565b91505062002828565b508094508195508384604051602001620029b6929190620053f7565b6040516020818303038152906040528051906020012093508280620029db9062005405565b9350505050620027ab565b5f835f81518110620029fc57620029fc62005326565b602002602001015190505f5b8281101562002a8157818460405160200162002a26929190620053f7565b604051602081830303815290604052805190602001209150838460405160200162002a53929190620053f7565b604051602081830303815290604052805190602001209350808062002a789062005350565b91505062002a08565b5095945050505050565b5f8051602062005e0983398151915262002aa581620031be565b62002ab284848462004065565b50505050565b5f8051602062005e2983398151915262002ad281620031be565b683635c9adc5dea0000082118062002aed5750633b9aca0082105b1562002b0c57604051638586952560e01b815260040160405180910390fd5b60868290556040518281527ffb383653f53ee079978d0c9aff7aeff04a10166ce244cca9c9f9d8d96bed45b290602001620012f2565b62002b4d82620013c3565b62002b5881620031be565b6200124e838362003c02565b5f8051602062005e8983398151915262002b7e81620031be565b608780546001600160401b031916426001600160401b031617905560408051636de0b4bb60e11b815290517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163dbc16976916004808301925f92919082900301818387803b15801562002bf9575f80fd5b505af115801562002c0c573d5f803e3d5ffd5b5050505062002c1a62004343565b50565b336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562002c65573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002c8b91906200536b565b6001600160a01b03161462002cb35760405163696072e960e01b815260040160405180910390fd5b6001600160a01b0382165f9081526082602090815260408083205463ffffffff1683526081909152902060068101546001600160401b03808216600160401b909204161462002d155760405163664316a560e11b815260040160405180910390fd5b600781015463ffffffff8316600160401b9091046001600160401b03161062002d5157604051633e37e23360e01b815260040160405180910390fd5b604080515f8152602081019091526200124e908490849062004065565b5f8051602062005ec983398151915262002d8881620031be565b6001600160401b0384165f9081526083602052604090205463ffffffff161562002dc5576040516337c8fe0960e11b815260040160405180910390fd5b63ffffffff6001600160401b038516111562002df457604051634c753f5760e01b815260040160405180910390fd5b6001600160a01b0387165f9081526082602052604090205463ffffffff161562002e3157604051630d409b9360e41b815260040160405180910390fd5b5f62002e4188888888876200439b565b5f8080526002909101602052604090209390935550505050505050565b5f8051602062005e6983398151915262002e7881620031be565b607e80545f9190829062002e929063ffffffff1662005220565b91906101000a81548163ffffffff021916908363ffffffff160217905590506040518060c00160405280896001600160a01b03168152602001886001600160a01b03168152602001876001600160401b031681526020018660ff1681526020015f1515815260200185815250607f5f8363ffffffff1663ffffffff1681526020019081526020015f205f820151815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160146101000a8154816001600160401b0302191690836001600160401b03160217905550606082015181600101601c6101000a81548160ff021916908360ff160217905550608082015181600101601d6101000a81548160ff02191690831515021790555060a082015181600201559050508063ffffffff167fa2970448b3bd66ba7e524e7b2a5b9cf94fa29e32488fb942afdfe70dd4b77b528989898989896040516200302e969594939291906200541d565b60405180910390a25050505050505050565b6085546001600160401b038281165f9081526004850160205260408120549092429262003072929181169116620051dc565b6001600160401b031611159392505050565b5f54610100900460ff16620013c15760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000bff565b6200142f828262003b97565b5f6200310883620013c3565b5f84815260346020526040808220600101859055519192508391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b60068101545f90600160801b90046001600160401b031615620031a1575060068101546001600160401b03600160801b90910481165f9081526004909201602052604090912054600160401b90041690565b5060060154600160401b90046001600160401b031690565b919050565b62002c1a8133620045bb565b60078801545f906001600160401b039081169087161015620031ff5760405163ead1340b60e01b815260040160405180910390fd5b6001600160401b038816156200329f5760068901546001600160401b03600160801b90910481169089161115620032495760405163bb14c20560e01b815260040160405180910390fd5b506001600160401b038088165f90815260048a0160205260409020600281015481549092888116600160401b90920416146200329857604051632bd2e3e760e01b815260040160405180910390fd5b5062003313565b506001600160401b0385165f90815260028901602052604090205480620032d9576040516324cbdcc360e11b815260040160405180910390fd5b60068901546001600160401b03600160401b909104811690871611156200331357604051630f2b74f160e11b815260040160405180910390fd5b60068901546001600160401b03600160801b909104811690881611806200334c5750876001600160401b0316876001600160401b031611155b8062003370575060068901546001600160401b03600160c01b909104811690881611155b156200338f5760405163bfa7079f60e01b815260040160405180910390fd5b6001600160401b038781165f90815260048b016020526040902054600160401b9004811690861614620033d5576040516332a2a77f60e01b815260040160405180910390fd5b5f620033e68a888888868962003c6b565b90505f5f8051602062005ea98339815191526002836040516200340a919062005469565b602060405180830381855afa15801562003426573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906200344b919062005389565b620034579190620053cb565b60018c0154604080516020810182528381529051634890ed4560e11b81529293506001600160a01b0390911691639121da8a916200349b9188919060040162005486565b602060405180830381865afa158015620034b7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620034dd9190620054c2565b620034fb576040516309bde33960e01b815260040160405180910390fd5b6001600160401b0389165f90815260048c016020526040902060020154859003620035395760405163a47276bd60e01b815260040160405180910390fd5b5050505050505050505050565b5f80620035538a6200314f565b60078b01549091506001600160401b039081169089161015620035895760405163ead1340b60e01b815260040160405180910390fd5b6001600160401b038916156200362b5760068a01546001600160401b03600160801b9091048116908a161115620035d35760405163bb14c20560e01b815260040160405180910390fd5b6001600160401b03808a165f90815260048c01602052604090206002810154815490945090918a8116600160401b90920416146200362457604051632bd2e3e760e01b815260040160405180910390fd5b506200369a565b6001600160401b0388165f90815260028b01602052604090205491508162003666576040516324cbdcc360e11b815260040160405180910390fd5b806001600160401b0316886001600160401b031611156200369a57604051630f2b74f160e11b815260040160405180910390fd5b806001600160401b0316876001600160401b031611620036cd5760405163b9b18f5760e01b815260040160405180910390fd5b5f620036de8b8a8a8a878b62003c6b565b90505f5f8051602062005ea983398151915260028360405162003702919062005469565b602060405180830381855afa1580156200371e573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019062003743919062005389565b6200374f9190620053cb565b60018d0154604080516020810182528381529051634890ed4560e11b81529293506001600160a01b0390911691639121da8a91620037939189919060040162005486565b602060405180830381865afa158015620037af573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620037d59190620054c2565b620037f3576040516309bde33960e01b815260040160405180910390fd5b5f62003800848b620052dd565b90506200385987826001600160401b03166200381b620022e9565b62003827919062005206565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190620045e5565b80608460088282829054906101000a90046001600160401b03166200387f9190620051dc565b82546101009290920a6001600160401b0381810219909316918316021790915560848054600160801b600160c01b031916600160801b428416021790558e546040516332c2d15360e01b8152918d166004830152602482018b90523360448301526001600160a01b031691506332c2d153906064015f604051808303815f87803b1580156200390c575f80fd5b505af11580156200391f573d5f803e3d5ffd5b5050505050505050505050505050505050565b60068201546001600160401b03600160c01b909104811690821611158062003971575060068201546001600160401b03600160801b9091048116908216115b15620039905760405163d086b70b60e01b815260040160405180910390fd5b6001600160401b038181165f81815260048501602090815260408083208054600689018054600160401b600160801b031916600160401b92839004909816918202979097178755600280830154828752908a0190945291909320919091556001820154600587015583546001600160c01b0316600160c01b909302929092179092557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62003a4b620026d6565b6040518263ffffffff1660e01b815260040162003a6a91815260200190565b5f604051808303815f87803b15801562003a82575f80fd5b505af115801562003a95573d5f803e3d5ffd5b505085546001600160a01b03165f90815260826020908152604091829020546002870154600188015484516001600160401b03898116825294810192909252818501529188166060830152915163ffffffff90921693507f581910eb7a27738945c2f00a91f2284b2d6de9d4e472b12f901c2b0df045e21b925081900360800190a250505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562003b76575f80fd5b505af115801562003b89573d5f803e3d5ffd5b50505050620013c162004639565b62003ba38282620022bf565b6200142f575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b62003c0e8282620022bf565b156200142f575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001600160401b038086165f818152600389016020526040808220549388168252902054606092911580159062003ca0575081155b1562003cbf5760405163340c614f60e11b815260040160405180910390fd5b8062003cde576040516366385b5160e01b815260040160405180910390fd5b62003ce98462004695565b62003d07576040516305dae44f60e21b815260040160405180910390fd5b885460018a01546040516001600160601b03193360601b16602082015260348101889052605481018590526001600160c01b031960c08c811b82166074840152600160a01b94859004811b8216607c84015293909204831b82166084820152608c810187905260ac810184905260cc81018990529189901b1660ec82015260f401604051602081830303815290604052925050509695505050505050565b5f62003db1836200314f565b9050815f8062003dc28484620052dd565b6085546001600160401b0391821692505f9162003de891600160401b90041642620053e1565b90505b846001600160401b0316846001600160401b03161462003e71576001600160401b038085165f9081526003890160205260409020600181015490911682101562003e4c576001810154600160401b90046001600160401b0316945062003e6a565b62003e588686620052dd565b6001600160401b031693505062003e71565b5062003deb565b5f62003e7e8484620053e1565b90508381101562003edc57808403600c811162003e9c578062003e9f565b600c5b9050806103e80a81608560109054906101000a900461ffff1661ffff160a608654028162003ed15762003ed1620053a1565b046086555062003f53565b838103600c811162003eef578062003ef2565b600c5b90505f816103e80a82608560109054906101000a900461ffff1661ffff160a670de0b6b3a7640000028162003f2b5762003f2b620053a1565b04905080608654670de0b6b3a7640000028162003f4c5762003f4c620053a1565b0460865550505b683635c9adc5dea00000608654111562003f7a57683635c9adc5dea0000060865562003f92565b633b9aca00608654101562003f9257633b9aca006086555b5050505050505050565b60068101546001600160401b03600160c01b82048116600160801b90920416111562002c1a5760068101545f9062003fe690600160c01b90046001600160401b03166001620051dc565b905062003ff4828262003040565b156200142f5760068201545f9060029062004021908490600160801b90046001600160401b0316620052dd565b6200402d9190620054e3565b620040399083620051dc565b905062004047838262003040565b1562004059576200124e838262003932565b6200124e838362003932565b63ffffffff82161580620040845750607e5463ffffffff908116908316115b15620040a357604051637512e5cb60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526082602052604081205463ffffffff1690819003620040e3576040516374a086a360e01b815260040160405180910390fd5b63ffffffff8181165f908152608160205260409020600781015490918516600160401b9091046001600160401b0316036200413157604051634f61d51960e01b815260040160405180910390fd5b63ffffffff84165f908152607f60205260409020600180820154600160e81b900460ff16151590036200417757604051633b8d3d9960e01b815260040160405180910390fd5b60018101546007830154600160801b900460ff908116600160e01b9092041614620041b557604051635aa0d5f160e11b815260040160405180910390fd5b6001818101805491840180546001600160a01b039093166001600160a01b031984168117825591546001600160e01b0319909316909117600160a01b928390046001600160401b03908116909302179055600783018054600160401b600160801b03191663ffffffff8816600160401b021790556006830154600160c01b81048216600160801b909104909116146200426157604051639d59507b60e01b815260040160405180910390fd5b5f6200426d8462000e71565b6007840180546001600160401b0319166001600160401b038316179055825460405163278f794360e11b81529192506001600160a01b0389811692634f1ef28692620042c092169089906004016200550b565b5f604051808303815f87803b158015620042d8575f80fd5b505af1158015620042eb573d5f803e3d5ffd5b50506040805163ffffffff8a811682526001600160401b0386166020830152881693507ff585e04c05d396901170247783d3e5f0ee9c1df23072985b50af089f5e48b19d92500160405180910390a250505050505050565b606f5460ff166200436757604051635386698160e01b815260040160405180910390fd5b606f805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b608080545f9182918290620043b69063ffffffff1662005220565b91906101000a81548163ffffffff021916908363ffffffff160217905590508060835f866001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508060825f896001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff16021790555060815f8263ffffffff1663ffffffff1681526020019081526020015f20915086825f015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550848260010160146101000a8154816001600160401b0302191690836001600160401b0316021790555085826001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555083825f0160146101000a8154816001600160401b0302191690836001600160401b03160217905550828260070160106101000a81548160ff021916908360ff1602179055508063ffffffff167fadfc7d56f7e39b08b321534f14bfb135ad27698f7d2f5ad0edc2356ea9a3f850868987875f604051620045a99594939291906001600160401b0395861681526001600160a01b03949094166020850152918416604084015260ff166060830152909116608082015260a00190565b60405180910390a25095945050505050565b620045c78282620022bf565b6200142f57604051637615be1f60e11b815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526200124e90849062004719565b606f5460ff16156200465e57604051630bc011ff60e21b815260040160405180910390fd5b606f805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b5f67ffffffff000000016001600160401b038316108015620046cb575067ffffffff00000001604083901c6001600160401b0316105b8015620046ec575067ffffffff00000001608083901c6001600160401b0316105b801562004704575067ffffffff0000000160c083901c105b156200471257506001919050565b505f919050565b5f6200476f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620047f19092919063ffffffff16565b8051909150156200124e5780806020019051810190620047909190620054c2565b6200124e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000bff565b60606200480184845f8562004809565b949350505050565b6060824710156200486c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000bff565b5f80866001600160a01b0316858760405162004889919062005469565b5f6040518083038185875af1925050503d805f8114620048c5576040519150601f19603f3d011682016040523d82523d5f602084013e620048ca565b606091505b509150915062001a8187838387606083156200494a5782515f0362004942576001600160a01b0385163b620049425760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000bff565b508162004801565b620048018383815115620049615781518083602001fd5b8060405162461bcd60e51b815260040162000bff919062004eab565b6108b8806200553183390190565b6001600160401b0391909116815260200190565b803563ffffffff81168114620031b9575f80fd5b80356001600160401b0381168114620031b9575f80fd5b5f8060408385031215620049dc575f80fd5b620049e7836200499f565b9150620049f760208401620049b3565b90509250929050565b6001600160a01b038116811462002c1a575f80fd5b5f805f805f8060c0878903121562004a2b575f80fd5b863562004a388162004a00565b955062004a4860208801620049b3565b945062004a5860408801620049b3565b9350606087013562004a6a8162004a00565b9250608087013562004a7c8162004a00565b915060a087013562004a8e8162004a00565b809150509295509295509295565b5f6020828403121562004aad575f80fd5b62000b75826200499f565b80610300810183101562000b78575f80fd5b5f805f805f805f806103e0898b03121562004ae3575f80fd5b62004aee896200499f565b975062004afe60208a01620049b3565b965062004b0e60408a01620049b3565b955062004b1e60608a01620049b3565b945062004b2e60808a01620049b3565b935060a0890135925060c0890135915062004b4d8a60e08b0162004ab8565b90509295985092959890939650565b5f805f805f805f806103e0898b03121562004b75575f80fd5b62004b80896200499f565b975062004b9060208a01620049b3565b965062004ba060408a01620049b3565b955062004bb060608a01620049b3565b94506080890135935060a0890135925060c089013562004bd08162004a00565b915062004b4d8a60e08b0162004ab8565b5f6020828403121562004bf2575f80fd5b813561ffff8116811462004c04575f80fd5b9392505050565b5f6020828403121562004c1c575f80fd5b5035919050565b5f806040838503121562004c35575f80fd5b82359150602083013562004c498162004a00565b809150509250929050565b5f6020828403121562004c65575f80fd5b62000b7582620049b3565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171562004caf5762004caf62004c70565b604052919050565b5f6001600160401b0383111562004cd25762004cd262004c70565b62004ce7601f8401601f191660200162004c84565b905082815283838301111562004cfb575f80fd5b828260208301375f602084830101529392505050565b5f82601f83011262004d21575f80fd5b62000b758383356020850162004cb7565b5f805f805f805f60e0888a03121562004d49575f80fd5b62004d54886200499f565b965062004d6460208901620049b3565b9550604088013562004d768162004a00565b9450606088013562004d888162004a00565b9350608088013562004d9a8162004a00565b925060a08801356001600160401b038082111562004db6575f80fd5b62004dc48b838c0162004d11565b935060c08a013591508082111562004dda575f80fd5b5062004de98a828b0162004d11565b91505092959891949750929550565b5f805f805f8060c0878903121562004e0e575f80fd5b62004e19876200499f565b955062004e2960208801620049b3565b945062004e3960408801620049b3565b9350606087013592506080870135915060a087013590509295509295509295565b5f5b8381101562004e7657818101518382015260200162004e5c565b50505f910152565b5f815180845262004e9781602086016020860162004e5a565b601f01601f19169290920160200192915050565b602081525f62000b75602083018462004e7e565b5f602080838503121562004ed1575f80fd5b82356001600160401b038082111562004ee8575f80fd5b818501915085601f83011262004efc575f80fd5b81358181111562004f115762004f1162004c70565b8060051b915062004f2484830162004c84565b818152918301840191848101908884111562004f3e575f80fd5b938501935b8385101562004f5e5784358252938501939085019062004f43565b98975050505050505050565b5f806040838503121562004f7c575f80fd5b8235620049e78162004a00565b5f806040838503121562004f9b575f80fd5b62004fa683620049b3565b946020939093013593505050565b6001600160a01b0391909116815260200190565b5f805f6060848603121562004fdb575f80fd5b833562004fe88162004a00565b925062004ff8602085016200499f565b915060408401356001600160401b0381111562005013575f80fd5b8401601f8101861362005024575f80fd5b620050358682356020840162004cb7565b9150509250925092565b5f6020828403121562005050575f80fd5b813562004c048162004a00565b5f80604083850312156200506f575f80fd5b82356200507c8162004a00565b9150620049f7602084016200499f565b803560ff81168114620031b9575f80fd5b5f805f805f8060c08789031215620050b3575f80fd5b8635620050c08162004a00565b95506020870135620050d28162004a00565b9450620050e260408801620049b3565b9350620050f260608801620049b3565b9250608087013591506200510960a088016200508c565b90509295509295509295565b5f805f805f8060c087890312156200512b575f80fd5b8635620051388162004a00565b955060208701356200514a8162004a00565b94506200515a60408801620049b3565b93506200516a606088016200508c565b92506080870135915060a08701356001600160401b038111156200518c575f80fd5b6200519a89828a0162004d11565b9150509295509295509295565b6001600160401b039390931683526020830191909152604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b03818116838216019080821115620051ff57620051ff620051c8565b5092915050565b808202811582820484141762000b785762000b78620051c8565b5f63ffffffff8083168181036200523b576200523b620051c8565b6001019392505050565b6001600160a01b038481168252831660208201526060604082018190525f90620052729083018462004e7e565b95945050505050565b6001600160a01b038781168252868116602083015263ffffffff861660408301528416606082015260c0608082018190525f90620052bc9083018562004e7e565b82810360a0840152620052d0818562004e7e565b9998505050505050505050565b6001600160401b03828116828216039080821115620051ff57620051ff620051c8565b5f6001600160401b038281166002600160401b031981016200523b576200523b620051c8565b634e487b7160e01b5f52603260045260245ffd5b8082018082111562000b785762000b78620051c8565b5f60018201620053645762005364620051c8565b5060010190565b5f602082840312156200537c575f80fd5b815162004c048162004a00565b5f602082840312156200539a575f80fd5b5051919050565b634e487b7160e01b5f52601260045260245ffd5b5f82620053c657620053c6620053a1565b500490565b5f82620053dc57620053dc620053a1565b500690565b8181038181111562000b785762000b78620051c8565b918252602082015260400190565b5f81620054165762005416620051c8565b505f190190565b6001600160a01b038781168252861660208201526001600160401b038516604082015260ff841660608201526080810183905260c060a082018190525f9062004f5e9083018462004e7e565b5f82516200547c81846020870162004e5a565b9190910192915050565b6103208101610300808584378201835f5b6001811015620054b857815183526020928301929091019060010162005497565b5050509392505050565b5f60208284031215620054d3575f80fd5b8151801515811462004c04575f80fd5b5f6001600160401b0383811680620054ff57620054ff620053a1565b92169190910492915050565b6001600160a01b03831681526040602082018190525f90620048019083018462004e7e56fe60a06040526040516108b83803806108b883398101604081905261002291610349565b828161002e8282610056565b50506001600160a01b03821660805261004e61004960805190565b6100b4565b50505061042e565b61005f82610121565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156100a8576100a3828261019f565b505050565b6100b0610212565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6100f35f80516020610898833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a161011e81610233565b50565b806001600160a01b03163b5f0361015b57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b0316846040516101bb9190610413565b5f60405180830381855af49150503d805f81146101f3576040519150601f19603f3d011682016040523d82523d5f602084013e6101f8565b606091505b509092509050610209858383610270565b95945050505050565b34156102315760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b03811661025c57604051633173bdd160e11b81525f6004820152602401610152565b805f8051602061089883398151915261017e565b60608261028557610280826102cf565b6102c8565b815115801561029c57506001600160a01b0384163b155b156102c557604051639996b31560e01b81526001600160a01b0385166004820152602401610152565b50805b9392505050565b8051156102df5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811461030e575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b83811015610341578181015183820152602001610329565b50505f910152565b5f805f6060848603121561035b575f80fd5b610364846102f8565b9250610372602085016102f8565b60408501519092506001600160401b038082111561038e575f80fd5b818601915086601f8301126103a1575f80fd5b8151818111156103b3576103b3610313565b604051601f8201601f19908116603f011681019083821181831017156103db576103db610313565b816040528281528960208487010111156103f3575f80fd5b610404836020830160208801610327565b80955050505050509250925092565b5f8251610424818460208701610327565b9190910192915050565b6080516104536104455f395f601001526104535ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610069575f356001600160e01b03191663278f794360e11b146100615761005f61006d565b565b61005f61007d565b61005f5b61005f6100786100ab565b6100cf565b5f8061008c36600481846102ba565b81019061009991906102f5565b915091506100a782826100ed565b5050565b5f6100ca5f805160206103fe833981519152546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e8080156100e9573d5ff35b3d5ffd5b6100f682610147565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561013f5761013a82826101aa565b505050565b6100a761021c565b806001600160a01b03163b5f0361017c5780604051634c9c8ce360e01b815260040161017391906103bd565b60405180910390fd5b5f805160206103fe83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516101c691906103d1565b5f60405180830381855af49150503d805f81146101fe576040519150601f19603f3d011682016040523d82523d5f602084013e610203565b606091505b509150915061021385838361023b565b95945050505050565b341561005f5760405163b398979f60e01b815260040160405180910390fd5b6060826102505761024b82610291565b61028a565b815115801561026757506001600160a01b0384163b155b156102875783604051639996b31560e01b815260040161017391906103bd565b50805b9392505050565b8051156102a15780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f80858511156102c8575f80fd5b838611156102d4575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f8060408385031215610306575f80fd5b82356001600160a01b038116811461031c575f80fd5b915060208301356001600160401b0380821115610337575f80fd5b818501915085601f83011261034a575f80fd5b81358181111561035c5761035c6102e1565b604051601f8201601f19908116603f01168101908382118183101715610384576103846102e1565b8160405282815288602084870101111561039c575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b6001600160a01b0391909116815260200190565b5f82515f5b818110156103f057602081860181015185830152016103d6565b505f92019182525091905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220dd2cb78057147a82db29935f054595b8dd0503a8ab6ff81a03858f4554a1885864736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610373cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f066156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fbab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bdac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f59062ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f430644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000013dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68ea5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db19b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff285951141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545ea0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd08084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4a2646970667358221220a6f281564bb978fcc163a5a97bf772c7241055405295cd71dbd2f4a0bcdd9aaa64736f6c63430008140033", - "deployedBytecode": "0x608060405234801562000010575f80fd5b5060043610620002c0575f3560e01c8063066ec01214620002c4578063080b311114620002f05780630a0d9fbe14620003185780630e36f582146200033357806311f6b287146200034c57806312b86e1914620003635780631489ed10146200037a57806315064c9614620003915780631608859c146200039f5780631796a1ae14620003b65780631816b7e514620003dd5780632072f6c514620003f4578063248a9ca314620003fe5780632528016914620004245780632f2ff15d14620004d857806330c27dde14620004ef57806336568abe1462000503578063394218e9146200051a578063477fa270146200053157806355a71ee0146200053a57806360469169146200057d57806365c0504d14620005875780637222020f1462000635578063727885e9146200064c5780637975fcfe14620006635780637fb6e76a1462000689578063841b24d714620006b157806387c20c0114620006cc5780638bd4f07114620006e35780638f698ec514620006fa5780638fd88cc2146200071157806391d14854146200072857806399f5634e146200073f5780639a908e7314620007495780639c9f3dfe1462000760578063a066215c1462000777578063a217fddf146200078e578063a2967d991462000796578063a3c573eb14620007a0578063afd23cbe14620007d7578063b99d0ad71462000801578063c1acbc3414620008d8578063c4c928c214620008f3578063ceee281d146200090a578063d02103ca1462000932578063d5073f6f146200095a578063d547741f1462000971578063d939b3151462000988578063dbc16976146200099c578063dde0ff7714620009a6578063dfdb8c5e14620009c1578063e0bfd3d214620009d8578063e46761c414620009ef578063f34eb8eb1462000a17578063f4e926751462000a2e578063f9c4c2ae1462000a3f575b5f80fd5b608454620002d8906001600160401b031681565b604051620002e791906200498b565b60405180910390f35b6200030762000301366004620049ca565b62000b55565b6040519015158152602001620002e7565b608554620002d890600160401b90046001600160401b031681565b6200034a6200034436600462004a15565b62000b7e565b005b620002d86200035d36600462004a9c565b62000e71565b6200034a6200037436600462004aca565b62000e90565b6200034a6200038b36600462004b5c565b62001038565b606f54620003079060ff1681565b6200034a620003b0366004620049ca565b620011c0565b607e54620003c79063ffffffff1681565b60405163ffffffff9091168152602001620002e7565b6200034a620003ee36600462004be1565b62001253565b6200034a620012fe565b620004156200040f36600462004c0b565b620013c3565b604051908152602001620002e7565b620004a462000435366004620049ca565b60408051606080820183525f808352602080840182905292840181905263ffffffff959095168552608182528285206001600160401b03948516865260030182529382902082519485018352805485526001015480841691850191909152600160401b90049091169082015290565b60408051825181526020808401516001600160401b03908116918301919091529282015190921690820152606001620002e7565b6200034a620004e936600462004c23565b620013d7565b608754620002d8906001600160401b031681565b6200034a6200051436600462004c23565b620013f9565b6200034a6200052b36600462004c54565b62001433565b60865462000415565b620004156200054b366004620049ca565b63ffffffff82165f9081526081602090815260408083206001600160401b038516845260020190915290205492915050565b62000415620014e1565b620005eb6200059836600462004a9c565b607f6020525f90815260409020805460018201546002909201546001600160a01b0391821692918216916001600160401b03600160a01b8204169160ff600160e01b8304811692600160e81b9004169086565b604080516001600160a01b0397881681529690951660208701526001600160401b039093169385019390935260ff166060840152901515608083015260a082015260c001620002e7565b6200034a6200064636600462004a9c565b620014f8565b6200034a6200065d36600462004d32565b620015e0565b6200067a6200067436600462004df8565b62001a5a565b604051620002e7919062004eab565b620003c76200069a36600462004c54565b60836020525f908152604090205463ffffffff1681565b608454620002d890600160c01b90046001600160401b031681565b6200034a620006dd36600462004b5c565b62001a8c565b6200034a620006f436600462004aca565b62001da7565b6200034a6200070b36600462004ebf565b62001e5e565b6200034a6200072236600462004f6a565b62001ee2565b620003076200073936600462004c23565b620022bf565b62000415620022e9565b620002d86200075a36600462004f89565b620023cf565b6200034a6200077136600462004c54565b62002596565b6200034a6200078836600462004c54565b62002638565b620004155f81565b62000415620026d6565b620007c87f000000000000000000000000000000000000000000000000000000000000000081565b604051620002e7919062004fb4565b608554620007ed90600160801b900461ffff1681565b60405161ffff9091168152602001620002e7565b6200089662000812366004620049ca565b60408051608080820183525f8083526020808401829052838501829052606093840182905263ffffffff969096168152608186528381206001600160401b03958616825260040186528390208351918201845280548086168352600160401b9004909416948101949094526001830154918401919091526002909101549082015290565b604051620002e7919081516001600160401b03908116825260208084015190911690820152604082810151908201526060918201519181019190915260800190565b608454620002d890600160801b90046001600160401b031681565b6200034a6200090436600462004fc8565b62002a8b565b620003c76200091b3660046200503f565b60826020525f908152604090205463ffffffff1681565b620007c87f000000000000000000000000000000000000000000000000000000000000000081565b6200034a6200096b36600462004c0b565b62002ab8565b6200034a6200098236600462004c23565b62002b42565b608554620002d8906001600160401b031681565b6200034a62002b64565b608454620002d890600160401b90046001600160401b031681565b6200034a620009d23660046200505d565b62002c1d565b6200034a620009e93660046200509d565b62002d6e565b620007c87f000000000000000000000000000000000000000000000000000000000000000081565b6200034a62000a2836600462005115565b62002e5e565b608054620003c79063ffffffff1681565b62000ad562000a5036600462004a9c565b60816020525f9081526040902080546001820154600583015460068401546007909401546001600160a01b0380851695600160a01b958690046001600160401b039081169692861695929092048216939282821692600160401b808404821693600160801b808204841694600160c01b90920484169380831693830416910460ff168c565b604080516001600160a01b039d8e1681526001600160401b039c8d1660208201529c909a16998c019990995296891660608b015260808a019590955292871660a089015290861660c0880152851660e0870152841661010086015283166101208501529190911661014083015260ff1661016082015261018001620002e7565b63ffffffff82165f90815260816020526040812062000b75908362003040565b90505b92915050565b5f54600290610100900460ff1615801562000b9f57505f5460ff8083169116105b62000c085760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805461010060ff841661ffff199092169190911717905560858054608480546001600160c01b0316600160c01b6001600160401b038a8116919091029190911790915567016345785d8a000060865588166001600160801b03199091161760e160431b1761ffff60801b19166101f560811b17905562000c8862003084565b62000ca25f8051602062005f6983398151915288620030f0565b62000cae5f84620030f0565b62000cc85f8051602062005e6983398151915284620030f0565b62000ce25f8051602062005ec983398151915284620030f0565b62000cfc5f8051602062005e0983398151915284620030f0565b62000d165f8051602062005e4983398151915285620030f0565b62000d305f8051602062005f4983398151915285620030f0565b62000d4a5f8051602062005e8983398151915285620030f0565b62000d645f8051602062005ee983398151915285620030f0565b62000d8c5f8051602062005f698339815191525f8051602062005de9833981519152620030fc565b62000da65f8051602062005de983398151915285620030f0565b62000dc05f8051602062005e2983398151915285620030f0565b62000de85f8051602062005f298339815191525f8051602062005f09833981519152620030fc565b62000e025f8051602062005f2983398151915283620030f0565b62000e1c5f8051602062005f0983398151915283620030f0565b62000e285f33620030f0565b5f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b63ffffffff81165f90815260816020526040812062000b78906200314f565b5f8051602062005f6983398151915262000eaa81620031be565b63ffffffff89165f90815260816020526040902062000ed0818a8a8a8a8a8a8a620031ca565b600681018054600160401b600160801b031916600160401b6001600160401b038981169182029290921783555f9081526002840160205260409020869055600583018790559054600160801b9004161562000f37576006810180546001600160801b031690555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62000f70620026d6565b6040518263ffffffff1660e01b815260040162000f8f91815260200190565b5f604051808303815f87803b15801562000fa7575f80fd5b505af115801562000fba573d5f803e3d5ffd5b5050608480546001600160c01b031661127560c71b1790555050604080516001600160401b03881681526020810186905290810186905233606082015263ffffffff8b16907f3182bd6e6f74fc1fdc88b60f3a4f4c7f79db6ae6f5b88a1b3f5a1e28ec210d5e9060800160405180910390a250505050505050505050565b5f8051602062005f698339815191526200105281620031be565b63ffffffff89165f90815260816020526040902062001078818a8a8a8a8a8a8a62003546565b600681018054600160401b600160801b031916600160401b6001600160401b038a81169182029290921783555f9081526002840160205260409020879055600583018890559054600160801b90041615620010df576006810180546001600160801b031690555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62001118620026d6565b6040518263ffffffff1660e01b81526004016200113791815260200190565b5f604051808303815f87803b1580156200114f575f80fd5b505af115801562001162573d5f803e3d5ffd5b50505050336001600160a01b03168a63ffffffff167fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d389888a604051620011ac93929190620051a7565b60405180910390a350505050505050505050565b63ffffffff82165f908152608160205260409020620011ee5f8051602062005f6983398151915233620022bf565b6200124257606f5460ff16156200121857604051630bc011ff60e21b815260040160405180910390fd5b62001224818362003040565b6200124257604051630674f25160e11b815260040160405180910390fd5b6200124e818362003932565b505050565b5f8051602062005ee98339815191526200126d81620031be565b6103e88261ffff1610806200128757506103ff8261ffff16115b15620012a657604051630984a67960e31b815260040160405180910390fd5b6085805461ffff60801b1916600160801b61ffff8516908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a15050565b620013185f8051602062005f2983398151915233620022bf565b620013b757608454600160801b90046001600160401b0316158062001368575060845442906200135d9062093a8090600160801b90046001600160401b0316620051dc565b6001600160401b0316115b8062001398575060875442906200138d9062093a80906001600160401b0316620051dc565b6001600160401b0316115b15620013b75760405163692baaad60e11b815260040160405180910390fd5b620013c162003b1d565b565b5f9081526034602052604090206001015490565b620013e282620013c3565b620013ed81620031be565b6200124e838362003b97565b6001600160a01b03811633146200142357604051630b4ad1cd60e31b815260040160405180910390fd5b6200142f828262003c02565b5050565b5f8051602062005ee98339815191526200144d81620031be565b606f5460ff166200148f576084546001600160401b03600160c01b9091048116908316106200148f5760405163401636df60e01b815260040160405180910390fd5b608480546001600160c01b0316600160c01b6001600160401b038516021790556040517f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a190620012f29084906200498b565b5f6086546064620014f3919062005206565b905090565b5f8051602062005e498339815191526200151281620031be565b63ffffffff82161580620015315750607e5463ffffffff908116908316115b156200155057604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff82165f908152607f60205260409020600180820154600160e81b900460ff16151590036200159657604051633b8d3d9960e01b815260040160405180910390fd5b60018101805460ff60e81b1916600160e81b17905560405163ffffffff8416907f4710d2ee567ef1ed6eb2f651dde4589524bcf7cebc62147a99b281cc836e7e44905f90a2505050565b5f8051602062005f49833981519152620015fa81620031be565b63ffffffff88161580620016195750607e5463ffffffff908116908916115b156200163857604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff88165f908152607f60205260409020600180820154600160e81b900460ff16151590036200167e57604051633b8d3d9960e01b815260040160405180910390fd5b63ffffffff6001600160401b0389161115620016ad57604051634c753f5760e01b815260040160405180910390fd5b6001600160401b0388165f9081526083602052604090205463ffffffff1615620016ea576040516337c8fe0960e11b815260040160405180910390fd5b608080545f91908290620017049063ffffffff1662005220565b825463ffffffff8281166101009490940a93840293021916919091179091558254604080515f80825260208201928390529394506001600160a01b0390921691309162001751906200497d565b6200175f9392919062005245565b604051809103905ff08015801562001779573d5f803e3d5ffd5b5090508160835f8c6001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508160825f836001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8463ffffffff1663ffffffff1681526020019081526020015f20905081815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508360010160149054906101000a90046001600160401b03168160010160146101000a8154816001600160401b0302191690836001600160401b03160217905550836001015f9054906101000a90046001600160a01b0316816001015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508a815f0160146101000a8154816001600160401b0302191690836001600160401b031602179055508360020154816002015f806001600160401b031681526020019081526020015f20819055508b63ffffffff168160070160086101000a8154816001600160401b0302191690836001600160401b0316021790555083600101601c9054906101000a900460ff168160070160106101000a81548160ff021916908360ff1602179055508263ffffffff167f194c983456df6701c6a50830b90fe80e72b823411d0d524970c9590dc277a6418d848e8c604051620019dd949392919063ffffffff9490941684526001600160a01b0392831660208501526001600160401b0391909116604084015216606082015260800190565b60405180910390a2604051633892b81160e11b81526001600160a01b0383169063712570229062001a1d908d908d9088908e908e908e906004016200527b565b5f604051808303815f87803b15801562001a35575f80fd5b505af115801562001a48573d5f803e3d5ffd5b50505050505050505050505050505050565b63ffffffff86165f90815260816020526040902060609062001a8190878787878762003c6b565b979650505050505050565b606f5460ff161562001ab157604051630bc011ff60e21b815260040160405180910390fd5b63ffffffff88165f9081526081602090815260408083206084546001600160401b038a81168652600383019094529190932060010154429262001aff92600160c01b900481169116620051dc565b6001600160401b0316111562001b2857604051638a0704d360e01b815260040160405180910390fd5b6103e862001b378888620052dd565b6001600160401b0316111562001b6057604051635acfba9d60e11b815260040160405180910390fd5b62001b72818989898989898962003546565b62001b7e818762003da5565b6085546001600160401b03165f0362001c8557600681018054600160401b600160801b031916600160401b6001600160401b038981169182029290921783555f9081526002840160205260409020869055600583018790559054600160801b9004161562001bf8576006810180546001600160801b031690555b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62001c31620026d6565b6040518263ffffffff1660e01b815260040162001c5091815260200190565b5f604051808303815f87803b15801562001c68575f80fd5b505af115801562001c7b573d5f803e3d5ffd5b5050505062001d4e565b62001c908162003f9c565b600681018054600160801b90046001600160401b031690601062001cb48362005300565b82546001600160401b039182166101009390930a92830292820219169190911790915560408051608081018252428316815289831660208083019182528284018b8152606084018b81526006890154600160801b900487165f90815260048a01909352949091209251835492518616600160401b026001600160801b03199093169516949094171781559151600183015551600290910155505b336001600160a01b03168963ffffffff167faac1e7a157b259544ebacd6e8a82ae5d6c8f174e12aa48696277bcc9a661f0b488878960405162001d9493929190620051a7565b60405180910390a3505050505050505050565b606f5460ff161562001dcc57604051630bc011ff60e21b815260040160405180910390fd5b63ffffffff88165f90815260816020526040902062001df28189898989898989620031ca565b6001600160401b0387165f9081526004820160209081526040918290206002015482519081529081018590527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a162001e5362003b1d565b505050505050505050565b80516080805463ffffffff191663ffffffff9092169190911790555f5b81518110156200142f5781818151811062001e9a5762001e9a62005326565b602002602001015160815f83600162001eb491906200533a565b63ffffffff16815260208101919091526040015f20600501558062001ed98162005350565b91505062001e7b565b62001efc5f8051602062005e0983398151915233620022bf565b15801562001f7f5750336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562001f4d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001f7391906200536b565b6001600160a01b031614155b1562001f9e57604051630d03687f60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526082602052604081205463ffffffff169081900362001fde576040516374a086a360e01b815260040160405180910390fd5b63ffffffff81165f90815260816020526040902060068101546001600160401b03908116908416811115806200202b575060068201546001600160401b03600160401b9091048116908516105b156200204a5760405163cb23ebdf60e01b815260040160405180910390fd5b805b846001600160401b0316816001600160401b031614620020e5576001600160401b038082165f908152600385016020526040902060010154600160401b90048116908616811015620020b157604051639753965f60e01b815260040160405180910390fd5b6001600160401b039091165f908152600384016020526040812090815560010180546001600160801b03191690556200204c565b6006830180546001600160401b0319166001600160401b0387161790556200210e8583620052dd565b608480545f906200212a9084906001600160401b0316620052dd565b82546101009290920a6001600160401b038181021990931691831602179091556006850154600160801b900416159050620021e9575f6200216b846200314f565b60068501549091506200218f90600160401b90046001600160401b031682620052dd565b60848054600890620021b3908490600160401b90046001600160401b0316620052dd565b82546001600160401b039182166101009390930a928302919092021990911617905550506006830180546001600160801b031690555b6001600160401b0385165f8181526003850160205260409081902054905163334d6f6760e11b8152600481019290925260248201526001600160a01b0387169063669adece906044015f604051808303815f87803b1580156200224a575f80fd5b505af11580156200225d573d5f803e3d5ffd5b505050506001600160401b0385165f81815260038501602090815260409182902054915191825263ffffffff8716917f80a6d395a55aed8126079cb8247f0a6848b1440ca2cdca3b4386f250c3529402910160405180910390a3505050505050565b5f9182526034602090815260408084206001600160a01b0393909316845291905290205460ff1690565b5f807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b815260040162002339919062004fb4565b602060405180830381865afa15801562002355573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200237b919062005389565b6084549091505f90620023a1906001600160401b03600160401b820481169116620052dd565b6001600160401b03169050805f03620023bc575f9250505090565b620023c88183620053b5565b9250505090565b606f545f9060ff1615620023f657604051630bc011ff60e21b815260040160405180910390fd5b335f9081526082602052604081205463ffffffff16908190036200242d576040516371653c1560e01b815260040160405180910390fd5b836001600160401b03165f036200245757604051632590ccf960e01b815260040160405180910390fd5b63ffffffff81165f9081526081602052604081206084805491928792620024899084906001600160401b0316620051dc565b82546101009290920a6001600160401b0381810219909316918316021790915560068301541690505f620024be8783620051dc565b6006840180546001600160401b038084166001600160401b03199092168217909255604080516060810182528a815242841660208083019182528886168385019081525f95865260038b0190915292909320905181559151600192909201805491518416600160401b026001600160801b0319909216929093169190911717905590506200254c8362003f9c565b8363ffffffff167f1d9f30260051d51d70339da239ea7b080021adcaabfa71c9b0ea339a20cf9a25826040516200258491906200498b565b60405180910390a29695505050505050565b5f8051602062005ee9833981519152620025b081620031be565b606f5460ff16620025eb576085546001600160401b0390811690831610620025eb5760405163048a05a960e41b815260040160405180910390fd5b608580546001600160401b0319166001600160401b0384161790556040517fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c7590620012f29084906200498b565b5f8051602062005ee98339815191526200265281620031be565b62015180826001600160401b031611156200268057604051631c0cfbfd60e31b815260040160405180910390fd5b60858054600160401b600160801b031916600160401b6001600160401b038516021790556040517f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c2890620012f29084906200498b565b6080545f9063ffffffff16808203620026f057505f919050565b5f816001600160401b038111156200270c576200270c62004c70565b60405190808252806020026020018201604052801562002736578160200160208202803683370190505b5090505f5b82811015620027a65760815f620027548360016200533a565b63ffffffff1663ffffffff1681526020019081526020015f206005015482828151811062002786576200278662005326565b6020908102919091010152806200279d8162005350565b9150506200273b565b505f60205b83600114620029e6575f620027c2600286620053cb565b620027cf600287620053b5565b620027db91906200533a565b90505f816001600160401b03811115620027f957620027f962004c70565b60405190808252806020026020018201604052801562002823578160200160208202803683370190505b5090505f5b828110156200299a576200283e600184620053e1565b8114801562002859575062002855600288620053cb565b6001145b15620028d957856200286d82600262005206565b8151811062002880576200288062005326565b6020026020010151856040516020016200289c929190620053f7565b60405160208183030381529060405280519060200120828281518110620028c757620028c762005326565b60200260200101818152505062002985565b85620028e782600262005206565b81518110620028fa57620028fa62005326565b60200260200101518682600262002912919062005206565b6200291f9060016200533a565b8151811062002932576200293262005326565b60200260200101516040516020016200294d929190620053f7565b6040516020818303038152906040528051906020012082828151811062002978576200297862005326565b6020026020010181815250505b80620029918162005350565b91505062002828565b508094508195508384604051602001620029b6929190620053f7565b6040516020818303038152906040528051906020012093508280620029db9062005405565b9350505050620027ab565b5f835f81518110620029fc57620029fc62005326565b602002602001015190505f5b8281101562002a8157818460405160200162002a26929190620053f7565b604051602081830303815290604052805190602001209150838460405160200162002a53929190620053f7565b604051602081830303815290604052805190602001209350808062002a789062005350565b91505062002a08565b5095945050505050565b5f8051602062005e0983398151915262002aa581620031be565b62002ab284848462004065565b50505050565b5f8051602062005e2983398151915262002ad281620031be565b683635c9adc5dea0000082118062002aed5750633b9aca0082105b1562002b0c57604051638586952560e01b815260040160405180910390fd5b60868290556040518281527ffb383653f53ee079978d0c9aff7aeff04a10166ce244cca9c9f9d8d96bed45b290602001620012f2565b62002b4d82620013c3565b62002b5881620031be565b6200124e838362003c02565b5f8051602062005e8983398151915262002b7e81620031be565b608780546001600160401b031916426001600160401b031617905560408051636de0b4bb60e11b815290517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163dbc16976916004808301925f92919082900301818387803b15801562002bf9575f80fd5b505af115801562002c0c573d5f803e3d5ffd5b5050505062002c1a62004343565b50565b336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562002c65573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002c8b91906200536b565b6001600160a01b03161462002cb35760405163696072e960e01b815260040160405180910390fd5b6001600160a01b0382165f9081526082602090815260408083205463ffffffff1683526081909152902060068101546001600160401b03808216600160401b909204161462002d155760405163664316a560e11b815260040160405180910390fd5b600781015463ffffffff8316600160401b9091046001600160401b03161062002d5157604051633e37e23360e01b815260040160405180910390fd5b604080515f8152602081019091526200124e908490849062004065565b5f8051602062005ec983398151915262002d8881620031be565b6001600160401b0384165f9081526083602052604090205463ffffffff161562002dc5576040516337c8fe0960e11b815260040160405180910390fd5b63ffffffff6001600160401b038516111562002df457604051634c753f5760e01b815260040160405180910390fd5b6001600160a01b0387165f9081526082602052604090205463ffffffff161562002e3157604051630d409b9360e41b815260040160405180910390fd5b5f62002e4188888888876200439b565b5f8080526002909101602052604090209390935550505050505050565b5f8051602062005e6983398151915262002e7881620031be565b607e80545f9190829062002e929063ffffffff1662005220565b91906101000a81548163ffffffff021916908363ffffffff160217905590506040518060c00160405280896001600160a01b03168152602001886001600160a01b03168152602001876001600160401b031681526020018660ff1681526020015f1515815260200185815250607f5f8363ffffffff1663ffffffff1681526020019081526020015f205f820151815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055506020820151816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160010160146101000a8154816001600160401b0302191690836001600160401b03160217905550606082015181600101601c6101000a81548160ff021916908360ff160217905550608082015181600101601d6101000a81548160ff02191690831515021790555060a082015181600201559050508063ffffffff167fa2970448b3bd66ba7e524e7b2a5b9cf94fa29e32488fb942afdfe70dd4b77b528989898989896040516200302e969594939291906200541d565b60405180910390a25050505050505050565b6085546001600160401b038281165f9081526004850160205260408120549092429262003072929181169116620051dc565b6001600160401b031611159392505050565b5f54610100900460ff16620013c15760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000bff565b6200142f828262003b97565b5f6200310883620013c3565b5f84815260346020526040808220600101859055519192508391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b60068101545f90600160801b90046001600160401b031615620031a1575060068101546001600160401b03600160801b90910481165f9081526004909201602052604090912054600160401b90041690565b5060060154600160401b90046001600160401b031690565b919050565b62002c1a8133620045bb565b60078801545f906001600160401b039081169087161015620031ff5760405163ead1340b60e01b815260040160405180910390fd5b6001600160401b038816156200329f5760068901546001600160401b03600160801b90910481169089161115620032495760405163bb14c20560e01b815260040160405180910390fd5b506001600160401b038088165f90815260048a0160205260409020600281015481549092888116600160401b90920416146200329857604051632bd2e3e760e01b815260040160405180910390fd5b5062003313565b506001600160401b0385165f90815260028901602052604090205480620032d9576040516324cbdcc360e11b815260040160405180910390fd5b60068901546001600160401b03600160401b909104811690871611156200331357604051630f2b74f160e11b815260040160405180910390fd5b60068901546001600160401b03600160801b909104811690881611806200334c5750876001600160401b0316876001600160401b031611155b8062003370575060068901546001600160401b03600160c01b909104811690881611155b156200338f5760405163bfa7079f60e01b815260040160405180910390fd5b6001600160401b038781165f90815260048b016020526040902054600160401b9004811690861614620033d5576040516332a2a77f60e01b815260040160405180910390fd5b5f620033e68a888888868962003c6b565b90505f5f8051602062005ea98339815191526002836040516200340a919062005469565b602060405180830381855afa15801562003426573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906200344b919062005389565b620034579190620053cb565b60018c0154604080516020810182528381529051634890ed4560e11b81529293506001600160a01b0390911691639121da8a916200349b9188919060040162005486565b602060405180830381865afa158015620034b7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620034dd9190620054c2565b620034fb576040516309bde33960e01b815260040160405180910390fd5b6001600160401b0389165f90815260048c016020526040902060020154859003620035395760405163a47276bd60e01b815260040160405180910390fd5b5050505050505050505050565b5f80620035538a6200314f565b60078b01549091506001600160401b039081169089161015620035895760405163ead1340b60e01b815260040160405180910390fd5b6001600160401b038916156200362b5760068a01546001600160401b03600160801b9091048116908a161115620035d35760405163bb14c20560e01b815260040160405180910390fd5b6001600160401b03808a165f90815260048c01602052604090206002810154815490945090918a8116600160401b90920416146200362457604051632bd2e3e760e01b815260040160405180910390fd5b506200369a565b6001600160401b0388165f90815260028b01602052604090205491508162003666576040516324cbdcc360e11b815260040160405180910390fd5b806001600160401b0316886001600160401b031611156200369a57604051630f2b74f160e11b815260040160405180910390fd5b806001600160401b0316876001600160401b031611620036cd5760405163b9b18f5760e01b815260040160405180910390fd5b5f620036de8b8a8a8a878b62003c6b565b90505f5f8051602062005ea983398151915260028360405162003702919062005469565b602060405180830381855afa1580156200371e573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019062003743919062005389565b6200374f9190620053cb565b60018d0154604080516020810182528381529051634890ed4560e11b81529293506001600160a01b0390911691639121da8a91620037939189919060040162005486565b602060405180830381865afa158015620037af573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620037d59190620054c2565b620037f3576040516309bde33960e01b815260040160405180910390fd5b5f62003800848b620052dd565b90506200385987826001600160401b03166200381b620022e9565b62003827919062005206565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190620045e5565b80608460088282829054906101000a90046001600160401b03166200387f9190620051dc565b82546101009290920a6001600160401b0381810219909316918316021790915560848054600160801b600160c01b031916600160801b428416021790558e546040516332c2d15360e01b8152918d166004830152602482018b90523360448301526001600160a01b031691506332c2d153906064015f604051808303815f87803b1580156200390c575f80fd5b505af11580156200391f573d5f803e3d5ffd5b5050505050505050505050505050505050565b60068201546001600160401b03600160c01b909104811690821611158062003971575060068201546001600160401b03600160801b9091048116908216115b15620039905760405163d086b70b60e01b815260040160405180910390fd5b6001600160401b038181165f81815260048501602090815260408083208054600689018054600160401b600160801b031916600160401b92839004909816918202979097178755600280830154828752908a0190945291909320919091556001820154600587015583546001600160c01b0316600160c01b909302929092179092557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62003a4b620026d6565b6040518263ffffffff1660e01b815260040162003a6a91815260200190565b5f604051808303815f87803b15801562003a82575f80fd5b505af115801562003a95573d5f803e3d5ffd5b505085546001600160a01b03165f90815260826020908152604091829020546002870154600188015484516001600160401b03898116825294810192909252818501529188166060830152915163ffffffff90921693507f581910eb7a27738945c2f00a91f2284b2d6de9d4e472b12f901c2b0df045e21b925081900360800190a250505050565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562003b76575f80fd5b505af115801562003b89573d5f803e3d5ffd5b50505050620013c162004639565b62003ba38282620022bf565b6200142f575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b62003c0e8282620022bf565b156200142f575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6001600160401b038086165f818152600389016020526040808220549388168252902054606092911580159062003ca0575081155b1562003cbf5760405163340c614f60e11b815260040160405180910390fd5b8062003cde576040516366385b5160e01b815260040160405180910390fd5b62003ce98462004695565b62003d07576040516305dae44f60e21b815260040160405180910390fd5b885460018a01546040516001600160601b03193360601b16602082015260348101889052605481018590526001600160c01b031960c08c811b82166074840152600160a01b94859004811b8216607c84015293909204831b82166084820152608c810187905260ac810184905260cc81018990529189901b1660ec82015260f401604051602081830303815290604052925050509695505050505050565b5f62003db1836200314f565b9050815f8062003dc28484620052dd565b6085546001600160401b0391821692505f9162003de891600160401b90041642620053e1565b90505b846001600160401b0316846001600160401b03161462003e71576001600160401b038085165f9081526003890160205260409020600181015490911682101562003e4c576001810154600160401b90046001600160401b0316945062003e6a565b62003e588686620052dd565b6001600160401b031693505062003e71565b5062003deb565b5f62003e7e8484620053e1565b90508381101562003edc57808403600c811162003e9c578062003e9f565b600c5b9050806103e80a81608560109054906101000a900461ffff1661ffff160a608654028162003ed15762003ed1620053a1565b046086555062003f53565b838103600c811162003eef578062003ef2565b600c5b90505f816103e80a82608560109054906101000a900461ffff1661ffff160a670de0b6b3a7640000028162003f2b5762003f2b620053a1565b04905080608654670de0b6b3a7640000028162003f4c5762003f4c620053a1565b0460865550505b683635c9adc5dea00000608654111562003f7a57683635c9adc5dea0000060865562003f92565b633b9aca00608654101562003f9257633b9aca006086555b5050505050505050565b60068101546001600160401b03600160c01b82048116600160801b90920416111562002c1a5760068101545f9062003fe690600160c01b90046001600160401b03166001620051dc565b905062003ff4828262003040565b156200142f5760068201545f9060029062004021908490600160801b90046001600160401b0316620052dd565b6200402d9190620054e3565b620040399083620051dc565b905062004047838262003040565b1562004059576200124e838262003932565b6200124e838362003932565b63ffffffff82161580620040845750607e5463ffffffff908116908316115b15620040a357604051637512e5cb60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526082602052604081205463ffffffff1690819003620040e3576040516374a086a360e01b815260040160405180910390fd5b63ffffffff8181165f908152608160205260409020600781015490918516600160401b9091046001600160401b0316036200413157604051634f61d51960e01b815260040160405180910390fd5b63ffffffff84165f908152607f60205260409020600180820154600160e81b900460ff16151590036200417757604051633b8d3d9960e01b815260040160405180910390fd5b60018101546007830154600160801b900460ff908116600160e01b9092041614620041b557604051635aa0d5f160e11b815260040160405180910390fd5b6001818101805491840180546001600160a01b039093166001600160a01b031984168117825591546001600160e01b0319909316909117600160a01b928390046001600160401b03908116909302179055600783018054600160401b600160801b03191663ffffffff8816600160401b021790556006830154600160c01b81048216600160801b909104909116146200426157604051639d59507b60e01b815260040160405180910390fd5b5f6200426d8462000e71565b6007840180546001600160401b0319166001600160401b038316179055825460405163278f794360e11b81529192506001600160a01b0389811692634f1ef28692620042c092169089906004016200550b565b5f604051808303815f87803b158015620042d8575f80fd5b505af1158015620042eb573d5f803e3d5ffd5b50506040805163ffffffff8a811682526001600160401b0386166020830152881693507ff585e04c05d396901170247783d3e5f0ee9c1df23072985b50af089f5e48b19d92500160405180910390a250505050505050565b606f5460ff166200436757604051635386698160e01b815260040160405180910390fd5b606f805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b608080545f9182918290620043b69063ffffffff1662005220565b91906101000a81548163ffffffff021916908363ffffffff160217905590508060835f866001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508060825f896001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff16021790555060815f8263ffffffff1663ffffffff1681526020019081526020015f20915086825f015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550848260010160146101000a8154816001600160401b0302191690836001600160401b0316021790555085826001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555083825f0160146101000a8154816001600160401b0302191690836001600160401b03160217905550828260070160106101000a81548160ff021916908360ff1602179055508063ffffffff167fadfc7d56f7e39b08b321534f14bfb135ad27698f7d2f5ad0edc2356ea9a3f850868987875f604051620045a99594939291906001600160401b0395861681526001600160a01b03949094166020850152918416604084015260ff166060830152909116608082015260a00190565b60405180910390a25095945050505050565b620045c78282620022bf565b6200142f57604051637615be1f60e11b815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526200124e90849062004719565b606f5460ff16156200465e57604051630bc011ff60e21b815260040160405180910390fd5b606f805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b5f67ffffffff000000016001600160401b038316108015620046cb575067ffffffff00000001604083901c6001600160401b0316105b8015620046ec575067ffffffff00000001608083901c6001600160401b0316105b801562004704575067ffffffff0000000160c083901c105b156200471257506001919050565b505f919050565b5f6200476f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620047f19092919063ffffffff16565b8051909150156200124e5780806020019051810190620047909190620054c2565b6200124e5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000bff565b60606200480184845f8562004809565b949350505050565b6060824710156200486c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b606482015260840162000bff565b5f80866001600160a01b0316858760405162004889919062005469565b5f6040518083038185875af1925050503d805f8114620048c5576040519150601f19603f3d011682016040523d82523d5f602084013e620048ca565b606091505b509150915062001a8187838387606083156200494a5782515f0362004942576001600160a01b0385163b620049425760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000bff565b508162004801565b620048018383815115620049615781518083602001fd5b8060405162461bcd60e51b815260040162000bff919062004eab565b6108b8806200553183390190565b6001600160401b0391909116815260200190565b803563ffffffff81168114620031b9575f80fd5b80356001600160401b0381168114620031b9575f80fd5b5f8060408385031215620049dc575f80fd5b620049e7836200499f565b9150620049f760208401620049b3565b90509250929050565b6001600160a01b038116811462002c1a575f80fd5b5f805f805f8060c0878903121562004a2b575f80fd5b863562004a388162004a00565b955062004a4860208801620049b3565b945062004a5860408801620049b3565b9350606087013562004a6a8162004a00565b9250608087013562004a7c8162004a00565b915060a087013562004a8e8162004a00565b809150509295509295509295565b5f6020828403121562004aad575f80fd5b62000b75826200499f565b80610300810183101562000b78575f80fd5b5f805f805f805f806103e0898b03121562004ae3575f80fd5b62004aee896200499f565b975062004afe60208a01620049b3565b965062004b0e60408a01620049b3565b955062004b1e60608a01620049b3565b945062004b2e60808a01620049b3565b935060a0890135925060c0890135915062004b4d8a60e08b0162004ab8565b90509295985092959890939650565b5f805f805f805f806103e0898b03121562004b75575f80fd5b62004b80896200499f565b975062004b9060208a01620049b3565b965062004ba060408a01620049b3565b955062004bb060608a01620049b3565b94506080890135935060a0890135925060c089013562004bd08162004a00565b915062004b4d8a60e08b0162004ab8565b5f6020828403121562004bf2575f80fd5b813561ffff8116811462004c04575f80fd5b9392505050565b5f6020828403121562004c1c575f80fd5b5035919050565b5f806040838503121562004c35575f80fd5b82359150602083013562004c498162004a00565b809150509250929050565b5f6020828403121562004c65575f80fd5b62000b7582620049b3565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171562004caf5762004caf62004c70565b604052919050565b5f6001600160401b0383111562004cd25762004cd262004c70565b62004ce7601f8401601f191660200162004c84565b905082815283838301111562004cfb575f80fd5b828260208301375f602084830101529392505050565b5f82601f83011262004d21575f80fd5b62000b758383356020850162004cb7565b5f805f805f805f60e0888a03121562004d49575f80fd5b62004d54886200499f565b965062004d6460208901620049b3565b9550604088013562004d768162004a00565b9450606088013562004d888162004a00565b9350608088013562004d9a8162004a00565b925060a08801356001600160401b038082111562004db6575f80fd5b62004dc48b838c0162004d11565b935060c08a013591508082111562004dda575f80fd5b5062004de98a828b0162004d11565b91505092959891949750929550565b5f805f805f8060c0878903121562004e0e575f80fd5b62004e19876200499f565b955062004e2960208801620049b3565b945062004e3960408801620049b3565b9350606087013592506080870135915060a087013590509295509295509295565b5f5b8381101562004e7657818101518382015260200162004e5c565b50505f910152565b5f815180845262004e9781602086016020860162004e5a565b601f01601f19169290920160200192915050565b602081525f62000b75602083018462004e7e565b5f602080838503121562004ed1575f80fd5b82356001600160401b038082111562004ee8575f80fd5b818501915085601f83011262004efc575f80fd5b81358181111562004f115762004f1162004c70565b8060051b915062004f2484830162004c84565b818152918301840191848101908884111562004f3e575f80fd5b938501935b8385101562004f5e5784358252938501939085019062004f43565b98975050505050505050565b5f806040838503121562004f7c575f80fd5b8235620049e78162004a00565b5f806040838503121562004f9b575f80fd5b62004fa683620049b3565b946020939093013593505050565b6001600160a01b0391909116815260200190565b5f805f6060848603121562004fdb575f80fd5b833562004fe88162004a00565b925062004ff8602085016200499f565b915060408401356001600160401b0381111562005013575f80fd5b8401601f8101861362005024575f80fd5b620050358682356020840162004cb7565b9150509250925092565b5f6020828403121562005050575f80fd5b813562004c048162004a00565b5f80604083850312156200506f575f80fd5b82356200507c8162004a00565b9150620049f7602084016200499f565b803560ff81168114620031b9575f80fd5b5f805f805f8060c08789031215620050b3575f80fd5b8635620050c08162004a00565b95506020870135620050d28162004a00565b9450620050e260408801620049b3565b9350620050f260608801620049b3565b9250608087013591506200510960a088016200508c565b90509295509295509295565b5f805f805f8060c087890312156200512b575f80fd5b8635620051388162004a00565b955060208701356200514a8162004a00565b94506200515a60408801620049b3565b93506200516a606088016200508c565b92506080870135915060a08701356001600160401b038111156200518c575f80fd5b6200519a89828a0162004d11565b9150509295509295509295565b6001600160401b039390931683526020830191909152604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b03818116838216019080821115620051ff57620051ff620051c8565b5092915050565b808202811582820484141762000b785762000b78620051c8565b5f63ffffffff8083168181036200523b576200523b620051c8565b6001019392505050565b6001600160a01b038481168252831660208201526060604082018190525f90620052729083018462004e7e565b95945050505050565b6001600160a01b038781168252868116602083015263ffffffff861660408301528416606082015260c0608082018190525f90620052bc9083018562004e7e565b82810360a0840152620052d0818562004e7e565b9998505050505050505050565b6001600160401b03828116828216039080821115620051ff57620051ff620051c8565b5f6001600160401b038281166002600160401b031981016200523b576200523b620051c8565b634e487b7160e01b5f52603260045260245ffd5b8082018082111562000b785762000b78620051c8565b5f60018201620053645762005364620051c8565b5060010190565b5f602082840312156200537c575f80fd5b815162004c048162004a00565b5f602082840312156200539a575f80fd5b5051919050565b634e487b7160e01b5f52601260045260245ffd5b5f82620053c657620053c6620053a1565b500490565b5f82620053dc57620053dc620053a1565b500690565b8181038181111562000b785762000b78620051c8565b918252602082015260400190565b5f81620054165762005416620051c8565b505f190190565b6001600160a01b038781168252861660208201526001600160401b038516604082015260ff841660608201526080810183905260c060a082018190525f9062004f5e9083018462004e7e565b5f82516200547c81846020870162004e5a565b9190910192915050565b6103208101610300808584378201835f5b6001811015620054b857815183526020928301929091019060010162005497565b5050509392505050565b5f60208284031215620054d3575f80fd5b8151801515811462004c04575f80fd5b5f6001600160401b0383811680620054ff57620054ff620053a1565b92169190910492915050565b6001600160a01b03831681526040602082018190525f90620048019083018462004e7e56fe60a06040526040516108b83803806108b883398101604081905261002291610349565b828161002e8282610056565b50506001600160a01b03821660805261004e61004960805190565b6100b4565b50505061042e565b61005f82610121565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156100a8576100a3828261019f565b505050565b6100b0610212565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6100f35f80516020610898833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a161011e81610233565b50565b806001600160a01b03163b5f0361015b57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b0316846040516101bb9190610413565b5f60405180830381855af49150503d805f81146101f3576040519150601f19603f3d011682016040523d82523d5f602084013e6101f8565b606091505b509092509050610209858383610270565b95945050505050565b34156102315760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b03811661025c57604051633173bdd160e11b81525f6004820152602401610152565b805f8051602061089883398151915261017e565b60608261028557610280826102cf565b6102c8565b815115801561029c57506001600160a01b0384163b155b156102c557604051639996b31560e01b81526001600160a01b0385166004820152602401610152565b50805b9392505050565b8051156102df5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811461030e575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b83811015610341578181015183820152602001610329565b50505f910152565b5f805f6060848603121561035b575f80fd5b610364846102f8565b9250610372602085016102f8565b60408501519092506001600160401b038082111561038e575f80fd5b818601915086601f8301126103a1575f80fd5b8151818111156103b3576103b3610313565b604051601f8201601f19908116603f011681019083821181831017156103db576103db610313565b816040528281528960208487010111156103f3575f80fd5b610404836020830160208801610327565b80955050505050509250925092565b5f8251610424818460208701610327565b9190910192915050565b6080516104536104455f395f601001526104535ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610069575f356001600160e01b03191663278f794360e11b146100615761005f61006d565b565b61005f61007d565b61005f5b61005f6100786100ab565b6100cf565b5f8061008c36600481846102ba565b81019061009991906102f5565b915091506100a782826100ed565b5050565b5f6100ca5f805160206103fe833981519152546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e8080156100e9573d5ff35b3d5ffd5b6100f682610147565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561013f5761013a82826101aa565b505050565b6100a761021c565b806001600160a01b03163b5f0361017c5780604051634c9c8ce360e01b815260040161017391906103bd565b60405180910390fd5b5f805160206103fe83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516101c691906103d1565b5f60405180830381855af49150503d805f81146101fe576040519150601f19603f3d011682016040523d82523d5f602084013e610203565b606091505b509150915061021385838361023b565b95945050505050565b341561005f5760405163b398979f60e01b815260040160405180910390fd5b6060826102505761024b82610291565b61028a565b815115801561026757506001600160a01b0384163b155b156102875783604051639996b31560e01b815260040161017391906103bd565b50805b9392505050565b8051156102a15780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f80858511156102c8575f80fd5b838611156102d4575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f8060408385031215610306575f80fd5b82356001600160a01b038116811461031c575f80fd5b915060208301356001600160401b0380821115610337575f80fd5b818501915085601f83011261034a575f80fd5b81358181111561035c5761035c6102e1565b604051601f8201601f19908116603f01168101908382118183101715610384576103846102e1565b8160405282815288602084870101111561039c575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b6001600160a01b0391909116815260200190565b5f82515f5b818110156103f057602081860181015185830152016103d6565b505f92019182525091905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220dd2cb78057147a82db29935f054595b8dd0503a8ab6ff81a03858f4554a1885864736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610373cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f066156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fbab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bdac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f59062ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f430644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000013dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68ea5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db19b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff285951141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545ea0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd08084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4a2646970667358221220a6f281564bb978fcc163a5a97bf772c7241055405295cd71dbd2f4a0bcdd9aaa64736f6c63430008140033", + "bytecode": "0x60e060405234801562000010575f80fd5b50604051620059833803806200598383398101604081905262000033916200013c565b6001600160a01b0380841660805280831660c052811660a0528282826200005962000065565b5050505050506200018d565b5f54610100900460ff1615620000d15760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116101562000122575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b038116811462000139575f80fd5b50565b5f805f606084860312156200014f575f80fd5b83516200015c8162000124565b60208501519093506200016f8162000124565b6040850151909250620001828162000124565b809150509250925092565b60805160a05160c05161579a620001e95f395f818161097501528181612338015261342e01525f818161080601528181612dd101526134fa01525f81816108b801528181610ec3015281816119cc0152611b14015261579a5ff3fe608060405234801562000010575f80fd5b50600436106200035c575f3560e01c80638875f03c11620001cb578063c1acbc341162000107578063d890581211620000ab578063dfdb8c5e1162000083578063dfdb8c5e1462000958578063e46761c4146200096f578063f4e926751462000997578063f9c4c2ae14620009a8575f80fd5b8063d89058121462000908578063dbc169761462000933578063dde0ff77146200093d575f80fd5b8063d02103ca11620000df578063d02103ca14620008b2578063d5073f6f14620008da578063d547741f14620008f1575f80fd5b8063c1acbc341462000858578063c4c928c21462000873578063ceee281d146200088a575f80fd5b80639a908e73116200016f578063a2967d991162000147578063a2967d9914620007f6578063a3c573eb1462000800578063abcb51981462000841575f80fd5b80639a908e7314620007c05780639e36c56514620007d7578063a217fddf14620007ee575f80fd5b806391d1485411620001a357806391d14854146200076457806397bf07e8146200079f57806399f5634e14620007b6575f80fd5b80638875f03c146200071f5780638f698ec514620007365780638fd88cc2146200074d575f80fd5b8063477fa270116200029b5780637222020f116200023f5780637975fcfe11620002175780637975fcfe14620006c75780637fb6e76a14620006ed5780638129fc1c1462000715575f80fd5b80637222020f1462000673578063727885e9146200068a57806374d9c24414620006a1575f80fd5b806362d87e66116200027357806362d87e6614620005a857806365c0504d14620005bf578063680658a1146200063f575f80fd5b8063477fa270146200055257806355a71ee0146200055b57806360469169146200059e575f80fd5b80632072f6c511620003035780632f2ff15d11620002db5780632f2ff15d146200051057806330c27dde146200052757806336568abe146200053b575f80fd5b80632072f6c5146200041e578063248a9ca3146200042857806325280169146200045c575f80fd5b80631489ed1011620003375780631489ed1014620003c157806315064c9614620003d85780631796a1ae14620003f7575f80fd5b8063066ec01214620003605780630e36f582146200039157806311f6b28714620003aa575b5f80fd5b60845462000374906001600160401b031681565b6040516001600160401b0390911681526020015b60405180910390f35b620003a8620003a236600462003fb1565b620009ce565b005b62000374620003bb3660046200404c565b62000d8a565b620003a8620003d23660046200406f565b62000db9565b606f54620003e69060ff1681565b604051901515815260200162000388565b607e54620004089063ffffffff1681565b60405163ffffffff909116815260200162000388565b620003a862000fa9565b6200044d6200043936600462004109565b5f9081526034602052604090206001015490565b60405190815260200162000388565b620004dc6200046d36600462004121565b60408051606080820183525f808352602080840182905292840181905263ffffffff959095168552608182528285206001600160401b03948516865260030182529382902082519485018352805485526001015480841691850191909152600160401b90049091169082015290565b60408051825181526020808401516001600160401b0390811691830191909152928201519092169082015260600162000388565b620003a86200052136600462004157565b62001085565b60875462000374906001600160401b031681565b620003a86200054c36600462004157565b620010b2565b6086546200044d565b6200044d6200056c36600462004121565b63ffffffff82165f9081526081602090815260408083206001600160401b038516845260020190915290205492915050565b6200044d620010ec565b620003e6620005b936600462004109565b62001103565b6200062a620005d03660046200404c565b607f6020525f908152604090208054600182015460028301546003909301546001600160a01b0392831693928216926001600160401b03600160a01b8404169260ff600160e01b8204811693600160e81b90920416919087565b604051620003889796959493929190620041bd565b620003a86200065036600462004211565b63ffffffff9092165f908152608160205260409020600581019190915560080155565b620003a8620006843660046200404c565b6200110f565b620003a86200069b36600462004306565b62001205565b620006b8620006b23660046200404c565b62001693565b604051620003889190620043cc565b620006de620006d8366004620044d8565b620017c5565b6040516200038891906200458b565b62000408620006fe3660046200459f565b60836020525f908152604090205463ffffffff1681565b620003a8620017f7565b620003a862000730366004620045bb565b6200192b565b620003a86200074736600462004661565b62001be1565b620003a86200075e3660046200470c565b62001c65565b620003e66200077536600462004157565b5f9182526034602090815260408084206001600160a01b0393909316845291905290205460ff1690565b620003a8620007b03660046200473a565b62001fff565b6200044d62002317565b62000374620007d1366004620047bc565b620023f8565b620006de620007e8366004620047e7565b620025f9565b6200044d5f81565b6200044d6200262b565b620008287f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200162000388565b620003a86200085236600462004820565b620029f3565b6084546200037490600160801b90046001600160401b031681565b620003a862000884366004620048bc565b62002c6e565b620004086200089b36600462004933565b60826020525f908152604090205463ffffffff1681565b620008287f000000000000000000000000000000000000000000000000000000000000000081565b620003a8620008eb36600462004109565b62002cad565b620003a86200090236600462004157565b62002d4f565b620006de6040518060400160405280600b81526020016a70657373696d697374696360a81b81525081565b620003a862002d77565b6084546200037490600160401b90046001600160401b031681565b620003a86200096936600462004951565b62002e43565b620008287f000000000000000000000000000000000000000000000000000000000000000081565b608054620004089063ffffffff1681565b620009bf620009b93660046200404c565b62002f93565b60405162000388919062004980565b5f54600290610100900460ff16158015620009ef57505f5460ff8083169116105b62000a585760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805461ffff191660ff83161761010017905567016345785d8a000060865562000a81620030f3565b62000aad7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4886200315f565b62000ab95f846200315f565b62000ae57fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f590846200315f565b62000b117f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e846200315f565b62000b3d7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac846200315f565b62000b697fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd856200315f565b62000b957fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd08856200315f565b62000bc17f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f4856200315f565b62000bed7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1856200315f565b62000c397f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd47f73cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f06200316b565b62000c657f73cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f0856200315f565b62000c917f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb856200315f565b62000cdd7f141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545e7f9b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff2859516200316b565b62000d097f141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545e836200315f565b62000d357f9b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff285951836200315f565b62000d415f336200315f565b5f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b63ffffffff81165f90815260816020526040812060060154600160401b90046001600160401b03165b92915050565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd462000de581620031b5565b6001600160401b0388161562000e0e5760405163306dfc5760e11b815260040160405180910390fd5b63ffffffff89165f908152608160205260408120906007820154600160801b900460ff16600181111562000e465762000e4662004188565b1462000e65576040516390db0d0760e01b815260040160405180910390fd5b62000e7681898989898989620031c1565b6006810180546fffffffffffffffff00000000000000001916600160401b6001600160401b038a16908102919091179091555f9081526002820160205260409020859055600581018690557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62000efa6200262b565b6040518263ffffffff1660e01b815260040162000f1991815260200190565b5f604051808303815f87803b15801562000f31575f80fd5b505af115801562000f44573d5f803e3d5ffd5b5050604080516001600160401b038b1681526020810189905290810189905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d3906060015b60405180910390a350505050505050505050565b335f9081527f8875b94af5657a2903def9906d67a3f42d8a836d24b5602c00f00fc855339fcd602052604090205460ff166200107957608454600160801b90046001600160401b031615806200102a575060845442906200101f9062093a8090600160801b90046001600160401b031662004aa9565b6001600160401b0316115b806200105a575060875442906200104f9062093a80906001600160401b031662004aa9565b6001600160401b0316115b15620010795760405163692baaad60e11b815260040160405180910390fd5b62001083620034f8565b565b5f82815260346020526040902060010154620010a181620031b5565b620010ad838362003572565b505050565b6001600160a01b0381163314620010dc57604051630b4ad1cd60e31b815260040160405180910390fd5b620010e88282620035f6565b5050565b5f6086546064620010fe919062004ad3565b905090565b5f62000db38262003678565b7fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd6200113b81620031b5565b63ffffffff821615806200115a5750607e5463ffffffff908116908316115b156200117957604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff82165f908152607f602052604090206001810154600160e81b900460ff1615620011bb57604051633b8d3d9960e01b815260040160405180910390fd5b60018101805460ff60e81b1916600160e81b17905560405163ffffffff8416907f4710d2ee567ef1ed6eb2f651dde4589524bcf7cebc62147a99b281cc836e7e44905f90a2505050565b7fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd086200123181620031b5565b63ffffffff88161580620012505750607e5463ffffffff908116908916115b156200126f57604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff88165f908152607f602052604090206001810154600160e81b900460ff1615620012b157604051633b8d3d9960e01b815260040160405180910390fd5b63ffffffff6001600160401b0389161115620012e057604051634c753f5760e01b815260040160405180910390fd5b6001600160401b0388165f9081526083602052604090205463ffffffff16156200131d576040516337c8fe0960e11b815260040160405180910390fd5b608080545f91908290620013379063ffffffff1662004aed565b825463ffffffff8281166101009490940a93840293021916919091179091558254604080515f80825260208201928390529394506001600160a01b03909216913091620013849062003f77565b620013929392919062004b12565b604051809103905ff080158015620013ac573d5f803e3d5ffd5b5090508160835f8c6001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508160825f836001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8463ffffffff1663ffffffff1681526020019081526020015f20905081815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508360010160149054906101000a90046001600160401b03168160010160146101000a8154816001600160401b0302191690836001600160401b03160217905550836001015f9054906101000a90046001600160a01b0316816001015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508a815f0160146101000a8154816001600160401b0302191690836001600160401b031602179055508360020154816002015f806001600160401b031681526020019081526020015f20819055508b63ffffffff168160070160086101000a8154816001600160401b0302191690836001600160401b0316021790555083600101601c9054906101000a900460ff168160070160106101000a81548160ff02191690836001811115620015ac57620015ac62004188565b0217905550600384015460098201556040805163ffffffff8e811682526001600160a01b0385811660208401526001600160401b038f16838501528b1660608301529151918516917f194c983456df6701c6a50830b90fe80e72b823411d0d524970c9590dc277a6419181900360800190a2604051633892b81160e11b81526001600160a01b0383169063712570229062001656908d908d9088908e908e908e9060040162004b3f565b5f604051808303815f87803b1580156200166e575f80fd5b505af115801562001681573d5f803e3d5ffd5b50505050505050505050505050505050565b60408051610180810182525f8082526020808301828152838501838152606085018481526080860185815260a0870186815260c0880187815260e089018881526101008a018981526101208b018a81526101408c018b90526101608c018b905263ffffffff8e168b5260819099529a90982080546001600160a01b038082168c52600160a01b918290046001600160401b0390811690995260018084015491821690985204871690945260058401549092526006830154808616909152600160401b9081900485169091526007820154808516909652850490921690955292939091600160801b900460ff169081111562001792576200179262004188565b90816001811115620017a857620017a862004188565b905250600881015461014083015260090154610160820152919050565b63ffffffff86165f908152608160205260409020606090620017ec90878787878762003701565b979650505050505050565b5f54600390610100900460ff161580156200181857505f5460ff8083169116105b6200187d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840162000a4f565b5f805461ffff191660ff831617610100179055604080518082018252600b81526a70657373696d697374696360a81b602082015290517f50cadc0c001f05dd4b81db1e92b98d77e718fd2f103fb7b77293e867d329a4c291620018e0916200458b565b60405180910390a15f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd46200195781620031b5565b63ffffffff87165f90815260816020526040902060016007820154600160801b900460ff16600181111562001990576200199062004188565b14620019af57604051633a64d97360e01b815260040160405180910390fd5b60405163ef4eeb3560e01b815263ffffffff881660048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef4eeb3590602401602060405180830381865afa15801562001a1a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001a40919062004ba1565b90508062001a615760405163a60721e160e01b815260040160405180910390fd5b5f62001a718a84848b8b62003858565b6001840154600985015460405163020a49e360e51b81529293506001600160a01b03909116916341493c609162001ab19185908b908b9060040162004bb9565b5f6040518083038186803b15801562001ac8575f80fd5b505afa15801562001adb573d5f803e3d5ffd5b50506084805467ffffffffffffffff60801b1916600160801b426001600160401b031602179055505060058301889055600883018790557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62001b4b6200262b565b6040518263ffffffff1660e01b815260040162001b6a91815260200190565b5f604051808303815f87803b15801562001b82575f80fd5b505af115801562001b95573d5f803e3d5ffd5b5050604080515f80825260208201529081018b905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d39060600162000f95565b80516080805463ffffffff191663ffffffff9092169190911790555f5b8151811015620010e85781818151811062001c1d5762001c1d62004c06565b602002602001015160815f83600162001c37919062004c1a565b63ffffffff16815260208101919091526040015f20600501558062001c5c8162004c30565b91505062001bfe565b335f9081527ff14f5a8ad59d90593602e905b358229bff5ceea677d5bf0f5a1701793550a9a6602052604090205460ff1615801562001d185750336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001ce6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001d0c919062004c4b565b6001600160a01b031614155b1562001d3757604051630d03687f60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526082602052604081205463ffffffff169081900362001d77576040516374a086a360e01b815260040160405180910390fd5b63ffffffff81165f908152608160205260408120906007820154600160801b900460ff16600181111562001daf5762001daf62004188565b1462001dce576040516390db0d0760e01b815260040160405180910390fd5b60068101546001600160401b039081169084168111158062001e07575060068201546001600160401b03600160401b9091048116908516105b1562001e265760405163cb23ebdf60e01b815260040160405180910390fd5b805b846001600160401b0316816001600160401b03161462001eca576001600160401b038082165f908152600385016020526040902060010154600160401b9004811690861681101562001e8d57604051639753965f60e01b815260040160405180910390fd5b6001600160401b039091165f908152600384016020526040812090815560010180546fffffffffffffffffffffffffffffffff1916905562001e28565b60068301805467ffffffffffffffff19166001600160401b03871617905562001ef4858362004c69565b608480545f9062001f109084906001600160401b031662004c69565b82546101009290920a6001600160401b0381810219909316918316021790915586165f8181526003860160205260409081902054905163334d6f6760e11b8152600481019290925260248201526001600160a01b038816915063669adece906044015f604051808303815f87803b15801562001f8a575f80fd5b505af115801562001f9d573d5f803e3d5ffd5b505050506001600160401b0385165f81815260038501602090815260409182902054915191825263ffffffff8716917f80a6d395a55aed8126079cb8247f0a6848b1440ca2cdca3b4386f250c3529402910160405180910390a3505050505050565b7f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e6200202b81620031b5565b6001600160401b0385165f9081526083602052604090205463ffffffff161562002068576040516337c8fe0960e11b815260040160405180910390fd5b63ffffffff6001600160401b03861611156200209757604051634c753f5760e01b815260040160405180910390fd5b6001600160a01b0388165f9081526082602052604090205463ffffffff1615620020d457604051630d409b9360e41b815260040160405180910390fd5b608080545f91908290620020ee9063ffffffff1662004aed565b91906101000a81548163ffffffff021916908363ffffffff160217905590508060835f886001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508060825f8b6001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8363ffffffff1663ffffffff1681526020019081526020015f20905089815f015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550878160010160146101000a8154816001600160401b0302191690836001600160401b0316021790555088816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555086815f0160146101000a8154816001600160401b0302191690836001600160401b03160217905550848160070160106101000a81548160ff0219169083600181111562002278576200227862004188565b0217905550600185600181111562002294576200229462004188565b03620022ae576009810184905560058101869055620022c1565b5f80805260028201602052604090208690555b8163ffffffff167fd490df184152edba8455dac3228134939c71f8cb4c8f310c3145dec9037147ac898c8a895f8a604051620023039695949392919062004c8c565b60405180910390a250505050505050505050565b6040516370a0823160e01b81523060048201525f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156200237e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620023a4919062004ba1565b6084549091505f90620023ca906001600160401b03600160401b82048116911662004c69565b6001600160401b03169050805f03620023e5575f9250505090565b620023f1818362004ced565b9250505090565b606f545f9060ff16156200241f57604051630bc011ff60e21b815260040160405180910390fd5b335f9081526082602052604081205463ffffffff169081900362002456576040516371653c1560e01b815260040160405180910390fd5b836001600160401b03165f036200248057604051632590ccf960e01b815260040160405180910390fd5b63ffffffff81165f908152608160205260408120906007820154600160801b900460ff166001811115620024b857620024b862004188565b14620024d7576040516390db0d0760e01b815260040160405180910390fd5b608480548691905f90620024f69084906001600160401b031662004aa9565b82546101009290920a6001600160401b0381810219909316918316021790915560068301541690505f6200252b878362004aa9565b6006840180546001600160401b0383811667ffffffffffffffff199092168217909255604080516060810182528a815242841660208083019182528886168385019081525f86815260038c018352859020935184559151600193909301805492518716600160401b026fffffffffffffffffffffffffffffffff199093169390961692909217179093555190815291925063ffffffff8616917f1d9f30260051d51d70339da239ea7b080021adcaabfa71c9b0ea339a20cf9a25910160405180910390a29695505050505050565b63ffffffff84165f9081526081602052604090206060906200262090869086868662003858565b90505b949350505050565b6080545f9063ffffffff168082036200264557505f919050565b5f816001600160401b0381111562002661576200266162004244565b6040519080825280602002602001820160405280156200268b578160200160208202803683370190505b5090505f5b82811015620026fb5760815f620026a983600162004c1a565b63ffffffff1663ffffffff1681526020019081526020015f2060050154828281518110620026db57620026db62004c06565b602090810291909101015280620026f28162004c30565b91505062002690565b505f60205b8360011462002953575f6200271760028662004d03565b6200272460028762004ced565b62002730919062004c1a565b90505f816001600160401b038111156200274e576200274e62004244565b60405190808252806020026020018201604052801562002778578160200160208202803683370190505b5090505f5b82811015620028ff576200279360018462004d19565b81148015620027ae5750620027aa60028862004d03565b6001145b15620028365785620027c282600262004ad3565b81518110620027d557620027d562004c06565b602002602001015185604051602001620027f9929190918252602082015260400190565b6040516020818303038152906040528051906020012082828151811062002824576200282462004c06565b602002602001018181525050620028ea565b856200284482600262004ad3565b8151811062002857576200285762004c06565b6020026020010151868260026200286f919062004ad3565b6200287c90600162004c1a565b815181106200288f576200288f62004c06565b6020026020010151604051602001620028b2929190918252602082015260400190565b60405160208183030381529060405280519060200120828281518110620028dd57620028dd62004c06565b6020026020010181815250505b80620028f68162004c30565b9150506200277d565b50809450819550838460405160200162002923929190918252602082015260400190565b6040516020818303038152906040528051906020012093508280620029489062004d2f565b935050505062002700565b5f835f8151811062002969576200296962004c06565b602002602001015190505f5b82811015620029e957604080516020810184905290810185905260600160408051601f19818403018152828252805160209182012090830187905290820186905292506060016040516020818303038152906040528051906020012093508080620029e09062004c30565b91505062002975565b5095945050505050565b7fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f59062002a1f81620031b5565b607e80545f9190829062002a399063ffffffff1662004aed565b91906101000a81548163ffffffff021916908363ffffffff1602179055905060018081111562002a6d5762002a6d62004188565b86600181111562002a825762002a8262004188565b0362002aae57841562002aa8576040516363d722e760e01b815260040160405180910390fd5b62002ace565b821562002ace576040516363d722e760e01b815260040160405180910390fd5b6040518060e001604052808a6001600160a01b03168152602001896001600160a01b03168152602001886001600160401b0316815260200187600181111562002b1b5762002b1b62004188565b81525f602080830182905260408084018a9052606093840188905263ffffffff86168352607f825291829020845181546001600160a01b0391821673ffffffffffffffffffffffffffffffffffffffff199091161782559185015160018281018054958801516001600160401b0316600160a01b026001600160e01b0319909616929094169190911793909317808355938501519093909260ff60e01b1990911690600160e01b90849081111562002bd75762002bd762004188565b02179055506080820151600182018054911515600160e81b0260ff60e81b1990921691909117905560a0820151600282015560c09091015160039091015560405163ffffffff8216907f9eaf2ecbddb14889c9e141a63175c55ac25e0cd7cdea312cdfbd0397976b383a9062002c5b908c908c908c908c908c908c908c9062004d47565b60405180910390a2505050505050505050565b7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac62002c9a81620031b5565b62002ca78484846200393d565b50505050565b7f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb62002cd981620031b5565b683635c9adc5dea0000082118062002cf45750633b9aca0082105b1562002d1357604051638586952560e01b815260040160405180910390fd5b60868290556040518281527ffb383653f53ee079978d0c9aff7aeff04a10166ce244cca9c9f9d8d96bed45b29060200160405180910390a15050565b5f8281526034602052604090206001015462002d6b81620031b5565b620010ad8383620035f6565b7f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f462002da381620031b5565b6087805467ffffffffffffffff1916426001600160401b031617905560408051636de0b4bb60e11b815290517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163dbc16976916004808301925f92919082900301818387803b15801562002e1f575f80fd5b505af115801562002e32573d5f803e3d5ffd5b5050505062002e4062003c23565b50565b336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002e8a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002eb0919062004c4b565b6001600160a01b03161462002ed85760405163696072e960e01b815260040160405180910390fd5b6001600160a01b0382165f9081526082602090815260408083205463ffffffff1683526081909152902060068101546001600160401b03808216600160401b909204161462002f3a5760405163664316a560e11b815260040160405180910390fd5b600781015463ffffffff8316600160401b9091046001600160401b03161062002f7657604051633e37e23360e01b815260040160405180910390fd5b604080515f815260208101909152620010ad90849084906200393d565b62002ff860408051610180810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290529061016082015290565b63ffffffff82165f9081526081602090815260409182902080546001600160a01b038082168652600160a01b918290046001600160401b039081169487019490945260018084015491821695870195909552048216606085015260058101546080850152600681015480831660a0860152600160401b808204841660c0870152600160801b808304851660e0880152600160c01b9092048416610100870152600783015480851661012088015290810490931661014086015290926101608501929190910460ff1690811115620030d357620030d362004188565b90816001811115620030e957620030e962004188565b8152505050919050565b5f54610100900460ff16620010835760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000a4f565b620010e8828262003572565b5f82815260346020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b62002e40813362003c7b565b5f80620031e089600601546001600160401b03600160401b9091041690565b60078a01549091506001600160401b039081169089161015620032165760405163ead1340b60e01b815260040160405180910390fd5b6001600160401b0388165f90815260028a01602052604090205491508162003251576040516324cbdcc360e11b815260040160405180910390fd5b806001600160401b0316886001600160401b031611156200328557604051630f2b74f160e11b815260040160405180910390fd5b806001600160401b0316876001600160401b031611620032b85760405163b9b18f5760e01b815260040160405180910390fd5b5f620032c98a8a8a8a878b62003701565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051620032ff919062004daa565b602060405180830381855afa1580156200331b573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019062003340919062004ba1565b6200334c919062004d03565b60018c0154604080516020810182528381529051634890ed4560e11b81529293506001600160a01b0390911691639121da8a91620033909189919060040162004dc7565b602060405180830381865afa158015620033ac573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620033d2919062004e03565b620033f0576040516309bde33960e01b815260040160405180910390fd5b5f620033fd848b62004c69565b90506200345687826001600160401b03166200341862002317565b62003424919062004ad3565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016919062003cbe565b80608460088282829054906101000a90046001600160401b03166200347c919062004aa9565b82546101009290920a6001600160401b038181021990931691831602179091556084805467ffffffffffffffff60801b1916600160801b428416021790558d546040516332c2d15360e01b8152918d166004830152602482018b90523360448301526001600160a01b031691506332c2d1539060640162001656565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562003551575f80fd5b505af115801562003564573d5f803e3d5ffd5b505050506200108362003d27565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff16620010e8575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff1615620010e8575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b5f67ffffffff000000016001600160401b038316108015620036ae575067ffffffff00000001604083901c6001600160401b0316105b8015620036cf575067ffffffff00000001608083901c6001600160401b0316105b8015620036e7575067ffffffff0000000160c083901c105b15620036f557506001919050565b505f919050565b919050565b6001600160401b038086165f818152600389016020526040808220549388168252902054606092911580159062003736575081155b15620037555760405163340c614f60e11b815260040160405180910390fd5b8062003774576040516366385b5160e01b815260040160405180910390fd5b6200377f8462003678565b6200379d576040516305dae44f60e21b815260040160405180910390fd5b885460018a01546040516bffffffffffffffffffffffff193360601b16602082015260348101889052605481018590527fffffffffffffffff00000000000000000000000000000000000000000000000060c08c811b82166074840152600160a01b94859004811b8216607c84015293909204831b82166084820152608c810187905260ac810184905260cc81018990529189901b1660ec82015260f401604051602081830303815290604052925050509695505050505050565b60605f855f015f9054906101000a90046001600160a01b03166001600160a01b031663ad1edf346040518163ffffffff1660e01b8152600401602060405180830381865afa158015620038ad573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620038d3919062004ba1565b60058701546008880154604080516020810193909352820152606081018790526001600160e01b031960e08a901b1660808201526084810182905260a4810186905260c4810185905290915060e40160405160208183030381529060405291505095945050505050565b63ffffffff821615806200395c5750607e5463ffffffff908116908316115b156200397b57604051637512e5cb60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526082602052604081205463ffffffff1690819003620039bb576040516374a086a360e01b815260040160405180910390fd5b63ffffffff8181165f908152608160205260409020600781015490918516600160401b9091046001600160401b03160362003a0957604051634f61d51960e01b815260040160405180910390fd5b63ffffffff84165f908152607f602052604090206001810154600160e81b900460ff161562003a4b57604051633b8d3d9960e01b815260040160405180910390fd5b600181810154600160e01b900460ff169081111562003a6e5762003a6e62004188565b6007830154600160801b900460ff16600181111562003a915762003a9162004188565b1462003ab057604051635aa0d5f160e11b815260040160405180910390fd5b60018082018054918401805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03909416938417825591546001600160401b03600160a01b9182900416026001600160e01b031990921690921717905560038101546009830155600782018054600160401b63ffffffff8816026fffffffffffffffff0000000000000000199091161790555f62003b4c8462000d8a565b60078401805467ffffffffffffffff19166001600160401b038316179055825460405163278f794360e11b81529192506001600160a01b0389811692634f1ef2869262003ba0921690899060040162004e24565b5f604051808303815f87803b15801562003bb8575f80fd5b505af115801562003bcb573d5f803e3d5ffd5b50506040805163ffffffff8a811682526001600160401b0386166020830152881693507ff585e04c05d396901170247783d3e5f0ee9c1df23072985b50af089f5e48b19d92500160405180910390a250505050505050565b606f5460ff1662003c4757604051635386698160e01b815260040160405180910390fd5b606f805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff16620010e857604051637615be1f60e11b815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b179052620010ad90849062003d83565b606f5460ff161562003d4c57604051630bc011ff60e21b815260040160405180910390fd5b606f805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b5f62003dd9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662003e5b9092919063ffffffff16565b805190915015620010ad578080602001905181019062003dfa919062004e03565b620010ad5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000a4f565b60606200262384845f85855f80866001600160a01b0316858760405162003e83919062004daa565b5f6040518083038185875af1925050503d805f811462003ebf576040519150601f19603f3d011682016040523d82523d5f602084013e62003ec4565b606091505b5091509150620017ec878383876060831562003f445782515f0362003f3c576001600160a01b0385163b62003f3c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000a4f565b508162002623565b62002623838381511562003f5b5781518083602001fd5b8060405162461bcd60e51b815260040162000a4f91906200458b565b61091d8062004e4883390190565b6001600160a01b038116811462002e40575f80fd5b80356001600160401b0381168114620036fc575f80fd5b5f805f805f8060c0878903121562003fc7575f80fd5b863562003fd48162003f85565b955062003fe46020880162003f9a565b945062003ff46040880162003f9a565b93506060870135620040068162003f85565b92506080870135620040188162003f85565b915060a08701356200402a8162003f85565b809150509295509295509295565b803563ffffffff81168114620036fc575f80fd5b5f602082840312156200405d575f80fd5b620040688262004038565b9392505050565b5f805f805f805f806103e0808a8c03121562004089575f80fd5b620040948a62004038565b9850620040a460208b0162003f9a565b9750620040b460408b0162003f9a565b9650620040c460608b0162003f9a565b955060808a0135945060a08a0135935060c08a0135620040e48162003f85565b92508981018b1015620040f5575f80fd5b5060e0890190509295985092959890939650565b5f602082840312156200411a575f80fd5b5035919050565b5f806040838503121562004133575f80fd5b6200413e8362004038565b91506200414e6020840162003f9a565b90509250929050565b5f806040838503121562004169575f80fd5b8235915060208301356200417d8162003f85565b809150509250929050565b634e487b7160e01b5f52602160045260245ffd5b60028110620041b957634e487b7160e01b5f52602160045260245ffd5b9052565b6001600160a01b038881168252871660208201526001600160401b038616604082015260e08101620041f360608301876200419c565b931515608082015260a081019290925260c090910152949350505050565b5f805f6060848603121562004224575f80fd5b6200422f8462004038565b95602085013595506040909401359392505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171562004283576200428362004244565b604052919050565b5f6001600160401b03831115620042a657620042a662004244565b620042bb601f8401601f191660200162004258565b9050828152838383011115620042cf575f80fd5b828260208301375f602084830101529392505050565b5f82601f830112620042f5575f80fd5b62004068838335602085016200428b565b5f805f805f805f60e0888a0312156200431d575f80fd5b620043288862004038565b9650620043386020890162003f9a565b955060408801356200434a8162003f85565b945060608801356200435c8162003f85565b935060808801356200436e8162003f85565b925060a08801356001600160401b03808211156200438a575f80fd5b620043988b838c01620042e5565b935060c08a0135915080821115620043ae575f80fd5b50620043bd8a828b01620042e5565b91505092959891949750929550565b81516001600160a01b0316815261018081016020830151620043f960208401826001600160401b03169052565b5060408301516200441560408401826001600160a01b03169052565b5060608301516200443160608401826001600160401b03169052565b506080830151608083015260a08301516200445760a08401826001600160401b03169052565b5060c08301516200447360c08401826001600160401b03169052565b5060e08301516200448f60e08401826001600160401b03169052565b50610100838101516001600160401b03169083015261012080840151620044b9828501826200419c565b5050610140838101519083015261016092830151929091019190915290565b5f805f805f8060c08789031215620044ee575f80fd5b620044f98762004038565b9550620045096020880162003f9a565b9450620045196040880162003f9a565b9350606087013592506080870135915060a087013590509295509295509295565b5f5b83811015620045565781810151838201526020016200453c565b50505f910152565b5f8151808452620045778160208601602086016200453a565b601f01601f19169290920160200192915050565b602081525f6200406860208301846200455e565b5f60208284031215620045b0575f80fd5b620040688262003f9a565b5f805f805f8060a08789031215620045d1575f80fd5b620045dc8762004038565b9550620045ec6020880162004038565b9450604087013593506060870135925060808701356001600160401b038082111562004616575f80fd5b818901915089601f8301126200462a575f80fd5b81358181111562004639575f80fd5b8a60208285010111156200464b575f80fd5b6020830194508093505050509295509295509295565b5f602080838503121562004673575f80fd5b82356001600160401b03808211156200468a575f80fd5b818501915085601f8301126200469e575f80fd5b813581811115620046b357620046b362004244565b8060051b9150620046c684830162004258565b8181529183018401918481019088841115620046e0575f80fd5b938501935b838510156200470057843582529385019390850190620046e5565b98975050505050505050565b5f80604083850312156200471e575f80fd5b82356200413e8162003f85565b803560028110620036fc575f80fd5b5f805f805f805f60e0888a03121562004751575f80fd5b87356200475e8162003f85565b96506020880135620047708162003f85565b9550620047806040890162003f9a565b9450620047906060890162003f9a565b935060808801359250620047a760a089016200472b565b915060c0880135905092959891949750929550565b5f8060408385031215620047ce575f80fd5b620047d98362003f9a565b946020939093013593505050565b5f805f8060808587031215620047fb575f80fd5b620048068562004038565b966020860135965060408601359560600135945092505050565b5f805f805f805f60e0888a03121562004837575f80fd5b8735620048448162003f85565b96506020880135620048568162003f85565b9550620048666040890162003f9a565b945062004876606089016200472b565b93506080880135925060a08801356001600160401b0381111562004898575f80fd5b620048a68a828b01620042e5565b92505060c0880135905092959891949750929550565b5f805f60608486031215620048cf575f80fd5b8335620048dc8162003f85565b9250620048ec6020850162004038565b915060408401356001600160401b0381111562004907575f80fd5b8401601f8101861362004918575f80fd5b62004929868235602084016200428b565b9150509250925092565b5f6020828403121562004944575f80fd5b8135620040688162003f85565b5f806040838503121562004963575f80fd5b8235620049708162003f85565b91506200414e6020840162004038565b81516001600160a01b0316815261018081016020830151620049ad60208401826001600160401b03169052565b506040830151620049c960408401826001600160a01b03169052565b506060830151620049e560608401826001600160401b03169052565b506080830151608083015260a083015162004a0b60a08401826001600160401b03169052565b5060c083015162004a2760c08401826001600160401b03169052565b5060e083015162004a4360e08401826001600160401b03169052565b50610100838101516001600160401b03908116918401919091526101208085015182169084015261014080850151909116908301526101608084015162004a8d828501826200419c565b505092915050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b0381811683821601908082111562004acc5762004acc62004a95565b5092915050565b808202811582820484141762000db35762000db362004a95565b5f63ffffffff80831681810362004b085762004b0862004a95565b6001019392505050565b5f6001600160a01b038086168352808516602084015250606060408301526200262060608301846200455e565b5f6001600160a01b038089168352808816602084015263ffffffff8716604084015280861660608401525060c0608083015262004b8060c08301856200455e565b82810360a084015262004b9481856200455e565b9998505050505050505050565b5f6020828403121562004bb2575f80fd5b5051919050565b848152606060208201525f62004bd360608301866200455e565b8281036040840152838152838560208301375f602085830101526020601f19601f86011682010191505095945050505050565b634e487b7160e01b5f52603260045260245ffd5b8082018082111562000db35762000db362004a95565b5f6001820162004c445762004c4462004a95565b5060010190565b5f6020828403121562004c5c575f80fd5b8151620040688162003f85565b6001600160401b0382811682821603908082111562004acc5762004acc62004a95565b6001600160401b0387811682526001600160a01b0387166020830152858116604083015260c082019062004cc460608401876200419c565b93909316608082015260a00152949350505050565b634e487b7160e01b5f52601260045260245ffd5b5f8262004cfe5762004cfe62004cd9565b500490565b5f8262004d145762004d1462004cd9565b500690565b8181038181111562000db35762000db362004a95565b5f8162004d405762004d4062004a95565b505f190190565b6001600160a01b038881168252871660208201526001600160401b03861660408201525f62004d7a60608301876200419c565b84608083015260e060a083015262004d9660e08301856200455e565b90508260c083015298975050505050505050565b5f825162004dbd8184602087016200453a565b9190910192915050565b6103208101610300808584378201835f5b600181101562004df957815183526020928301929091019060010162004dd8565b5050509392505050565b5f6020828403121562004e14575f80fd5b8151801515811462004068575f80fd5b6001600160a01b0383168152604060208201525f6200262360408301846200455e56fe60a06040526040516200091d3803806200091d833981016040819052620000269162000375565b828162000034828262000060565b50506001600160a01b038216608052620000576200005160805190565b620000c5565b5050506200046c565b6200006b8262000136565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000b757620000b28282620001b5565b505050565b620000c16200022e565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620001065f80516020620008fd833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001338162000250565b50565b806001600160a01b03163b5f036200017157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b031684604051620001d391906200044f565b5f60405180830381855af49150503d805f81146200020d576040519150601f19603f3d011682016040523d82523d5f602084013e62000212565b606091505b5090925090506200022585838362000291565b95945050505050565b34156200024e5760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b0381166200027b57604051633173bdd160e11b81525f600482015260240162000168565b805f80516020620008fd83398151915262000194565b606082620002aa57620002a482620002f7565b620002f0565b8151158015620002c257506001600160a01b0384163b155b15620002ed57604051639996b31560e01b81526001600160a01b038516600482015260240162000168565b50805b9392505050565b805115620003085780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811462000338575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b838110156200036d57818101518382015260200162000353565b50505f910152565b5f805f6060848603121562000388575f80fd5b620003938462000321565b9250620003a36020850162000321565b60408501519092506001600160401b0380821115620003c0575f80fd5b818601915086601f830112620003d4575f80fd5b815181811115620003e957620003e96200033d565b604051601f8201601f19908116603f011681019083821181831017156200041457620004146200033d565b816040528281528960208487010111156200042d575f80fd5b6200044083602083016020880162000351565b80955050505050509250925092565b5f82516200046281846020870162000351565b9190910192915050565b608051610479620004845f395f601001526104795ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610081575f357fffffffff000000000000000000000000000000000000000000000000000000001663278f794360e11b1461007957610077610085565b565b610077610095565b6100775b6100776100906100c3565b6100fa565b5f806100a43660048184610313565b8101906100b1919061034e565b915091506100bf8282610118565b5050565b5f6100f57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e808015610114573d5ff35b3d5ffd5b61012182610172565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561016a5761016582826101fa565b505050565b6100bf61026c565b806001600160a01b03163b5f036101ac57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516102169190610417565b5f60405180830381855af49150503d805f811461024e576040519150601f19603f3d011682016040523d82523d5f602084013e610253565b606091505b509150915061026385838361028b565b95945050505050565b34156100775760405163b398979f60e01b815260040160405180910390fd5b6060826102a05761029b826102ea565b6102e3565b81511580156102b757506001600160a01b0384163b155b156102e057604051639996b31560e01b81526001600160a01b03851660048201526024016101a3565b50805b9392505050565b8051156102fa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f8085851115610321575f80fd5b8386111561032d575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561035f575f80fd5b82356001600160a01b0381168114610375575f80fd5b9150602083013567ffffffffffffffff80821115610391575f80fd5b818501915085601f8301126103a4575f80fd5b8135818111156103b6576103b661033a565b604051601f8201601f19908116603f011681019083821181831017156103de576103de61033a565b816040528281528860208487010111156103f6575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610436576020818601810151858301520161041c565b505f92019182525091905056fea264697066735822122021e23b4641727aa4aa8fd2d3ef7960a43cab420d4c8632503bedc3eb2d30690764736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103a26469706673582212200ba7709ac5122ac8329e53f4c86801ef6b95d32e3af0d4683702b6e1064e468764736f6c63430008140033", + "deployedBytecode": "0x608060405234801562000010575f80fd5b50600436106200035c575f3560e01c80638875f03c11620001cb578063c1acbc341162000107578063d890581211620000ab578063dfdb8c5e1162000083578063dfdb8c5e1462000958578063e46761c4146200096f578063f4e926751462000997578063f9c4c2ae14620009a8575f80fd5b8063d89058121462000908578063dbc169761462000933578063dde0ff77146200093d575f80fd5b8063d02103ca11620000df578063d02103ca14620008b2578063d5073f6f14620008da578063d547741f14620008f1575f80fd5b8063c1acbc341462000858578063c4c928c21462000873578063ceee281d146200088a575f80fd5b80639a908e73116200016f578063a2967d991162000147578063a2967d9914620007f6578063a3c573eb1462000800578063abcb51981462000841575f80fd5b80639a908e7314620007c05780639e36c56514620007d7578063a217fddf14620007ee575f80fd5b806391d1485411620001a357806391d14854146200076457806397bf07e8146200079f57806399f5634e14620007b6575f80fd5b80638875f03c146200071f5780638f698ec514620007365780638fd88cc2146200074d575f80fd5b8063477fa270116200029b5780637222020f116200023f5780637975fcfe11620002175780637975fcfe14620006c75780637fb6e76a14620006ed5780638129fc1c1462000715575f80fd5b80637222020f1462000673578063727885e9146200068a57806374d9c24414620006a1575f80fd5b806362d87e66116200027357806362d87e6614620005a857806365c0504d14620005bf578063680658a1146200063f575f80fd5b8063477fa270146200055257806355a71ee0146200055b57806360469169146200059e575f80fd5b80632072f6c511620003035780632f2ff15d11620002db5780632f2ff15d146200051057806330c27dde146200052757806336568abe146200053b575f80fd5b80632072f6c5146200041e578063248a9ca3146200042857806325280169146200045c575f80fd5b80631489ed1011620003375780631489ed1014620003c157806315064c9614620003d85780631796a1ae14620003f7575f80fd5b8063066ec01214620003605780630e36f582146200039157806311f6b28714620003aa575b5f80fd5b60845462000374906001600160401b031681565b6040516001600160401b0390911681526020015b60405180910390f35b620003a8620003a236600462003fb1565b620009ce565b005b62000374620003bb3660046200404c565b62000d8a565b620003a8620003d23660046200406f565b62000db9565b606f54620003e69060ff1681565b604051901515815260200162000388565b607e54620004089063ffffffff1681565b60405163ffffffff909116815260200162000388565b620003a862000fa9565b6200044d6200043936600462004109565b5f9081526034602052604090206001015490565b60405190815260200162000388565b620004dc6200046d36600462004121565b60408051606080820183525f808352602080840182905292840181905263ffffffff959095168552608182528285206001600160401b03948516865260030182529382902082519485018352805485526001015480841691850191909152600160401b90049091169082015290565b60408051825181526020808401516001600160401b0390811691830191909152928201519092169082015260600162000388565b620003a86200052136600462004157565b62001085565b60875462000374906001600160401b031681565b620003a86200054c36600462004157565b620010b2565b6086546200044d565b6200044d6200056c36600462004121565b63ffffffff82165f9081526081602090815260408083206001600160401b038516845260020190915290205492915050565b6200044d620010ec565b620003e6620005b936600462004109565b62001103565b6200062a620005d03660046200404c565b607f6020525f908152604090208054600182015460028301546003909301546001600160a01b0392831693928216926001600160401b03600160a01b8404169260ff600160e01b8204811693600160e81b90920416919087565b604051620003889796959493929190620041bd565b620003a86200065036600462004211565b63ffffffff9092165f908152608160205260409020600581019190915560080155565b620003a8620006843660046200404c565b6200110f565b620003a86200069b36600462004306565b62001205565b620006b8620006b23660046200404c565b62001693565b604051620003889190620043cc565b620006de620006d8366004620044d8565b620017c5565b6040516200038891906200458b565b62000408620006fe3660046200459f565b60836020525f908152604090205463ffffffff1681565b620003a8620017f7565b620003a862000730366004620045bb565b6200192b565b620003a86200074736600462004661565b62001be1565b620003a86200075e3660046200470c565b62001c65565b620003e66200077536600462004157565b5f9182526034602090815260408084206001600160a01b0393909316845291905290205460ff1690565b620003a8620007b03660046200473a565b62001fff565b6200044d62002317565b62000374620007d1366004620047bc565b620023f8565b620006de620007e8366004620047e7565b620025f9565b6200044d5f81565b6200044d6200262b565b620008287f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200162000388565b620003a86200085236600462004820565b620029f3565b6084546200037490600160801b90046001600160401b031681565b620003a862000884366004620048bc565b62002c6e565b620004086200089b36600462004933565b60826020525f908152604090205463ffffffff1681565b620008287f000000000000000000000000000000000000000000000000000000000000000081565b620003a8620008eb36600462004109565b62002cad565b620003a86200090236600462004157565b62002d4f565b620006de6040518060400160405280600b81526020016a70657373696d697374696360a81b81525081565b620003a862002d77565b6084546200037490600160401b90046001600160401b031681565b620003a86200096936600462004951565b62002e43565b620008287f000000000000000000000000000000000000000000000000000000000000000081565b608054620004089063ffffffff1681565b620009bf620009b93660046200404c565b62002f93565b60405162000388919062004980565b5f54600290610100900460ff16158015620009ef57505f5460ff8083169116105b62000a585760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805461ffff191660ff83161761010017905567016345785d8a000060865562000a81620030f3565b62000aad7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4886200315f565b62000ab95f846200315f565b62000ae57fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f590846200315f565b62000b117f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e846200315f565b62000b3d7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac846200315f565b62000b697fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd856200315f565b62000b957fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd08856200315f565b62000bc17f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f4856200315f565b62000bed7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1856200315f565b62000c397f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd47f73cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f06200316b565b62000c657f73cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f0856200315f565b62000c917f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb856200315f565b62000cdd7f141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545e7f9b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff2859516200316b565b62000d097f141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545e836200315f565b62000d357f9b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff285951836200315f565b62000d415f336200315f565b5f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b63ffffffff81165f90815260816020526040812060060154600160401b90046001600160401b03165b92915050565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd462000de581620031b5565b6001600160401b0388161562000e0e5760405163306dfc5760e11b815260040160405180910390fd5b63ffffffff89165f908152608160205260408120906007820154600160801b900460ff16600181111562000e465762000e4662004188565b1462000e65576040516390db0d0760e01b815260040160405180910390fd5b62000e7681898989898989620031c1565b6006810180546fffffffffffffffff00000000000000001916600160401b6001600160401b038a16908102919091179091555f9081526002820160205260409020859055600581018690557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62000efa6200262b565b6040518263ffffffff1660e01b815260040162000f1991815260200190565b5f604051808303815f87803b15801562000f31575f80fd5b505af115801562000f44573d5f803e3d5ffd5b5050604080516001600160401b038b1681526020810189905290810189905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d3906060015b60405180910390a350505050505050505050565b335f9081527f8875b94af5657a2903def9906d67a3f42d8a836d24b5602c00f00fc855339fcd602052604090205460ff166200107957608454600160801b90046001600160401b031615806200102a575060845442906200101f9062093a8090600160801b90046001600160401b031662004aa9565b6001600160401b0316115b806200105a575060875442906200104f9062093a80906001600160401b031662004aa9565b6001600160401b0316115b15620010795760405163692baaad60e11b815260040160405180910390fd5b62001083620034f8565b565b5f82815260346020526040902060010154620010a181620031b5565b620010ad838362003572565b505050565b6001600160a01b0381163314620010dc57604051630b4ad1cd60e31b815260040160405180910390fd5b620010e88282620035f6565b5050565b5f6086546064620010fe919062004ad3565b905090565b5f62000db38262003678565b7fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd6200113b81620031b5565b63ffffffff821615806200115a5750607e5463ffffffff908116908316115b156200117957604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff82165f908152607f602052604090206001810154600160e81b900460ff1615620011bb57604051633b8d3d9960e01b815260040160405180910390fd5b60018101805460ff60e81b1916600160e81b17905560405163ffffffff8416907f4710d2ee567ef1ed6eb2f651dde4589524bcf7cebc62147a99b281cc836e7e44905f90a2505050565b7fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd086200123181620031b5565b63ffffffff88161580620012505750607e5463ffffffff908116908916115b156200126f57604051637512e5cb60e01b815260040160405180910390fd5b63ffffffff88165f908152607f602052604090206001810154600160e81b900460ff1615620012b157604051633b8d3d9960e01b815260040160405180910390fd5b63ffffffff6001600160401b0389161115620012e057604051634c753f5760e01b815260040160405180910390fd5b6001600160401b0388165f9081526083602052604090205463ffffffff16156200131d576040516337c8fe0960e11b815260040160405180910390fd5b608080545f91908290620013379063ffffffff1662004aed565b825463ffffffff8281166101009490940a93840293021916919091179091558254604080515f80825260208201928390529394506001600160a01b03909216913091620013849062003f77565b620013929392919062004b12565b604051809103905ff080158015620013ac573d5f803e3d5ffd5b5090508160835f8c6001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508160825f836001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8463ffffffff1663ffffffff1681526020019081526020015f20905081815f015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508360010160149054906101000a90046001600160401b03168160010160146101000a8154816001600160401b0302191690836001600160401b03160217905550836001015f9054906101000a90046001600160a01b0316816001015f6101000a8154816001600160a01b0302191690836001600160a01b031602179055508a815f0160146101000a8154816001600160401b0302191690836001600160401b031602179055508360020154816002015f806001600160401b031681526020019081526020015f20819055508b63ffffffff168160070160086101000a8154816001600160401b0302191690836001600160401b0316021790555083600101601c9054906101000a900460ff168160070160106101000a81548160ff02191690836001811115620015ac57620015ac62004188565b0217905550600384015460098201556040805163ffffffff8e811682526001600160a01b0385811660208401526001600160401b038f16838501528b1660608301529151918516917f194c983456df6701c6a50830b90fe80e72b823411d0d524970c9590dc277a6419181900360800190a2604051633892b81160e11b81526001600160a01b0383169063712570229062001656908d908d9088908e908e908e9060040162004b3f565b5f604051808303815f87803b1580156200166e575f80fd5b505af115801562001681573d5f803e3d5ffd5b50505050505050505050505050505050565b60408051610180810182525f8082526020808301828152838501838152606085018481526080860185815260a0870186815260c0880187815260e089018881526101008a018981526101208b018a81526101408c018b90526101608c018b905263ffffffff8e168b5260819099529a90982080546001600160a01b038082168c52600160a01b918290046001600160401b0390811690995260018084015491821690985204871690945260058401549092526006830154808616909152600160401b9081900485169091526007820154808516909652850490921690955292939091600160801b900460ff169081111562001792576200179262004188565b90816001811115620017a857620017a862004188565b905250600881015461014083015260090154610160820152919050565b63ffffffff86165f908152608160205260409020606090620017ec90878787878762003701565b979650505050505050565b5f54600390610100900460ff161580156200181857505f5460ff8083169116105b6200187d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b606482015260840162000a4f565b5f805461ffff191660ff831617610100179055604080518082018252600b81526a70657373696d697374696360a81b602082015290517f50cadc0c001f05dd4b81db1e92b98d77e718fd2f103fb7b77293e867d329a4c291620018e0916200458b565b60405180910390a15f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd46200195781620031b5565b63ffffffff87165f90815260816020526040902060016007820154600160801b900460ff16600181111562001990576200199062004188565b14620019af57604051633a64d97360e01b815260040160405180910390fd5b60405163ef4eeb3560e01b815263ffffffff881660048201525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063ef4eeb3590602401602060405180830381865afa15801562001a1a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001a40919062004ba1565b90508062001a615760405163a60721e160e01b815260040160405180910390fd5b5f62001a718a84848b8b62003858565b6001840154600985015460405163020a49e360e51b81529293506001600160a01b03909116916341493c609162001ab19185908b908b9060040162004bb9565b5f6040518083038186803b15801562001ac8575f80fd5b505afa15801562001adb573d5f803e3d5ffd5b50506084805467ffffffffffffffff60801b1916600160801b426001600160401b031602179055505060058301889055600883018790557f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166333d6247d62001b4b6200262b565b6040518263ffffffff1660e01b815260040162001b6a91815260200190565b5f604051808303815f87803b15801562001b82575f80fd5b505af115801562001b95573d5f803e3d5ffd5b5050604080515f80825260208201529081018b905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d39060600162000f95565b80516080805463ffffffff191663ffffffff9092169190911790555f5b8151811015620010e85781818151811062001c1d5762001c1d62004c06565b602002602001015160815f83600162001c37919062004c1a565b63ffffffff16815260208101919091526040015f20600501558062001c5c8162004c30565b91505062001bfe565b335f9081527ff14f5a8ad59d90593602e905b358229bff5ceea677d5bf0f5a1701793550a9a6602052604090205460ff1615801562001d185750336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001ce6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001d0c919062004c4b565b6001600160a01b031614155b1562001d3757604051630d03687f60e11b815260040160405180910390fd5b6001600160a01b0382165f9081526082602052604081205463ffffffff169081900362001d77576040516374a086a360e01b815260040160405180910390fd5b63ffffffff81165f908152608160205260408120906007820154600160801b900460ff16600181111562001daf5762001daf62004188565b1462001dce576040516390db0d0760e01b815260040160405180910390fd5b60068101546001600160401b039081169084168111158062001e07575060068201546001600160401b03600160401b9091048116908516105b1562001e265760405163cb23ebdf60e01b815260040160405180910390fd5b805b846001600160401b0316816001600160401b03161462001eca576001600160401b038082165f908152600385016020526040902060010154600160401b9004811690861681101562001e8d57604051639753965f60e01b815260040160405180910390fd5b6001600160401b039091165f908152600384016020526040812090815560010180546fffffffffffffffffffffffffffffffff1916905562001e28565b60068301805467ffffffffffffffff19166001600160401b03871617905562001ef4858362004c69565b608480545f9062001f109084906001600160401b031662004c69565b82546101009290920a6001600160401b0381810219909316918316021790915586165f8181526003860160205260409081902054905163334d6f6760e11b8152600481019290925260248201526001600160a01b038816915063669adece906044015f604051808303815f87803b15801562001f8a575f80fd5b505af115801562001f9d573d5f803e3d5ffd5b505050506001600160401b0385165f81815260038501602090815260409182902054915191825263ffffffff8716917f80a6d395a55aed8126079cb8247f0a6848b1440ca2cdca3b4386f250c3529402910160405180910390a3505050505050565b7f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e6200202b81620031b5565b6001600160401b0385165f9081526083602052604090205463ffffffff161562002068576040516337c8fe0960e11b815260040160405180910390fd5b63ffffffff6001600160401b03861611156200209757604051634c753f5760e01b815260040160405180910390fd5b6001600160a01b0388165f9081526082602052604090205463ffffffff1615620020d457604051630d409b9360e41b815260040160405180910390fd5b608080545f91908290620020ee9063ffffffff1662004aed565b91906101000a81548163ffffffff021916908363ffffffff160217905590508060835f886001600160401b03166001600160401b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508060825f8b6001600160a01b03166001600160a01b031681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8363ffffffff1663ffffffff1681526020019081526020015f20905089815f015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550878160010160146101000a8154816001600160401b0302191690836001600160401b0316021790555088816001015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555086815f0160146101000a8154816001600160401b0302191690836001600160401b03160217905550848160070160106101000a81548160ff0219169083600181111562002278576200227862004188565b0217905550600185600181111562002294576200229462004188565b03620022ae576009810184905560058101869055620022c1565b5f80805260028201602052604090208690555b8163ffffffff167fd490df184152edba8455dac3228134939c71f8cb4c8f310c3145dec9037147ac898c8a895f8a604051620023039695949392919062004c8c565b60405180910390a250505050505050505050565b6040516370a0823160e01b81523060048201525f9081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa1580156200237e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620023a4919062004ba1565b6084549091505f90620023ca906001600160401b03600160401b82048116911662004c69565b6001600160401b03169050805f03620023e5575f9250505090565b620023f1818362004ced565b9250505090565b606f545f9060ff16156200241f57604051630bc011ff60e21b815260040160405180910390fd5b335f9081526082602052604081205463ffffffff169081900362002456576040516371653c1560e01b815260040160405180910390fd5b836001600160401b03165f036200248057604051632590ccf960e01b815260040160405180910390fd5b63ffffffff81165f908152608160205260408120906007820154600160801b900460ff166001811115620024b857620024b862004188565b14620024d7576040516390db0d0760e01b815260040160405180910390fd5b608480548691905f90620024f69084906001600160401b031662004aa9565b82546101009290920a6001600160401b0381810219909316918316021790915560068301541690505f6200252b878362004aa9565b6006840180546001600160401b0383811667ffffffffffffffff199092168217909255604080516060810182528a815242841660208083019182528886168385019081525f86815260038c018352859020935184559151600193909301805492518716600160401b026fffffffffffffffffffffffffffffffff199093169390961692909217179093555190815291925063ffffffff8616917f1d9f30260051d51d70339da239ea7b080021adcaabfa71c9b0ea339a20cf9a25910160405180910390a29695505050505050565b63ffffffff84165f9081526081602052604090206060906200262090869086868662003858565b90505b949350505050565b6080545f9063ffffffff168082036200264557505f919050565b5f816001600160401b0381111562002661576200266162004244565b6040519080825280602002602001820160405280156200268b578160200160208202803683370190505b5090505f5b82811015620026fb5760815f620026a983600162004c1a565b63ffffffff1663ffffffff1681526020019081526020015f2060050154828281518110620026db57620026db62004c06565b602090810291909101015280620026f28162004c30565b91505062002690565b505f60205b8360011462002953575f6200271760028662004d03565b6200272460028762004ced565b62002730919062004c1a565b90505f816001600160401b038111156200274e576200274e62004244565b60405190808252806020026020018201604052801562002778578160200160208202803683370190505b5090505f5b82811015620028ff576200279360018462004d19565b81148015620027ae5750620027aa60028862004d03565b6001145b15620028365785620027c282600262004ad3565b81518110620027d557620027d562004c06565b602002602001015185604051602001620027f9929190918252602082015260400190565b6040516020818303038152906040528051906020012082828151811062002824576200282462004c06565b602002602001018181525050620028ea565b856200284482600262004ad3565b8151811062002857576200285762004c06565b6020026020010151868260026200286f919062004ad3565b6200287c90600162004c1a565b815181106200288f576200288f62004c06565b6020026020010151604051602001620028b2929190918252602082015260400190565b60405160208183030381529060405280519060200120828281518110620028dd57620028dd62004c06565b6020026020010181815250505b80620028f68162004c30565b9150506200277d565b50809450819550838460405160200162002923929190918252602082015260400190565b6040516020818303038152906040528051906020012093508280620029489062004d2f565b935050505062002700565b5f835f8151811062002969576200296962004c06565b602002602001015190505f5b82811015620029e957604080516020810184905290810185905260600160408051601f19818403018152828252805160209182012090830187905290820186905292506060016040516020818303038152906040528051906020012093508080620029e09062004c30565b91505062002975565b5095945050505050565b7fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f59062002a1f81620031b5565b607e80545f9190829062002a399063ffffffff1662004aed565b91906101000a81548163ffffffff021916908363ffffffff1602179055905060018081111562002a6d5762002a6d62004188565b86600181111562002a825762002a8262004188565b0362002aae57841562002aa8576040516363d722e760e01b815260040160405180910390fd5b62002ace565b821562002ace576040516363d722e760e01b815260040160405180910390fd5b6040518060e001604052808a6001600160a01b03168152602001896001600160a01b03168152602001886001600160401b0316815260200187600181111562002b1b5762002b1b62004188565b81525f602080830182905260408084018a9052606093840188905263ffffffff86168352607f825291829020845181546001600160a01b0391821673ffffffffffffffffffffffffffffffffffffffff199091161782559185015160018281018054958801516001600160401b0316600160a01b026001600160e01b0319909616929094169190911793909317808355938501519093909260ff60e01b1990911690600160e01b90849081111562002bd75762002bd762004188565b02179055506080820151600182018054911515600160e81b0260ff60e81b1990921691909117905560a0820151600282015560c09091015160039091015560405163ffffffff8216907f9eaf2ecbddb14889c9e141a63175c55ac25e0cd7cdea312cdfbd0397976b383a9062002c5b908c908c908c908c908c908c908c9062004d47565b60405180910390a2505050505050505050565b7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac62002c9a81620031b5565b62002ca78484846200393d565b50505050565b7f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb62002cd981620031b5565b683635c9adc5dea0000082118062002cf45750633b9aca0082105b1562002d1357604051638586952560e01b815260040160405180910390fd5b60868290556040518281527ffb383653f53ee079978d0c9aff7aeff04a10166ce244cca9c9f9d8d96bed45b29060200160405180910390a15050565b5f8281526034602052604090206001015462002d6b81620031b5565b620010ad8383620035f6565b7f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f462002da381620031b5565b6087805467ffffffffffffffff1916426001600160401b031617905560408051636de0b4bb60e11b815290517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169163dbc16976916004808301925f92919082900301818387803b15801562002e1f575f80fd5b505af115801562002e32573d5f803e3d5ffd5b5050505062002e4062003c23565b50565b336001600160a01b0316826001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801562002e8a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002eb0919062004c4b565b6001600160a01b03161462002ed85760405163696072e960e01b815260040160405180910390fd5b6001600160a01b0382165f9081526082602090815260408083205463ffffffff1683526081909152902060068101546001600160401b03808216600160401b909204161462002f3a5760405163664316a560e11b815260040160405180910390fd5b600781015463ffffffff8316600160401b9091046001600160401b03161062002f7657604051633e37e23360e01b815260040160405180910390fd5b604080515f815260208101909152620010ad90849084906200393d565b62002ff860408051610180810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290529061016082015290565b63ffffffff82165f9081526081602090815260409182902080546001600160a01b038082168652600160a01b918290046001600160401b039081169487019490945260018084015491821695870195909552048216606085015260058101546080850152600681015480831660a0860152600160401b808204841660c0870152600160801b808304851660e0880152600160c01b9092048416610100870152600783015480851661012088015290810490931661014086015290926101608501929190910460ff1690811115620030d357620030d362004188565b90816001811115620030e957620030e962004188565b8152505050919050565b5f54610100900460ff16620010835760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840162000a4f565b620010e8828262003572565b5f82815260346020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b62002e40813362003c7b565b5f80620031e089600601546001600160401b03600160401b9091041690565b60078a01549091506001600160401b039081169089161015620032165760405163ead1340b60e01b815260040160405180910390fd5b6001600160401b0388165f90815260028a01602052604090205491508162003251576040516324cbdcc360e11b815260040160405180910390fd5b806001600160401b0316886001600160401b031611156200328557604051630f2b74f160e11b815260040160405180910390fd5b806001600160401b0316876001600160401b031611620032b85760405163b9b18f5760e01b815260040160405180910390fd5b5f620032c98a8a8a8a878b62003701565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051620032ff919062004daa565b602060405180830381855afa1580156200331b573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019062003340919062004ba1565b6200334c919062004d03565b60018c0154604080516020810182528381529051634890ed4560e11b81529293506001600160a01b0390911691639121da8a91620033909189919060040162004dc7565b602060405180830381865afa158015620033ac573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620033d2919062004e03565b620033f0576040516309bde33960e01b815260040160405180910390fd5b5f620033fd848b62004c69565b90506200345687826001600160401b03166200341862002317565b62003424919062004ad3565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016919062003cbe565b80608460088282829054906101000a90046001600160401b03166200347c919062004aa9565b82546101009290920a6001600160401b038181021990931691831602179091556084805467ffffffffffffffff60801b1916600160801b428416021790558d546040516332c2d15360e01b8152918d166004830152602482018b90523360448301526001600160a01b031691506332c2d1539060640162001656565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562003551575f80fd5b505af115801562003564573d5f803e3d5ffd5b505050506200108362003d27565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff16620010e8575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff1615620010e8575f8281526034602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b5f67ffffffff000000016001600160401b038316108015620036ae575067ffffffff00000001604083901c6001600160401b0316105b8015620036cf575067ffffffff00000001608083901c6001600160401b0316105b8015620036e7575067ffffffff0000000160c083901c105b15620036f557506001919050565b505f919050565b919050565b6001600160401b038086165f818152600389016020526040808220549388168252902054606092911580159062003736575081155b15620037555760405163340c614f60e11b815260040160405180910390fd5b8062003774576040516366385b5160e01b815260040160405180910390fd5b6200377f8462003678565b6200379d576040516305dae44f60e21b815260040160405180910390fd5b885460018a01546040516bffffffffffffffffffffffff193360601b16602082015260348101889052605481018590527fffffffffffffffff00000000000000000000000000000000000000000000000060c08c811b82166074840152600160a01b94859004811b8216607c84015293909204831b82166084820152608c810187905260ac810184905260cc81018990529189901b1660ec82015260f401604051602081830303815290604052925050509695505050505050565b60605f855f015f9054906101000a90046001600160a01b03166001600160a01b031663ad1edf346040518163ffffffff1660e01b8152600401602060405180830381865afa158015620038ad573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620038d3919062004ba1565b60058701546008880154604080516020810193909352820152606081018790526001600160e01b031960e08a901b1660808201526084810182905260a4810186905260c4810185905290915060e40160405160208183030381529060405291505095945050505050565b63ffffffff821615806200395c5750607e5463ffffffff908116908316115b156200397b57604051637512e5cb60e01b815260040160405180910390fd5b6001600160a01b0383165f9081526082602052604081205463ffffffff1690819003620039bb576040516374a086a360e01b815260040160405180910390fd5b63ffffffff8181165f908152608160205260409020600781015490918516600160401b9091046001600160401b03160362003a0957604051634f61d51960e01b815260040160405180910390fd5b63ffffffff84165f908152607f602052604090206001810154600160e81b900460ff161562003a4b57604051633b8d3d9960e01b815260040160405180910390fd5b600181810154600160e01b900460ff169081111562003a6e5762003a6e62004188565b6007830154600160801b900460ff16600181111562003a915762003a9162004188565b1462003ab057604051635aa0d5f160e11b815260040160405180910390fd5b60018082018054918401805473ffffffffffffffffffffffffffffffffffffffff1981166001600160a01b03909416938417825591546001600160401b03600160a01b9182900416026001600160e01b031990921690921717905560038101546009830155600782018054600160401b63ffffffff8816026fffffffffffffffff0000000000000000199091161790555f62003b4c8462000d8a565b60078401805467ffffffffffffffff19166001600160401b038316179055825460405163278f794360e11b81529192506001600160a01b0389811692634f1ef2869262003ba0921690899060040162004e24565b5f604051808303815f87803b15801562003bb8575f80fd5b505af115801562003bcb573d5f803e3d5ffd5b50506040805163ffffffff8a811682526001600160401b0386166020830152881693507ff585e04c05d396901170247783d3e5f0ee9c1df23072985b50af089f5e48b19d92500160405180910390a250505050505050565b606f5460ff1662003c4757604051635386698160e01b815260040160405180910390fd5b606f805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f8281526034602090815260408083206001600160a01b038516845290915290205460ff16620010e857604051637615be1f60e11b815260040160405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b179052620010ad90849062003d83565b606f5460ff161562003d4c57604051630bc011ff60e21b815260040160405180910390fd5b606f805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b5f62003dd9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031662003e5b9092919063ffffffff16565b805190915015620010ad578080602001905181019062003dfa919062004e03565b620010ad5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b606482015260840162000a4f565b60606200262384845f85855f80866001600160a01b0316858760405162003e83919062004daa565b5f6040518083038185875af1925050503d805f811462003ebf576040519150601f19603f3d011682016040523d82523d5f602084013e62003ec4565b606091505b5091509150620017ec878383876060831562003f445782515f0362003f3c576001600160a01b0385163b62003f3c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000a4f565b508162002623565b62002623838381511562003f5b5781518083602001fd5b8060405162461bcd60e51b815260040162000a4f91906200458b565b61091d8062004e4883390190565b6001600160a01b038116811462002e40575f80fd5b80356001600160401b0381168114620036fc575f80fd5b5f805f805f8060c0878903121562003fc7575f80fd5b863562003fd48162003f85565b955062003fe46020880162003f9a565b945062003ff46040880162003f9a565b93506060870135620040068162003f85565b92506080870135620040188162003f85565b915060a08701356200402a8162003f85565b809150509295509295509295565b803563ffffffff81168114620036fc575f80fd5b5f602082840312156200405d575f80fd5b620040688262004038565b9392505050565b5f805f805f805f806103e0808a8c03121562004089575f80fd5b620040948a62004038565b9850620040a460208b0162003f9a565b9750620040b460408b0162003f9a565b9650620040c460608b0162003f9a565b955060808a0135945060a08a0135935060c08a0135620040e48162003f85565b92508981018b1015620040f5575f80fd5b5060e0890190509295985092959890939650565b5f602082840312156200411a575f80fd5b5035919050565b5f806040838503121562004133575f80fd5b6200413e8362004038565b91506200414e6020840162003f9a565b90509250929050565b5f806040838503121562004169575f80fd5b8235915060208301356200417d8162003f85565b809150509250929050565b634e487b7160e01b5f52602160045260245ffd5b60028110620041b957634e487b7160e01b5f52602160045260245ffd5b9052565b6001600160a01b038881168252871660208201526001600160401b038616604082015260e08101620041f360608301876200419c565b931515608082015260a081019290925260c090910152949350505050565b5f805f6060848603121562004224575f80fd5b6200422f8462004038565b95602085013595506040909401359392505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171562004283576200428362004244565b604052919050565b5f6001600160401b03831115620042a657620042a662004244565b620042bb601f8401601f191660200162004258565b9050828152838383011115620042cf575f80fd5b828260208301375f602084830101529392505050565b5f82601f830112620042f5575f80fd5b62004068838335602085016200428b565b5f805f805f805f60e0888a0312156200431d575f80fd5b620043288862004038565b9650620043386020890162003f9a565b955060408801356200434a8162003f85565b945060608801356200435c8162003f85565b935060808801356200436e8162003f85565b925060a08801356001600160401b03808211156200438a575f80fd5b620043988b838c01620042e5565b935060c08a0135915080821115620043ae575f80fd5b50620043bd8a828b01620042e5565b91505092959891949750929550565b81516001600160a01b0316815261018081016020830151620043f960208401826001600160401b03169052565b5060408301516200441560408401826001600160a01b03169052565b5060608301516200443160608401826001600160401b03169052565b506080830151608083015260a08301516200445760a08401826001600160401b03169052565b5060c08301516200447360c08401826001600160401b03169052565b5060e08301516200448f60e08401826001600160401b03169052565b50610100838101516001600160401b03169083015261012080840151620044b9828501826200419c565b5050610140838101519083015261016092830151929091019190915290565b5f805f805f8060c08789031215620044ee575f80fd5b620044f98762004038565b9550620045096020880162003f9a565b9450620045196040880162003f9a565b9350606087013592506080870135915060a087013590509295509295509295565b5f5b83811015620045565781810151838201526020016200453c565b50505f910152565b5f8151808452620045778160208601602086016200453a565b601f01601f19169290920160200192915050565b602081525f6200406860208301846200455e565b5f60208284031215620045b0575f80fd5b620040688262003f9a565b5f805f805f8060a08789031215620045d1575f80fd5b620045dc8762004038565b9550620045ec6020880162004038565b9450604087013593506060870135925060808701356001600160401b038082111562004616575f80fd5b818901915089601f8301126200462a575f80fd5b81358181111562004639575f80fd5b8a60208285010111156200464b575f80fd5b6020830194508093505050509295509295509295565b5f602080838503121562004673575f80fd5b82356001600160401b03808211156200468a575f80fd5b818501915085601f8301126200469e575f80fd5b813581811115620046b357620046b362004244565b8060051b9150620046c684830162004258565b8181529183018401918481019088841115620046e0575f80fd5b938501935b838510156200470057843582529385019390850190620046e5565b98975050505050505050565b5f80604083850312156200471e575f80fd5b82356200413e8162003f85565b803560028110620036fc575f80fd5b5f805f805f805f60e0888a03121562004751575f80fd5b87356200475e8162003f85565b96506020880135620047708162003f85565b9550620047806040890162003f9a565b9450620047906060890162003f9a565b935060808801359250620047a760a089016200472b565b915060c0880135905092959891949750929550565b5f8060408385031215620047ce575f80fd5b620047d98362003f9a565b946020939093013593505050565b5f805f8060808587031215620047fb575f80fd5b620048068562004038565b966020860135965060408601359560600135945092505050565b5f805f805f805f60e0888a03121562004837575f80fd5b8735620048448162003f85565b96506020880135620048568162003f85565b9550620048666040890162003f9a565b945062004876606089016200472b565b93506080880135925060a08801356001600160401b0381111562004898575f80fd5b620048a68a828b01620042e5565b92505060c0880135905092959891949750929550565b5f805f60608486031215620048cf575f80fd5b8335620048dc8162003f85565b9250620048ec6020850162004038565b915060408401356001600160401b0381111562004907575f80fd5b8401601f8101861362004918575f80fd5b62004929868235602084016200428b565b9150509250925092565b5f6020828403121562004944575f80fd5b8135620040688162003f85565b5f806040838503121562004963575f80fd5b8235620049708162003f85565b91506200414e6020840162004038565b81516001600160a01b0316815261018081016020830151620049ad60208401826001600160401b03169052565b506040830151620049c960408401826001600160a01b03169052565b506060830151620049e560608401826001600160401b03169052565b506080830151608083015260a083015162004a0b60a08401826001600160401b03169052565b5060c083015162004a2760c08401826001600160401b03169052565b5060e083015162004a4360e08401826001600160401b03169052565b50610100838101516001600160401b03908116918401919091526101208085015182169084015261014080850151909116908301526101608084015162004a8d828501826200419c565b505092915050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b0381811683821601908082111562004acc5762004acc62004a95565b5092915050565b808202811582820484141762000db35762000db362004a95565b5f63ffffffff80831681810362004b085762004b0862004a95565b6001019392505050565b5f6001600160a01b038086168352808516602084015250606060408301526200262060608301846200455e565b5f6001600160a01b038089168352808816602084015263ffffffff8716604084015280861660608401525060c0608083015262004b8060c08301856200455e565b82810360a084015262004b9481856200455e565b9998505050505050505050565b5f6020828403121562004bb2575f80fd5b5051919050565b848152606060208201525f62004bd360608301866200455e565b8281036040840152838152838560208301375f602085830101526020601f19601f86011682010191505095945050505050565b634e487b7160e01b5f52603260045260245ffd5b8082018082111562000db35762000db362004a95565b5f6001820162004c445762004c4462004a95565b5060010190565b5f6020828403121562004c5c575f80fd5b8151620040688162003f85565b6001600160401b0382811682821603908082111562004acc5762004acc62004a95565b6001600160401b0387811682526001600160a01b0387166020830152858116604083015260c082019062004cc460608401876200419c565b93909316608082015260a00152949350505050565b634e487b7160e01b5f52601260045260245ffd5b5f8262004cfe5762004cfe62004cd9565b500490565b5f8262004d145762004d1462004cd9565b500690565b8181038181111562000db35762000db362004a95565b5f8162004d405762004d4062004a95565b505f190190565b6001600160a01b038881168252871660208201526001600160401b03861660408201525f62004d7a60608301876200419c565b84608083015260e060a083015262004d9660e08301856200455e565b90508260c083015298975050505050505050565b5f825162004dbd8184602087016200453a565b9190910192915050565b6103208101610300808584378201835f5b600181101562004df957815183526020928301929091019060010162004dd8565b5050509392505050565b5f6020828403121562004e14575f80fd5b8151801515811462004068575f80fd5b6001600160a01b0383168152604060208201525f6200262360408301846200455e56fe60a06040526040516200091d3803806200091d833981016040819052620000269162000375565b828162000034828262000060565b50506001600160a01b038216608052620000576200005160805190565b620000c5565b5050506200046c565b6200006b8262000136565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000b757620000b28282620001b5565b505050565b620000c16200022e565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620001065f80516020620008fd833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001338162000250565b50565b806001600160a01b03163b5f036200017157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b031684604051620001d391906200044f565b5f60405180830381855af49150503d805f81146200020d576040519150601f19603f3d011682016040523d82523d5f602084013e62000212565b606091505b5090925090506200022585838362000291565b95945050505050565b34156200024e5760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b0381166200027b57604051633173bdd160e11b81525f600482015260240162000168565b805f80516020620008fd83398151915262000194565b606082620002aa57620002a482620002f7565b620002f0565b8151158015620002c257506001600160a01b0384163b155b15620002ed57604051639996b31560e01b81526001600160a01b038516600482015260240162000168565b50805b9392505050565b805115620003085780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811462000338575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b838110156200036d57818101518382015260200162000353565b50505f910152565b5f805f6060848603121562000388575f80fd5b620003938462000321565b9250620003a36020850162000321565b60408501519092506001600160401b0380821115620003c0575f80fd5b818601915086601f830112620003d4575f80fd5b815181811115620003e957620003e96200033d565b604051601f8201601f19908116603f011681019083821181831017156200041457620004146200033d565b816040528281528960208487010111156200042d575f80fd5b6200044083602083016020880162000351565b80955050505050509250925092565b5f82516200046281846020870162000351565b9190910192915050565b608051610479620004845f395f601001526104795ff3fe608060405261000c61000e565b005b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610081575f357fffffffff000000000000000000000000000000000000000000000000000000001663278f794360e11b1461007957610077610085565b565b610077610095565b6100775b6100776100906100c3565b6100fa565b5f806100a43660048184610313565b8101906100b1919061034e565b915091506100bf8282610118565b5050565b5f6100f57f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b365f80375f80365f845af43d5f803e808015610114573d5ff35b3d5ffd5b61012182610172565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561016a5761016582826101fa565b505050565b6100bf61026c565b806001600160a01b03163b5f036101ac57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516102169190610417565b5f60405180830381855af49150503d805f811461024e576040519150601f19603f3d011682016040523d82523d5f602084013e610253565b606091505b509150915061026385838361028b565b95945050505050565b34156100775760405163b398979f60e01b815260040160405180910390fd5b6060826102a05761029b826102ea565b6102e3565b81511580156102b757506001600160a01b0384163b155b156102e057604051639996b31560e01b81526001600160a01b03851660048201526024016101a3565b50805b9392505050565b8051156102fa5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f8085851115610321575f80fd5b8386111561032d575f80fd5b5050820193919092039150565b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561035f575f80fd5b82356001600160a01b0381168114610375575f80fd5b9150602083013567ffffffffffffffff80821115610391575f80fd5b818501915085601f8301126103a4575f80fd5b8135818111156103b6576103b661033a565b604051601f8201601f19908116603f011681019083821181831017156103de576103de61033a565b816040528281528860208487010111156103f6575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610436576020818601810151858301520161041c565b505f92019182525091905056fea264697066735822122021e23b4641727aa4aa8fd2d3ef7960a43cab420d4c8632503bedc3eb2d30690764736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103a26469706673582212200ba7709ac5122ac8329e53f4c86801ef6b95d32e3af0d4683702b6e1064e468764736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonRollupManagerMockInternalTest.json b/compiled-contracts/PolygonRollupManagerMockInternalTest.json index 5c571c301..963e25ad5 100644 --- a/compiled-contracts/PolygonRollupManagerMockInternalTest.json +++ b/compiled-contracts/PolygonRollupManagerMockInternalTest.json @@ -104,6 +104,11 @@ "name": "FinalPendingStateNumInvalid", "type": "error" }, + { + "inputs": [], + "name": "GlobalExitRootNotExist", + "type": "error" + }, { "inputs": [], "name": "HaltTimeoutNotExpired", @@ -134,6 +139,11 @@ "name": "InitSequenceNumDoesNotMatchPendingState", "type": "error" }, + { + "inputs": [], + "name": "InvalidPessimisticProof", + "type": "error" + }, { "inputs": [], "name": "InvalidProof", @@ -159,6 +169,21 @@ "name": "InvalidRangeSequenceTimeTarget", "type": "error" }, + { + "inputs": [], + "name": "InvalidRollup", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRollupType", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidVerifierType", + "type": "error" + }, { "inputs": [], "name": "MustSequenceSomeBatch", @@ -204,6 +229,11 @@ "name": "OldStateRootDoesNotExist", "type": "error" }, + { + "inputs": [], + "name": "OnlyChainsWithPessimisticProofs", + "type": "error" + }, { "inputs": [], "name": "OnlyEmergencyState", @@ -219,6 +249,11 @@ "name": "OnlyRollupAdmin", "type": "error" }, + { + "inputs": [], + "name": "OnlyStateTransitionChains", + "type": "error" + }, { "inputs": [], "name": "PendingStateDoesNotExist", @@ -234,6 +269,11 @@ "name": "PendingStateNotConsolidable", "type": "error" }, + { + "inputs": [], + "name": "PendingStateNumExist", + "type": "error" + }, { "inputs": [], "name": "RollbackBatchIsNotEndOfSequence", @@ -333,8 +373,8 @@ }, { "indexed": false, - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" }, { @@ -342,6 +382,12 @@ "internalType": "uint64", "name": "lastVerifiedBatchBeforeUpgrade", "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" } ], "name": "AddExistingRollup", @@ -376,8 +422,8 @@ }, { "indexed": false, - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" }, { @@ -391,46 +437,15 @@ "internalType": "string", "name": "description", "type": "string" - } - ], - "name": "AddNewRollupType", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" }, { "indexed": false, "internalType": "bytes32", - "name": "exitRoot", + "name": "programVKey", "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "pendingStateNum", - "type": "uint64" } ], - "name": "ConsolidatePendingState", + "name": "AddNewRollupType", "type": "event" }, { @@ -527,62 +542,6 @@ "name": "OnSequenceBatches", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "exitRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "OverridePendingState", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "bytes32", - "name": "storedStateRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "provedStateRoot", - "type": "bytes32" - } - ], - "name": "ProveNonDeterministicPendingState", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -696,32 +655,6 @@ "name": "SetBatchFee", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint16", - "name": "newMultiplierBatchFee", - "type": "uint16" - } - ], - "name": "SetMultiplierBatchFee", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "newPendingStateTimeout", - "type": "uint64" - } - ], - "name": "SetPendingStateTimeout", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -735,32 +668,6 @@ "name": "SetTrustedAggregator", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "newTrustedAggregatorTimeout", - "type": "uint64" - } - ], - "name": "SetTrustedAggregatorTimeout", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint64", - "name": "newVerifyBatchTimeTarget", - "type": "uint64" - } - ], - "name": "SetVerifyBatchTimeTarget", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -786,43 +693,6 @@ "name": "UpdateRollup", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "indexed": false, - "internalType": "uint64", - "name": "numBatch", - "type": "uint64" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "exitRoot", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "aggregator", - "type": "address" - } - ], - "name": "VerifyBatches", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -888,7 +758,7 @@ "type": "address" }, { - "internalType": "contract IVerifierRollup", + "internalType": "address", "name": "verifier", "type": "address" }, @@ -904,13 +774,18 @@ }, { "internalType": "bytes32", - "name": "genesis", + "name": "initRoot", "type": "bytes32" }, { - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" } ], "name": "addExistingRollup", @@ -926,7 +801,7 @@ "type": "address" }, { - "internalType": "contract IVerifierRollup", + "internalType": "address", "name": "verifier", "type": "address" }, @@ -936,8 +811,8 @@ "type": "uint64" }, { - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" }, { @@ -949,6 +824,11 @@ "internalType": "string", "name": "description", "type": "string" + }, + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" } ], "name": "addNewRollupType", @@ -1001,24 +881,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "pendingStateNum", - "type": "uint64" - } - ], - "name": "consolidatePendingState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1102,33 +964,23 @@ "name": "rollupID", "type": "uint32" }, - { - "internalType": "uint64", - "name": "initNumBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalNewBatch", - "type": "uint64" - }, { "internalType": "bytes32", - "name": "newLocalExitRoot", + "name": "selectedGlobalExitRoot", "type": "bytes32" }, { "internalType": "bytes32", - "name": "oldStateRoot", + "name": "newLocalExitRoot", "type": "bytes32" }, { "internalType": "bytes32", - "name": "newStateRoot", + "name": "newPessimisticRoot", "type": "bytes32" } ], - "name": "getInputSnarkBytes", + "name": "getInputPessimisticBytes", "outputs": [ { "internalType": "bytes", @@ -1145,33 +997,39 @@ "internalType": "uint32", "name": "rollupID", "type": "uint32" - } - ], - "name": "getLastVerifiedBatch", - "outputs": [ + }, { "internalType": "uint64", - "name": "", + "name": "initNumBatch", "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ + }, + { + "internalType": "uint64", + "name": "finalNewBatch", + "type": "uint64" + }, { "internalType": "bytes32", - "name": "role", + "name": "newLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "oldStateRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "newStateRoot", "type": "bytes32" } ], - "name": "getRoleAdmin", + "name": "getInputSnarkBytes", "outputs": [ { - "internalType": "bytes32", + "internalType": "bytes", "name": "", - "type": "bytes32" + "type": "bytes" } ], "stateMutability": "view", @@ -1183,27 +1041,28 @@ "internalType": "uint32", "name": "rollupID", "type": "uint32" - }, - { - "internalType": "uint64", - "name": "batchNum", - "type": "uint64" } ], - "name": "getRollupBatchNumToStateRoot", + "name": "getLastVerifiedBatch", "outputs": [ { - "internalType": "bytes32", + "internalType": "uint64", "name": "", - "type": "bytes32" + "type": "uint64" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [], - "name": "getRollupExitRoot", + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", "outputs": [ { "internalType": "bytes32", @@ -1227,34 +1086,25 @@ "type": "uint64" } ], - "name": "getRollupPendingStateTransitions", + "name": "getRollupBatchNumToStateRoot", "outputs": [ { - "components": [ - { - "internalType": "uint64", - "name": "timestamp", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastVerifiedBatch", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "exitRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "stateRoot", - "type": "bytes32" - } - ], - "internalType": "struct LegacyZKEVMStateVariables.PendingState", + "internalType": "bytes32", "name": "", - "type": "tuple" + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRollupExitRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" } ], "stateMutability": "view", @@ -1427,30 +1277,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "pendingStateNum", - "type": "uint64" - } - ], - "name": "isPendingStateConsolidable", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "lastAggregationTimestamp", @@ -1477,19 +1303,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "multiplierBatchFee", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1527,67 +1340,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "initPendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalPendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initNumBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalNewBatch", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "newLocalExitRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newStateRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[24]", - "name": "proof", - "type": "bytes32[24]" - } - ], - "name": "overridePendingState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "pendingStateTimeout", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "pol", @@ -1601,54 +1353,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint32", - "name": "rollupID", - "type": "uint32" - }, - { - "internalType": "uint64", - "name": "initPendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalPendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initNumBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalNewBatch", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "newLocalExitRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "newStateRoot", - "type": "bytes32" - }, - { - "internalType": "bytes32[24]", - "name": "proof", - "type": "bytes32[24]" - } - ], - "name": "proveNonDeterministicPendingState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -1746,64 +1450,152 @@ "name": "rollupIDToRollupData", "outputs": [ { - "internalType": "contract IPolygonRollupBase", - "name": "rollupContract", - "type": "address" - }, - { - "internalType": "uint64", - "name": "chainID", - "type": "uint64" - }, - { - "internalType": "contract IVerifierRollup", - "name": "verifier", - "type": "address" - }, - { - "internalType": "uint64", - "name": "forkID", - "type": "uint64" - }, - { - "internalType": "bytes32", - "name": "lastLocalExitRoot", - "type": "bytes32" - }, - { - "internalType": "uint64", - "name": "lastBatchSequenced", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastVerifiedBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastPendingState", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastPendingStateConsolidated", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "lastVerifiedBatchBeforeUpgrade", - "type": "uint64" - }, + "components": [ + { + "internalType": "contract IPolygonRollupBase", + "name": "rollupContract", + "type": "address" + }, + { + "internalType": "uint64", + "name": "chainID", + "type": "uint64" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint64", + "name": "forkID", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "lastLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "lastBatchSequenced", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "_legacyLastPendingState", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "_legacyLastPendingStateConsolidated", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatchBeforeUpgrade", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rollupTypeID", + "type": "uint64" + }, + { + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", + "type": "uint8" + } + ], + "internalType": "struct PolygonRollupManager.RollupDataReturn", + "name": "rollupData", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { - "internalType": "uint64", - "name": "rollupTypeID", - "type": "uint64" - }, + "internalType": "uint32", + "name": "rollupID", + "type": "uint32" + } + ], + "name": "rollupIDToRollupDataV2", + "outputs": [ { - "internalType": "uint8", - "name": "rollupCompatibilityID", - "type": "uint8" + "components": [ + { + "internalType": "contract IPolygonRollupBase", + "name": "rollupContract", + "type": "address" + }, + { + "internalType": "uint64", + "name": "chainID", + "type": "uint64" + }, + { + "internalType": "address", + "name": "verifier", + "type": "address" + }, + { + "internalType": "uint64", + "name": "forkID", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "lastLocalExitRoot", + "type": "bytes32" + }, + { + "internalType": "uint64", + "name": "lastBatchSequenced", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "lastVerifiedBatchBeforeUpgrade", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "rollupTypeID", + "type": "uint64" + }, + { + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "lastPessimisticRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" + } + ], + "internalType": "struct PolygonRollupManager.RollupDataReturnV2", + "name": "rollupData", + "type": "tuple" } ], "stateMutability": "view", @@ -1838,7 +1630,7 @@ "type": "address" }, { - "internalType": "contract IVerifierRollup", + "internalType": "address", "name": "verifier", "type": "address" }, @@ -1848,8 +1640,8 @@ "type": "uint64" }, { - "internalType": "uint8", - "name": "rollupCompatibilityID", + "internalType": "enum IPolygonRollupManager.VerifierType", + "name": "rollupVerifierType", "type": "uint8" }, { @@ -1861,6 +1653,11 @@ "internalType": "bytes32", "name": "genesis", "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" } ], "stateMutability": "view", @@ -1879,58 +1676,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint16", - "name": "newMultiplierBatchFee", - "type": "uint16" - } - ], - "name": "setMultiplierBatchFee", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "newPendingStateTimeout", - "type": "uint64" - } - ], - "name": "setPendingStateTimeout", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "newTrustedAggregatorTimeout", - "type": "uint64" - } - ], - "name": "setTrustedAggregatorTimeout", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint64", - "name": "newVerifyBatchTimeTarget", - "type": "uint64" - } - ], - "name": "setVerifyBatchTimeTarget", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "totalSequencedBatches", @@ -1957,19 +1702,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "trustedAggregatorTimeout", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -2011,19 +1743,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "verifyBatchTimeTarget", - "outputs": [ - { - "internalType": "uint64", - "name": "", - "type": "uint64" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -2067,7 +1786,7 @@ "type": "bytes32[24]" } ], - "name": "verifyBatches", + "name": "verifyBatchesTrustedAggregator", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -2080,19 +1799,9 @@ "type": "uint32" }, { - "internalType": "uint64", - "name": "pendingStateNum", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "initNumBatch", - "type": "uint64" - }, - { - "internalType": "uint64", - "name": "finalNewBatch", - "type": "uint64" + "internalType": "bytes32", + "name": "selectedGlobalExitRoot", + "type": "bytes32" }, { "internalType": "bytes32", @@ -2101,28 +1810,23 @@ }, { "internalType": "bytes32", - "name": "newStateRoot", + "name": "newPessimisticRoot", "type": "bytes32" }, { - "internalType": "address", - "name": "beneficiary", - "type": "address" - }, - { - "internalType": "bytes32[24]", + "internalType": "bytes", "name": "proof", - "type": "bytes32[24]" + "type": "bytes" } ], - "name": "verifyBatchesTrustedAggregator", + "name": "verifyPessimisticTrustedAggregator", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ], - "bytecode": "0x60e060405234801562000010575f80fd5b50604051620078203803806200782083398101604081905262000033916200013c565b6001600160a01b0380841660805280831660c052811660a0528282826200005962000065565b5050505050506200018d565b5f54610100900460ff1615620000d15760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116101562000122575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b038116811462000139575f80fd5b50565b5f805f606084860312156200014f575f80fd5b83516200015c8162000124565b60208501519093506200016f8162000124565b6040850151909250620001828162000124565b809150509250925092565b60805160a05160c051617630620001f05f395f8181610bd001528181612ce6015261480b01525f818161093e0152818161375f0152614bdc01525f8181610b0c0152818161139e015281816115be015281816124ba0152614ab601526176305ff3fe608060405234801562000010575f80fd5b5060043610620003a4575f3560e01c806387c20c0111620001ef578063c4c928c21162000113578063dde0ff7711620000ab578063e46761c41162000083578063e46761c41462000bca578063f34eb8eb1462000bf2578063f4e926751462000c09578063f9c4c2ae1462000c1a575f80fd5b8063dde0ff771462000b7b578063dfdb8c5e1462000b9c578063e0bfd3d21462000bb3575f80fd5b8063d5073f6f11620000eb578063d5073f6f1462000b2e578063d547741f1462000b45578063d939b3151462000b5c578063dbc169761462000b71575f80fd5b8063c4c928c21462000ac7578063ceee281d1462000ade578063d02103ca1462000b06575f80fd5b8063a066215c1162000187578063a3c573eb116200015f578063a3c573eb1462000938578063afd23cbe1462000986578063b99d0ad714620009bd578063c1acbc341462000a9e575f80fd5b8063a066215c146200090f578063a217fddf1462000926578063a2967d99146200092e575f80fd5b806391d1485411620001c757806391d14854146200088f57806399f5634e14620008d75780639a908e7314620008e15780639c9f3dfe14620008f8575f80fd5b806387c20c01146200084a5780638bd4f07114620008615780638fd88cc21462000878575f80fd5b80632528016911620002d757806360469169116200026f578063727885e91162000247578063727885e914620007b45780637975fcfe14620007cb5780637fb6e76a14620007f1578063841b24d71462000819575f80fd5b806360469169146200068557806365c0504d146200068f5780637222020f146200079d575f80fd5b806336568abe11620002af57806336568abe146200060a578063394218e91462000621578063477fa270146200063857806355a71ee01462000641575f80fd5b80632528016914620005235780632f2ff15d14620005de57806330c27dde14620005f5575f80fd5b80631489ed10116200034b5780631796a1ae11620003235780631796a1ae14620004a75780631816b7e514620004ce5780632072f6c514620004e5578063248a9ca314620004ef575f80fd5b80631489ed10146200046b57806315064c9614620004825780631608859c1462000490575f80fd5b80630a0d9fbe116200037f5780630a0d9fbe146200041c57806311f6b287146200043d57806312b86e191462000454575f80fd5b80630645af0914620003a8578063066ec01214620003c1578063080b311114620003f4575b5f80fd5b620003bf620003b936600462005fcf565b62000d84565b005b608454620003d69067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6200040b62000405366004620060b8565b6200126a565b6040519015158152602001620003eb565b608554620003d69068010000000000000000900467ffffffffffffffff1681565b620003d66200044e366004620060ee565b62001293565b620003bf620004653660046200611c565b620012b2565b620003bf6200047c366004620061ae565b620014d2565b606f546200040b9060ff1681565b620003bf620004a1366004620060b8565b620016b1565b607e54620004b89063ffffffff1681565b60405163ffffffff9091168152602001620003eb565b620003bf620004df36600462006233565b6200178d565b620003bf6200188a565b62000514620005003660046200625d565b5f9081526034602052604090206001015490565b604051908152602001620003eb565b620005a962000534366004620060b8565b60408051606080820183525f808352602080840182905292840181905263ffffffff9590951685526081825282852067ffffffffffffffff9485168652600301825293829020825194850183528054855260010154808416918501919091526801000000000000000090049091169082015290565b604080518251815260208084015167ffffffffffffffff908116918301919091529282015190921690820152606001620003eb565b620003bf620005ef36600462006275565b6200199e565b608754620003d69067ffffffffffffffff1681565b620003bf6200061b36600462006275565b620019c6565b620003bf62000632366004620062a6565b62001a26565b60865462000514565b6200051462000652366004620060b8565b63ffffffff82165f90815260816020908152604080832067ffffffffffffffff8516845260020190915290205492915050565b6200051462001b41565b62000745620006a0366004620060ee565b607f6020525f908152604090208054600182015460029092015473ffffffffffffffffffffffffffffffffffffffff918216929182169167ffffffffffffffff740100000000000000000000000000000000000000008204169160ff7c010000000000000000000000000000000000000000000000000000000083048116927d0100000000000000000000000000000000000000000000000000000000009004169086565b6040805173ffffffffffffffffffffffffffffffffffffffff978816815296909516602087015267ffffffffffffffff9093169385019390935260ff166060840152901515608083015260a082015260c001620003eb565b620003bf620007ae366004620060ee565b62001b58565b620003bf620007c5366004620063a8565b62001cd3565b620007e2620007dc3660046200646f565b62002285565b604051620003eb919062006540565b620004b862000802366004620062a6565b60836020525f908152604090205463ffffffff1681565b608454620003d6907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b620003bf6200085b366004620061ae565b620022b7565b620003bf620008723660046200611c565b620026b4565b620003bf6200088936600462006554565b62002785565b6200040b620008a036600462006275565b5f91825260346020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6200051462002c9f565b620003d6620008f236600462006573565b62002dad565b620003bf62000909366004620062a6565b62002ffd565b620003bf62000920366004620062a6565b620030e6565b620005145f81565b62000514620031d0565b620009607f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620003eb565b608554620009a990700100000000000000000000000000000000900461ffff1681565b60405161ffff9091168152602001620003eb565b62000a58620009ce366004620060b8565b60408051608080820183525f8083526020808401829052838501829052606093840182905263ffffffff9690961681526081865283812067ffffffffffffffff958616825260040186528390208351918201845280548086168352680100000000000000009004909416948101949094526001830154918401919091526002909101549082015290565b604051620003eb91905f60808201905067ffffffffffffffff80845116835280602085015116602084015250604083015160408301526060830151606083015292915050565b608454620003d690700100000000000000000000000000000000900467ffffffffffffffff1681565b620003bf62000ad83660046200659e565b620035b8565b620004b862000aef36600462006616565b60826020525f908152604090205463ffffffff1681565b620009607f000000000000000000000000000000000000000000000000000000000000000081565b620003bf62000b3f3660046200625d565b620035f7565b620003bf62000b5636600462006275565b620036ac565b608554620003d69067ffffffffffffffff1681565b620003bf620036d4565b608454620003d69068010000000000000000900467ffffffffffffffff1681565b620003bf62000bad36600462006634565b620037de565b620003bf62000bc436600462006674565b620039ba565b620009607f000000000000000000000000000000000000000000000000000000000000000081565b620003bf62000c03366004620066ec565b62003b16565b608054620004b89063ffffffff1681565b62000cf662000c2b366004620060ee565b60816020525f90815260409020805460018201546005830154600684015460079094015473ffffffffffffffffffffffffffffffffffffffff80851695740100000000000000000000000000000000000000009586900467ffffffffffffffff908116969286169592909204821693928282169268010000000000000000808404821693700100000000000000000000000000000000808204841694780100000000000000000000000000000000000000000000000090920484169380831693830416910460ff168c565b6040805173ffffffffffffffffffffffffffffffffffffffff9d8e16815267ffffffffffffffff9c8d1660208201529c909a16998c019990995296891660608b015260808a019590955292871660a089015290861660c0880152851660e0870152841661010086015283166101208501529190911661014083015260ff1661016082015261018001620003eb565b5f54600290610100900460ff1615801562000da557505f5460ff8083169116105b62000e37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090921691909117179055608580546084805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8e8116919091029190911790915567016345785d8a00006086558c167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116176907080000000000000000177fffffffffffffffffffffffffffff0000ffffffffffffffffffffffffffffffff167103ea0000000000000000000000000000000017905562000f4062003d5b565b62000f6c7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd48c62003df3565b62000f785f8862003df3565b62000fa47fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f5908862003df3565b62000fd07f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e8862003df3565b62000ffc7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac8862003df3565b620010287fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd8962003df3565b620010547fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd088962003df3565b620010807f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f48962003df3565b620010ac7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db18962003df3565b620010f87f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd47f73cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f062003dff565b620011247f73cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f08962003df3565b620011507f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb8962003df3565b6200119c7f141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545e7f9b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff28595162003dff565b620011c87f141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545e8762003df3565b620011f47f9b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff2859518762003df3565b620012005f3362003df3565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050505050565b63ffffffff82165f9081526081602052604081206200128a908362003e49565b90505b92915050565b63ffffffff81165f9081526081602052604081206200128d9062003e8f565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4620012de8162003f25565b63ffffffff89165f90815260816020526040902062001304818a8a8a8a8a8a8a62003f31565b6006810180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8981169182029290921783555f9081526002840160205260409020869055600583018790559054700100000000000000000000000000000000900416156200139c576006810180546fffffffffffffffffffffffffffffffff1690555b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166333d6247d620013e2620031d0565b6040518263ffffffff1660e01b81526004016200140191815260200190565b5f604051808303815f87803b15801562001419575f80fd5b505af11580156200142c573d5f803e3d5ffd5b50506084805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a8000000000000000000000000000000000000000000000000017905550506040805167ffffffffffffffff881681526020810186905290810186905233606082015263ffffffff8b16907f3182bd6e6f74fc1fdc88b60f3a4f4c7f79db6ae6f5b88a1b3f5a1e28ec210d5e9060800160405180910390a250505050505050505050565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4620014fe8162003f25565b63ffffffff89165f90815260816020526040902062001524818a8a8a8a8a8a8a62004410565b6006810180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8a81169182029290921783555f908152600284016020526040902087905560058301889055905470010000000000000000000000000000000090041615620015bc576006810180546fffffffffffffffffffffffffffffffff1690555b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166333d6247d62001602620031d0565b6040518263ffffffff1660e01b81526004016200162191815260200190565b5f604051808303815f87803b15801562001639575f80fd5b505af11580156200164c573d5f803e3d5ffd5b50506040805167ffffffffffffffff8b1681526020810189905290810189905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d39060600160405180910390a350505050505050505050565b63ffffffff82165f9081526081602090815260408083203384527fc17b14a573f65366cdad721c7c0a0f76536bb4a86b935cdac44610e4f010b52a9092529091205460ff166200177c57606f5460ff161562001739576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001745818362003e49565b6200177c576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001788818362004956565b505050565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620017b98162003f25565b6103e88261ffff161080620017d357506103ff8261ffff16115b156200180b576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608580547fffffffffffffffffffffffffffff0000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000061ffff8516908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a15050565b335f9081527f8875b94af5657a2903def9906d67a3f42d8a836d24b5602c00f00fc855339fcd602052604090205460ff166200199257608454700100000000000000000000000000000000900467ffffffffffffffff16158062001928575060845442906200191c9062093a8090700100000000000000000000000000000000900467ffffffffffffffff16620067ac565b67ffffffffffffffff16115b806200195a575060875442906200194e9062093a809067ffffffffffffffff16620067ac565b67ffffffffffffffff16115b1562001992576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200199c62004bda565b565b5f82815260346020526040902060010154620019ba8162003f25565b62001788838362004c61565b73ffffffffffffffffffffffffffffffffffffffff8116331462001a16576040517f5a568e6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001a22828262004d1d565b5050565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db162001a528162003f25565b606f5460ff1662001ac35760845467ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169083161062001ac3576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6084805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8516908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a1906020016200187e565b5f608654606462001b539190620067d7565b905090565b7fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd62001b848162003f25565b63ffffffff8216158062001ba35750607e5463ffffffff908116908316115b1562001bdb576040517f7512e5cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff82165f908152607f602052604090206001808201547d010000000000000000000000000000000000000000000000000000000000900460ff161515900362001c54576040517f3b8d3d9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001810180547fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167d01000000000000000000000000000000000000000000000000000000000017905560405163ffffffff8416907f4710d2ee567ef1ed6eb2f651dde4589524bcf7cebc62147a99b281cc836e7e44905f90a2505050565b7fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd0862001cff8162003f25565b63ffffffff8816158062001d1e5750607e5463ffffffff908116908916115b1562001d56576040517f7512e5cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff88165f908152607f602052604090206001808201547d010000000000000000000000000000000000000000000000000000000000900460ff161515900362001dcf576040517f3b8d3d9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff67ffffffffffffffff8916111562001e18576040517f4c753f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff88165f9081526083602052604090205463ffffffff161562001e6f576040517f6f91fc1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608080545f9190829062001e899063ffffffff16620067f1565b825463ffffffff8281166101009490940a93840293021916919091179091558254604080515f808252602082019283905293945073ffffffffffffffffffffffffffffffffffffffff90921691309162001ee39062005f87565b62001ef19392919062006816565b604051809103905ff08015801562001f0b573d5f803e3d5ffd5b5090508160835f8c67ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508160825f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8463ffffffff1663ffffffff1681526020019081526020015f20905081815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360010160149054906101000a900467ffffffffffffffff168160010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550836001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508a815f0160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508360020154816002015f8067ffffffffffffffff1681526020019081526020015f20819055508b63ffffffff168160070160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083600101601c9054906101000a900460ff168160070160106101000a81548160ff021916908360ff1602179055508263ffffffff167f194c983456df6701c6a50830b90fe80e72b823411d0d524970c9590dc277a6418d848e8c604051620021e2949392919063ffffffff94909416845273ffffffffffffffffffffffffffffffffffffffff928316602085015267ffffffffffffffff91909116604084015216606082015260800190565b60405180910390a26040517f7125702200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063712570229062002248908d908d9088908e908e908e9060040162006859565b5f604051808303815f87803b15801562002260575f80fd5b505af115801562002273573d5f803e3d5ffd5b50505050505050505050505050505050565b63ffffffff86165f908152608160205260409020606090620022ac90878787878762004dd7565b979650505050505050565b606f5460ff1615620022f5576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff88165f90815260816020908152604080832060845467ffffffffffffffff8a81168652600383019094529190932060010154429262002359927801000000000000000000000000000000000000000000000000900481169116620067ac565b67ffffffffffffffff1611156200239c576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8620023ab8888620068c8565b67ffffffffffffffff161115620023ee576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62002400818989898989898962004410565b6200240c818762004f9e565b60855467ffffffffffffffff165f0362002552576006810180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8981169182029290921783555f908152600284016020526040902086905560058301879055905470010000000000000000000000000000000090041615620024b8576006810180546fffffffffffffffffffffffffffffffff1690555b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166333d6247d620024fe620031d0565b6040518263ffffffff1660e01b81526004016200251d91815260200190565b5f604051808303815f87803b15801562002535575f80fd5b505af115801562002548573d5f803e3d5ffd5b5050505062002654565b6200255d81620051a5565b600681018054700100000000000000000000000000000000900467ffffffffffffffff169060106200258f83620068ec565b825467ffffffffffffffff9182166101009390930a92830292820219169190911790915560408051608081018252428316815289831660208083019182528284018b8152606084018b81526006890154700100000000000000000000000000000000900487165f90815260048a0190935294909120925183549251861668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169516949094171781559151600183015551600290910155505b6040805167ffffffffffffffff8816815260208101869052908101869052339063ffffffff8b16907faac1e7a157b259544ebacd6e8a82ae5d6c8f174e12aa48696277bcc9a661f0b49060600160405180910390a3505050505050505050565b606f5460ff1615620026f2576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff88165f90815260816020526040902062002718818989898989898962003f31565b67ffffffffffffffff87165f9081526004820160209081526040918290206002015482519081529081018590527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a16200277a62004bda565b505050505050505050565b335f9081527ff14f5a8ad59d90593602e905b358229bff5ceea677d5bf0f5a1701793550a9a6602052604090205460ff161580156200286057503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562002821573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200284791906200690b565b73ffffffffffffffffffffffffffffffffffffffff1614155b1562002898576040517f1a06d0fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f9081526082602052604081205463ffffffff1690819003620028fe576040517f74a086a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff81165f908152608160205260409020600681015467ffffffffffffffff90811690841681111580620029525750600682015467ffffffffffffffff680100000000000000009091048116908516105b156200298a576040517fcb23ebdf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805b8467ffffffffffffffff168167ffffffffffffffff161462002a5f5767ffffffffffffffff8082165f908152600385016020526040902060010154680100000000000000009004811690861681101562002a12576040517f9753965f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff9091165f908152600384016020526040812090815560010180547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690556200298c565b6006830180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff871617905562002aa18583620068c8565b608480545f9062002abe90849067ffffffffffffffff16620068c8565b82546101009290920a67ffffffffffffffff818102199093169183160217909155600685015470010000000000000000000000000000000090041615905062002ba1575f62002b0d8462003e8f565b600685015490915062002b379068010000000000000000900467ffffffffffffffff1682620068c8565b6084805460089062002b6190849068010000000000000000900467ffffffffffffffff16620068c8565b825467ffffffffffffffff9182166101009390930a928302919092021990911617905550506006830180546fffffffffffffffffffffffffffffffff1690555b67ffffffffffffffff85165f818152600385016020526040908190205490517f669adece0000000000000000000000000000000000000000000000000000000081526004810192909252602482015273ffffffffffffffffffffffffffffffffffffffff87169063669adece906044015f604051808303815f87803b15801562002c29575f80fd5b505af115801562002c3c573d5f803e3d5ffd5b5050505067ffffffffffffffff85165f81815260038501602090815260409182902054915191825263ffffffff8716917f80a6d395a55aed8126079cb8247f0a6848b1440ca2cdca3b4386f250c3529402910160405180910390a3505050505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801562002d2c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002d52919062006929565b6084549091505f9062002d7e9067ffffffffffffffff68010000000000000000820481169116620068c8565b67ffffffffffffffff169050805f0362002d9a575f9250505090565b62002da681836200696e565b9250505090565b606f545f9060ff161562002ded576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f9081526082602052604081205463ffffffff169081900362002e3d576040517f71653c1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8367ffffffffffffffff165f0362002e81576040517f2590ccf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff81165f908152608160205260408120608480549192879262002eb490849067ffffffffffffffff16620067ac565b82546101009290920a67ffffffffffffffff81810219909316918316021790915560068301541690505f62002eea8783620067ac565b60068401805467ffffffffffffffff8084167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217909255604080516060810182528a815242841660208083019182528886168385019081525f95865260038b019091529290932090518155915160019290920180549151841668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009092169290931691909117179055905062002fae83620051a5565b60405167ffffffffffffffff8216815263ffffffff8516907f1d9f30260051d51d70339da239ea7b080021adcaabfa71c9b0ea339a20cf9a259060200160405180910390a29695505050505050565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620030298162003f25565b606f5460ff166200307e5760855467ffffffffffffffff908116908316106200307e576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608580547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff84169081179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c75906020016200187e565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620031128162003f25565b620151808267ffffffffffffffff1611156200315a576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608580547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8516908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c28906020016200187e565b6080545f9063ffffffff16808203620031ea57505f919050565b5f8167ffffffffffffffff811115620032075762003207620062c2565b60405190808252806020026020018201604052801562003231578160200160208202803683370190505b5090505f5b82811015620032a15760815f6200324f83600162006984565b63ffffffff1663ffffffff1681526020019081526020015f20600501548282815181106200328157620032816200699a565b6020908102919091010152806200329881620069c7565b91505062003236565b505f60205b83600114620034fa575f620032bd60028662006a01565b620032ca6002876200696e565b620032d6919062006984565b90505f8167ffffffffffffffff811115620032f557620032f5620062c2565b6040519080825280602002602001820160405280156200331f578160200160208202803683370190505b5090505f5b82811015620034a6576200333a60018462006a17565b811480156200335557506200335160028862006a01565b6001145b15620033dd578562003369826002620067d7565b815181106200337c576200337c6200699a565b602002602001015185604051602001620033a0929190918252602082015260400190565b60405160208183030381529060405280519060200120828281518110620033cb57620033cb6200699a565b60200260200101818152505062003491565b85620033eb826002620067d7565b81518110620033fe57620033fe6200699a565b602002602001015186826002620034169190620067d7565b6200342390600162006984565b815181106200343657620034366200699a565b602002602001015160405160200162003459929190918252602082015260400190565b604051602081830303815290604052805190602001208282815181106200348457620034846200699a565b6020026020010181815250505b806200349d81620069c7565b91505062003324565b508094508195508384604051602001620034ca929190918252602082015260400190565b6040516020818303038152906040528051906020012093508280620034ef9062006a2d565b9350505050620032a6565b5f835f815181106200351057620035106200699a565b602002602001015190505f5b82811015620035ae576040805160208101849052908101859052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830187905290820186905292506060016040516020818303038152906040528051906020012093508080620035a590620069c7565b9150506200351c565b5095945050505050565b7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac620035e48162003f25565b620035f1848484620052b5565b50505050565b7f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb620036238162003f25565b683635c9adc5dea000008211806200363e5750633b9aca0082105b1562003676576040517f8586952500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60868290556040518281527ffb383653f53ee079978d0c9aff7aeff04a10166ce244cca9c9f9d8d96bed45b2906020016200187e565b5f82815260346020526040902060010154620036c88162003f25565b62001788838362004d1d565b7f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f4620037008162003f25565b608780547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff16179055604080517fdbc1697600000000000000000000000000000000000000000000000000000000815290517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169163dbc16976916004808301925f92919082900301818387803b158015620037ba575f80fd5b505af1158015620037cd573d5f803e3d5ffd5b50505050620037db62005747565b50565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562003840573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200386691906200690b565b73ffffffffffffffffffffffffffffffffffffffff1614620038b4576040517f696072e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f9081526082602090815260408083205463ffffffff16835260819091529020600681015467ffffffffffffffff80821668010000000000000000909204161462003942576040517fcc862d4a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600781015463ffffffff83166801000000000000000090910467ffffffffffffffff16106200399d576040517f3e37e23300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080515f815260208101909152620017889084908490620052b5565b7f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e620039e68162003f25565b67ffffffffffffffff84165f9081526083602052604090205463ffffffff161562003a3d576040517f6f91fc1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff67ffffffffffffffff8516111562003a86576040517f4c753f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87165f9081526082602052604090205463ffffffff161562003ae9576040517fd409b93000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62003af98888888887620057d6565b5f8080526002909101602052604090209390935550505050505050565b7fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f59062003b428162003f25565b607e80545f9190829062003b5c9063ffffffff16620067f1565b91906101000a81548163ffffffff021916908363ffffffff160217905590506040518060c001604052808973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018767ffffffffffffffff1681526020018660ff1681526020015f1515815260200185815250607f5f8363ffffffff1663ffffffff1681526020019081526020015f205f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550606082015181600101601c6101000a81548160ff021916908360ff160217905550608082015181600101601d6101000a81548160ff02191690831515021790555060a082015181600201559050508063ffffffff167fa2970448b3bd66ba7e524e7b2a5b9cf94fa29e32488fb942afdfe70dd4b77b5289898989898960405162003d499695949392919062006a64565b60405180910390a25050505050505050565b5f54610100900460ff166200199c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840162000e2e565b62001a22828262004c61565b5f82815260346020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b60855467ffffffffffffffff8281165f9081526004850160205260408120549092429262003e7c929181169116620067ac565b67ffffffffffffffff1611159392505050565b60068101545f90700100000000000000000000000000000000900467ffffffffffffffff161562003f025750600681015467ffffffffffffffff70010000000000000000000000000000000090910481165f90815260049092016020526040909120546801000000000000000090041690565b506006015468010000000000000000900467ffffffffffffffff1690565b919050565b620037db813362005a58565b60078801545f9067ffffffffffffffff908116908716101562003f80576040517fead1340b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8816156200406757600689015467ffffffffffffffff7001000000000000000000000000000000009091048116908916111562003ff2576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5067ffffffffffffffff8088165f90815260048a016020526040902060028101548154909288811668010000000000000000909204161462004060576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5062004114565b5067ffffffffffffffff85165f90815260028901602052604090205480620040bb576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600689015467ffffffffffffffff680100000000000000009091048116908716111562004114576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600689015467ffffffffffffffff700100000000000000000000000000000000909104811690881611806200415d57508767ffffffffffffffff168767ffffffffffffffff1611155b80620041975750600689015467ffffffffffffffff7801000000000000000000000000000000000000000000000000909104811690881611155b15620041cf576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8781165f90815260048b01602052604090205468010000000000000000900481169086161462004234576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f620042458a888888868962004dd7565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516200427b919062006ac9565b602060405180830381855afa15801562004297573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190620042bc919062006929565b620042c8919062006a01565b60018c01546040805160208101825283815290517f9121da8a00000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff90911691639121da8a91620043329188919060040162006ae6565b602060405180830381865afa1580156200434e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062004374919062006b22565b620043ab576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff89165f90815260048c01602052604090206002015485900362004403576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050565b5f806200441d8a62003e8f565b60078b015490915067ffffffffffffffff90811690891610156200446d576040517fead1340b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff891615620045565760068a015467ffffffffffffffff7001000000000000000000000000000000009091048116908a161115620044df576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff808a165f90815260048c01602052604090206002810154815490945090918a81166801000000000000000090920416146200454f576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50620045fa565b67ffffffffffffffff88165f90815260028b016020526040902054915081620045ab576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168867ffffffffffffffff161115620045fa576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff161162004648576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f620046598b8a8a8a878b62004dd7565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516200468f919062006ac9565b602060405180830381855afa158015620046ab573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190620046d0919062006929565b620046dc919062006a01565b60018d01546040805160208101825283815290517f9121da8a00000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff90911691639121da8a91620047469189919060040162006ae6565b602060405180830381865afa15801562004762573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062004788919062006b22565b620047bf576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f620047cc848b620068c8565b905062004833878267ffffffffffffffff16620047e862002c9f565b620047f49190620067d7565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919062005ac1565b80608460088282829054906101000a900467ffffffffffffffff166200485a9190620067ac565b82546101009290920a67ffffffffffffffff818102199093169183160217909155608480547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16700100000000000000000000000000000000428416021790558e546040517f32c2d153000000000000000000000000000000000000000000000000000000008152918d166004830152602482018b905233604483015273ffffffffffffffffffffffffffffffffffffffff1691506332c2d153906064015f604051808303815f87803b15801562004930575f80fd5b505af115801562004943573d5f803e3d5ffd5b5050505050505050505050505050505050565b600682015467ffffffffffffffff78010000000000000000000000000000000000000000000000009091048116908216111580620049b95750600682015467ffffffffffffffff7001000000000000000000000000000000009091048116908216115b15620049f1576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8181165f818152600485016020908152604080832080546006890180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000092839004909816918202979097178755600280830154828752908a01909452919093209190915560018201546005870155835477ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000909302929092179092557f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166333d6247d62004afa620031d0565b6040518263ffffffff1660e01b815260040162004b1991815260200190565b5f604051808303815f87803b15801562004b31575f80fd5b505af115801562004b44573d5f803e3d5ffd5b5050855473ffffffffffffffffffffffffffffffffffffffff165f908152608260209081526040918290205460028701546001880154845167ffffffffffffffff898116825294810192909252818501529188166060830152915163ffffffff90921693507f581910eb7a27738945c2f00a91f2284b2d6de9d4e472b12f901c2b0df045e21b925081900360800190a250505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562004c40575f80fd5b505af115801562004c53573d5f803e3d5ffd5b505050506200199c62005b50565b5f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1662001a22575f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b5f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff161562001a22575f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b67ffffffffffffffff8086165f818152600389016020526040808220549388168252902054606092911580159062004e0d575081155b1562004e45576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8062004e7d576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62004e888462005be3565b62004ebf576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b885460018a01546040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015260348101889052605481018590527fffffffffffffffff00000000000000000000000000000000000000000000000060c08c811b821660748401527401000000000000000000000000000000000000000094859004811b8216607c84015293909204831b82166084820152608c810187905260ac810184905260cc81018990529189901b1660ec82015260f401604051602081830303815290604052925050509695505050505050565b5f62004faa8362003e8f565b9050815f8062004fbb8484620068c8565b60855467ffffffffffffffff91821692505f9162004fe791680100000000000000009004164262006a17565b90505b8467ffffffffffffffff168467ffffffffffffffff16146200507a5767ffffffffffffffff8085165f908152600389016020526040902060018101549091168210156200505457600181015468010000000000000000900467ffffffffffffffff16945062005073565b620050608686620068c8565b67ffffffffffffffff169350506200507a565b5062004fea565b5f62005087848462006a17565b905083811015620050e557808403600c8111620050a55780620050a8565b600c5b9050806103e80a81608560109054906101000a900461ffff1661ffff160a6086540281620050da57620050da62006941565b04608655506200515c565b838103600c8111620050f85780620050fb565b600c5b90505f816103e80a82608560109054906101000a900461ffff1661ffff160a670de0b6b3a7640000028162005134576200513462006941565b04905080608654670de0b6b3a7640000028162005155576200515562006941565b0460865550505b683635c9adc5dea0000060865411156200518357683635c9adc5dea000006086556200519b565b633b9aca0060865410156200519b57633b9aca006086555b5050505050505050565b600681015467ffffffffffffffff780100000000000000000000000000000000000000000000000082048116700100000000000000000000000000000000909204161115620037db5760068101545f9062005228907801000000000000000000000000000000000000000000000000900467ffffffffffffffff166001620067ac565b905062005236828262003e49565b1562001a225760068201545f9060029062005271908490700100000000000000000000000000000000900467ffffffffffffffff16620068c8565b6200527d919062006b43565b620052899083620067ac565b905062005297838262003e49565b15620052a95762001788838262004956565b62001788838362004956565b63ffffffff82161580620052d45750607e5463ffffffff908116908316115b156200530c576040517f7512e5cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f9081526082602052604081205463ffffffff169081900362005372576040517f74a086a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8181165f9081526081602052604090206007810154909185166801000000000000000090910467ffffffffffffffff1603620053df576040517f4f61d51900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff84165f908152607f602052604090206001808201547d010000000000000000000000000000000000000000000000000000000000900460ff161515900362005458576040517f3b8d3d9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018101546007830154700100000000000000000000000000000000900460ff9081167c01000000000000000000000000000000000000000000000000000000009092041614620054d5576040517fb541abe200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018181018054918401805473ffffffffffffffffffffffffffffffffffffffff9093167fffffffffffffffffffffffff000000000000000000000000000000000000000084168117825591547fffffffff00000000000000000000000000000000000000000000000000000000909316909117740100000000000000000000000000000000000000009283900467ffffffffffffffff9081169093021790556007830180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff1663ffffffff8816680100000000000000000217905560068301547801000000000000000000000000000000000000000000000000810482167001000000000000000000000000000000009091049091161462005625576040517f9d59507b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f620056318462001293565b6007840180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff831617905582546040517f4f1ef28600000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff89811692634f1ef28692620056c3921690899060040162006b6c565b5f604051808303815f87803b158015620056db575f80fd5b505af1158015620056ee573d5f803e3d5ffd5b50506040805163ffffffff8a8116825267ffffffffffffffff86166020830152881693507ff585e04c05d396901170247783d3e5f0ee9c1df23072985b50af089f5e48b19d92500160405180910390a250505050505050565b606f5460ff1662005784576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b608080545f9182918290620057f19063ffffffff16620067f1565b91906101000a81548163ffffffff021916908363ffffffff160217905590508060835f8667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508060825f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff16021790555060815f8263ffffffff1663ffffffff1681526020019081526020015f20915086825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848260010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555085826001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083825f0160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550828260070160106101000a81548160ff021916908360ff1602179055508063ffffffff167fadfc7d56f7e39b08b321534f14bfb135ad27698f7d2f5ad0edc2356ea9a3f850868987875f60405162005a4695949392919067ffffffffffffffff958616815273ffffffffffffffffffffffffffffffffffffffff949094166020850152918416604084015260ff166060830152909116608082015260a00190565b60405180910390a25095945050505050565b5f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1662001a22576040517fec2b7c3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526200178890849062005c6a565b606f5460ff161562005b8e576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b5f67ffffffff0000000167ffffffffffffffff831610801562005c1b575067ffffffff00000001604083901c67ffffffffffffffff16105b801562005c3d575067ffffffff00000001608083901c67ffffffffffffffff16105b801562005c55575067ffffffff0000000160c083901c105b1562005c6357506001919050565b505f919050565b5f62005ccd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1662005d7c9092919063ffffffff16565b80519091501562001788578080602001905181019062005cee919062006b22565b62001788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162000e2e565b606062005d8c84845f8562005d94565b949350505050565b60608247101562005e28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840162000e2e565b5f808673ffffffffffffffffffffffffffffffffffffffff16858760405162005e52919062006ac9565b5f6040518083038185875af1925050503d805f811462005e8e576040519150601f19603f3d011682016040523d82523d5f602084013e62005e93565b606091505b5091509150620022ac878383876060831562005f3a5782515f0362005f325773ffffffffffffffffffffffffffffffffffffffff85163b62005f32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000e2e565b508162005d8c565b62005d8c838381511562005f515781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000e2e919062006540565b610a5e8062006b9d83390190565b73ffffffffffffffffffffffffffffffffffffffff81168114620037db575f80fd5b803567ffffffffffffffff8116811462003f20575f80fd5b5f805f805f805f805f806101408b8d03121562005fea575f80fd5b8a3562005ff78162005f95565b99506200600760208c0162005fb7565b98506200601760408c0162005fb7565b975060608b0135620060298162005f95565b965060808b01356200603b8162005f95565b955060a08b01356200604d8162005f95565b945060c08b01356200605f8162005f95565b935060e08b0135620060718162005f95565b9250620060826101008c0162005fb7565b9150620060936101208c0162005fb7565b90509295989b9194979a5092959850565b803563ffffffff8116811462003f20575f80fd5b5f8060408385031215620060ca575f80fd5b620060d583620060a4565b9150620060e56020840162005fb7565b90509250929050565b5f60208284031215620060ff575f80fd5b6200128a82620060a4565b8061030081018310156200128d575f80fd5b5f805f805f805f806103e0898b03121562006135575f80fd5b6200614089620060a4565b97506200615060208a0162005fb7565b96506200616060408a0162005fb7565b95506200617060608a0162005fb7565b94506200618060808a0162005fb7565b935060a0890135925060c089013591506200619f8a60e08b016200610a565b90509295985092959890939650565b5f805f805f805f806103e0898b031215620061c7575f80fd5b620061d289620060a4565b9750620061e260208a0162005fb7565b9650620061f260408a0162005fb7565b95506200620260608a0162005fb7565b94506080890135935060a0890135925060c0890135620062228162005f95565b91506200619f8a60e08b016200610a565b5f6020828403121562006244575f80fd5b813561ffff8116811462006256575f80fd5b9392505050565b5f602082840312156200626e575f80fd5b5035919050565b5f806040838503121562006287575f80fd5b8235915060208301356200629b8162005f95565b809150509250929050565b5f60208284031215620062b7575f80fd5b6200128a8262005fb7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f67ffffffffffffffff808411156200630c576200630c620062c2565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620063555762006355620062c2565b816040528093508581528686860111156200636e575f80fd5b858560208301375f602087830101525050509392505050565b5f82601f83011262006397575f80fd5b6200128a83833560208501620062ef565b5f805f805f805f60e0888a031215620063bf575f80fd5b620063ca88620060a4565b9650620063da6020890162005fb7565b95506040880135620063ec8162005f95565b94506060880135620063fe8162005f95565b93506080880135620064108162005f95565b925060a088013567ffffffffffffffff808211156200642d575f80fd5b6200643b8b838c0162006387565b935060c08a013591508082111562006451575f80fd5b50620064608a828b0162006387565b91505092959891949750929550565b5f805f805f8060c0878903121562006485575f80fd5b6200649087620060a4565b9550620064a06020880162005fb7565b9450620064b06040880162005fb7565b9350606087013592506080870135915060a087013590509295509295509295565b5f5b83811015620064ed578181015183820152602001620064d3565b50505f910152565b5f81518084526200650e816020860160208601620064d1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f6200128a6020830184620064f5565b5f806040838503121562006566575f80fd5b8235620060d58162005f95565b5f806040838503121562006585575f80fd5b620065908362005fb7565b946020939093013593505050565b5f805f60608486031215620065b1575f80fd5b8335620065be8162005f95565b9250620065ce60208501620060a4565b9150604084013567ffffffffffffffff811115620065ea575f80fd5b8401601f81018613620065fb575f80fd5b6200660c86823560208401620062ef565b9150509250925092565b5f6020828403121562006627575f80fd5b8135620062568162005f95565b5f806040838503121562006646575f80fd5b8235620066538162005f95565b9150620060e560208401620060a4565b803560ff8116811462003f20575f80fd5b5f805f805f8060c087890312156200668a575f80fd5b8635620066978162005f95565b95506020870135620066a98162005f95565b9450620066b96040880162005fb7565b9350620066c96060880162005fb7565b925060808701359150620066e060a0880162006663565b90509295509295509295565b5f805f805f8060c0878903121562006702575f80fd5b86356200670f8162005f95565b95506020870135620067218162005f95565b9450620067316040880162005fb7565b9350620067416060880162006663565b92506080870135915060a087013567ffffffffffffffff81111562006764575f80fd5b6200677289828a0162006387565b9150509295509295509295565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff818116838216019080821115620067d057620067d06200677f565b5092915050565b80820281158282048414176200128d576200128d6200677f565b5f63ffffffff8083168181036200680c576200680c6200677f565b6001019392505050565b5f73ffffffffffffffffffffffffffffffffffffffff808616835280851660208401525060606040830152620068506060830184620064f5565b95945050505050565b5f73ffffffffffffffffffffffffffffffffffffffff8089168352808816602084015263ffffffff8716604084015280861660608401525060c06080830152620068a760c0830185620064f5565b82810360a0840152620068bb8185620064f5565b9998505050505050505050565b67ffffffffffffffff828116828216039080821115620067d057620067d06200677f565b5f67ffffffffffffffff8083168181036200680c576200680c6200677f565b5f602082840312156200691c575f80fd5b8151620062568162005f95565b5f602082840312156200693a575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f826200697f576200697f62006941565b500490565b808201808211156200128d576200128d6200677f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620069fa57620069fa6200677f565b5060010190565b5f8262006a125762006a1262006941565b500690565b818103818111156200128d576200128d6200677f565b5f8162006a3e5762006a3e6200677f565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b5f73ffffffffffffffffffffffffffffffffffffffff808916835280881660208401525067ffffffffffffffff8616604083015260ff8516606083015283608083015260c060a083015262006abd60c0830184620064f5565b98975050505050505050565b5f825162006adc818460208701620064d1565b9190910192915050565b6103208101610300808584378201835f5b600181101562006b1857815183526020928301929091019060010162006af7565b5050509392505050565b5f6020828403121562006b33575f80fd5b8151801515811462006256575f80fd5b5f67ffffffffffffffff8084168062006b605762006b6062006941565b92169190910492915050565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201525f62005d8c6040830184620064f556fe60a060405260405162000a5e38038062000a5e833981016040819052620000269162000375565b828162000034828262000060565b50506001600160a01b038216608052620000576200005160805190565b620000c5565b5050506200046c565b6200006b8262000136565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000b757620000b28282620001b5565b505050565b620000c16200022e565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620001065f8051602062000a3e833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001338162000250565b50565b806001600160a01b03163b5f036200017157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b031684604051620001d391906200044f565b5f60405180830381855af49150503d805f81146200020d576040519150601f19603f3d011682016040523d82523d5f602084013e62000212565b606091505b5090925090506200022585838362000291565b95945050505050565b34156200024e5760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b0381166200027b57604051633173bdd160e11b81525f600482015260240162000168565b805f8051602062000a3e83398151915262000194565b606082620002aa57620002a482620002f7565b620002f0565b8151158015620002c257506001600160a01b0384163b155b15620002ed57604051639996b31560e01b81526001600160a01b038516600482015260240162000168565b50805b9392505050565b805115620003085780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811462000338575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b838110156200036d57818101518382015260200162000353565b50505f910152565b5f805f6060848603121562000388575f80fd5b620003938462000321565b9250620003a36020850162000321565b60408501519092506001600160401b0380821115620003c0575f80fd5b818601915086601f830112620003d4575f80fd5b815181811115620003e957620003e96200033d565b604051601f8201601f19908116603f011681019083821181831017156200041457620004146200033d565b816040528281528960208487010111156200042d575f80fd5b6200044083602083016020880162000351565b80955050505050509250925092565b5f82516200046281846020870162000351565b9190910192915050565b6080516105ba620004845f395f601001526105ba5ff3fe608060405261000c61000e565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633036100a7575f357fffffffff00000000000000000000000000000000000000000000000000000000167f4f1ef286000000000000000000000000000000000000000000000000000000001461009f5761009d6100ab565b565b61009d6100bb565b61009d5b61009d6100b66100e9565b61012d565b5f806100ca3660048184610410565b8101906100d79190610464565b915091506100e5828261014b565b5050565b5f6101287f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e808015610147573d5ff35b3d5ffd5b610154826101b2565b60405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101aa576101a58282610285565b505050565b6100e5610304565b8073ffffffffffffffffffffffffffffffffffffffff163b5f0361021f576040517f4c9c8ce300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60605f808473ffffffffffffffffffffffffffffffffffffffff16846040516102ae9190610558565b5f60405180830381855af49150503d805f81146102e6576040519150601f19603f3d011682016040523d82523d5f602084013e6102eb565b606091505b50915091506102fb85838361033c565b95945050505050565b341561009d576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060826103515761034c826103ce565b6103c7565b8151158015610375575073ffffffffffffffffffffffffffffffffffffffff84163b155b156103c4576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610216565b50805b9392505050565b8051156103de5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808585111561041e575f80fd5b8386111561042a575f80fd5b5050820193919092039150565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f8060408385031215610475575f80fd5b823573ffffffffffffffffffffffffffffffffffffffff81168114610498575f80fd5b9150602083013567ffffffffffffffff808211156104b4575f80fd5b818501915085601f8301126104c7575f80fd5b8135818111156104d9576104d9610437565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561051f5761051f610437565b81604052828152886020848701011115610537575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610577576020818601810151858301520161055d565b505f92019182525091905056fea264697066735822122052b5bba3494b1e5512431e77157bb64992f00cd96273780f749f0677c4cb3be064736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103a2646970667358221220f0e6054fa205ece2d4b26ccacb67fce15ea89ea0f8d6d08884bcf3607d6fda8c64736f6c63430008140033", - "deployedBytecode": "0x608060405234801562000010575f80fd5b5060043610620003a4575f3560e01c806387c20c0111620001ef578063c4c928c21162000113578063dde0ff7711620000ab578063e46761c41162000083578063e46761c41462000bca578063f34eb8eb1462000bf2578063f4e926751462000c09578063f9c4c2ae1462000c1a575f80fd5b8063dde0ff771462000b7b578063dfdb8c5e1462000b9c578063e0bfd3d21462000bb3575f80fd5b8063d5073f6f11620000eb578063d5073f6f1462000b2e578063d547741f1462000b45578063d939b3151462000b5c578063dbc169761462000b71575f80fd5b8063c4c928c21462000ac7578063ceee281d1462000ade578063d02103ca1462000b06575f80fd5b8063a066215c1162000187578063a3c573eb116200015f578063a3c573eb1462000938578063afd23cbe1462000986578063b99d0ad714620009bd578063c1acbc341462000a9e575f80fd5b8063a066215c146200090f578063a217fddf1462000926578063a2967d99146200092e575f80fd5b806391d1485411620001c757806391d14854146200088f57806399f5634e14620008d75780639a908e7314620008e15780639c9f3dfe14620008f8575f80fd5b806387c20c01146200084a5780638bd4f07114620008615780638fd88cc21462000878575f80fd5b80632528016911620002d757806360469169116200026f578063727885e91162000247578063727885e914620007b45780637975fcfe14620007cb5780637fb6e76a14620007f1578063841b24d71462000819575f80fd5b806360469169146200068557806365c0504d146200068f5780637222020f146200079d575f80fd5b806336568abe11620002af57806336568abe146200060a578063394218e91462000621578063477fa270146200063857806355a71ee01462000641575f80fd5b80632528016914620005235780632f2ff15d14620005de57806330c27dde14620005f5575f80fd5b80631489ed10116200034b5780631796a1ae11620003235780631796a1ae14620004a75780631816b7e514620004ce5780632072f6c514620004e5578063248a9ca314620004ef575f80fd5b80631489ed10146200046b57806315064c9614620004825780631608859c1462000490575f80fd5b80630a0d9fbe116200037f5780630a0d9fbe146200041c57806311f6b287146200043d57806312b86e191462000454575f80fd5b80630645af0914620003a8578063066ec01214620003c1578063080b311114620003f4575b5f80fd5b620003bf620003b936600462005fcf565b62000d84565b005b608454620003d69067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6200040b62000405366004620060b8565b6200126a565b6040519015158152602001620003eb565b608554620003d69068010000000000000000900467ffffffffffffffff1681565b620003d66200044e366004620060ee565b62001293565b620003bf620004653660046200611c565b620012b2565b620003bf6200047c366004620061ae565b620014d2565b606f546200040b9060ff1681565b620003bf620004a1366004620060b8565b620016b1565b607e54620004b89063ffffffff1681565b60405163ffffffff9091168152602001620003eb565b620003bf620004df36600462006233565b6200178d565b620003bf6200188a565b62000514620005003660046200625d565b5f9081526034602052604090206001015490565b604051908152602001620003eb565b620005a962000534366004620060b8565b60408051606080820183525f808352602080840182905292840181905263ffffffff9590951685526081825282852067ffffffffffffffff9485168652600301825293829020825194850183528054855260010154808416918501919091526801000000000000000090049091169082015290565b604080518251815260208084015167ffffffffffffffff908116918301919091529282015190921690820152606001620003eb565b620003bf620005ef36600462006275565b6200199e565b608754620003d69067ffffffffffffffff1681565b620003bf6200061b36600462006275565b620019c6565b620003bf62000632366004620062a6565b62001a26565b60865462000514565b6200051462000652366004620060b8565b63ffffffff82165f90815260816020908152604080832067ffffffffffffffff8516845260020190915290205492915050565b6200051462001b41565b62000745620006a0366004620060ee565b607f6020525f908152604090208054600182015460029092015473ffffffffffffffffffffffffffffffffffffffff918216929182169167ffffffffffffffff740100000000000000000000000000000000000000008204169160ff7c010000000000000000000000000000000000000000000000000000000083048116927d0100000000000000000000000000000000000000000000000000000000009004169086565b6040805173ffffffffffffffffffffffffffffffffffffffff978816815296909516602087015267ffffffffffffffff9093169385019390935260ff166060840152901515608083015260a082015260c001620003eb565b620003bf620007ae366004620060ee565b62001b58565b620003bf620007c5366004620063a8565b62001cd3565b620007e2620007dc3660046200646f565b62002285565b604051620003eb919062006540565b620004b862000802366004620062a6565b60836020525f908152604090205463ffffffff1681565b608454620003d6907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b620003bf6200085b366004620061ae565b620022b7565b620003bf620008723660046200611c565b620026b4565b620003bf6200088936600462006554565b62002785565b6200040b620008a036600462006275565b5f91825260346020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6200051462002c9f565b620003d6620008f236600462006573565b62002dad565b620003bf62000909366004620062a6565b62002ffd565b620003bf62000920366004620062a6565b620030e6565b620005145f81565b62000514620031d0565b620009607f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620003eb565b608554620009a990700100000000000000000000000000000000900461ffff1681565b60405161ffff9091168152602001620003eb565b62000a58620009ce366004620060b8565b60408051608080820183525f8083526020808401829052838501829052606093840182905263ffffffff9690961681526081865283812067ffffffffffffffff958616825260040186528390208351918201845280548086168352680100000000000000009004909416948101949094526001830154918401919091526002909101549082015290565b604051620003eb91905f60808201905067ffffffffffffffff80845116835280602085015116602084015250604083015160408301526060830151606083015292915050565b608454620003d690700100000000000000000000000000000000900467ffffffffffffffff1681565b620003bf62000ad83660046200659e565b620035b8565b620004b862000aef36600462006616565b60826020525f908152604090205463ffffffff1681565b620009607f000000000000000000000000000000000000000000000000000000000000000081565b620003bf62000b3f3660046200625d565b620035f7565b620003bf62000b5636600462006275565b620036ac565b608554620003d69067ffffffffffffffff1681565b620003bf620036d4565b608454620003d69068010000000000000000900467ffffffffffffffff1681565b620003bf62000bad36600462006634565b620037de565b620003bf62000bc436600462006674565b620039ba565b620009607f000000000000000000000000000000000000000000000000000000000000000081565b620003bf62000c03366004620066ec565b62003b16565b608054620004b89063ffffffff1681565b62000cf662000c2b366004620060ee565b60816020525f90815260409020805460018201546005830154600684015460079094015473ffffffffffffffffffffffffffffffffffffffff80851695740100000000000000000000000000000000000000009586900467ffffffffffffffff908116969286169592909204821693928282169268010000000000000000808404821693700100000000000000000000000000000000808204841694780100000000000000000000000000000000000000000000000090920484169380831693830416910460ff168c565b6040805173ffffffffffffffffffffffffffffffffffffffff9d8e16815267ffffffffffffffff9c8d1660208201529c909a16998c019990995296891660608b015260808a019590955292871660a089015290861660c0880152851660e0870152841661010086015283166101208501529190911661014083015260ff1661016082015261018001620003eb565b5f54600290610100900460ff1615801562000da557505f5460ff8083169116105b62000e37576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805461010060ff84167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090921691909117179055608580546084805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8e8116919091029190911790915567016345785d8a00006086558c167fffffffffffffffffffffffffffffffff00000000000000000000000000000000909116176907080000000000000000177fffffffffffffffffffffffffffff0000ffffffffffffffffffffffffffffffff167103ea0000000000000000000000000000000017905562000f4062003d5b565b62000f6c7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd48c62003df3565b62000f785f8862003df3565b62000fa47fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f5908862003df3565b62000fd07f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e8862003df3565b62000ffc7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac8862003df3565b620010287fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd8962003df3565b620010547fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd088962003df3565b620010807f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f48962003df3565b620010ac7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db18962003df3565b620010f87f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd47f73cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f062003dff565b620011247f73cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f08962003df3565b620011507f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb8962003df3565b6200119c7f141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545e7f9b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff28595162003dff565b620011c87f141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545e8762003df3565b620011f47f9b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff2859518762003df3565b620012005f3362003df3565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050505050565b63ffffffff82165f9081526081602052604081206200128a908362003e49565b90505b92915050565b63ffffffff81165f9081526081602052604081206200128d9062003e8f565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4620012de8162003f25565b63ffffffff89165f90815260816020526040902062001304818a8a8a8a8a8a8a62003f31565b6006810180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8981169182029290921783555f9081526002840160205260409020869055600583018790559054700100000000000000000000000000000000900416156200139c576006810180546fffffffffffffffffffffffffffffffff1690555b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166333d6247d620013e2620031d0565b6040518263ffffffff1660e01b81526004016200140191815260200190565b5f604051808303815f87803b15801562001419575f80fd5b505af11580156200142c573d5f803e3d5ffd5b50506084805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a8000000000000000000000000000000000000000000000000017905550506040805167ffffffffffffffff881681526020810186905290810186905233606082015263ffffffff8b16907f3182bd6e6f74fc1fdc88b60f3a4f4c7f79db6ae6f5b88a1b3f5a1e28ec210d5e9060800160405180910390a250505050505050505050565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4620014fe8162003f25565b63ffffffff89165f90815260816020526040902062001524818a8a8a8a8a8a8a62004410565b6006810180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8a81169182029290921783555f908152600284016020526040902087905560058301889055905470010000000000000000000000000000000090041615620015bc576006810180546fffffffffffffffffffffffffffffffff1690555b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166333d6247d62001602620031d0565b6040518263ffffffff1660e01b81526004016200162191815260200190565b5f604051808303815f87803b15801562001639575f80fd5b505af11580156200164c573d5f803e3d5ffd5b50506040805167ffffffffffffffff8b1681526020810189905290810189905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d39060600160405180910390a350505050505050505050565b63ffffffff82165f9081526081602090815260408083203384527fc17b14a573f65366cdad721c7c0a0f76536bb4a86b935cdac44610e4f010b52a9092529091205460ff166200177c57606f5460ff161562001739576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001745818362003e49565b6200177c576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001788818362004956565b505050565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620017b98162003f25565b6103e88261ffff161080620017d357506103ff8261ffff16115b156200180b576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608580547fffffffffffffffffffffffffffff0000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000061ffff8516908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a15050565b335f9081527f8875b94af5657a2903def9906d67a3f42d8a836d24b5602c00f00fc855339fcd602052604090205460ff166200199257608454700100000000000000000000000000000000900467ffffffffffffffff16158062001928575060845442906200191c9062093a8090700100000000000000000000000000000000900467ffffffffffffffff16620067ac565b67ffffffffffffffff16115b806200195a575060875442906200194e9062093a809067ffffffffffffffff16620067ac565b67ffffffffffffffff16115b1562001992576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200199c62004bda565b565b5f82815260346020526040902060010154620019ba8162003f25565b62001788838362004c61565b73ffffffffffffffffffffffffffffffffffffffff8116331462001a16576040517f5a568e6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001a22828262004d1d565b5050565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db162001a528162003f25565b606f5460ff1662001ac35760845467ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169083161062001ac3576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6084805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8516908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a1906020016200187e565b5f608654606462001b539190620067d7565b905090565b7fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd62001b848162003f25565b63ffffffff8216158062001ba35750607e5463ffffffff908116908316115b1562001bdb576040517f7512e5cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff82165f908152607f602052604090206001808201547d010000000000000000000000000000000000000000000000000000000000900460ff161515900362001c54576040517f3b8d3d9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001810180547fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167d01000000000000000000000000000000000000000000000000000000000017905560405163ffffffff8416907f4710d2ee567ef1ed6eb2f651dde4589524bcf7cebc62147a99b281cc836e7e44905f90a2505050565b7fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd0862001cff8162003f25565b63ffffffff8816158062001d1e5750607e5463ffffffff908116908916115b1562001d56576040517f7512e5cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff88165f908152607f602052604090206001808201547d010000000000000000000000000000000000000000000000000000000000900460ff161515900362001dcf576040517f3b8d3d9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff67ffffffffffffffff8916111562001e18576040517f4c753f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff88165f9081526083602052604090205463ffffffff161562001e6f576040517f6f91fc1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608080545f9190829062001e899063ffffffff16620067f1565b825463ffffffff8281166101009490940a93840293021916919091179091558254604080515f808252602082019283905293945073ffffffffffffffffffffffffffffffffffffffff90921691309162001ee39062005f87565b62001ef19392919062006816565b604051809103905ff08015801562001f0b573d5f803e3d5ffd5b5090508160835f8c67ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508160825f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8463ffffffff1663ffffffff1681526020019081526020015f20905081815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360010160149054906101000a900467ffffffffffffffff168160010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550836001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508a815f0160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508360020154816002015f8067ffffffffffffffff1681526020019081526020015f20819055508b63ffffffff168160070160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083600101601c9054906101000a900460ff168160070160106101000a81548160ff021916908360ff1602179055508263ffffffff167f194c983456df6701c6a50830b90fe80e72b823411d0d524970c9590dc277a6418d848e8c604051620021e2949392919063ffffffff94909416845273ffffffffffffffffffffffffffffffffffffffff928316602085015267ffffffffffffffff91909116604084015216606082015260800190565b60405180910390a26040517f7125702200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063712570229062002248908d908d9088908e908e908e9060040162006859565b5f604051808303815f87803b15801562002260575f80fd5b505af115801562002273573d5f803e3d5ffd5b50505050505050505050505050505050565b63ffffffff86165f908152608160205260409020606090620022ac90878787878762004dd7565b979650505050505050565b606f5460ff1615620022f5576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff88165f90815260816020908152604080832060845467ffffffffffffffff8a81168652600383019094529190932060010154429262002359927801000000000000000000000000000000000000000000000000900481169116620067ac565b67ffffffffffffffff1611156200239c576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8620023ab8888620068c8565b67ffffffffffffffff161115620023ee576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62002400818989898989898962004410565b6200240c818762004f9e565b60855467ffffffffffffffff165f0362002552576006810180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8981169182029290921783555f908152600284016020526040902086905560058301879055905470010000000000000000000000000000000090041615620024b8576006810180546fffffffffffffffffffffffffffffffff1690555b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166333d6247d620024fe620031d0565b6040518263ffffffff1660e01b81526004016200251d91815260200190565b5f604051808303815f87803b15801562002535575f80fd5b505af115801562002548573d5f803e3d5ffd5b5050505062002654565b6200255d81620051a5565b600681018054700100000000000000000000000000000000900467ffffffffffffffff169060106200258f83620068ec565b825467ffffffffffffffff9182166101009390930a92830292820219169190911790915560408051608081018252428316815289831660208083019182528284018b8152606084018b81526006890154700100000000000000000000000000000000900487165f90815260048a0190935294909120925183549251861668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169516949094171781559151600183015551600290910155505b6040805167ffffffffffffffff8816815260208101869052908101869052339063ffffffff8b16907faac1e7a157b259544ebacd6e8a82ae5d6c8f174e12aa48696277bcc9a661f0b49060600160405180910390a3505050505050505050565b606f5460ff1615620026f2576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff88165f90815260816020526040902062002718818989898989898962003f31565b67ffffffffffffffff87165f9081526004820160209081526040918290206002015482519081529081018590527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a16200277a62004bda565b505050505050505050565b335f9081527ff14f5a8ad59d90593602e905b358229bff5ceea677d5bf0f5a1701793550a9a6602052604090205460ff161580156200286057503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562002821573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200284791906200690b565b73ffffffffffffffffffffffffffffffffffffffff1614155b1562002898576040517f1a06d0fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f9081526082602052604081205463ffffffff1690819003620028fe576040517f74a086a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff81165f908152608160205260409020600681015467ffffffffffffffff90811690841681111580620029525750600682015467ffffffffffffffff680100000000000000009091048116908516105b156200298a576040517fcb23ebdf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805b8467ffffffffffffffff168167ffffffffffffffff161462002a5f5767ffffffffffffffff8082165f908152600385016020526040902060010154680100000000000000009004811690861681101562002a12576040517f9753965f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff9091165f908152600384016020526040812090815560010180547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690556200298c565b6006830180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff871617905562002aa18583620068c8565b608480545f9062002abe90849067ffffffffffffffff16620068c8565b82546101009290920a67ffffffffffffffff818102199093169183160217909155600685015470010000000000000000000000000000000090041615905062002ba1575f62002b0d8462003e8f565b600685015490915062002b379068010000000000000000900467ffffffffffffffff1682620068c8565b6084805460089062002b6190849068010000000000000000900467ffffffffffffffff16620068c8565b825467ffffffffffffffff9182166101009390930a928302919092021990911617905550506006830180546fffffffffffffffffffffffffffffffff1690555b67ffffffffffffffff85165f818152600385016020526040908190205490517f669adece0000000000000000000000000000000000000000000000000000000081526004810192909252602482015273ffffffffffffffffffffffffffffffffffffffff87169063669adece906044015f604051808303815f87803b15801562002c29575f80fd5b505af115801562002c3c573d5f803e3d5ffd5b5050505067ffffffffffffffff85165f81815260038501602090815260409182902054915191825263ffffffff8716917f80a6d395a55aed8126079cb8247f0a6848b1440ca2cdca3b4386f250c3529402910160405180910390a3505050505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801562002d2c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002d52919062006929565b6084549091505f9062002d7e9067ffffffffffffffff68010000000000000000820481169116620068c8565b67ffffffffffffffff169050805f0362002d9a575f9250505090565b62002da681836200696e565b9250505090565b606f545f9060ff161562002ded576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f9081526082602052604081205463ffffffff169081900362002e3d576040517f71653c1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8367ffffffffffffffff165f0362002e81576040517f2590ccf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff81165f908152608160205260408120608480549192879262002eb490849067ffffffffffffffff16620067ac565b82546101009290920a67ffffffffffffffff81810219909316918316021790915560068301541690505f62002eea8783620067ac565b60068401805467ffffffffffffffff8084167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217909255604080516060810182528a815242841660208083019182528886168385019081525f95865260038b019091529290932090518155915160019290920180549151841668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009092169290931691909117179055905062002fae83620051a5565b60405167ffffffffffffffff8216815263ffffffff8516907f1d9f30260051d51d70339da239ea7b080021adcaabfa71c9b0ea339a20cf9a259060200160405180910390a29695505050505050565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620030298162003f25565b606f5460ff166200307e5760855467ffffffffffffffff908116908316106200307e576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608580547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff84169081179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c75906020016200187e565b7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db1620031128162003f25565b620151808267ffffffffffffffff1611156200315a576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608580547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8516908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c28906020016200187e565b6080545f9063ffffffff16808203620031ea57505f919050565b5f8167ffffffffffffffff811115620032075762003207620062c2565b60405190808252806020026020018201604052801562003231578160200160208202803683370190505b5090505f5b82811015620032a15760815f6200324f83600162006984565b63ffffffff1663ffffffff1681526020019081526020015f20600501548282815181106200328157620032816200699a565b6020908102919091010152806200329881620069c7565b91505062003236565b505f60205b83600114620034fa575f620032bd60028662006a01565b620032ca6002876200696e565b620032d6919062006984565b90505f8167ffffffffffffffff811115620032f557620032f5620062c2565b6040519080825280602002602001820160405280156200331f578160200160208202803683370190505b5090505f5b82811015620034a6576200333a60018462006a17565b811480156200335557506200335160028862006a01565b6001145b15620033dd578562003369826002620067d7565b815181106200337c576200337c6200699a565b602002602001015185604051602001620033a0929190918252602082015260400190565b60405160208183030381529060405280519060200120828281518110620033cb57620033cb6200699a565b60200260200101818152505062003491565b85620033eb826002620067d7565b81518110620033fe57620033fe6200699a565b602002602001015186826002620034169190620067d7565b6200342390600162006984565b815181106200343657620034366200699a565b602002602001015160405160200162003459929190918252602082015260400190565b604051602081830303815290604052805190602001208282815181106200348457620034846200699a565b6020026020010181815250505b806200349d81620069c7565b91505062003324565b508094508195508384604051602001620034ca929190918252602082015260400190565b6040516020818303038152906040528051906020012093508280620034ef9062006a2d565b9350505050620032a6565b5f835f815181106200351057620035106200699a565b602002602001015190505f5b82811015620035ae576040805160208101849052908101859052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152828252805160209182012090830187905290820186905292506060016040516020818303038152906040528051906020012093508080620035a590620069c7565b9150506200351c565b5095945050505050565b7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac620035e48162003f25565b620035f1848484620052b5565b50505050565b7f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb620036238162003f25565b683635c9adc5dea000008211806200363e5750633b9aca0082105b1562003676576040517f8586952500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60868290556040518281527ffb383653f53ee079978d0c9aff7aeff04a10166ce244cca9c9f9d8d96bed45b2906020016200187e565b5f82815260346020526040902060010154620036c88162003f25565b62001788838362004d1d565b7f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f4620037008162003f25565b608780547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff16179055604080517fdbc1697600000000000000000000000000000000000000000000000000000000815290517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169163dbc16976916004808301925f92919082900301818387803b158015620037ba575f80fd5b505af1158015620037cd573d5f803e3d5ffd5b50505050620037db62005747565b50565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562003840573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200386691906200690b565b73ffffffffffffffffffffffffffffffffffffffff1614620038b4576040517f696072e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f9081526082602090815260408083205463ffffffff16835260819091529020600681015467ffffffffffffffff80821668010000000000000000909204161462003942576040517fcc862d4a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600781015463ffffffff83166801000000000000000090910467ffffffffffffffff16106200399d576040517f3e37e23300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080515f815260208101909152620017889084908490620052b5565b7f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e620039e68162003f25565b67ffffffffffffffff84165f9081526083602052604090205463ffffffff161562003a3d576040517f6f91fc1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff67ffffffffffffffff8516111562003a86576040517f4c753f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff87165f9081526082602052604090205463ffffffff161562003ae9576040517fd409b93000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62003af98888888887620057d6565b5f8080526002909101602052604090209390935550505050505050565b7fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f59062003b428162003f25565b607e80545f9190829062003b5c9063ffffffff16620067f1565b91906101000a81548163ffffffff021916908363ffffffff160217905590506040518060c001604052808973ffffffffffffffffffffffffffffffffffffffff1681526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018767ffffffffffffffff1681526020018660ff1681526020015f1515815260200185815250607f5f8363ffffffff1663ffffffff1681526020019081526020015f205f820151815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506020820151816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550606082015181600101601c6101000a81548160ff021916908360ff160217905550608082015181600101601d6101000a81548160ff02191690831515021790555060a082015181600201559050508063ffffffff167fa2970448b3bd66ba7e524e7b2a5b9cf94fa29e32488fb942afdfe70dd4b77b5289898989898960405162003d499695949392919062006a64565b60405180910390a25050505050505050565b5f54610100900460ff166200199c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840162000e2e565b62001a22828262004c61565b5f82815260346020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b60855467ffffffffffffffff8281165f9081526004850160205260408120549092429262003e7c929181169116620067ac565b67ffffffffffffffff1611159392505050565b60068101545f90700100000000000000000000000000000000900467ffffffffffffffff161562003f025750600681015467ffffffffffffffff70010000000000000000000000000000000090910481165f90815260049092016020526040909120546801000000000000000090041690565b506006015468010000000000000000900467ffffffffffffffff1690565b919050565b620037db813362005a58565b60078801545f9067ffffffffffffffff908116908716101562003f80576040517fead1340b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8816156200406757600689015467ffffffffffffffff7001000000000000000000000000000000009091048116908916111562003ff2576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5067ffffffffffffffff8088165f90815260048a016020526040902060028101548154909288811668010000000000000000909204161462004060576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5062004114565b5067ffffffffffffffff85165f90815260028901602052604090205480620040bb576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600689015467ffffffffffffffff680100000000000000009091048116908716111562004114576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600689015467ffffffffffffffff700100000000000000000000000000000000909104811690881611806200415d57508767ffffffffffffffff168767ffffffffffffffff1611155b80620041975750600689015467ffffffffffffffff7801000000000000000000000000000000000000000000000000909104811690881611155b15620041cf576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8781165f90815260048b01602052604090205468010000000000000000900481169086161462004234576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f620042458a888888868962004dd7565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516200427b919062006ac9565b602060405180830381855afa15801562004297573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190620042bc919062006929565b620042c8919062006a01565b60018c01546040805160208101825283815290517f9121da8a00000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff90911691639121da8a91620043329188919060040162006ae6565b602060405180830381865afa1580156200434e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062004374919062006b22565b620043ab576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff89165f90815260048c01602052604090206002015485900362004403576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050565b5f806200441d8a62003e8f565b60078b015490915067ffffffffffffffff90811690891610156200446d576040517fead1340b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff891615620045565760068a015467ffffffffffffffff7001000000000000000000000000000000009091048116908a161115620044df576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff808a165f90815260048c01602052604090206002810154815490945090918a81166801000000000000000090920416146200454f576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50620045fa565b67ffffffffffffffff88165f90815260028b016020526040902054915081620045ab576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168867ffffffffffffffff161115620045fa576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff161162004648576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f620046598b8a8a8a878b62004dd7565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516200468f919062006ac9565b602060405180830381855afa158015620046ab573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190620046d0919062006929565b620046dc919062006a01565b60018d01546040805160208101825283815290517f9121da8a00000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff90911691639121da8a91620047469189919060040162006ae6565b602060405180830381865afa15801562004762573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062004788919062006b22565b620047bf576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f620047cc848b620068c8565b905062004833878267ffffffffffffffff16620047e862002c9f565b620047f49190620067d7565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919062005ac1565b80608460088282829054906101000a900467ffffffffffffffff166200485a9190620067ac565b82546101009290920a67ffffffffffffffff818102199093169183160217909155608480547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16700100000000000000000000000000000000428416021790558e546040517f32c2d153000000000000000000000000000000000000000000000000000000008152918d166004830152602482018b905233604483015273ffffffffffffffffffffffffffffffffffffffff1691506332c2d153906064015f604051808303815f87803b15801562004930575f80fd5b505af115801562004943573d5f803e3d5ffd5b5050505050505050505050505050505050565b600682015467ffffffffffffffff78010000000000000000000000000000000000000000000000009091048116908216111580620049b95750600682015467ffffffffffffffff7001000000000000000000000000000000009091048116908216115b15620049f1576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8181165f818152600485016020908152604080832080546006890180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000092839004909816918202979097178755600280830154828752908a01909452919093209190915560018201546005870155835477ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000909302929092179092557f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166333d6247d62004afa620031d0565b6040518263ffffffff1660e01b815260040162004b1991815260200190565b5f604051808303815f87803b15801562004b31575f80fd5b505af115801562004b44573d5f803e3d5ffd5b5050855473ffffffffffffffffffffffffffffffffffffffff165f908152608260209081526040918290205460028701546001880154845167ffffffffffffffff898116825294810192909252818501529188166060830152915163ffffffff90921693507f581910eb7a27738945c2f00a91f2284b2d6de9d4e472b12f901c2b0df045e21b925081900360800190a250505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562004c40575f80fd5b505af115801562004c53573d5f803e3d5ffd5b505050506200199c62005b50565b5f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1662001a22575f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b5f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff161562001a22575f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b67ffffffffffffffff8086165f818152600389016020526040808220549388168252902054606092911580159062004e0d575081155b1562004e45576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8062004e7d576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62004e888462005be3565b62004ebf576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b885460018a01546040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015260348101889052605481018590527fffffffffffffffff00000000000000000000000000000000000000000000000060c08c811b821660748401527401000000000000000000000000000000000000000094859004811b8216607c84015293909204831b82166084820152608c810187905260ac810184905260cc81018990529189901b1660ec82015260f401604051602081830303815290604052925050509695505050505050565b5f62004faa8362003e8f565b9050815f8062004fbb8484620068c8565b60855467ffffffffffffffff91821692505f9162004fe791680100000000000000009004164262006a17565b90505b8467ffffffffffffffff168467ffffffffffffffff16146200507a5767ffffffffffffffff8085165f908152600389016020526040902060018101549091168210156200505457600181015468010000000000000000900467ffffffffffffffff16945062005073565b620050608686620068c8565b67ffffffffffffffff169350506200507a565b5062004fea565b5f62005087848462006a17565b905083811015620050e557808403600c8111620050a55780620050a8565b600c5b9050806103e80a81608560109054906101000a900461ffff1661ffff160a6086540281620050da57620050da62006941565b04608655506200515c565b838103600c8111620050f85780620050fb565b600c5b90505f816103e80a82608560109054906101000a900461ffff1661ffff160a670de0b6b3a7640000028162005134576200513462006941565b04905080608654670de0b6b3a7640000028162005155576200515562006941565b0460865550505b683635c9adc5dea0000060865411156200518357683635c9adc5dea000006086556200519b565b633b9aca0060865410156200519b57633b9aca006086555b5050505050505050565b600681015467ffffffffffffffff780100000000000000000000000000000000000000000000000082048116700100000000000000000000000000000000909204161115620037db5760068101545f9062005228907801000000000000000000000000000000000000000000000000900467ffffffffffffffff166001620067ac565b905062005236828262003e49565b1562001a225760068201545f9060029062005271908490700100000000000000000000000000000000900467ffffffffffffffff16620068c8565b6200527d919062006b43565b620052899083620067ac565b905062005297838262003e49565b15620052a95762001788838262004956565b62001788838362004956565b63ffffffff82161580620052d45750607e5463ffffffff908116908316115b156200530c576040517f7512e5cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f9081526082602052604081205463ffffffff169081900362005372576040517f74a086a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8181165f9081526081602052604090206007810154909185166801000000000000000090910467ffffffffffffffff1603620053df576040517f4f61d51900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff84165f908152607f602052604090206001808201547d010000000000000000000000000000000000000000000000000000000000900460ff161515900362005458576040517f3b8d3d9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018101546007830154700100000000000000000000000000000000900460ff9081167c01000000000000000000000000000000000000000000000000000000009092041614620054d5576040517fb541abe200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018181018054918401805473ffffffffffffffffffffffffffffffffffffffff9093167fffffffffffffffffffffffff000000000000000000000000000000000000000084168117825591547fffffffff00000000000000000000000000000000000000000000000000000000909316909117740100000000000000000000000000000000000000009283900467ffffffffffffffff9081169093021790556007830180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff1663ffffffff8816680100000000000000000217905560068301547801000000000000000000000000000000000000000000000000810482167001000000000000000000000000000000009091049091161462005625576040517f9d59507b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f620056318462001293565b6007840180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff831617905582546040517f4f1ef28600000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff89811692634f1ef28692620056c3921690899060040162006b6c565b5f604051808303815f87803b158015620056db575f80fd5b505af1158015620056ee573d5f803e3d5ffd5b50506040805163ffffffff8a8116825267ffffffffffffffff86166020830152881693507ff585e04c05d396901170247783d3e5f0ee9c1df23072985b50af089f5e48b19d92500160405180910390a250505050505050565b606f5460ff1662005784576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b608080545f9182918290620057f19063ffffffff16620067f1565b91906101000a81548163ffffffff021916908363ffffffff160217905590508060835f8667ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508060825f8973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff16021790555060815f8263ffffffff1663ffffffff1681526020019081526020015f20915086825f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550848260010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555085826001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083825f0160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550828260070160106101000a81548160ff021916908360ff1602179055508063ffffffff167fadfc7d56f7e39b08b321534f14bfb135ad27698f7d2f5ad0edc2356ea9a3f850868987875f60405162005a4695949392919067ffffffffffffffff958616815273ffffffffffffffffffffffffffffffffffffffff949094166020850152918416604084015260ff166060830152909116608082015260a00190565b60405180910390a25095945050505050565b5f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1662001a22576040517fec2b7c3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526200178890849062005c6a565b606f5460ff161562005b8e576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b5f67ffffffff0000000167ffffffffffffffff831610801562005c1b575067ffffffff00000001604083901c67ffffffffffffffff16105b801562005c3d575067ffffffff00000001608083901c67ffffffffffffffff16105b801562005c55575067ffffffff0000000160c083901c105b1562005c6357506001919050565b505f919050565b5f62005ccd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1662005d7c9092919063ffffffff16565b80519091501562001788578080602001905181019062005cee919062006b22565b62001788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162000e2e565b606062005d8c84845f8562005d94565b949350505050565b60608247101562005e28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840162000e2e565b5f808673ffffffffffffffffffffffffffffffffffffffff16858760405162005e52919062006ac9565b5f6040518083038185875af1925050503d805f811462005e8e576040519150601f19603f3d011682016040523d82523d5f602084013e62005e93565b606091505b5091509150620022ac878383876060831562005f3a5782515f0362005f325773ffffffffffffffffffffffffffffffffffffffff85163b62005f32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000e2e565b508162005d8c565b62005d8c838381511562005f515781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000e2e919062006540565b610a5e8062006b9d83390190565b73ffffffffffffffffffffffffffffffffffffffff81168114620037db575f80fd5b803567ffffffffffffffff8116811462003f20575f80fd5b5f805f805f805f805f806101408b8d03121562005fea575f80fd5b8a3562005ff78162005f95565b99506200600760208c0162005fb7565b98506200601760408c0162005fb7565b975060608b0135620060298162005f95565b965060808b01356200603b8162005f95565b955060a08b01356200604d8162005f95565b945060c08b01356200605f8162005f95565b935060e08b0135620060718162005f95565b9250620060826101008c0162005fb7565b9150620060936101208c0162005fb7565b90509295989b9194979a5092959850565b803563ffffffff8116811462003f20575f80fd5b5f8060408385031215620060ca575f80fd5b620060d583620060a4565b9150620060e56020840162005fb7565b90509250929050565b5f60208284031215620060ff575f80fd5b6200128a82620060a4565b8061030081018310156200128d575f80fd5b5f805f805f805f806103e0898b03121562006135575f80fd5b6200614089620060a4565b97506200615060208a0162005fb7565b96506200616060408a0162005fb7565b95506200617060608a0162005fb7565b94506200618060808a0162005fb7565b935060a0890135925060c089013591506200619f8a60e08b016200610a565b90509295985092959890939650565b5f805f805f805f806103e0898b031215620061c7575f80fd5b620061d289620060a4565b9750620061e260208a0162005fb7565b9650620061f260408a0162005fb7565b95506200620260608a0162005fb7565b94506080890135935060a0890135925060c0890135620062228162005f95565b91506200619f8a60e08b016200610a565b5f6020828403121562006244575f80fd5b813561ffff8116811462006256575f80fd5b9392505050565b5f602082840312156200626e575f80fd5b5035919050565b5f806040838503121562006287575f80fd5b8235915060208301356200629b8162005f95565b809150509250929050565b5f60208284031215620062b7575f80fd5b6200128a8262005fb7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f67ffffffffffffffff808411156200630c576200630c620062c2565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715620063555762006355620062c2565b816040528093508581528686860111156200636e575f80fd5b858560208301375f602087830101525050509392505050565b5f82601f83011262006397575f80fd5b6200128a83833560208501620062ef565b5f805f805f805f60e0888a031215620063bf575f80fd5b620063ca88620060a4565b9650620063da6020890162005fb7565b95506040880135620063ec8162005f95565b94506060880135620063fe8162005f95565b93506080880135620064108162005f95565b925060a088013567ffffffffffffffff808211156200642d575f80fd5b6200643b8b838c0162006387565b935060c08a013591508082111562006451575f80fd5b50620064608a828b0162006387565b91505092959891949750929550565b5f805f805f8060c0878903121562006485575f80fd5b6200649087620060a4565b9550620064a06020880162005fb7565b9450620064b06040880162005fb7565b9350606087013592506080870135915060a087013590509295509295509295565b5f5b83811015620064ed578181015183820152602001620064d3565b50505f910152565b5f81518084526200650e816020860160208601620064d1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f6200128a6020830184620064f5565b5f806040838503121562006566575f80fd5b8235620060d58162005f95565b5f806040838503121562006585575f80fd5b620065908362005fb7565b946020939093013593505050565b5f805f60608486031215620065b1575f80fd5b8335620065be8162005f95565b9250620065ce60208501620060a4565b9150604084013567ffffffffffffffff811115620065ea575f80fd5b8401601f81018613620065fb575f80fd5b6200660c86823560208401620062ef565b9150509250925092565b5f6020828403121562006627575f80fd5b8135620062568162005f95565b5f806040838503121562006646575f80fd5b8235620066538162005f95565b9150620060e560208401620060a4565b803560ff8116811462003f20575f80fd5b5f805f805f8060c087890312156200668a575f80fd5b8635620066978162005f95565b95506020870135620066a98162005f95565b9450620066b96040880162005fb7565b9350620066c96060880162005fb7565b925060808701359150620066e060a0880162006663565b90509295509295509295565b5f805f805f8060c0878903121562006702575f80fd5b86356200670f8162005f95565b95506020870135620067218162005f95565b9450620067316040880162005fb7565b9350620067416060880162006663565b92506080870135915060a087013567ffffffffffffffff81111562006764575f80fd5b6200677289828a0162006387565b9150509295509295509295565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff818116838216019080821115620067d057620067d06200677f565b5092915050565b80820281158282048414176200128d576200128d6200677f565b5f63ffffffff8083168181036200680c576200680c6200677f565b6001019392505050565b5f73ffffffffffffffffffffffffffffffffffffffff808616835280851660208401525060606040830152620068506060830184620064f5565b95945050505050565b5f73ffffffffffffffffffffffffffffffffffffffff8089168352808816602084015263ffffffff8716604084015280861660608401525060c06080830152620068a760c0830185620064f5565b82810360a0840152620068bb8185620064f5565b9998505050505050505050565b67ffffffffffffffff828116828216039080821115620067d057620067d06200677f565b5f67ffffffffffffffff8083168181036200680c576200680c6200677f565b5f602082840312156200691c575f80fd5b8151620062568162005f95565b5f602082840312156200693a575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f826200697f576200697f62006941565b500490565b808201808211156200128d576200128d6200677f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620069fa57620069fa6200677f565b5060010190565b5f8262006a125762006a1262006941565b500690565b818103818111156200128d576200128d6200677f565b5f8162006a3e5762006a3e6200677f565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b5f73ffffffffffffffffffffffffffffffffffffffff808916835280881660208401525067ffffffffffffffff8616604083015260ff8516606083015283608083015260c060a083015262006abd60c0830184620064f5565b98975050505050505050565b5f825162006adc818460208701620064d1565b9190910192915050565b6103208101610300808584378201835f5b600181101562006b1857815183526020928301929091019060010162006af7565b5050509392505050565b5f6020828403121562006b33575f80fd5b8151801515811462006256575f80fd5b5f67ffffffffffffffff8084168062006b605762006b6062006941565b92169190910492915050565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201525f62005d8c6040830184620064f556fe60a060405260405162000a5e38038062000a5e833981016040819052620000269162000375565b828162000034828262000060565b50506001600160a01b038216608052620000576200005160805190565b620000c5565b5050506200046c565b6200006b8262000136565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000b757620000b28282620001b5565b505050565b620000c16200022e565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620001065f8051602062000a3e833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001338162000250565b50565b806001600160a01b03163b5f036200017157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b031684604051620001d391906200044f565b5f60405180830381855af49150503d805f81146200020d576040519150601f19603f3d011682016040523d82523d5f602084013e62000212565b606091505b5090925090506200022585838362000291565b95945050505050565b34156200024e5760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b0381166200027b57604051633173bdd160e11b81525f600482015260240162000168565b805f8051602062000a3e83398151915262000194565b606082620002aa57620002a482620002f7565b620002f0565b8151158015620002c257506001600160a01b0384163b155b15620002ed57604051639996b31560e01b81526001600160a01b038516600482015260240162000168565b50805b9392505050565b805115620003085780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811462000338575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b838110156200036d57818101518382015260200162000353565b50505f910152565b5f805f6060848603121562000388575f80fd5b620003938462000321565b9250620003a36020850162000321565b60408501519092506001600160401b0380821115620003c0575f80fd5b818601915086601f830112620003d4575f80fd5b815181811115620003e957620003e96200033d565b604051601f8201601f19908116603f011681019083821181831017156200041457620004146200033d565b816040528281528960208487010111156200042d575f80fd5b6200044083602083016020880162000351565b80955050505050509250925092565b5f82516200046281846020870162000351565b9190910192915050565b6080516105ba620004845f395f601001526105ba5ff3fe608060405261000c61000e565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633036100a7575f357fffffffff00000000000000000000000000000000000000000000000000000000167f4f1ef286000000000000000000000000000000000000000000000000000000001461009f5761009d6100ab565b565b61009d6100bb565b61009d5b61009d6100b66100e9565b61012d565b5f806100ca3660048184610410565b8101906100d79190610464565b915091506100e5828261014b565b5050565b5f6101287f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e808015610147573d5ff35b3d5ffd5b610154826101b2565b60405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101aa576101a58282610285565b505050565b6100e5610304565b8073ffffffffffffffffffffffffffffffffffffffff163b5f0361021f576040517f4c9c8ce300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60605f808473ffffffffffffffffffffffffffffffffffffffff16846040516102ae9190610558565b5f60405180830381855af49150503d805f81146102e6576040519150601f19603f3d011682016040523d82523d5f602084013e6102eb565b606091505b50915091506102fb85838361033c565b95945050505050565b341561009d576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060826103515761034c826103ce565b6103c7565b8151158015610375575073ffffffffffffffffffffffffffffffffffffffff84163b155b156103c4576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610216565b50805b9392505050565b8051156103de5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808585111561041e575f80fd5b8386111561042a575f80fd5b5050820193919092039150565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f8060408385031215610475575f80fd5b823573ffffffffffffffffffffffffffffffffffffffff81168114610498575f80fd5b9150602083013567ffffffffffffffff808211156104b4575f80fd5b818501915085601f8301126104c7575f80fd5b8135818111156104d9576104d9610437565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561051f5761051f610437565b81604052828152886020848701011115610537575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610577576020818601810151858301520161055d565b505f92019182525091905056fea264697066735822122052b5bba3494b1e5512431e77157bb64992f00cd96273780f749f0677c4cb3be064736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103a2646970667358221220f0e6054fa205ece2d4b26ccacb67fce15ea89ea0f8d6d08884bcf3607d6fda8c64736f6c63430008140033", + "bytecode": "0x60e060405234801562000010575f80fd5b506040516200671c3803806200671c83398101604081905262000033916200013c565b6001600160a01b0380841660805280831660c052811660a0528282826200005962000065565b5050505050506200018d565b5f54610100900460ff1615620000d15760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116101562000122575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b038116811462000139575f80fd5b50565b5f805f606084860312156200014f575f80fd5b83516200015c8162000124565b60208501519093506200016f8162000124565b6040850151909250620001828162000124565b809150509250925092565b60805160a05160c051616533620001e95f395f8181610916015281816123760152613b4901525f81816107b101528181612fae0152613c5e01525f818161087e01528181610f3d015281816132e2015261349801526165335ff3fe608060405234801562000010575f80fd5b506004361062000320575f3560e01c806391d1485411620001a7578063ceee281d11620000ef578063dde0ff77116200009f578063e4a4b6a21162000077578063e4a4b6a21462000938578063f4e92675146200094f578063f9c4c2ae1462000960575f80fd5b8063dde0ff7714620008d8578063dfdb8c5e14620008f9578063e46761c41462000910575f80fd5b8063d5073f6f11620000d3578063d5073f6f14620008a0578063d547741f14620008b7578063dbc1697614620008ce575f80fd5b8063ceee281d1462000850578063d02103ca1462000878575f80fd5b8063a217fddf1162000157578063abcb5198116200012f578063abcb519814620007f9578063c1acbc341462000810578063c4c928c21462000839575f80fd5b8063a217fddf1462000799578063a2967d9914620007a1578063a3c573eb14620007ab575f80fd5b806399f5634e116200018b57806399f5634e14620007615780639a908e73146200076b5780639e36c5651462000782575f80fd5b806391d14854146200070257806397bf07e8146200074a575f80fd5b806336568abe116200026b5780637222020f116200021b5780637975fcfe11620001f35780637975fcfe146200069d5780637fb6e76a14620006c35780638fd88cc214620006eb575f80fd5b80637222020f1462000649578063727885e9146200066057806374d9c2441462000677575f80fd5b806355a71ee0116200024f57806355a71ee0146200052957806360469169146200056d57806365c0504d1462000577575f80fd5b806336568abe1462000509578063477fa2701462000520575f80fd5b80631796a1ae11620002d35780632528016911620002ab5780632528016914620004225780632f2ff15d14620004dd57806330c27dde14620004f4575f80fd5b80631796a1ae14620003bd5780632072f6c514620003e4578063248a9ca314620003ee575f80fd5b806311f6b287116200030757806311f6b28714620003705780631489ed10146200038757806315064c96146200039e575f80fd5b80630645af091462000324578063066ec012146200033d575b5f80fd5b6200033b6200033536600462004af0565b62000986565b005b608454620003529067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b620003526200038136600462004bd9565b62000da9565b6200033b6200039836600462004bfc565b62000dde565b606f54620003ac9060ff1681565b604051901515815260200162000367565b607e54620003ce9063ffffffff1681565b60405163ffffffff909116815260200162000367565b6200033b62001030565b62000413620003ff36600462004c96565b5f9081526034602052604090206001015490565b60405190815260200162000367565b620004a86200043336600462004cae565b60408051606080820183525f808352602080840182905292840181905263ffffffff9590951685526081825282852067ffffffffffffffff9485168652600301825293829020825194850183528054855260010154808416918501919091526801000000000000000090049091169082015290565b604080518251815260208084015167ffffffffffffffff90811691830191909152928201519092169082015260600162000367565b6200033b620004ee36600462004ce4565b62001144565b608754620003529067ffffffffffffffff1681565b6200033b6200051a36600462004ce4565b62001171565b60865462000413565b620004136200053a36600462004cae565b63ffffffff82165f90815260816020908152604080832067ffffffffffffffff8516845260020190915290205492915050565b62000413620011d1565b620006346200058836600462004bd9565b607f6020525f9081526040902080546001820154600283015460039093015473ffffffffffffffffffffffffffffffffffffffff928316939282169267ffffffffffffffff740100000000000000000000000000000000000000008404169260ff7c010000000000000000000000000000000000000000000000000000000082048116937d01000000000000000000000000000000000000000000000000000000000090920416919087565b60405162000367979695949392919062004d7c565b6200033b6200065a36600462004bd9565b620011e8565b6200033b6200067136600462004ec4565b62001363565b6200068e6200068836600462004bd9565b6200191b565b60405162000367919062004f8b565b620006b4620006ae366004620050b7565b62001a7e565b60405162000367919062005188565b620003ce620006d43660046200519c565b60836020525f908152604090205463ffffffff1681565b6200033b620006fc366004620051b8565b62001ab0565b620003ac6200071336600462004ce4565b5f91825260346020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6200033b6200075b366004620051e6565b62001f69565b620004136200232f565b620003526200077c36600462005268565b6200243d565b620006b46200079336600462005293565b62002674565b620004135f81565b62000413620026a6565b620007d37f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200162000367565b6200033b6200080a366004620052cc565b62002a8e565b6084546200035290700100000000000000000000000000000000900467ffffffffffffffff1681565b6200033b6200084a36600462005369565b62002e01565b620003ce62000861366004620053e1565b60826020525f908152604090205463ffffffff1681565b620007d37f000000000000000000000000000000000000000000000000000000000000000081565b6200033b620008b136600462004c96565b62002e40565b6200033b620008c836600462004ce4565b62002efb565b6200033b62002f23565b608454620003529068010000000000000000900467ffffffffffffffff1681565b6200033b6200090a366004620053ff565b6200302d565b620007d37f000000000000000000000000000000000000000000000000000000000000000081565b6200033b620009493660046200542e565b62003209565b608054620003ce9063ffffffff1681565b620009776200097136600462004bd9565b6200357f565b604051620003679190620054cc565b5f54600290610100900460ff16158015620009a757505f5460ff8083169116105b62000a39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905567016345785d8a000060865562000a7f62003725565b62000aab7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd48c620037bd565b62000ab75f88620037bd565b62000ae37fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f59088620037bd565b62000b0f7f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e88620037bd565b62000b3b7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac88620037bd565b62000b677fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd89620037bd565b62000b937fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd0889620037bd565b62000bbf7f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f489620037bd565b62000beb7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db189620037bd565b62000c377f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd47f73cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f0620037c9565b62000c637f73cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f089620037bd565b62000c8f7f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb89620037bd565b62000cdb7f141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545e7f9b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff285951620037c9565b62000d077f141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545e87620037bd565b62000d337f9b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff28595187620037bd565b62000d3f5f33620037bd565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050505050565b63ffffffff81165f9081526081602052604081206006015468010000000000000000900467ffffffffffffffff165b92915050565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd462000e0a8162003813565b67ffffffffffffffff88161562000e4d576040517f60dbf8ae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff89165f908152608160205260408120906007820154700100000000000000000000000000000000900460ff16600181111562000e925762000e9262004d15565b1462000eca576040517f90db0d0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000edb818989898989896200381f565b6006810180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8a16908102919091179091555f9081526002820160205260409020859055600581018690557f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166333d6247d62000f81620026a6565b6040518263ffffffff1660e01b815260040162000fa091815260200190565b5f604051808303815f87803b15801562000fb8575f80fd5b505af115801562000fcb573d5f803e3d5ffd5b50506040805167ffffffffffffffff8b1681526020810189905290810189905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d39060600160405180910390a350505050505050505050565b335f9081527f8875b94af5657a2903def9906d67a3f42d8a836d24b5602c00f00fc855339fcd602052604090205460ff166200113857608454700100000000000000000000000000000000900467ffffffffffffffff161580620010ce57506084544290620010c29062093a8090700100000000000000000000000000000000900467ffffffffffffffff166200562e565b67ffffffffffffffff16115b806200110057506087544290620010f49062093a809067ffffffffffffffff166200562e565b67ffffffffffffffff16115b1562001138576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200114262003c5c565b565b5f82815260346020526040902060010154620011608162003813565b6200116c838362003ce3565b505050565b73ffffffffffffffffffffffffffffffffffffffff81163314620011c1576040517f5a568e6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620011cd828262003d9f565b5050565b5f6086546064620011e3919062005659565b905090565b7fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd620012148162003813565b63ffffffff82161580620012335750607e5463ffffffff908116908316115b156200126b576040517f7512e5cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff82165f908152607f602052604090206001808201547d010000000000000000000000000000000000000000000000000000000000900460ff1615159003620012e4576040517f3b8d3d9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001810180547fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167d01000000000000000000000000000000000000000000000000000000000017905560405163ffffffff8416907f4710d2ee567ef1ed6eb2f651dde4589524bcf7cebc62147a99b281cc836e7e44905f90a2505050565b7fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd086200138f8162003813565b63ffffffff88161580620013ae5750607e5463ffffffff908116908916115b15620013e6576040517f7512e5cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff88165f908152607f602052604090206001808201547d010000000000000000000000000000000000000000000000000000000000900460ff16151590036200145f576040517f3b8d3d9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff67ffffffffffffffff89161115620014a8576040517f4c753f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff88165f9081526083602052604090205463ffffffff1615620014ff576040517f6f91fc1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608080545f91908290620015199063ffffffff1662005673565b825463ffffffff8281166101009490940a93840293021916919091179091558254604080515f808252602082019283905293945073ffffffffffffffffffffffffffffffffffffffff909216913091620015739062004aa8565b620015819392919062005698565b604051809103905ff0801580156200159b573d5f803e3d5ffd5b5090508160835f8c67ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508160825f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8463ffffffff1663ffffffff1681526020019081526020015f20905081815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360010160149054906101000a900467ffffffffffffffff168160010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550836001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508a815f0160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508360020154816002015f8067ffffffffffffffff1681526020019081526020015f20819055508b63ffffffff168160070160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083600101601c9054906101000a900460ff168160070160106101000a81548160ff0219169083600181111562001800576200180062004d15565b0217905550600384015460098201556040805163ffffffff8e8116825273ffffffffffffffffffffffffffffffffffffffff858116602084015267ffffffffffffffff8f16838501528b1660608301529151918516917f194c983456df6701c6a50830b90fe80e72b823411d0d524970c9590dc277a6419181900360800190a26040517f7125702200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831690637125702290620018de908d908d9088908e908e908e90600401620056d2565b5f604051808303815f87803b158015620018f6575f80fd5b505af115801562001909573d5f803e3d5ffd5b50505050505050505050505050505050565b60408051610180810182525f8082526020808301828152838501838152606085018481526080860185815260a0870186815260c0880187815260e089018881526101008a018981526101208b018a81526101408c018b90526101608c018b905263ffffffff8e168b5260819099529a909820805473ffffffffffffffffffffffffffffffffffffffff8082168c52740100000000000000000000000000000000000000009182900467ffffffffffffffff90811690995260018084015491821690985204871690945260058401549092526006830154808616909152680100000000000000009081900485169091526007820154808516909652850490921690955292939091700100000000000000000000000000000000900460ff169081111562001a4b5762001a4b62004d15565b9081600181111562001a615762001a6162004d15565b905250600881015461014083015260090154610160820152919050565b63ffffffff86165f90815260816020526040902060609062001aa590878787878762003e59565b979650505050505050565b335f9081527ff14f5a8ad59d90593602e905b358229bff5ceea677d5bf0f5a1701793550a9a6602052604090205460ff1615801562001b8b57503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562001b4c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001b72919062005741565b73ffffffffffffffffffffffffffffffffffffffff1614155b1562001bc3576040517f1a06d0fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f9081526082602052604081205463ffffffff169081900362001c29576040517f74a086a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff81165f908152608160205260408120906007820154700100000000000000000000000000000000900460ff16600181111562001c6e5762001c6e62004d15565b1462001ca6576040517f90db0d0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600681015467ffffffffffffffff9081169084168111158062001ce65750600682015467ffffffffffffffff680100000000000000009091048116908516105b1562001d1e576040517fcb23ebdf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805b8467ffffffffffffffff168167ffffffffffffffff161462001df35767ffffffffffffffff8082165f908152600385016020526040902060010154680100000000000000009004811690861681101562001da6576040517f9753965f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff9091165f908152600384016020526040812090815560010180547fffffffffffffffffffffffffffffffff0000000000000000000000000000000016905562001d20565b6006830180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff871617905562001e3585836200575f565b608480545f9062001e5290849067ffffffffffffffff166200575f565b82546101009290920a67ffffffffffffffff81810219909316918316021790915586165f818152600386016020526040908190205490517f669adece0000000000000000000000000000000000000000000000000000000081526004810192909252602482015273ffffffffffffffffffffffffffffffffffffffff8816915063669adece906044015f604051808303815f87803b15801562001ef3575f80fd5b505af115801562001f06573d5f803e3d5ffd5b5050505067ffffffffffffffff85165f81815260038501602090815260409182902054915191825263ffffffff8716917f80a6d395a55aed8126079cb8247f0a6848b1440ca2cdca3b4386f250c3529402910160405180910390a3505050505050565b7f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e62001f958162003813565b67ffffffffffffffff85165f9081526083602052604090205463ffffffff161562001fec576040517f6f91fc1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff67ffffffffffffffff8616111562002035576040517f4c753f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff88165f9081526082602052604090205463ffffffff161562002098576040517fd409b93000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608080545f91908290620020b29063ffffffff1662005673565b91906101000a81548163ffffffff021916908363ffffffff160217905590508060835f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508060825f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8363ffffffff1663ffffffff1681526020019081526020015f20905089815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550878160010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555088816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086815f0160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550848160070160106101000a81548160ff0219169083600181111562002290576200229062004d15565b02179055506001856001811115620022ac57620022ac62004d15565b03620022c6576009810184905560058101869055620022d9565b5f80805260028201602052604090208690555b8163ffffffff167fd490df184152edba8455dac3228134939c71f8cb4c8f310c3145dec9037147ac898c8a895f8a6040516200231b9695949392919062005783565b60405180910390a250505050505050505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015620023bc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620023e29190620057de565b6084549091505f906200240e9067ffffffffffffffff680100000000000000008204811691166200575f565b67ffffffffffffffff169050805f036200242a575f9250505090565b62002436818362005823565b9250505090565b606f545f9060ff16156200247d576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f9081526082602052604081205463ffffffff1690819003620024cd576040517f71653c1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8367ffffffffffffffff165f0362002511576040517f2590ccf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff81165f90815260816020526040812060848054919287926200254490849067ffffffffffffffff166200562e565b82546101009290920a67ffffffffffffffff81810219909316918316021790915560068301541690505f6200257a87836200562e565b60068401805467ffffffffffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217909255604080516060810182528a815242841660208083019182528886168385019081525f86815260038c01835285902093518455915160019390930180549251871668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169390961692909217179093555190815291925063ffffffff8616917f1d9f30260051d51d70339da239ea7b080021adcaabfa71c9b0ea339a20cf9a25910160405180910390a29695505050505050565b63ffffffff84165f9081526081602052604090206060906200269b90869086868662004020565b90505b949350505050565b6080545f9063ffffffff16808203620026c057505f919050565b5f8167ffffffffffffffff811115620026dd57620026dd62004dde565b60405190808252806020026020018201604052801562002707578160200160208202803683370190505b5090505f5b82811015620027775760815f6200272583600162005839565b63ffffffff1663ffffffff1681526020019081526020015f20600501548282815181106200275757620027576200584f565b6020908102919091010152806200276e816200587c565b9150506200270c565b505f60205b83600114620029d0575f62002793600286620058b6565b620027a060028762005823565b620027ac919062005839565b90505f8167ffffffffffffffff811115620027cb57620027cb62004dde565b604051908082528060200260200182016040528015620027f5578160200160208202803683370190505b5090505f5b828110156200297c5762002810600184620058cc565b811480156200282b575062002827600288620058b6565b6001145b15620028b357856200283f82600262005659565b815181106200285257620028526200584f565b60200260200101518560405160200162002876929190918252602082015260400190565b60405160208183030381529060405280519060200120828281518110620028a157620028a16200584f565b60200260200101818152505062002967565b85620028c182600262005659565b81518110620028d457620028d46200584f565b602002602001015186826002620028ec919062005659565b620028f990600162005839565b815181106200290c576200290c6200584f565b60200260200101516040516020016200292f929190918252602082015260400190565b604051602081830303815290604052805190602001208282815181106200295a576200295a6200584f565b6020026020010181815250505b8062002973816200587c565b915050620027fa565b508094508195508384604051602001620029a0929190918252602082015260400190565b6040516020818303038152906040528051906020012093508280620029c590620058e2565b93505050506200277c565b5f835f81518110620029e657620029e66200584f565b602002602001015190505f5b8281101562002a84576040805160208101849052908101859052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018790529082018690529250606001604051602081830303815290604052805190602001209350808062002a7b906200587c565b915050620029f2565b5095945050505050565b7fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f59062002aba8162003813565b607e80545f9190829062002ad49063ffffffff1662005673565b91906101000a81548163ffffffff021916908363ffffffff1602179055905060018081111562002b085762002b0862004d15565b86600181111562002b1d5762002b1d62004d15565b0362002b6257841562002b5c576040517f63d722e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62002b9b565b821562002b9b576040517f63d722e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040518060e001604052808a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018867ffffffffffffffff16815260200187600181111562002c035762002c0362004d15565b81525f602080830182905260408084018a9052606093840188905263ffffffff86168352607f8252918290208451815473ffffffffffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617825591850151600182810180549588015167ffffffffffffffff1674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090961692909416919091179390931780835593850151909390927fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116907c010000000000000000000000000000000000000000000000000000000090849081111562002d355762002d3562004d15565b021790555060808201516001820180549115157d010000000000000000000000000000000000000000000000000000000000027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905560a0820151600282015560c09091015160039091015560405163ffffffff8216907f9eaf2ecbddb14889c9e141a63175c55ac25e0cd7cdea312cdfbd0397976b383a9062002dee908c908c908c908c908c908c908c9062005919565b60405180910390a2505050505050505050565b7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac62002e2d8162003813565b62002e3a84848462004137565b50505050565b7f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb62002e6c8162003813565b683635c9adc5dea0000082118062002e875750633b9aca0082105b1562002ebf576040517f8586952500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60868290556040518281527ffb383653f53ee079978d0c9aff7aeff04a10166ce244cca9c9f9d8d96bed45b29060200160405180910390a15050565b5f8281526034602052604090206001015462002f178162003813565b6200116c838362003d9f565b7f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f462002f4f8162003813565b608780547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff16179055604080517fdbc1697600000000000000000000000000000000000000000000000000000000815290517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169163dbc16976916004808301925f92919082900301818387803b15801562003009575f80fd5b505af11580156200301c573d5f803e3d5ffd5b505050506200302a62004586565b50565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af11580156200308f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620030b5919062005741565b73ffffffffffffffffffffffffffffffffffffffff161462003103576040517f696072e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f9081526082602090815260408083205463ffffffff16835260819091529020600681015467ffffffffffffffff80821668010000000000000000909204161462003191576040517fcc862d4a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600781015463ffffffff83166801000000000000000090910467ffffffffffffffff1610620031ec576040517f3e37e23300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080515f8152602081019091526200116c908490849062004137565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4620032358162003813565b63ffffffff87165f90815260816020526040902060016007820154700100000000000000000000000000000000900460ff1660018111156200327b576200327b62004d15565b14620032b3576040517f3a64d97300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f257b3632000000000000000000000000000000000000000000000000000000008152600481018890527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063257b3632906024016020604051808303815f875af11580156200333e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620033649190620057de565b5f036200339d576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f620033ad89838a8a8a62004020565b600183015460098401546040517f41493c6000000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff909116916341493c6091620034139185908a908a906004016200598a565b5f6040518083038186803b1580156200342a575f80fd5b505afa1580156200343d573d5f803e3d5ffd5b5050608480547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004267ffffffffffffffff1602179055505060058201879055600882018690557f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166333d6247d620034dc620026a6565b6040518263ffffffff1660e01b8152600401620034fb91815260200190565b5f604051808303815f87803b15801562003513575f80fd5b505af115801562003526573d5f803e3d5ffd5b5050604080515f80825260208201529081018a905233925063ffffffff8c1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d39060600160405180910390a3505050505050505050565b620035e460408051610180810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290529061016082015290565b63ffffffff82165f90815260816020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff8082168652740100000000000000000000000000000000000000009182900467ffffffffffffffff9081169487019490945260018084015491821695870195909552048216606085015260058101546080850152600681015480831660a086015268010000000000000000808204841660c0870152700100000000000000000000000000000000808304851660e088015278010000000000000000000000000000000000000000000000009092048416610100870152600783015480851661012088015290810490931661014086015290926101608501929190910460ff169081111562003705576200370562004d15565b908160018111156200371b576200371b62004d15565b8152505050919050565b5f54610100900460ff1662001142576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840162000a30565b620011cd828262003ce3565b5f82815260346020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6200302a813362004615565b5f8062003844896006015467ffffffffffffffff680100000000000000009091041690565b60078a015490915067ffffffffffffffff908116908916101562003894576040517fead1340b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff88165f90815260028a016020526040902054915081620038e9576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168867ffffffffffffffff16111562003938576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff161162003986576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f620039978a8a8a8a878b62003e59565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051620039cd9190620059f5565b602060405180830381855afa158015620039e9573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019062003a0e9190620057de565b62003a1a9190620058b6565b60018c01546040805160208101825283815290517f9121da8a00000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff90911691639121da8a9162003a849189919060040162005a12565b602060405180830381865afa15801562003aa0573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062003ac6919062005a4e565b62003afd576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62003b0a848b6200575f565b905062003b71878267ffffffffffffffff1662003b266200232f565b62003b32919062005659565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691906200467e565b80608460088282829054906101000a900467ffffffffffffffff1662003b9891906200562e565b82546101009290920a67ffffffffffffffff818102199093169183160217909155608480547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16700100000000000000000000000000000000428416021790558d546040517f32c2d153000000000000000000000000000000000000000000000000000000008152918d166004830152602482018b905233604483015273ffffffffffffffffffffffffffffffffffffffff1691506332c2d15390606401620018de565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562003cc2575f80fd5b505af115801562003cd5573d5f803e3d5ffd5b50505050620011426200470d565b5f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16620011cd575f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b5f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1615620011cd575f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b67ffffffffffffffff8086165f818152600389016020526040808220549388168252902054606092911580159062003e8f575081155b1562003ec7576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8062003eff576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62003f0a84620047a0565b62003f41576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b885460018a01546040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015260348101889052605481018590527fffffffffffffffff00000000000000000000000000000000000000000000000060c08c811b821660748401527401000000000000000000000000000000000000000094859004811b8216607c84015293909204831b82166084820152608c810187905260ac810184905260cc81018990529189901b1660ec82015260f401604051602081830303815290604052925050509695505050505050565b60605f855f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ad1edf346040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200408f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620040b59190620057de565b60058701546008880154604080516020810193909352820152606081018790527fffffffff0000000000000000000000000000000000000000000000000000000060e08a901b1660808201526084810182905260a4810186905260c4810185905290915060e40160405160208183030381529060405291505095945050505050565b63ffffffff82161580620041565750607e5463ffffffff908116908316115b156200418e576040517f7512e5cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f9081526082602052604081205463ffffffff1690819003620041f4576040517f74a086a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8181165f9081526081602052604090206007810154909185166801000000000000000090910467ffffffffffffffff160362004261576040517f4f61d51900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff84165f908152607f602052604090206001808201547d010000000000000000000000000000000000000000000000000000000000900460ff1615159003620042da576040517f3b8d3d9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001818101547c0100000000000000000000000000000000000000000000000000000000900460ff169081111562004316576200431662004d15565b6007830154700100000000000000000000000000000000900460ff16600181111562004346576200434662004d15565b146200437e576040517fb541abe200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001808201805491840180547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff9094169384178255915467ffffffffffffffff740100000000000000000000000000000000000000009182900416027fffffffff00000000000000000000000000000000000000000000000000000000909216909217179055600381015460098301556007820180546801000000000000000063ffffffff8816027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790555f620044708462000da9565b6007840180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff831617905582546040517f4f1ef28600000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff89811692634f1ef2869262004502921690899060040162005a6f565b5f604051808303815f87803b1580156200451a575f80fd5b505af11580156200452d573d5f803e3d5ffd5b50506040805163ffffffff8a8116825267ffffffffffffffff86166020830152881693507ff585e04c05d396901170247783d3e5f0ee9c1df23072985b50af089f5e48b19d92500160405180910390a250505050505050565b606f5460ff16620045c3576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16620011cd576040517fec2b7c3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526200116c9084906200482c565b606f5460ff16156200474b576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b5f67ffffffff0000000167ffffffffffffffff8316108015620047d8575067ffffffff00000001604083901c67ffffffffffffffff16105b8015620047fa575067ffffffff00000001608083901c67ffffffffffffffff16105b801562004812575067ffffffff0000000160c083901c105b156200482057506001919050565b505f919050565b919050565b5f6200488f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166200493e9092919063ffffffff16565b8051909150156200116c5780806020019051810190620048b0919062005a4e565b6200116c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162000a30565b60606200269e84845f85855f808673ffffffffffffffffffffffffffffffffffffffff168587604051620049739190620059f5565b5f6040518083038185875af1925050503d805f8114620049af576040519150601f19603f3d011682016040523d82523d5f602084013e620049b4565b606091505b509150915062001aa5878383876060831562004a5b5782515f0362004a535773ffffffffffffffffffffffffffffffffffffffff85163b62004a53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000a30565b50816200269e565b6200269e838381511562004a725781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000a30919062005188565b610a5e8062005aa083390190565b73ffffffffffffffffffffffffffffffffffffffff811681146200302a575f80fd5b803567ffffffffffffffff8116811462004827575f80fd5b5f805f805f805f805f806101408b8d03121562004b0b575f80fd5b8a3562004b188162004ab6565b995062004b2860208c0162004ad8565b985062004b3860408c0162004ad8565b975060608b013562004b4a8162004ab6565b965060808b013562004b5c8162004ab6565b955060a08b013562004b6e8162004ab6565b945060c08b013562004b808162004ab6565b935060e08b013562004b928162004ab6565b925062004ba36101008c0162004ad8565b915062004bb46101208c0162004ad8565b90509295989b9194979a5092959850565b803563ffffffff8116811462004827575f80fd5b5f6020828403121562004bea575f80fd5b62004bf58262004bc5565b9392505050565b5f805f805f805f806103e0808a8c03121562004c16575f80fd5b62004c218a62004bc5565b985062004c3160208b0162004ad8565b975062004c4160408b0162004ad8565b965062004c5160608b0162004ad8565b955060808a0135945060a08a0135935060c08a013562004c718162004ab6565b92508981018b101562004c82575f80fd5b5060e0890190509295985092959890939650565b5f6020828403121562004ca7575f80fd5b5035919050565b5f806040838503121562004cc0575f80fd5b62004ccb8362004bc5565b915062004cdb6020840162004ad8565b90509250929050565b5f806040838503121562004cf6575f80fd5b82359150602083013562004d0a8162004ab6565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6002811062004d78577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b73ffffffffffffffffffffffffffffffffffffffff88811682528716602082015267ffffffffffffffff8616604082015260e0810162004dc0606083018762004d42565b931515608082015260a081019290925260c090910152949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f67ffffffffffffffff8084111562004e285762004e2862004dde565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171562004e715762004e7162004dde565b8160405280935085815286868601111562004e8a575f80fd5b858560208301375f602087830101525050509392505050565b5f82601f83011262004eb3575f80fd5b62004bf58383356020850162004e0b565b5f805f805f805f60e0888a03121562004edb575f80fd5b62004ee68862004bc5565b965062004ef66020890162004ad8565b9550604088013562004f088162004ab6565b9450606088013562004f1a8162004ab6565b9350608088013562004f2c8162004ab6565b925060a088013567ffffffffffffffff8082111562004f49575f80fd5b62004f578b838c0162004ea3565b935060c08a013591508082111562004f6d575f80fd5b5062004f7c8a828b0162004ea3565b91505092959891949750929550565b815173ffffffffffffffffffffffffffffffffffffffff1681526101808101602083015162004fc6602084018267ffffffffffffffff169052565b50604083015162004fef604084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060608301516200500c606084018267ffffffffffffffff169052565b506080830151608083015260a08301516200503360a084018267ffffffffffffffff169052565b5060c08301516200505060c084018267ffffffffffffffff169052565b5060e08301516200506d60e084018267ffffffffffffffff169052565b506101008381015167ffffffffffffffff169083015261012080840151620050988285018262004d42565b5050610140838101519083015261016092830151929091019190915290565b5f805f805f8060c08789031215620050cd575f80fd5b620050d88762004bc5565b9550620050e86020880162004ad8565b9450620050f86040880162004ad8565b9350606087013592506080870135915060a087013590509295509295509295565b5f5b83811015620051355781810151838201526020016200511b565b50505f910152565b5f81518084526200515681602086016020860162005119565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f62004bf560208301846200513d565b5f60208284031215620051ad575f80fd5b62004bf58262004ad8565b5f8060408385031215620051ca575f80fd5b823562004ccb8162004ab6565b80356002811062004827575f80fd5b5f805f805f805f60e0888a031215620051fd575f80fd5b87356200520a8162004ab6565b965060208801356200521c8162004ab6565b95506200522c6040890162004ad8565b94506200523c6060890162004ad8565b9350608088013592506200525360a08901620051d7565b915060c0880135905092959891949750929550565b5f80604083850312156200527a575f80fd5b620052858362004ad8565b946020939093013593505050565b5f805f8060808587031215620052a7575f80fd5b620052b28562004bc5565b966020860135965060408601359560600135945092505050565b5f805f805f805f60e0888a031215620052e3575f80fd5b8735620052f08162004ab6565b96506020880135620053028162004ab6565b9550620053126040890162004ad8565b94506200532260608901620051d7565b93506080880135925060a088013567ffffffffffffffff81111562005345575f80fd5b620053538a828b0162004ea3565b92505060c0880135905092959891949750929550565b5f805f606084860312156200537c575f80fd5b8335620053898162004ab6565b9250620053996020850162004bc5565b9150604084013567ffffffffffffffff811115620053b5575f80fd5b8401601f81018613620053c6575f80fd5b620053d78682356020840162004e0b565b9150509250925092565b5f60208284031215620053f2575f80fd5b813562004bf58162004ab6565b5f806040838503121562005411575f80fd5b82356200541e8162004ab6565b915062004cdb6020840162004bc5565b5f805f805f8060a0878903121562005444575f80fd5b6200544f8762004bc5565b9550602087013594506040870135935060608701359250608087013567ffffffffffffffff8082111562005481575f80fd5b818901915089601f83011262005495575f80fd5b813581811115620054a4575f80fd5b8a6020828501011115620054b6575f80fd5b6020830194508093505050509295509295509295565b815173ffffffffffffffffffffffffffffffffffffffff1681526101808101602083015162005507602084018267ffffffffffffffff169052565b50604083015162005530604084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060608301516200554d606084018267ffffffffffffffff169052565b506080830151608083015260a08301516200557460a084018267ffffffffffffffff169052565b5060c08301516200559160c084018267ffffffffffffffff169052565b5060e0830151620055ae60e084018267ffffffffffffffff169052565b506101008381015167ffffffffffffffff9081169184019190915261012080850151821690840152610140808501519091169083015261016080840151620055f98285018262004d42565b505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff81811683821601908082111562005652576200565262005601565b5092915050565b808202811582820484141762000dd85762000dd862005601565b5f63ffffffff8083168181036200568e576200568e62005601565b6001019392505050565b5f73ffffffffffffffffffffffffffffffffffffffff8086168352808516602084015250606060408301526200269b60608301846200513d565b5f73ffffffffffffffffffffffffffffffffffffffff8089168352808816602084015263ffffffff8716604084015280861660608401525060c060808301526200572060c08301856200513d565b82810360a08401526200573481856200513d565b9998505050505050505050565b5f6020828403121562005752575f80fd5b815162004bf58162004ab6565b67ffffffffffffffff82811682821603908082111562005652576200565262005601565b67ffffffffffffffff878116825273ffffffffffffffffffffffffffffffffffffffff87166020830152858116604083015260c0820190620057c9606084018762004d42565b93909316608082015260a00152949350505050565b5f60208284031215620057ef575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f82620058345762005834620057f6565b500490565b8082018082111562000dd85762000dd862005601565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620058af57620058af62005601565b5060010190565b5f82620058c757620058c7620057f6565b500690565b8181038181111562000dd85762000dd862005601565b5f81620058f357620058f362005601565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b73ffffffffffffffffffffffffffffffffffffffff88811682528716602082015267ffffffffffffffff861660408201525f6200595a606083018762004d42565b84608083015260e060a08301526200597660e08301856200513d565b90508260c083015298975050505050505050565b848152606060208201525f620059a460608301866200513d565b8281036040840152838152838560208301375f6020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011682010191505095945050505050565b5f825162005a0881846020870162005119565b9190910192915050565b6103208101610300808584378201835f5b600181101562005a4457815183526020928301929091019060010162005a23565b5050509392505050565b5f6020828403121562005a5f575f80fd5b8151801515811462004bf5575f80fd5b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201525f6200269e60408301846200513d56fe60a060405260405162000a5e38038062000a5e833981016040819052620000269162000375565b828162000034828262000060565b50506001600160a01b038216608052620000576200005160805190565b620000c5565b5050506200046c565b6200006b8262000136565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000b757620000b28282620001b5565b505050565b620000c16200022e565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620001065f8051602062000a3e833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001338162000250565b50565b806001600160a01b03163b5f036200017157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b031684604051620001d391906200044f565b5f60405180830381855af49150503d805f81146200020d576040519150601f19603f3d011682016040523d82523d5f602084013e62000212565b606091505b5090925090506200022585838362000291565b95945050505050565b34156200024e5760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b0381166200027b57604051633173bdd160e11b81525f600482015260240162000168565b805f8051602062000a3e83398151915262000194565b606082620002aa57620002a482620002f7565b620002f0565b8151158015620002c257506001600160a01b0384163b155b15620002ed57604051639996b31560e01b81526001600160a01b038516600482015260240162000168565b50805b9392505050565b805115620003085780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811462000338575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b838110156200036d57818101518382015260200162000353565b50505f910152565b5f805f6060848603121562000388575f80fd5b620003938462000321565b9250620003a36020850162000321565b60408501519092506001600160401b0380821115620003c0575f80fd5b818601915086601f830112620003d4575f80fd5b815181811115620003e957620003e96200033d565b604051601f8201601f19908116603f011681019083821181831017156200041457620004146200033d565b816040528281528960208487010111156200042d575f80fd5b6200044083602083016020880162000351565b80955050505050509250925092565b5f82516200046281846020870162000351565b9190910192915050565b6080516105ba620004845f395f601001526105ba5ff3fe608060405261000c61000e565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633036100a7575f357fffffffff00000000000000000000000000000000000000000000000000000000167f4f1ef286000000000000000000000000000000000000000000000000000000001461009f5761009d6100ab565b565b61009d6100bb565b61009d5b61009d6100b66100e9565b61012d565b5f806100ca3660048184610410565b8101906100d79190610464565b915091506100e5828261014b565b5050565b5f6101287f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e808015610147573d5ff35b3d5ffd5b610154826101b2565b60405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101aa576101a58282610285565b505050565b6100e5610304565b8073ffffffffffffffffffffffffffffffffffffffff163b5f0361021f576040517f4c9c8ce300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60605f808473ffffffffffffffffffffffffffffffffffffffff16846040516102ae9190610558565b5f60405180830381855af49150503d805f81146102e6576040519150601f19603f3d011682016040523d82523d5f602084013e6102eb565b606091505b50915091506102fb85838361033c565b95945050505050565b341561009d576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060826103515761034c826103ce565b6103c7565b8151158015610375575073ffffffffffffffffffffffffffffffffffffffff84163b155b156103c4576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610216565b50805b9392505050565b8051156103de5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808585111561041e575f80fd5b8386111561042a575f80fd5b5050820193919092039150565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f8060408385031215610475575f80fd5b823573ffffffffffffffffffffffffffffffffffffffff81168114610498575f80fd5b9150602083013567ffffffffffffffff808211156104b4575f80fd5b818501915085601f8301126104c7575f80fd5b8135818111156104d9576104d9610437565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561051f5761051f610437565b81604052828152886020848701011115610537575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610577576020818601810151858301520161055d565b505f92019182525091905056fea26469706673582212200ca61bd1e45d482203caba1d216b11bb6992f1ce0f6427bfe86e65b2f53457a264736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103a264697066735822122070e0184cb0298270cb77d252235752ad92c48991a113c85600c93d56d7d33b3664736f6c63430008140033", + "deployedBytecode": "0x608060405234801562000010575f80fd5b506004361062000320575f3560e01c806391d1485411620001a7578063ceee281d11620000ef578063dde0ff77116200009f578063e4a4b6a21162000077578063e4a4b6a21462000938578063f4e92675146200094f578063f9c4c2ae1462000960575f80fd5b8063dde0ff7714620008d8578063dfdb8c5e14620008f9578063e46761c41462000910575f80fd5b8063d5073f6f11620000d3578063d5073f6f14620008a0578063d547741f14620008b7578063dbc1697614620008ce575f80fd5b8063ceee281d1462000850578063d02103ca1462000878575f80fd5b8063a217fddf1162000157578063abcb5198116200012f578063abcb519814620007f9578063c1acbc341462000810578063c4c928c21462000839575f80fd5b8063a217fddf1462000799578063a2967d9914620007a1578063a3c573eb14620007ab575f80fd5b806399f5634e116200018b57806399f5634e14620007615780639a908e73146200076b5780639e36c5651462000782575f80fd5b806391d14854146200070257806397bf07e8146200074a575f80fd5b806336568abe116200026b5780637222020f116200021b5780637975fcfe11620001f35780637975fcfe146200069d5780637fb6e76a14620006c35780638fd88cc214620006eb575f80fd5b80637222020f1462000649578063727885e9146200066057806374d9c2441462000677575f80fd5b806355a71ee0116200024f57806355a71ee0146200052957806360469169146200056d57806365c0504d1462000577575f80fd5b806336568abe1462000509578063477fa2701462000520575f80fd5b80631796a1ae11620002d35780632528016911620002ab5780632528016914620004225780632f2ff15d14620004dd57806330c27dde14620004f4575f80fd5b80631796a1ae14620003bd5780632072f6c514620003e4578063248a9ca314620003ee575f80fd5b806311f6b287116200030757806311f6b28714620003705780631489ed10146200038757806315064c96146200039e575f80fd5b80630645af091462000324578063066ec012146200033d575b5f80fd5b6200033b6200033536600462004af0565b62000986565b005b608454620003529067ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b620003526200038136600462004bd9565b62000da9565b6200033b6200039836600462004bfc565b62000dde565b606f54620003ac9060ff1681565b604051901515815260200162000367565b607e54620003ce9063ffffffff1681565b60405163ffffffff909116815260200162000367565b6200033b62001030565b62000413620003ff36600462004c96565b5f9081526034602052604090206001015490565b60405190815260200162000367565b620004a86200043336600462004cae565b60408051606080820183525f808352602080840182905292840181905263ffffffff9590951685526081825282852067ffffffffffffffff9485168652600301825293829020825194850183528054855260010154808416918501919091526801000000000000000090049091169082015290565b604080518251815260208084015167ffffffffffffffff90811691830191909152928201519092169082015260600162000367565b6200033b620004ee36600462004ce4565b62001144565b608754620003529067ffffffffffffffff1681565b6200033b6200051a36600462004ce4565b62001171565b60865462000413565b620004136200053a36600462004cae565b63ffffffff82165f90815260816020908152604080832067ffffffffffffffff8516845260020190915290205492915050565b62000413620011d1565b620006346200058836600462004bd9565b607f6020525f9081526040902080546001820154600283015460039093015473ffffffffffffffffffffffffffffffffffffffff928316939282169267ffffffffffffffff740100000000000000000000000000000000000000008404169260ff7c010000000000000000000000000000000000000000000000000000000082048116937d01000000000000000000000000000000000000000000000000000000000090920416919087565b60405162000367979695949392919062004d7c565b6200033b6200065a36600462004bd9565b620011e8565b6200033b6200067136600462004ec4565b62001363565b6200068e6200068836600462004bd9565b6200191b565b60405162000367919062004f8b565b620006b4620006ae366004620050b7565b62001a7e565b60405162000367919062005188565b620003ce620006d43660046200519c565b60836020525f908152604090205463ffffffff1681565b6200033b620006fc366004620051b8565b62001ab0565b620003ac6200071336600462004ce4565b5f91825260346020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b6200033b6200075b366004620051e6565b62001f69565b620004136200232f565b620003526200077c36600462005268565b6200243d565b620006b46200079336600462005293565b62002674565b620004135f81565b62000413620026a6565b620007d37f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200162000367565b6200033b6200080a366004620052cc565b62002a8e565b6084546200035290700100000000000000000000000000000000900467ffffffffffffffff1681565b6200033b6200084a36600462005369565b62002e01565b620003ce62000861366004620053e1565b60826020525f908152604090205463ffffffff1681565b620007d37f000000000000000000000000000000000000000000000000000000000000000081565b6200033b620008b136600462004c96565b62002e40565b6200033b620008c836600462004ce4565b62002efb565b6200033b62002f23565b608454620003529068010000000000000000900467ffffffffffffffff1681565b6200033b6200090a366004620053ff565b6200302d565b620007d37f000000000000000000000000000000000000000000000000000000000000000081565b6200033b620009493660046200542e565b62003209565b608054620003ce9063ffffffff1681565b620009776200097136600462004bd9565b6200357f565b604051620003679190620054cc565b5f54600290610100900460ff16158015620009a757505f5460ff8083169116105b62000a39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001660ff83161761010017905567016345785d8a000060865562000a7f62003725565b62000aab7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd48c620037bd565b62000ab75f88620037bd565b62000ae37fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f59088620037bd565b62000b0f7f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e88620037bd565b62000b3b7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac88620037bd565b62000b677fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd89620037bd565b62000b937fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd0889620037bd565b62000bbf7f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f489620037bd565b62000beb7fa5c5790f581d443ed43873ab47cfb8c5d66a6db268e58b5971bb33fc66e07db189620037bd565b62000c377f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd47f73cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f0620037c9565b62000c637f73cb0569fdbea2544dae03fdb2fe10eda92a72a2e8cd2bd496e85b762505a3f089620037bd565b62000c8f7f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb89620037bd565b62000cdb7f141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545e7f9b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff285951620037c9565b62000d077f141f8f32ce6198eee741f695cec728bfd32d289f1acf73621fb303581000545e87620037bd565b62000d337f9b6f082d8d3644ae2f24a3c32e356d6f2d9b2844d9b26164fbc82663ff28595187620037bd565b62000d3f5f33620037bd565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050505050505050505050565b63ffffffff81165f9081526081602052604081206006015468010000000000000000900467ffffffffffffffff165b92915050565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd462000e0a8162003813565b67ffffffffffffffff88161562000e4d576040517f60dbf8ae00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff89165f908152608160205260408120906007820154700100000000000000000000000000000000900460ff16600181111562000e925762000e9262004d15565b1462000eca576040517f90db0d0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000edb818989898989896200381f565b6006810180547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8a16908102919091179091555f9081526002820160205260409020859055600581018690557f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166333d6247d62000f81620026a6565b6040518263ffffffff1660e01b815260040162000fa091815260200190565b5f604051808303815f87803b15801562000fb8575f80fd5b505af115801562000fcb573d5f803e3d5ffd5b50506040805167ffffffffffffffff8b1681526020810189905290810189905233925063ffffffff8d1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d39060600160405180910390a350505050505050505050565b335f9081527f8875b94af5657a2903def9906d67a3f42d8a836d24b5602c00f00fc855339fcd602052604090205460ff166200113857608454700100000000000000000000000000000000900467ffffffffffffffff161580620010ce57506084544290620010c29062093a8090700100000000000000000000000000000000900467ffffffffffffffff166200562e565b67ffffffffffffffff16115b806200110057506087544290620010f49062093a809067ffffffffffffffff166200562e565b67ffffffffffffffff16115b1562001138576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6200114262003c5c565b565b5f82815260346020526040902060010154620011608162003813565b6200116c838362003ce3565b505050565b73ffffffffffffffffffffffffffffffffffffffff81163314620011c1576040517f5a568e6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620011cd828262003d9f565b5050565b5f6086546064620011e3919062005659565b905090565b7fab66e11c4f712cd06ab11bf9339b48bef39e12d4a22eeef71d2860a0c90482bd620012148162003813565b63ffffffff82161580620012335750607e5463ffffffff908116908316115b156200126b576040517f7512e5cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff82165f908152607f602052604090206001808201547d010000000000000000000000000000000000000000000000000000000000900460ff1615159003620012e4576040517f3b8d3d9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001810180547fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167d01000000000000000000000000000000000000000000000000000000000017905560405163ffffffff8416907f4710d2ee567ef1ed6eb2f651dde4589524bcf7cebc62147a99b281cc836e7e44905f90a2505050565b7fa0fab074aba36a6fa69f1a83ee86e5abfb8433966eb57efb13dc2fc2f24ddd086200138f8162003813565b63ffffffff88161580620013ae5750607e5463ffffffff908116908916115b15620013e6576040517f7512e5cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff88165f908152607f602052604090206001808201547d010000000000000000000000000000000000000000000000000000000000900460ff16151590036200145f576040517f3b8d3d9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff67ffffffffffffffff89161115620014a8576040517f4c753f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff88165f9081526083602052604090205463ffffffff1615620014ff576040517f6f91fc1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608080545f91908290620015199063ffffffff1662005673565b825463ffffffff8281166101009490940a93840293021916919091179091558254604080515f808252602082019283905293945073ffffffffffffffffffffffffffffffffffffffff909216913091620015739062004aa8565b620015819392919062005698565b604051809103905ff0801580156200159b573d5f803e3d5ffd5b5090508160835f8c67ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508160825f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8463ffffffff1663ffffffff1681526020019081526020015f20905081815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508360010160149054906101000a900467ffffffffffffffff168160010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550836001015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508a815f0160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508360020154816002015f8067ffffffffffffffff1681526020019081526020015f20819055508b63ffffffff168160070160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555083600101601c9054906101000a900460ff168160070160106101000a81548160ff0219169083600181111562001800576200180062004d15565b0217905550600384015460098201556040805163ffffffff8e8116825273ffffffffffffffffffffffffffffffffffffffff858116602084015267ffffffffffffffff8f16838501528b1660608301529151918516917f194c983456df6701c6a50830b90fe80e72b823411d0d524970c9590dc277a6419181900360800190a26040517f7125702200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831690637125702290620018de908d908d9088908e908e908e90600401620056d2565b5f604051808303815f87803b158015620018f6575f80fd5b505af115801562001909573d5f803e3d5ffd5b50505050505050505050505050505050565b60408051610180810182525f8082526020808301828152838501838152606085018481526080860185815260a0870186815260c0880187815260e089018881526101008a018981526101208b018a81526101408c018b90526101608c018b905263ffffffff8e168b5260819099529a909820805473ffffffffffffffffffffffffffffffffffffffff8082168c52740100000000000000000000000000000000000000009182900467ffffffffffffffff90811690995260018084015491821690985204871690945260058401549092526006830154808616909152680100000000000000009081900485169091526007820154808516909652850490921690955292939091700100000000000000000000000000000000900460ff169081111562001a4b5762001a4b62004d15565b9081600181111562001a615762001a6162004d15565b905250600881015461014083015260090154610160820152919050565b63ffffffff86165f90815260816020526040902060609062001aa590878787878762003e59565b979650505050505050565b335f9081527ff14f5a8ad59d90593602e905b358229bff5ceea677d5bf0f5a1701793550a9a6602052604090205460ff1615801562001b8b57503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af115801562001b4c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001b72919062005741565b73ffffffffffffffffffffffffffffffffffffffff1614155b1562001bc3576040517f1a06d0fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f9081526082602052604081205463ffffffff169081900362001c29576040517f74a086a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff81165f908152608160205260408120906007820154700100000000000000000000000000000000900460ff16600181111562001c6e5762001c6e62004d15565b1462001ca6576040517f90db0d0700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600681015467ffffffffffffffff9081169084168111158062001ce65750600682015467ffffffffffffffff680100000000000000009091048116908516105b1562001d1e576040517fcb23ebdf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805b8467ffffffffffffffff168167ffffffffffffffff161462001df35767ffffffffffffffff8082165f908152600385016020526040902060010154680100000000000000009004811690861681101562001da6576040517f9753965f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff9091165f908152600384016020526040812090815560010180547fffffffffffffffffffffffffffffffff0000000000000000000000000000000016905562001d20565b6006830180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff871617905562001e3585836200575f565b608480545f9062001e5290849067ffffffffffffffff166200575f565b82546101009290920a67ffffffffffffffff81810219909316918316021790915586165f818152600386016020526040908190205490517f669adece0000000000000000000000000000000000000000000000000000000081526004810192909252602482015273ffffffffffffffffffffffffffffffffffffffff8816915063669adece906044015f604051808303815f87803b15801562001ef3575f80fd5b505af115801562001f06573d5f803e3d5ffd5b5050505067ffffffffffffffff85165f81815260038501602090815260409182902054915191825263ffffffff8716917f80a6d395a55aed8126079cb8247f0a6848b1440ca2cdca3b4386f250c3529402910160405180910390a3505050505050565b7f3dfe277d2a2c04b75fb2eb3743fa00005ae3678a20c299e65fdf4df76517f68e62001f958162003813565b67ffffffffffffffff85165f9081526083602052604090205463ffffffff161562001fec576040517f6f91fc1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff67ffffffffffffffff8616111562002035576040517f4c753f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff88165f9081526082602052604090205463ffffffff161562002098576040517fd409b93000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608080545f91908290620020b29063ffffffff1662005673565b91906101000a81548163ffffffff021916908363ffffffff160217905590508060835f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055508060825f8b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548163ffffffff021916908363ffffffff1602179055505f60815f8363ffffffff1663ffffffff1681526020019081526020015f20905089815f015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550878160010160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555088816001015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086815f0160146101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550848160070160106101000a81548160ff0219169083600181111562002290576200229062004d15565b02179055506001856001811115620022ac57620022ac62004d15565b03620022c6576009810184905560058101869055620022d9565b5f80805260028201602052604090208690555b8163ffffffff167fd490df184152edba8455dac3228134939c71f8cb4c8f310c3145dec9037147ac898c8a895f8a6040516200231b9695949392919062005783565b60405180910390a250505050505050505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015620023bc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620023e29190620057de565b6084549091505f906200240e9067ffffffffffffffff680100000000000000008204811691166200575f565b67ffffffffffffffff169050805f036200242a575f9250505090565b62002436818362005823565b9250505090565b606f545f9060ff16156200247d576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b335f9081526082602052604081205463ffffffff1690819003620024cd576040517f71653c1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8367ffffffffffffffff165f0362002511576040517f2590ccf900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff81165f90815260816020526040812060848054919287926200254490849067ffffffffffffffff166200562e565b82546101009290920a67ffffffffffffffff81810219909316918316021790915560068301541690505f6200257a87836200562e565b60068401805467ffffffffffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217909255604080516060810182528a815242841660208083019182528886168385019081525f86815260038c01835285902093518455915160019390930180549251871668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169390961692909217179093555190815291925063ffffffff8616917f1d9f30260051d51d70339da239ea7b080021adcaabfa71c9b0ea339a20cf9a25910160405180910390a29695505050505050565b63ffffffff84165f9081526081602052604090206060906200269b90869086868662004020565b90505b949350505050565b6080545f9063ffffffff16808203620026c057505f919050565b5f8167ffffffffffffffff811115620026dd57620026dd62004dde565b60405190808252806020026020018201604052801562002707578160200160208202803683370190505b5090505f5b82811015620027775760815f6200272583600162005839565b63ffffffff1663ffffffff1681526020019081526020015f20600501548282815181106200275757620027576200584f565b6020908102919091010152806200276e816200587c565b9150506200270c565b505f60205b83600114620029d0575f62002793600286620058b6565b620027a060028762005823565b620027ac919062005839565b90505f8167ffffffffffffffff811115620027cb57620027cb62004dde565b604051908082528060200260200182016040528015620027f5578160200160208202803683370190505b5090505f5b828110156200297c5762002810600184620058cc565b811480156200282b575062002827600288620058b6565b6001145b15620028b357856200283f82600262005659565b815181106200285257620028526200584f565b60200260200101518560405160200162002876929190918252602082015260400190565b60405160208183030381529060405280519060200120828281518110620028a157620028a16200584f565b60200260200101818152505062002967565b85620028c182600262005659565b81518110620028d457620028d46200584f565b602002602001015186826002620028ec919062005659565b620028f990600162005839565b815181106200290c576200290c6200584f565b60200260200101516040516020016200292f929190918252602082015260400190565b604051602081830303815290604052805190602001208282815181106200295a576200295a6200584f565b6020026020010181815250505b8062002973816200587c565b915050620027fa565b508094508195508384604051602001620029a0929190918252602082015260400190565b6040516020818303038152906040528051906020012093508280620029c590620058e2565b93505050506200277c565b5f835f81518110620029e657620029e66200584f565b602002602001015190505f5b8281101562002a84576040805160208101849052908101859052606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083018790529082018690529250606001604051602081830303815290604052805190602001209350808062002a7b906200587c565b915050620029f2565b5095945050505050565b7fac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f59062002aba8162003813565b607e80545f9190829062002ad49063ffffffff1662005673565b91906101000a81548163ffffffff021916908363ffffffff1602179055905060018081111562002b085762002b0862004d15565b86600181111562002b1d5762002b1d62004d15565b0362002b6257841562002b5c576040517f63d722e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62002b9b565b821562002b9b576040517f63d722e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040518060e001604052808a73ffffffffffffffffffffffffffffffffffffffff1681526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018867ffffffffffffffff16815260200187600181111562002c035762002c0362004d15565b81525f602080830182905260408084018a9052606093840188905263ffffffff86168352607f8252918290208451815473ffffffffffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff000000000000000000000000000000000000000090911617825591850151600182810180549588015167ffffffffffffffff1674010000000000000000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090961692909416919091179390931780835593850151909390927fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116907c010000000000000000000000000000000000000000000000000000000090849081111562002d355762002d3562004d15565b021790555060808201516001820180549115157d010000000000000000000000000000000000000000000000000000000000027fffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905560a0820151600282015560c09091015160039091015560405163ffffffff8216907f9eaf2ecbddb14889c9e141a63175c55ac25e0cd7cdea312cdfbd0397976b383a9062002dee908c908c908c908c908c908c908c9062005919565b60405180910390a2505050505050505050565b7f66156603fe29d13f97c6f3e3dff4ef71919f9aa61c555be0182d954e94221aac62002e2d8162003813565b62002e3a84848462004137565b50505050565b7f8cf807f6970720f8e2c208c7c5037595982c7bd9ed93c380d09df743d0dcc3fb62002e6c8162003813565b683635c9adc5dea0000082118062002e875750633b9aca0082105b1562002ebf576040517f8586952500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60868290556040518281527ffb383653f53ee079978d0c9aff7aeff04a10166ce244cca9c9f9d8d96bed45b29060200160405180910390a15050565b5f8281526034602052604090206001015462002f178162003813565b6200116c838362003d9f565b7f62ba6ba2ffed8cfe316b583325ea41ac6e7ba9e5864d2bc6fabba7ac26d2f0f462002f4f8162003813565b608780547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000164267ffffffffffffffff16179055604080517fdbc1697600000000000000000000000000000000000000000000000000000000815290517f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169163dbc16976916004808301925f92919082900301818387803b15801562003009575f80fd5b505af11580156200301c573d5f803e3d5ffd5b505050506200302a62004586565b50565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1663f851a4406040518163ffffffff1660e01b81526004016020604051808303815f875af11580156200308f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620030b5919062005741565b73ffffffffffffffffffffffffffffffffffffffff161462003103576040517f696072e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82165f9081526082602090815260408083205463ffffffff16835260819091529020600681015467ffffffffffffffff80821668010000000000000000909204161462003191576040517fcc862d4a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600781015463ffffffff83166801000000000000000090910467ffffffffffffffff1610620031ec576040517f3e37e23300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080515f8152602081019091526200116c908490849062004137565b7f084e94f375e9d647f87f5b2ceffba1e062c70f6009fdbcf80291e803b5c9edd4620032358162003813565b63ffffffff87165f90815260816020526040902060016007820154700100000000000000000000000000000000900460ff1660018111156200327b576200327b62004d15565b14620032b3576040517f3a64d97300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f257b3632000000000000000000000000000000000000000000000000000000008152600481018890527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063257b3632906024016020604051808303815f875af11580156200333e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620033649190620057de565b5f036200339d576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f620033ad89838a8a8a62004020565b600183015460098401546040517f41493c6000000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff909116916341493c6091620034139185908a908a906004016200598a565b5f6040518083038186803b1580156200342a575f80fd5b505afa1580156200343d573d5f803e3d5ffd5b5050608480547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004267ffffffffffffffff1602179055505060058201879055600882018690557f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166333d6247d620034dc620026a6565b6040518263ffffffff1660e01b8152600401620034fb91815260200190565b5f604051808303815f87803b15801562003513575f80fd5b505af115801562003526573d5f803e3d5ffd5b5050604080515f80825260208201529081018a905233925063ffffffff8c1691507fd1ec3a1216f08b6eff72e169ceb548b782db18a6614852618d86bb19f3f9b0d39060600160405180910390a3505050505050505050565b620035e460408051610180810182525f80825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290529061016082015290565b63ffffffff82165f90815260816020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff8082168652740100000000000000000000000000000000000000009182900467ffffffffffffffff9081169487019490945260018084015491821695870195909552048216606085015260058101546080850152600681015480831660a086015268010000000000000000808204841660c0870152700100000000000000000000000000000000808304851660e088015278010000000000000000000000000000000000000000000000009092048416610100870152600783015480851661012088015290810490931661014086015290926101608501929190910460ff169081111562003705576200370562004d15565b908160018111156200371b576200371b62004d15565b8152505050919050565b5f54610100900460ff1662001142576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e67000000000000000000000000000000000000000000606482015260840162000a30565b620011cd828262003ce3565b5f82815260346020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6200302a813362004615565b5f8062003844896006015467ffffffffffffffff680100000000000000009091041690565b60078a015490915067ffffffffffffffff908116908916101562003894576040517fead1340b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff88165f90815260028a016020526040902054915081620038e9576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168867ffffffffffffffff16111562003938576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff161162003986576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f620039978a8a8a8a878b62003e59565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051620039cd9190620059f5565b602060405180830381855afa158015620039e9573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019062003a0e9190620057de565b62003a1a9190620058b6565b60018c01546040805160208101825283815290517f9121da8a00000000000000000000000000000000000000000000000000000000815292935073ffffffffffffffffffffffffffffffffffffffff90911691639121da8a9162003a849189919060040162005a12565b602060405180830381865afa15801562003aa0573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062003ac6919062005a4e565b62003afd576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62003b0a848b6200575f565b905062003b71878267ffffffffffffffff1662003b266200232f565b62003b32919062005659565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691906200467e565b80608460088282829054906101000a900467ffffffffffffffff1662003b9891906200562e565b82546101009290920a67ffffffffffffffff818102199093169183160217909155608480547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16700100000000000000000000000000000000428416021790558d546040517f32c2d153000000000000000000000000000000000000000000000000000000008152918d166004830152602482018b905233604483015273ffffffffffffffffffffffffffffffffffffffff1691506332c2d15390606401620018de565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b15801562003cc2575f80fd5b505af115801562003cd5573d5f803e3d5ffd5b50505050620011426200470d565b5f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16620011cd575f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905551339285917f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9190a45050565b5f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff1615620011cd575f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b67ffffffffffffffff8086165f818152600389016020526040808220549388168252902054606092911580159062003e8f575081155b1562003ec7576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8062003eff576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62003f0a84620047a0565b62003f41576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b885460018a01546040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015260348101889052605481018590527fffffffffffffffff00000000000000000000000000000000000000000000000060c08c811b821660748401527401000000000000000000000000000000000000000094859004811b8216607c84015293909204831b82166084820152608c810187905260ac810184905260cc81018990529189901b1660ec82015260f401604051602081830303815290604052925050509695505050505050565b60605f855f015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663ad1edf346040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200408f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620040b59190620057de565b60058701546008880154604080516020810193909352820152606081018790527fffffffff0000000000000000000000000000000000000000000000000000000060e08a901b1660808201526084810182905260a4810186905260c4810185905290915060e40160405160208183030381529060405291505095945050505050565b63ffffffff82161580620041565750607e5463ffffffff908116908316115b156200418e576040517f7512e5cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83165f9081526082602052604081205463ffffffff1690819003620041f4576040517f74a086a300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff8181165f9081526081602052604090206007810154909185166801000000000000000090910467ffffffffffffffff160362004261576040517f4f61d51900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b63ffffffff84165f908152607f602052604090206001808201547d010000000000000000000000000000000000000000000000000000000000900460ff1615159003620042da576040517f3b8d3d9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001818101547c0100000000000000000000000000000000000000000000000000000000900460ff169081111562004316576200431662004d15565b6007830154700100000000000000000000000000000000900460ff16600181111562004346576200434662004d15565b146200437e576040517fb541abe200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001808201805491840180547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff9094169384178255915467ffffffffffffffff740100000000000000000000000000000000000000009182900416027fffffffff00000000000000000000000000000000000000000000000000000000909216909217179055600381015460098301556007820180546801000000000000000063ffffffff8816027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790555f620044708462000da9565b6007840180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff831617905582546040517f4f1ef28600000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff89811692634f1ef2869262004502921690899060040162005a6f565b5f604051808303815f87803b1580156200451a575f80fd5b505af11580156200452d573d5f803e3d5ffd5b50506040805163ffffffff8a8116825267ffffffffffffffff86166020830152881693507ff585e04c05d396901170247783d3e5f0ee9c1df23072985b50af089f5e48b19d92500160405180910390a250505050505050565b606f5460ff16620045c3576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f82815260346020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16620011cd576040517fec2b7c3e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526200116c9084906200482c565b606f5460ff16156200474b576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b5f67ffffffff0000000167ffffffffffffffff8316108015620047d8575067ffffffff00000001604083901c67ffffffffffffffff16105b8015620047fa575067ffffffff00000001608083901c67ffffffffffffffff16105b801562004812575067ffffffff0000000160c083901c105b156200482057506001919050565b505f919050565b919050565b5f6200488f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166200493e9092919063ffffffff16565b8051909150156200116c5780806020019051810190620048b0919062005a4e565b6200116c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162000a30565b60606200269e84845f85855f808673ffffffffffffffffffffffffffffffffffffffff168587604051620049739190620059f5565b5f6040518083038185875af1925050503d805f8114620049af576040519150601f19603f3d011682016040523d82523d5f602084013e620049b4565b606091505b509150915062001aa5878383876060831562004a5b5782515f0362004a535773ffffffffffffffffffffffffffffffffffffffff85163b62004a53576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000a30565b50816200269e565b6200269e838381511562004a725781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000a30919062005188565b610a5e8062005aa083390190565b73ffffffffffffffffffffffffffffffffffffffff811681146200302a575f80fd5b803567ffffffffffffffff8116811462004827575f80fd5b5f805f805f805f805f806101408b8d03121562004b0b575f80fd5b8a3562004b188162004ab6565b995062004b2860208c0162004ad8565b985062004b3860408c0162004ad8565b975060608b013562004b4a8162004ab6565b965060808b013562004b5c8162004ab6565b955060a08b013562004b6e8162004ab6565b945060c08b013562004b808162004ab6565b935060e08b013562004b928162004ab6565b925062004ba36101008c0162004ad8565b915062004bb46101208c0162004ad8565b90509295989b9194979a5092959850565b803563ffffffff8116811462004827575f80fd5b5f6020828403121562004bea575f80fd5b62004bf58262004bc5565b9392505050565b5f805f805f805f806103e0808a8c03121562004c16575f80fd5b62004c218a62004bc5565b985062004c3160208b0162004ad8565b975062004c4160408b0162004ad8565b965062004c5160608b0162004ad8565b955060808a0135945060a08a0135935060c08a013562004c718162004ab6565b92508981018b101562004c82575f80fd5b5060e0890190509295985092959890939650565b5f6020828403121562004ca7575f80fd5b5035919050565b5f806040838503121562004cc0575f80fd5b62004ccb8362004bc5565b915062004cdb6020840162004ad8565b90509250929050565b5f806040838503121562004cf6575f80fd5b82359150602083013562004d0a8162004ab6565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b6002811062004d78577f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b9052565b73ffffffffffffffffffffffffffffffffffffffff88811682528716602082015267ffffffffffffffff8616604082015260e0810162004dc0606083018762004d42565b931515608082015260a081019290925260c090910152949350505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f67ffffffffffffffff8084111562004e285762004e2862004dde565b604051601f85017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171562004e715762004e7162004dde565b8160405280935085815286868601111562004e8a575f80fd5b858560208301375f602087830101525050509392505050565b5f82601f83011262004eb3575f80fd5b62004bf58383356020850162004e0b565b5f805f805f805f60e0888a03121562004edb575f80fd5b62004ee68862004bc5565b965062004ef66020890162004ad8565b9550604088013562004f088162004ab6565b9450606088013562004f1a8162004ab6565b9350608088013562004f2c8162004ab6565b925060a088013567ffffffffffffffff8082111562004f49575f80fd5b62004f578b838c0162004ea3565b935060c08a013591508082111562004f6d575f80fd5b5062004f7c8a828b0162004ea3565b91505092959891949750929550565b815173ffffffffffffffffffffffffffffffffffffffff1681526101808101602083015162004fc6602084018267ffffffffffffffff169052565b50604083015162004fef604084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060608301516200500c606084018267ffffffffffffffff169052565b506080830151608083015260a08301516200503360a084018267ffffffffffffffff169052565b5060c08301516200505060c084018267ffffffffffffffff169052565b5060e08301516200506d60e084018267ffffffffffffffff169052565b506101008381015167ffffffffffffffff169083015261012080840151620050988285018262004d42565b5050610140838101519083015261016092830151929091019190915290565b5f805f805f8060c08789031215620050cd575f80fd5b620050d88762004bc5565b9550620050e86020880162004ad8565b9450620050f86040880162004ad8565b9350606087013592506080870135915060a087013590509295509295509295565b5f5b83811015620051355781810151838201526020016200511b565b50505f910152565b5f81518084526200515681602086016020860162005119565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f62004bf560208301846200513d565b5f60208284031215620051ad575f80fd5b62004bf58262004ad8565b5f8060408385031215620051ca575f80fd5b823562004ccb8162004ab6565b80356002811062004827575f80fd5b5f805f805f805f60e0888a031215620051fd575f80fd5b87356200520a8162004ab6565b965060208801356200521c8162004ab6565b95506200522c6040890162004ad8565b94506200523c6060890162004ad8565b9350608088013592506200525360a08901620051d7565b915060c0880135905092959891949750929550565b5f80604083850312156200527a575f80fd5b620052858362004ad8565b946020939093013593505050565b5f805f8060808587031215620052a7575f80fd5b620052b28562004bc5565b966020860135965060408601359560600135945092505050565b5f805f805f805f60e0888a031215620052e3575f80fd5b8735620052f08162004ab6565b96506020880135620053028162004ab6565b9550620053126040890162004ad8565b94506200532260608901620051d7565b93506080880135925060a088013567ffffffffffffffff81111562005345575f80fd5b620053538a828b0162004ea3565b92505060c0880135905092959891949750929550565b5f805f606084860312156200537c575f80fd5b8335620053898162004ab6565b9250620053996020850162004bc5565b9150604084013567ffffffffffffffff811115620053b5575f80fd5b8401601f81018613620053c6575f80fd5b620053d78682356020840162004e0b565b9150509250925092565b5f60208284031215620053f2575f80fd5b813562004bf58162004ab6565b5f806040838503121562005411575f80fd5b82356200541e8162004ab6565b915062004cdb6020840162004bc5565b5f805f805f8060a0878903121562005444575f80fd5b6200544f8762004bc5565b9550602087013594506040870135935060608701359250608087013567ffffffffffffffff8082111562005481575f80fd5b818901915089601f83011262005495575f80fd5b813581811115620054a4575f80fd5b8a6020828501011115620054b6575f80fd5b6020830194508093505050509295509295509295565b815173ffffffffffffffffffffffffffffffffffffffff1681526101808101602083015162005507602084018267ffffffffffffffff169052565b50604083015162005530604084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060608301516200554d606084018267ffffffffffffffff169052565b506080830151608083015260a08301516200557460a084018267ffffffffffffffff169052565b5060c08301516200559160c084018267ffffffffffffffff169052565b5060e0830151620055ae60e084018267ffffffffffffffff169052565b506101008381015167ffffffffffffffff9081169184019190915261012080850151821690840152610140808501519091169083015261016080840151620055f98285018262004d42565b505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff81811683821601908082111562005652576200565262005601565b5092915050565b808202811582820484141762000dd85762000dd862005601565b5f63ffffffff8083168181036200568e576200568e62005601565b6001019392505050565b5f73ffffffffffffffffffffffffffffffffffffffff8086168352808516602084015250606060408301526200269b60608301846200513d565b5f73ffffffffffffffffffffffffffffffffffffffff8089168352808816602084015263ffffffff8716604084015280861660608401525060c060808301526200572060c08301856200513d565b82810360a08401526200573481856200513d565b9998505050505050505050565b5f6020828403121562005752575f80fd5b815162004bf58162004ab6565b67ffffffffffffffff82811682821603908082111562005652576200565262005601565b67ffffffffffffffff878116825273ffffffffffffffffffffffffffffffffffffffff87166020830152858116604083015260c0820190620057c9606084018762004d42565b93909316608082015260a00152949350505050565b5f60208284031215620057ef575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f82620058345762005834620057f6565b500490565b8082018082111562000dd85762000dd862005601565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620058af57620058af62005601565b5060010190565b5f82620058c757620058c7620057f6565b500690565b8181038181111562000dd85762000dd862005601565b5f81620058f357620058f362005601565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b73ffffffffffffffffffffffffffffffffffffffff88811682528716602082015267ffffffffffffffff861660408201525f6200595a606083018762004d42565b84608083015260e060a08301526200597660e08301856200513d565b90508260c083015298975050505050505050565b848152606060208201525f620059a460608301866200513d565b8281036040840152838152838560208301375f6020858301015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011682010191505095945050505050565b5f825162005a0881846020870162005119565b9190910192915050565b6103208101610300808584378201835f5b600181101562005a4457815183526020928301929091019060010162005a23565b5050509392505050565b5f6020828403121562005a5f575f80fd5b8151801515811462004bf5575f80fd5b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201525f6200269e60408301846200513d56fe60a060405260405162000a5e38038062000a5e833981016040819052620000269162000375565b828162000034828262000060565b50506001600160a01b038216608052620000576200005160805190565b620000c5565b5050506200046c565b6200006b8262000136565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115620000b757620000b28282620001b5565b505050565b620000c16200022e565b5050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620001065f8051602062000a3e833981519152546001600160a01b031690565b604080516001600160a01b03928316815291841660208301520160405180910390a1620001338162000250565b50565b806001600160a01b03163b5f036200017157604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5b80546001600160a01b0319166001600160a01b039290921691909117905550565b60605f80846001600160a01b031684604051620001d391906200044f565b5f60405180830381855af49150503d805f81146200020d576040519150601f19603f3d011682016040523d82523d5f602084013e62000212565b606091505b5090925090506200022585838362000291565b95945050505050565b34156200024e5760405163b398979f60e01b815260040160405180910390fd5b565b6001600160a01b0381166200027b57604051633173bdd160e11b81525f600482015260240162000168565b805f8051602062000a3e83398151915262000194565b606082620002aa57620002a482620002f7565b620002f0565b8151158015620002c257506001600160a01b0384163b155b15620002ed57604051639996b31560e01b81526001600160a01b038516600482015260240162000168565b50805b9392505050565b805115620003085780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b80516001600160a01b038116811462000338575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5b838110156200036d57818101518382015260200162000353565b50505f910152565b5f805f6060848603121562000388575f80fd5b620003938462000321565b9250620003a36020850162000321565b60408501519092506001600160401b0380821115620003c0575f80fd5b818601915086601f830112620003d4575f80fd5b815181811115620003e957620003e96200033d565b604051601f8201601f19908116603f011681019083821181831017156200041457620004146200033d565b816040528281528960208487010111156200042d575f80fd5b6200044083602083016020880162000351565b80955050505050509250925092565b5f82516200046281846020870162000351565b9190910192915050565b6080516105ba620004845f395f601001526105ba5ff3fe608060405261000c61000e565b005b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633036100a7575f357fffffffff00000000000000000000000000000000000000000000000000000000167f4f1ef286000000000000000000000000000000000000000000000000000000001461009f5761009d6100ab565b565b61009d6100bb565b61009d5b61009d6100b66100e9565b61012d565b5f806100ca3660048184610410565b8101906100d79190610464565b915091506100e5828261014b565b5050565b5f6101287f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e808015610147573d5ff35b3d5ffd5b610154826101b2565b60405173ffffffffffffffffffffffffffffffffffffffff8316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a28051156101aa576101a58282610285565b505050565b6100e5610304565b8073ffffffffffffffffffffffffffffffffffffffff163b5f0361021f576040517f4c9c8ce300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60605f808473ffffffffffffffffffffffffffffffffffffffff16846040516102ae9190610558565b5f60405180830381855af49150503d805f81146102e6576040519150601f19603f3d011682016040523d82523d5f602084013e6102eb565b606091505b50915091506102fb85838361033c565b95945050505050565b341561009d576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060826103515761034c826103ce565b6103c7565b8151158015610375575073ffffffffffffffffffffffffffffffffffffffff84163b155b156103c4576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602401610216565b50805b9392505050565b8051156103de5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808585111561041e575f80fd5b8386111561042a575f80fd5b5050820193919092039150565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f8060408385031215610475575f80fd5b823573ffffffffffffffffffffffffffffffffffffffff81168114610498575f80fd5b9150602083013567ffffffffffffffff808211156104b4575f80fd5b818501915085601f8301126104c7575f80fd5b8135818111156104d9576104d9610437565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561051f5761051f610437565b81604052828152886020848701011115610537575f80fd5b826020860160208301375f6020848301015280955050505050509250929050565b5f82515f5b81811015610577576020818601810151858301520161055d565b505f92019182525091905056fea26469706673582212200ca61bd1e45d482203caba1d216b11bb6992f1ce0f6427bfe86e65b2f53457a264736f6c63430008140033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103a264697066735822122070e0184cb0298270cb77d252235752ad92c48991a113c85600c93d56d7d33b3664736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonValidiumEtrog.json b/compiled-contracts/PolygonValidiumEtrog.json index 7db8b14da..3f770812a 100644 --- a/compiled-contracts/PolygonValidiumEtrog.json +++ b/compiled-contracts/PolygonValidiumEtrog.json @@ -1361,8 +1361,8 @@ "type": "function" } ], - "bytecode": "0x61010060405234801562000011575f80fd5b506040516200524e3803806200524e83398101604081905262000034916200006f565b6001600160a01b0393841660a052918316608052821660c0521660e052620000d4565b6001600160a01b03811681146200006c575f80fd5b50565b5f805f806080858703121562000083575f80fd5b8451620000908162000057565b6020860151909450620000a38162000057565b6040860151909350620000b68162000057565b6060860151909250620000c98162000057565b939692955090935050565b60805160a05160c05160e051615066620001e85f395f818161055901528181611027015281816110ee01528181611110015281816112ac015281816114db01528181611647015281816117c60152818161194601528181611cc80152818161222c0152818161267b0152818161272801528181612e0e01528181612ed301528181613c2301528181613c9c01528181613cbe0152613d6601525f818161070d01528181610b4e015281816128f2015281816129fa015281816133fd015281816134d2015261371401525f81816107dc01528181610bfc01528181611b3f0152818161301b01526137c201525f818161080e015281816108eb0152818161107a015281816111bc0152612ff001526150665ff3fe608060405234801561000f575f80fd5b5060043610610319575f3560e01c80636ff512cc116101a8578063b910e0f9116100f3578063d7bc90ff1161009e578063e7a7ed0211610079578063e7a7ed0214610850578063eaeb077b14610864578063f35dda4714610877578063f851a4401461087f575f80fd5b8063d7bc90ff146107fe578063e46761c414610809578063e57a0b4c14610830575f80fd5b8063c89e42df116100ce578063c89e42df146107a4578063cfa8ed47146107b7578063d02103ca146107d7575f80fd5b8063b910e0f914610761578063c754c7ed14610774578063c7fffd4b1461079c575f80fd5b80639e00187711610153578063a652f26c1161012e578063a652f26c1461072f578063ada8f91914610742578063b0afe15414610755575f80fd5b80639e001877146106da5780639f26f840146106f5578063a3c573eb14610708575f80fd5b80637cd76b8b116101835780637cd76b8b146106ac5780638c3d7301146106bf57806391cafe32146106c7575f80fd5b80636ff512cc1461064a578063712570221461065d5780637a5460c514610670575f80fd5b806340b5de6c1161026857806352bdeb6d11610213578063676870d2116101ee578063676870d21461061a5780636b8616ce146106225780636e05d2cd14610641575f80fd5b806352bdeb6d146105c3578063542028d5146105ff578063669adece14610607575f80fd5b806349b7b8021161024357806349b7b802146105545780634c21fef31461057b5780634e487706146105b0575f80fd5b806340b5de6c146104bb57806342308fab14610513578063456052671461051b575f80fd5b806326782247116102c857806332c2d153116102a357806332c2d1531461044b5780633c351e101461045e5780633cbc795b1461047e575f80fd5b806326782247146103d35780632acdc2b6146104185780632c111c061461042b575f80fd5b8063107bf28c116102f8578063107bf28c1461039c57806311e892d4146103a4578063165e8a8d146103be575f80fd5b8062d0295d1461031d578063035089631461033857806305835f3714610353575b5f80fd5b6103256108a4565b6040519081526020015b60405180910390f35b610340602081565b60405161ffff909116815260200161032f565b61038f6040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b60405161032f9190614154565b61038f6109aa565b6103ac60f981565b60405160ff909116815260200161032f565b6103d16103cc36600461421d565b610a36565b005b6001546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161032f565b6103d16104263660046142fc565b6113bb565b6008546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b6103d1610459366004614317565b6114d9565b6009546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b6009546104a69074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff909116815260200161032f565b6104e27fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff00000000000000000000000000000000000000000000000000000000000000909116815260200161032f565b610325602481565b60075461053b9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161032f565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b603c546105a09074010000000000000000000000000000000000000000900460ff1681565b604051901515815260200161032f565b6103d16105be366004614356565b6115a8565b61038f6040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b61038f6117b7565b6103d1610615366004614371565b6117c4565b610340601f81565b610325610630366004614356565b60066020525f908152604090205481565b61032560055481565b6103d161065836600461439b565b61187b565b6103d161066b3660046144f2565b611944565b61038f6040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b6103d16106ba36600461439b565b611efd565b6103d1611fc6565b6103d16106d536600461439b565b612098565b6103f373a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b6103d16107033660046145da565b6121b0565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b61038f61073d366004614619565b6127f4565b6103d161075036600461439b565b612bd2565b6103256405ca1ab1e081565b6103d161076f36600461468a565b612c9b565b60075461053b90700100000000000000000000000000000000900467ffffffffffffffff1681565b6103ac60e481565b6103d16107b236600461470a565b612d05565b6002546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b610325635ca1ab1e81565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b603c546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b60075461053b9067ffffffffffffffff1681565b6103d161087236600461473c565b612d97565b6103ac601b81565b5f546103f39062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610930573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109549190614784565b6007549091505f9061097e9067ffffffffffffffff680100000000000000008204811691166147c8565b67ffffffffffffffff169050805f03610999575f9250505090565b6109a381836147f0565b9250505090565b600480546109b790614828565b80601f01602080910402602001604051908101604052809291908181526020018280546109e390614828565b8015610a2e5780601f10610a0557610100808354040283529160200191610a2e565b820191905f5260205f20905b815481529060010190602001808311610a1157829003601f168201915b505050505081565b60025473ffffffffffffffffffffffffffffffffffffffff163314610a87576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865f819003610ac2576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115610afe576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b09602442614879565b8667ffffffffffffffff161115610b4c576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610bb1575f80fd5b505af1158015610bc3573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff8a1660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa158015610c57573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7b9190614784565b905080610cb4576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b85811015610f9a575f8e8e83818110610cf057610cf0614892565b905060800201803603810190610d0691906148bf565b604081015190915067ffffffffffffffff1615610ef35784610d278161490b565b9550505f815f0151826020015183604001518460600151604051602001610d8c9493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f90815260069093529120549091508114610e14576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84825f0151836020015184604001518e8660600151604051602001610ead969594939291909586526020860194909452604085019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060808501919091521b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166068830152607c820152609c0190565b60405160208183030381529060405280519060200120945060065f8767ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550610f87565b8051604080516020810187905290810191909152606080820188905260c08e901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012093505b5080610f9281614931565b915050610cd5565b5060075467ffffffffffffffff9081169084161115610fe5576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff848116908316146110e2575f61100a83866147c8565b905061102067ffffffffffffffff821683614968565b91506110a17f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff166110596108a4565b611063919061497b565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919061325d565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b801561126b576111e4337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa158015611177573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061119b9190614784565b6111a5919061497b565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190613336565b603c546040517f3b51be4b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690633b51be4b9061123e908d908c908c906004016149d9565b5f6040518083038186803b158015611254575f80fd5b505afa158015611266573d5f803e3d5ffd5b505050505b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015611307573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061132b91906149fb565b90508a8414611366576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e766876040516113a291815260200190565b60405180910390a2505050505050505050505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611411576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c5474010000000000000000000000000000000000000000900460ff1615158115150361146b576040517f5f0e7abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000831515021790556040517ff32a0473f809a720a4f8af1e50d353f1caf7452030626fdaac4273f5e6587f41905f90a150565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314611548576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f59668460405161159b91815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146115fe576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611645576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116ae573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116d29190614a16565b6117335760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610611733576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546109b790614828565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314611833576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581905560405181815267ffffffffffffffff8316907f1125aaf62d132d8e2d02005114f8fc360ff204c3105e4f1a700a1340dc55d5b19060200160405180910390a25050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146118d1576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0906020016117ac565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146119b3576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff16158080156119d157505f54600160ff909116105b806119ea5750303b1580156119ea57505f5460ff166001145b611a7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611ad7575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f611ae18561339a565b6009549091505f90611b2b90889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff16856127f4565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ba6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bca9190614784565b90505f808483858f611bdd600143614968565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015611d23573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d4791906149fb565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508860039081611dd79190614a76565b506004611de48982614a76565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e604051611e8493929190614b8e565b60405180910390a15050505050508015611ef4575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611f53576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fd331bd4c4cd1afecb94a225184bded161ff3213624ba4fb58c4f30c5a861144a906020016117ac565b60015473ffffffffffffffffffffffffffffffffffffffff163314612017576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146120ee576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff1661213d576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb906020016117ac565b60085473ffffffffffffffffffffffffffffffffffffffff1680158015906121ee575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612225576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612293573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122b791906149fb565b6122c19190614bcc565b67ffffffffffffffff161115612303576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81900361233e576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e881111561237a576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff808216916123a291849168010000000000000000900416614879565b11156123da576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b83811015612675575f87878381811061241557612415614892565b90506020028101906124279190614bed565b61243090614c29565b90508361243c8161490b565b825180516020918201208185015160408087015160608801519151959a509295505f946124a8948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f90815260069093529120549091508114612530576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f90815260066020526040812055612554600188614968565b84036125c35742600760109054906101000a900467ffffffffffffffff1684604001516125819190614bcc565b67ffffffffffffffff1611156125c3576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc01604051602081830303815290604052805190602001209450505050808061266d90614931565b9150506123fa565b506126a37f0000000000000000000000000000000000000000000000000000000000000000846110596108a4565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e7390612774908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015612790573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127b491906149fb565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f8760405160240161282696959493929190614c94565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f036129765760f9601f83516128ba9190614cf6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e4876040516020016129609796959493929190614d11565b6040516020818303038152906040529050612a7a565b815161ffff10156129b3576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f96129c2602083614cf6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b90000000000000000000000000000000000000000000000000000000000008152508588604051602001612a679796959493929190614df3565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa158015612ad8573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612b50576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f90612b959084906405ca1ab1e090635ca1ab1e90601b907fff0000000000000000000000000000000000000000000000000000000000000090602001614ed5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612c28576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce6906020016117ac565b603c5474010000000000000000000000000000000000000000900460ff16612cef576040517f821935b400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612cfd8686868686866135fc565b505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612d5b576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003612d678282614a76565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20816040516117ac9190614154565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590612dd5575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612e0c576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e75573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e999190614a16565b15612ed0576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f3a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f5e9190614784565b905082811115612f9a576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115612fd6576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61301873ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084613336565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613082573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130a69190614784565b6007805491925067ffffffffffffffff909116905f6130c48361490b565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505085856040516130fb929190614f30565b6040519081900390208142613111600143614968565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303613207576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2612cfd565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319061324d90849033908b908b90614f3f565b60405180910390a2505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526133319084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613e73565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526133949085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016132af565b50505050565b606073ffffffffffffffffffffffffffffffffffffffff8216156135f7576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015613441573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526134869190810190614f7e565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa158015613518573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061353c9190614fe7565b915091508163ffffffff165f146135b3576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff8416171790556135f4565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60025473ffffffffffffffffffffffffffffffffffffffff16331461364d576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f819003613688576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156136c4576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6136cf602442614879565b8467ffffffffffffffff161115613712576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015613777575f80fd5b505af1158015613789573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff881660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa15801561381d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138419190614784565b90508061387a576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b85811015613b96575f8c8c838181106138b6576138b6614892565b90506020028101906138c89190614bed565b6138d190614c29565b8051805160209091012060408201519192509067ffffffffffffffff1615613ab157856138fd8161490b565b9650505f8183602001518460400151856060015160405160200161395f9493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f908152600690935291205490915081146139e7576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550613b81565b8151516201d4c01015613af0576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b50508080613b8e90614931565b91505061389b565b5060075467ffffffffffffffff9081169084161115613be1576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff84811690831614613c96575f613c0683866147c8565b9050613c1c67ffffffffffffffff821683614968565b9150613c557f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff166110596108a4565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b613d25337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa158015611177573d5f803e3d5ffd5b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015613dc1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613de591906149fb565b9050888414613e20576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e76687604051613e5c91815260200190565b60405180910390a250505050505050505050505050565b5f613ed4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613f7e9092919063ffffffff16565b8051909150156133315780806020019051810190613ef29190614a16565b613331576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611a72565b6060612bca84845f85855f808673ffffffffffffffffffffffffffffffffffffffff168587604051613fb0919061501f565b5f6040518083038185875af1925050503d805f8114613fea576040519150601f19603f3d011682016040523d82523d5f602084013e613fef565b606091505b50915091506140008783838761400b565b979650505050505050565b606083156140a05782515f036140995773ffffffffffffffffffffffffffffffffffffffff85163b614099576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611a72565b5081612bca565b612bca83838151156140b55781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a729190614154565b5f5b838110156141035781810151838201526020016140eb565b50505f910152565b5f81518084526141228160208601602086016140e9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f614166602083018461410b565b9392505050565b63ffffffff8116811461417e575f80fd5b50565b80356135f78161416d565b67ffffffffffffffff8116811461417e575f80fd5b80356135f78161418c565b73ffffffffffffffffffffffffffffffffffffffff8116811461417e575f80fd5b80356135f7816141ac565b5f8083601f8401126141e8575f80fd5b50813567ffffffffffffffff8111156141ff575f80fd5b602083019150836020828501011115614216575f80fd5b9250929050565b5f805f805f805f8060c0898b031215614234575f80fd5b883567ffffffffffffffff8082111561424b575f80fd5b818b0191508b601f83011261425e575f80fd5b81358181111561426c575f80fd5b8c60208260071b8501011115614280575f80fd5b602083019a508099505061429660208c01614181565b97506142a460408c016141a1565b965060608b013595506142b960808c016141cd565b945060a08b01359150808211156142ce575f80fd5b506142db8b828c016141d8565b999c989b5096995094979396929594505050565b801515811461417e575f80fd5b5f6020828403121561430c575f80fd5b8135614166816142ef565b5f805f60608486031215614329575f80fd5b83356143348161418c565b925060208401359150604084013561434b816141ac565b809150509250925092565b5f60208284031215614366575f80fd5b81356141668161418c565b5f8060408385031215614382575f80fd5b823561438d8161418c565b946020939093013593505050565b5f602082840312156143ab575f80fd5b8135614166816141ac565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516080810167ffffffffffffffff81118282101715614406576144066143b6565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614453576144536143b6565b604052919050565b5f67ffffffffffffffff821115614474576144746143b6565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f8301126144af575f80fd5b81356144c26144bd8261445b565b61440c565b8181528460208386010111156144d6575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060c08789031215614507575f80fd5b8635614512816141ac565b95506020870135614522816141ac565b945060408701356145328161416d565b93506060870135614542816141ac565b9250608087013567ffffffffffffffff8082111561455e575f80fd5b61456a8a838b016144a0565b935060a089013591508082111561457f575f80fd5b5061458c89828a016144a0565b9150509295509295509295565b5f8083601f8401126145a9575f80fd5b50813567ffffffffffffffff8111156145c0575f80fd5b6020830191508360208260051b8501011115614216575f80fd5b5f80602083850312156145eb575f80fd5b823567ffffffffffffffff811115614601575f80fd5b61460d85828601614599565b90969095509350505050565b5f805f806080858703121561462c575f80fd5b84356146378161416d565b93506020850135614647816141ac565b925060408501356146578161416d565b9150606085013567ffffffffffffffff811115614672575f80fd5b61467e878288016144a0565b91505092959194509250565b5f805f805f8060a0878903121561469f575f80fd5b863567ffffffffffffffff8111156146b5575f80fd5b6146c189828a01614599565b90975095505060208701356146d58161416d565b935060408701356146e58161418c565b92506060870135915060808701356146fc816141ac565b809150509295509295509295565b5f6020828403121561471a575f80fd5b813567ffffffffffffffff811115614730575f80fd5b612bca848285016144a0565b5f805f6040848603121561474e575f80fd5b833567ffffffffffffffff811115614764575f80fd5b614770868287016141d8565b909790965060209590950135949350505050565b5f60208284031215614794575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff8281168282160390808211156147e9576147e961479b565b5092915050565b5f82614823577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c9082168061483c57607f821691505b602082108103614873577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b8082018082111561488c5761488c61479b565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f608082840312156148cf575f80fd5b6148d76143e3565b823581526020830135602082015260408301356148f38161418c565b60408201526060928301359281019290925250919050565b5f67ffffffffffffffff8083168181036149275761492761479b565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149615761496161479b565b5060010190565b8181038181111561488c5761488c61479b565b808202811582820484141761488c5761488c61479b565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b838152604060208201525f6149f2604083018486614992565b95945050505050565b5f60208284031215614a0b575f80fd5b81516141668161418c565b5f60208284031215614a26575f80fd5b8151614166816142ef565b601f821115613331575f81815260208120601f850160051c81016020861015614a575750805b601f850160051c820191505b81811015612cfd57828155600101614a63565b815167ffffffffffffffff811115614a9057614a906143b6565b614aa481614a9e8454614828565b84614a31565b602080601f831160018114614af6575f8415614ac05750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612cfd565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614b4257888601518255948401946001909101908401614b23565b5085821015614b7e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f614ba0606083018661410b565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff8181168382160190808211156147e9576147e961479b565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614c1f575f80fd5b9190910192915050565b5f60808236031215614c39575f80fd5b614c416143e3565b823567ffffffffffffffff811115614c57575f80fd5b614c63368286016144a0565b825250602083013560208201526040830135614c7e8161418c565b6040820152606092830135928101929092525090565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a0830152614cea60c083018461410b565b98975050505050505050565b61ffff8181168382160190808211156147e9576147e961479b565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751614d79816003860160208c016140e9565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651614dbc816017840160208b016140e9565b808201915050818660f81b16601782015284519150614de28260188301602088016140e9565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b1660018401528751614e5b816003860160208c016140e9565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651614e9e816017840160208b016140e9565b808201915050818660f01b16601782015284519150614ec48260198301602088016140e9565b016019019998505050505050505050565b5f8651614ee6818460208b016140e9565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201525f614f74606083018486614992565b9695505050505050565b5f60208284031215614f8e575f80fd5b815167ffffffffffffffff811115614fa4575f80fd5b8201601f81018413614fb4575f80fd5b8051614fc26144bd8261445b565b818152856020838501011115614fd6575f80fd5b6149f28260208301602086016140e9565b5f8060408385031215614ff8575f80fd5b82516150038161416d565b6020840151909250615014816141ac565b809150509250929050565b5f8251614c1f8184602087016140e956fea2646970667358221220c23ad643c0305b1e8cce2b26fc9a8ea1aecd28dd8debfbc8c2d00aa1071e1bc464736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610319575f3560e01c80636ff512cc116101a8578063b910e0f9116100f3578063d7bc90ff1161009e578063e7a7ed0211610079578063e7a7ed0214610850578063eaeb077b14610864578063f35dda4714610877578063f851a4401461087f575f80fd5b8063d7bc90ff146107fe578063e46761c414610809578063e57a0b4c14610830575f80fd5b8063c89e42df116100ce578063c89e42df146107a4578063cfa8ed47146107b7578063d02103ca146107d7575f80fd5b8063b910e0f914610761578063c754c7ed14610774578063c7fffd4b1461079c575f80fd5b80639e00187711610153578063a652f26c1161012e578063a652f26c1461072f578063ada8f91914610742578063b0afe15414610755575f80fd5b80639e001877146106da5780639f26f840146106f5578063a3c573eb14610708575f80fd5b80637cd76b8b116101835780637cd76b8b146106ac5780638c3d7301146106bf57806391cafe32146106c7575f80fd5b80636ff512cc1461064a578063712570221461065d5780637a5460c514610670575f80fd5b806340b5de6c1161026857806352bdeb6d11610213578063676870d2116101ee578063676870d21461061a5780636b8616ce146106225780636e05d2cd14610641575f80fd5b806352bdeb6d146105c3578063542028d5146105ff578063669adece14610607575f80fd5b806349b7b8021161024357806349b7b802146105545780634c21fef31461057b5780634e487706146105b0575f80fd5b806340b5de6c146104bb57806342308fab14610513578063456052671461051b575f80fd5b806326782247116102c857806332c2d153116102a357806332c2d1531461044b5780633c351e101461045e5780633cbc795b1461047e575f80fd5b806326782247146103d35780632acdc2b6146104185780632c111c061461042b575f80fd5b8063107bf28c116102f8578063107bf28c1461039c57806311e892d4146103a4578063165e8a8d146103be575f80fd5b8062d0295d1461031d578063035089631461033857806305835f3714610353575b5f80fd5b6103256108a4565b6040519081526020015b60405180910390f35b610340602081565b60405161ffff909116815260200161032f565b61038f6040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b60405161032f9190614154565b61038f6109aa565b6103ac60f981565b60405160ff909116815260200161032f565b6103d16103cc36600461421d565b610a36565b005b6001546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161032f565b6103d16104263660046142fc565b6113bb565b6008546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b6103d1610459366004614317565b6114d9565b6009546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b6009546104a69074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff909116815260200161032f565b6104e27fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff00000000000000000000000000000000000000000000000000000000000000909116815260200161032f565b610325602481565b60075461053b9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161032f565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b603c546105a09074010000000000000000000000000000000000000000900460ff1681565b604051901515815260200161032f565b6103d16105be366004614356565b6115a8565b61038f6040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b61038f6117b7565b6103d1610615366004614371565b6117c4565b610340601f81565b610325610630366004614356565b60066020525f908152604090205481565b61032560055481565b6103d161065836600461439b565b61187b565b6103d161066b3660046144f2565b611944565b61038f6040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b6103d16106ba36600461439b565b611efd565b6103d1611fc6565b6103d16106d536600461439b565b612098565b6103f373a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b6103d16107033660046145da565b6121b0565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b61038f61073d366004614619565b6127f4565b6103d161075036600461439b565b612bd2565b6103256405ca1ab1e081565b6103d161076f36600461468a565b612c9b565b60075461053b90700100000000000000000000000000000000900467ffffffffffffffff1681565b6103ac60e481565b6103d16107b236600461470a565b612d05565b6002546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b610325635ca1ab1e81565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b603c546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b60075461053b9067ffffffffffffffff1681565b6103d161087236600461473c565b612d97565b6103ac601b81565b5f546103f39062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610930573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109549190614784565b6007549091505f9061097e9067ffffffffffffffff680100000000000000008204811691166147c8565b67ffffffffffffffff169050805f03610999575f9250505090565b6109a381836147f0565b9250505090565b600480546109b790614828565b80601f01602080910402602001604051908101604052809291908181526020018280546109e390614828565b8015610a2e5780601f10610a0557610100808354040283529160200191610a2e565b820191905f5260205f20905b815481529060010190602001808311610a1157829003601f168201915b505050505081565b60025473ffffffffffffffffffffffffffffffffffffffff163314610a87576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865f819003610ac2576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115610afe576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b09602442614879565b8667ffffffffffffffff161115610b4c576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610bb1575f80fd5b505af1158015610bc3573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff8a1660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa158015610c57573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7b9190614784565b905080610cb4576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b85811015610f9a575f8e8e83818110610cf057610cf0614892565b905060800201803603810190610d0691906148bf565b604081015190915067ffffffffffffffff1615610ef35784610d278161490b565b9550505f815f0151826020015183604001518460600151604051602001610d8c9493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f90815260069093529120549091508114610e14576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84825f0151836020015184604001518e8660600151604051602001610ead969594939291909586526020860194909452604085019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060808501919091521b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166068830152607c820152609c0190565b60405160208183030381529060405280519060200120945060065f8767ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550610f87565b8051604080516020810187905290810191909152606080820188905260c08e901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012093505b5080610f9281614931565b915050610cd5565b5060075467ffffffffffffffff9081169084161115610fe5576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff848116908316146110e2575f61100a83866147c8565b905061102067ffffffffffffffff821683614968565b91506110a17f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff166110596108a4565b611063919061497b565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919061325d565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b801561126b576111e4337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa158015611177573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061119b9190614784565b6111a5919061497b565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190613336565b603c546040517f3b51be4b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690633b51be4b9061123e908d908c908c906004016149d9565b5f6040518083038186803b158015611254575f80fd5b505afa158015611266573d5f803e3d5ffd5b505050505b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015611307573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061132b91906149fb565b90508a8414611366576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e766876040516113a291815260200190565b60405180910390a2505050505050505050505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611411576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c5474010000000000000000000000000000000000000000900460ff1615158115150361146b576040517f5f0e7abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000831515021790556040517ff32a0473f809a720a4f8af1e50d353f1caf7452030626fdaac4273f5e6587f41905f90a150565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314611548576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f59668460405161159b91815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146115fe576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611645576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116ae573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116d29190614a16565b6117335760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610611733576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546109b790614828565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314611833576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581905560405181815267ffffffffffffffff8316907f1125aaf62d132d8e2d02005114f8fc360ff204c3105e4f1a700a1340dc55d5b19060200160405180910390a25050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146118d1576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0906020016117ac565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146119b3576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff16158080156119d157505f54600160ff909116105b806119ea5750303b1580156119ea57505f5460ff166001145b611a7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611ad7575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f611ae18561339a565b6009549091505f90611b2b90889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff16856127f4565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ba6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bca9190614784565b90505f808483858f611bdd600143614968565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015611d23573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d4791906149fb565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508860039081611dd79190614a76565b506004611de48982614a76565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e604051611e8493929190614b8e565b60405180910390a15050505050508015611ef4575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611f53576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fd331bd4c4cd1afecb94a225184bded161ff3213624ba4fb58c4f30c5a861144a906020016117ac565b60015473ffffffffffffffffffffffffffffffffffffffff163314612017576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146120ee576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff1661213d576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb906020016117ac565b60085473ffffffffffffffffffffffffffffffffffffffff1680158015906121ee575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612225576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612293573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122b791906149fb565b6122c19190614bcc565b67ffffffffffffffff161115612303576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81900361233e576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e881111561237a576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff808216916123a291849168010000000000000000900416614879565b11156123da576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b83811015612675575f87878381811061241557612415614892565b90506020028101906124279190614bed565b61243090614c29565b90508361243c8161490b565b825180516020918201208185015160408087015160608801519151959a509295505f946124a8948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f90815260069093529120549091508114612530576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f90815260066020526040812055612554600188614968565b84036125c35742600760109054906101000a900467ffffffffffffffff1684604001516125819190614bcc565b67ffffffffffffffff1611156125c3576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc01604051602081830303815290604052805190602001209450505050808061266d90614931565b9150506123fa565b506126a37f0000000000000000000000000000000000000000000000000000000000000000846110596108a4565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e7390612774908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015612790573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127b491906149fb565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f8760405160240161282696959493929190614c94565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f036129765760f9601f83516128ba9190614cf6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e4876040516020016129609796959493929190614d11565b6040516020818303038152906040529050612a7a565b815161ffff10156129b3576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f96129c2602083614cf6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b90000000000000000000000000000000000000000000000000000000000008152508588604051602001612a679796959493929190614df3565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa158015612ad8573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612b50576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f90612b959084906405ca1ab1e090635ca1ab1e90601b907fff0000000000000000000000000000000000000000000000000000000000000090602001614ed5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612c28576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce6906020016117ac565b603c5474010000000000000000000000000000000000000000900460ff16612cef576040517f821935b400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612cfd8686868686866135fc565b505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612d5b576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003612d678282614a76565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20816040516117ac9190614154565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590612dd5575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612e0c576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e75573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e999190614a16565b15612ed0576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f3a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f5e9190614784565b905082811115612f9a576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115612fd6576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61301873ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084613336565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613082573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130a69190614784565b6007805491925067ffffffffffffffff909116905f6130c48361490b565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505085856040516130fb929190614f30565b6040519081900390208142613111600143614968565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303613207576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2612cfd565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319061324d90849033908b908b90614f3f565b60405180910390a2505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526133319084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613e73565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526133949085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016132af565b50505050565b606073ffffffffffffffffffffffffffffffffffffffff8216156135f7576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015613441573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526134869190810190614f7e565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa158015613518573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061353c9190614fe7565b915091508163ffffffff165f146135b3576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff8416171790556135f4565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60025473ffffffffffffffffffffffffffffffffffffffff16331461364d576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f819003613688576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156136c4576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6136cf602442614879565b8467ffffffffffffffff161115613712576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015613777575f80fd5b505af1158015613789573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff881660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa15801561381d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138419190614784565b90508061387a576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b85811015613b96575f8c8c838181106138b6576138b6614892565b90506020028101906138c89190614bed565b6138d190614c29565b8051805160209091012060408201519192509067ffffffffffffffff1615613ab157856138fd8161490b565b9650505f8183602001518460400151856060015160405160200161395f9493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f908152600690935291205490915081146139e7576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550613b81565b8151516201d4c01015613af0576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b50508080613b8e90614931565b91505061389b565b5060075467ffffffffffffffff9081169084161115613be1576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff84811690831614613c96575f613c0683866147c8565b9050613c1c67ffffffffffffffff821683614968565b9150613c557f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff166110596108a4565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b613d25337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa158015611177573d5f803e3d5ffd5b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015613dc1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613de591906149fb565b9050888414613e20576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e76687604051613e5c91815260200190565b60405180910390a250505050505050505050505050565b5f613ed4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613f7e9092919063ffffffff16565b8051909150156133315780806020019051810190613ef29190614a16565b613331576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611a72565b6060612bca84845f85855f808673ffffffffffffffffffffffffffffffffffffffff168587604051613fb0919061501f565b5f6040518083038185875af1925050503d805f8114613fea576040519150601f19603f3d011682016040523d82523d5f602084013e613fef565b606091505b50915091506140008783838761400b565b979650505050505050565b606083156140a05782515f036140995773ffffffffffffffffffffffffffffffffffffffff85163b614099576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611a72565b5081612bca565b612bca83838151156140b55781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a729190614154565b5f5b838110156141035781810151838201526020016140eb565b50505f910152565b5f81518084526141228160208601602086016140e9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f614166602083018461410b565b9392505050565b63ffffffff8116811461417e575f80fd5b50565b80356135f78161416d565b67ffffffffffffffff8116811461417e575f80fd5b80356135f78161418c565b73ffffffffffffffffffffffffffffffffffffffff8116811461417e575f80fd5b80356135f7816141ac565b5f8083601f8401126141e8575f80fd5b50813567ffffffffffffffff8111156141ff575f80fd5b602083019150836020828501011115614216575f80fd5b9250929050565b5f805f805f805f8060c0898b031215614234575f80fd5b883567ffffffffffffffff8082111561424b575f80fd5b818b0191508b601f83011261425e575f80fd5b81358181111561426c575f80fd5b8c60208260071b8501011115614280575f80fd5b602083019a508099505061429660208c01614181565b97506142a460408c016141a1565b965060608b013595506142b960808c016141cd565b945060a08b01359150808211156142ce575f80fd5b506142db8b828c016141d8565b999c989b5096995094979396929594505050565b801515811461417e575f80fd5b5f6020828403121561430c575f80fd5b8135614166816142ef565b5f805f60608486031215614329575f80fd5b83356143348161418c565b925060208401359150604084013561434b816141ac565b809150509250925092565b5f60208284031215614366575f80fd5b81356141668161418c565b5f8060408385031215614382575f80fd5b823561438d8161418c565b946020939093013593505050565b5f602082840312156143ab575f80fd5b8135614166816141ac565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516080810167ffffffffffffffff81118282101715614406576144066143b6565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614453576144536143b6565b604052919050565b5f67ffffffffffffffff821115614474576144746143b6565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f8301126144af575f80fd5b81356144c26144bd8261445b565b61440c565b8181528460208386010111156144d6575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060c08789031215614507575f80fd5b8635614512816141ac565b95506020870135614522816141ac565b945060408701356145328161416d565b93506060870135614542816141ac565b9250608087013567ffffffffffffffff8082111561455e575f80fd5b61456a8a838b016144a0565b935060a089013591508082111561457f575f80fd5b5061458c89828a016144a0565b9150509295509295509295565b5f8083601f8401126145a9575f80fd5b50813567ffffffffffffffff8111156145c0575f80fd5b6020830191508360208260051b8501011115614216575f80fd5b5f80602083850312156145eb575f80fd5b823567ffffffffffffffff811115614601575f80fd5b61460d85828601614599565b90969095509350505050565b5f805f806080858703121561462c575f80fd5b84356146378161416d565b93506020850135614647816141ac565b925060408501356146578161416d565b9150606085013567ffffffffffffffff811115614672575f80fd5b61467e878288016144a0565b91505092959194509250565b5f805f805f8060a0878903121561469f575f80fd5b863567ffffffffffffffff8111156146b5575f80fd5b6146c189828a01614599565b90975095505060208701356146d58161416d565b935060408701356146e58161418c565b92506060870135915060808701356146fc816141ac565b809150509295509295509295565b5f6020828403121561471a575f80fd5b813567ffffffffffffffff811115614730575f80fd5b612bca848285016144a0565b5f805f6040848603121561474e575f80fd5b833567ffffffffffffffff811115614764575f80fd5b614770868287016141d8565b909790965060209590950135949350505050565b5f60208284031215614794575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff8281168282160390808211156147e9576147e961479b565b5092915050565b5f82614823577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c9082168061483c57607f821691505b602082108103614873577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b8082018082111561488c5761488c61479b565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f608082840312156148cf575f80fd5b6148d76143e3565b823581526020830135602082015260408301356148f38161418c565b60408201526060928301359281019290925250919050565b5f67ffffffffffffffff8083168181036149275761492761479b565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149615761496161479b565b5060010190565b8181038181111561488c5761488c61479b565b808202811582820484141761488c5761488c61479b565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b838152604060208201525f6149f2604083018486614992565b95945050505050565b5f60208284031215614a0b575f80fd5b81516141668161418c565b5f60208284031215614a26575f80fd5b8151614166816142ef565b601f821115613331575f81815260208120601f850160051c81016020861015614a575750805b601f850160051c820191505b81811015612cfd57828155600101614a63565b815167ffffffffffffffff811115614a9057614a906143b6565b614aa481614a9e8454614828565b84614a31565b602080601f831160018114614af6575f8415614ac05750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612cfd565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614b4257888601518255948401946001909101908401614b23565b5085821015614b7e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f614ba0606083018661410b565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff8181168382160190808211156147e9576147e961479b565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614c1f575f80fd5b9190910192915050565b5f60808236031215614c39575f80fd5b614c416143e3565b823567ffffffffffffffff811115614c57575f80fd5b614c63368286016144a0565b825250602083013560208201526040830135614c7e8161418c565b6040820152606092830135928101929092525090565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a0830152614cea60c083018461410b565b98975050505050505050565b61ffff8181168382160190808211156147e9576147e961479b565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751614d79816003860160208c016140e9565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651614dbc816017840160208b016140e9565b808201915050818660f81b16601782015284519150614de28260188301602088016140e9565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b1660018401528751614e5b816003860160208c016140e9565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651614e9e816017840160208b016140e9565b808201915050818660f01b16601782015284519150614ec48260198301602088016140e9565b016019019998505050505050505050565b5f8651614ee6818460208b016140e9565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201525f614f74606083018486614992565b9695505050505050565b5f60208284031215614f8e575f80fd5b815167ffffffffffffffff811115614fa4575f80fd5b8201601f81018413614fb4575f80fd5b8051614fc26144bd8261445b565b818152856020838501011115614fd6575f80fd5b6149f28260208301602086016140e9565b5f8060408385031215614ff8575f80fd5b82516150038161416d565b6020840151909250615014816141ac565b809150509250929050565b5f8251614c1f8184602087016140e956fea2646970667358221220c23ad643c0305b1e8cce2b26fc9a8ea1aecd28dd8debfbc8c2d00aa1071e1bc464736f6c63430008140033", + "bytecode": "0x61010060405234801562000011575f80fd5b506040516200532d3803806200532d83398101604081905262000034916200014e565b6001600160a01b0380851660a05280841660805280831660c052811660e05283838383838383836200006562000077565b505050505050505050505050620001b3565b5f54610100900460ff1615620000e35760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116101562000134575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b03811681146200014b575f80fd5b50565b5f805f806080858703121562000162575f80fd5b84516200016f8162000136565b6020860151909450620001828162000136565b6040860151909350620001958162000136565b6060860151909250620001a88162000136565b939692955090935050565b60805160a05160c05160e051615066620002c75f395f818161055901528181611027015281816110ee01528181611110015281816112ac015281816114db01528181611647015281816117c60152818161194601528181611cc80152818161222c0152818161267b0152818161272801528181612e0e01528181612ed301528181613c2301528181613c9c01528181613cbe0152613d6601525f818161070d01528181610b4e015281816128f2015281816129fa015281816133fd015281816134d2015261371401525f81816107dc01528181610bfc01528181611b3f0152818161301b01526137c201525f818161080e015281816108eb0152818161107a015281816111bc0152612ff001526150665ff3fe608060405234801561000f575f80fd5b5060043610610319575f3560e01c80636ff512cc116101a8578063b910e0f9116100f3578063d7bc90ff1161009e578063e7a7ed0211610079578063e7a7ed0214610850578063eaeb077b14610864578063f35dda4714610877578063f851a4401461087f575f80fd5b8063d7bc90ff146107fe578063e46761c414610809578063e57a0b4c14610830575f80fd5b8063c89e42df116100ce578063c89e42df146107a4578063cfa8ed47146107b7578063d02103ca146107d7575f80fd5b8063b910e0f914610761578063c754c7ed14610774578063c7fffd4b1461079c575f80fd5b80639e00187711610153578063a652f26c1161012e578063a652f26c1461072f578063ada8f91914610742578063b0afe15414610755575f80fd5b80639e001877146106da5780639f26f840146106f5578063a3c573eb14610708575f80fd5b80637cd76b8b116101835780637cd76b8b146106ac5780638c3d7301146106bf57806391cafe32146106c7575f80fd5b80636ff512cc1461064a578063712570221461065d5780637a5460c514610670575f80fd5b806340b5de6c1161026857806352bdeb6d11610213578063676870d2116101ee578063676870d21461061a5780636b8616ce146106225780636e05d2cd14610641575f80fd5b806352bdeb6d146105c3578063542028d5146105ff578063669adece14610607575f80fd5b806349b7b8021161024357806349b7b802146105545780634c21fef31461057b5780634e487706146105b0575f80fd5b806340b5de6c146104bb57806342308fab14610513578063456052671461051b575f80fd5b806326782247116102c857806332c2d153116102a357806332c2d1531461044b5780633c351e101461045e5780633cbc795b1461047e575f80fd5b806326782247146103d35780632acdc2b6146104185780632c111c061461042b575f80fd5b8063107bf28c116102f8578063107bf28c1461039c57806311e892d4146103a4578063165e8a8d146103be575f80fd5b8062d0295d1461031d578063035089631461033857806305835f3714610353575b5f80fd5b6103256108a4565b6040519081526020015b60405180910390f35b610340602081565b60405161ffff909116815260200161032f565b61038f6040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b60405161032f9190614154565b61038f6109aa565b6103ac60f981565b60405160ff909116815260200161032f565b6103d16103cc36600461421d565b610a36565b005b6001546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161032f565b6103d16104263660046142fc565b6113bb565b6008546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b6103d1610459366004614317565b6114d9565b6009546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b6009546104a69074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff909116815260200161032f565b6104e27fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff00000000000000000000000000000000000000000000000000000000000000909116815260200161032f565b610325602481565b60075461053b9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161032f565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b603c546105a09074010000000000000000000000000000000000000000900460ff1681565b604051901515815260200161032f565b6103d16105be366004614356565b6115a8565b61038f6040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b61038f6117b7565b6103d1610615366004614371565b6117c4565b610340601f81565b610325610630366004614356565b60066020525f908152604090205481565b61032560055481565b6103d161065836600461439b565b61187b565b6103d161066b3660046144f2565b611944565b61038f6040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b6103d16106ba36600461439b565b611efd565b6103d1611fc6565b6103d16106d536600461439b565b612098565b6103f373a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b6103d16107033660046145da565b6121b0565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b61038f61073d366004614619565b6127f4565b6103d161075036600461439b565b612bd2565b6103256405ca1ab1e081565b6103d161076f36600461468a565b612c9b565b60075461053b90700100000000000000000000000000000000900467ffffffffffffffff1681565b6103ac60e481565b6103d16107b236600461470a565b612d05565b6002546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b610325635ca1ab1e81565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b603c546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b60075461053b9067ffffffffffffffff1681565b6103d161087236600461473c565b612d97565b6103ac601b81565b5f546103f39062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610930573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109549190614784565b6007549091505f9061097e9067ffffffffffffffff680100000000000000008204811691166147c8565b67ffffffffffffffff169050805f03610999575f9250505090565b6109a381836147f0565b9250505090565b600480546109b790614828565b80601f01602080910402602001604051908101604052809291908181526020018280546109e390614828565b8015610a2e5780601f10610a0557610100808354040283529160200191610a2e565b820191905f5260205f20905b815481529060010190602001808311610a1157829003601f168201915b505050505081565b60025473ffffffffffffffffffffffffffffffffffffffff163314610a87576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865f819003610ac2576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115610afe576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b09602442614879565b8667ffffffffffffffff161115610b4c576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610bb1575f80fd5b505af1158015610bc3573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff8a1660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa158015610c57573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7b9190614784565b905080610cb4576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b85811015610f9a575f8e8e83818110610cf057610cf0614892565b905060800201803603810190610d0691906148bf565b604081015190915067ffffffffffffffff1615610ef35784610d278161490b565b9550505f815f0151826020015183604001518460600151604051602001610d8c9493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f90815260069093529120549091508114610e14576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84825f0151836020015184604001518e8660600151604051602001610ead969594939291909586526020860194909452604085019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060808501919091521b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166068830152607c820152609c0190565b60405160208183030381529060405280519060200120945060065f8767ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550610f87565b8051604080516020810187905290810191909152606080820188905260c08e901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012093505b5080610f9281614931565b915050610cd5565b5060075467ffffffffffffffff9081169084161115610fe5576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff848116908316146110e2575f61100a83866147c8565b905061102067ffffffffffffffff821683614968565b91506110a17f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff166110596108a4565b611063919061497b565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919061325d565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b801561126b576111e4337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa158015611177573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061119b9190614784565b6111a5919061497b565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190613336565b603c546040517f3b51be4b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690633b51be4b9061123e908d908c908c906004016149d9565b5f6040518083038186803b158015611254575f80fd5b505afa158015611266573d5f803e3d5ffd5b505050505b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015611307573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061132b91906149fb565b90508a8414611366576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e766876040516113a291815260200190565b60405180910390a2505050505050505050505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611411576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c5474010000000000000000000000000000000000000000900460ff1615158115150361146b576040517f5f0e7abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000831515021790556040517ff32a0473f809a720a4f8af1e50d353f1caf7452030626fdaac4273f5e6587f41905f90a150565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314611548576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f59668460405161159b91815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146115fe576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611645576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116ae573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116d29190614a16565b6117335760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610611733576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546109b790614828565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314611833576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581905560405181815267ffffffffffffffff8316907f1125aaf62d132d8e2d02005114f8fc360ff204c3105e4f1a700a1340dc55d5b19060200160405180910390a25050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146118d1576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0906020016117ac565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146119b3576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff16158080156119d157505f54600160ff909116105b806119ea5750303b1580156119ea57505f5460ff166001145b611a7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611ad7575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f611ae18561339a565b6009549091505f90611b2b90889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff16856127f4565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ba6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bca9190614784565b90505f808483858f611bdd600143614968565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015611d23573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d4791906149fb565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508860039081611dd79190614a76565b506004611de48982614a76565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e604051611e8493929190614b8e565b60405180910390a15050505050508015611ef4575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611f53576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fd331bd4c4cd1afecb94a225184bded161ff3213624ba4fb58c4f30c5a861144a906020016117ac565b60015473ffffffffffffffffffffffffffffffffffffffff163314612017576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146120ee576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff1661213d576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb906020016117ac565b60085473ffffffffffffffffffffffffffffffffffffffff1680158015906121ee575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612225576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612293573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122b791906149fb565b6122c19190614bcc565b67ffffffffffffffff161115612303576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81900361233e576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e881111561237a576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff808216916123a291849168010000000000000000900416614879565b11156123da576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b83811015612675575f87878381811061241557612415614892565b90506020028101906124279190614bed565b61243090614c29565b90508361243c8161490b565b825180516020918201208185015160408087015160608801519151959a509295505f946124a8948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f90815260069093529120549091508114612530576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f90815260066020526040812055612554600188614968565b84036125c35742600760109054906101000a900467ffffffffffffffff1684604001516125819190614bcc565b67ffffffffffffffff1611156125c3576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc01604051602081830303815290604052805190602001209450505050808061266d90614931565b9150506123fa565b506126a37f0000000000000000000000000000000000000000000000000000000000000000846110596108a4565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e7390612774908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015612790573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127b491906149fb565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f8760405160240161282696959493929190614c94565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f036129765760f9601f83516128ba9190614cf6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e4876040516020016129609796959493929190614d11565b6040516020818303038152906040529050612a7a565b815161ffff10156129b3576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f96129c2602083614cf6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b90000000000000000000000000000000000000000000000000000000000008152508588604051602001612a679796959493929190614df3565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa158015612ad8573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612b50576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f90612b959084906405ca1ab1e090635ca1ab1e90601b907fff0000000000000000000000000000000000000000000000000000000000000090602001614ed5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612c28576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce6906020016117ac565b603c5474010000000000000000000000000000000000000000900460ff16612cef576040517f821935b400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612cfd8686868686866135fc565b505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612d5b576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003612d678282614a76565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20816040516117ac9190614154565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590612dd5575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612e0c576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e75573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e999190614a16565b15612ed0576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f3a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f5e9190614784565b905082811115612f9a576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115612fd6576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61301873ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084613336565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613082573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130a69190614784565b6007805491925067ffffffffffffffff909116905f6130c48361490b565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505085856040516130fb929190614f30565b6040519081900390208142613111600143614968565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303613207576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2612cfd565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319061324d90849033908b908b90614f3f565b60405180910390a2505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526133319084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613e73565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526133949085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016132af565b50505050565b606073ffffffffffffffffffffffffffffffffffffffff8216156135f7576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015613441573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526134869190810190614f7e565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa158015613518573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061353c9190614fe7565b915091508163ffffffff165f146135b3576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff8416171790556135f4565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60025473ffffffffffffffffffffffffffffffffffffffff16331461364d576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f819003613688576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156136c4576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6136cf602442614879565b8467ffffffffffffffff161115613712576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015613777575f80fd5b505af1158015613789573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff881660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa15801561381d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138419190614784565b90508061387a576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b85811015613b96575f8c8c838181106138b6576138b6614892565b90506020028101906138c89190614bed565b6138d190614c29565b8051805160209091012060408201519192509067ffffffffffffffff1615613ab157856138fd8161490b565b9650505f8183602001518460400151856060015160405160200161395f9493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f908152600690935291205490915081146139e7576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550613b81565b8151516201d4c01015613af0576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b50508080613b8e90614931565b91505061389b565b5060075467ffffffffffffffff9081169084161115613be1576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff84811690831614613c96575f613c0683866147c8565b9050613c1c67ffffffffffffffff821683614968565b9150613c557f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff166110596108a4565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b613d25337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa158015611177573d5f803e3d5ffd5b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015613dc1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613de591906149fb565b9050888414613e20576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e76687604051613e5c91815260200190565b60405180910390a250505050505050505050505050565b5f613ed4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613f7e9092919063ffffffff16565b8051909150156133315780806020019051810190613ef29190614a16565b613331576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611a72565b6060612bca84845f85855f808673ffffffffffffffffffffffffffffffffffffffff168587604051613fb0919061501f565b5f6040518083038185875af1925050503d805f8114613fea576040519150601f19603f3d011682016040523d82523d5f602084013e613fef565b606091505b50915091506140008783838761400b565b979650505050505050565b606083156140a05782515f036140995773ffffffffffffffffffffffffffffffffffffffff85163b614099576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611a72565b5081612bca565b612bca83838151156140b55781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a729190614154565b5f5b838110156141035781810151838201526020016140eb565b50505f910152565b5f81518084526141228160208601602086016140e9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f614166602083018461410b565b9392505050565b63ffffffff8116811461417e575f80fd5b50565b80356135f78161416d565b67ffffffffffffffff8116811461417e575f80fd5b80356135f78161418c565b73ffffffffffffffffffffffffffffffffffffffff8116811461417e575f80fd5b80356135f7816141ac565b5f8083601f8401126141e8575f80fd5b50813567ffffffffffffffff8111156141ff575f80fd5b602083019150836020828501011115614216575f80fd5b9250929050565b5f805f805f805f8060c0898b031215614234575f80fd5b883567ffffffffffffffff8082111561424b575f80fd5b818b0191508b601f83011261425e575f80fd5b81358181111561426c575f80fd5b8c60208260071b8501011115614280575f80fd5b602083019a508099505061429660208c01614181565b97506142a460408c016141a1565b965060608b013595506142b960808c016141cd565b945060a08b01359150808211156142ce575f80fd5b506142db8b828c016141d8565b999c989b5096995094979396929594505050565b801515811461417e575f80fd5b5f6020828403121561430c575f80fd5b8135614166816142ef565b5f805f60608486031215614329575f80fd5b83356143348161418c565b925060208401359150604084013561434b816141ac565b809150509250925092565b5f60208284031215614366575f80fd5b81356141668161418c565b5f8060408385031215614382575f80fd5b823561438d8161418c565b946020939093013593505050565b5f602082840312156143ab575f80fd5b8135614166816141ac565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516080810167ffffffffffffffff81118282101715614406576144066143b6565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614453576144536143b6565b604052919050565b5f67ffffffffffffffff821115614474576144746143b6565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f8301126144af575f80fd5b81356144c26144bd8261445b565b61440c565b8181528460208386010111156144d6575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060c08789031215614507575f80fd5b8635614512816141ac565b95506020870135614522816141ac565b945060408701356145328161416d565b93506060870135614542816141ac565b9250608087013567ffffffffffffffff8082111561455e575f80fd5b61456a8a838b016144a0565b935060a089013591508082111561457f575f80fd5b5061458c89828a016144a0565b9150509295509295509295565b5f8083601f8401126145a9575f80fd5b50813567ffffffffffffffff8111156145c0575f80fd5b6020830191508360208260051b8501011115614216575f80fd5b5f80602083850312156145eb575f80fd5b823567ffffffffffffffff811115614601575f80fd5b61460d85828601614599565b90969095509350505050565b5f805f806080858703121561462c575f80fd5b84356146378161416d565b93506020850135614647816141ac565b925060408501356146578161416d565b9150606085013567ffffffffffffffff811115614672575f80fd5b61467e878288016144a0565b91505092959194509250565b5f805f805f8060a0878903121561469f575f80fd5b863567ffffffffffffffff8111156146b5575f80fd5b6146c189828a01614599565b90975095505060208701356146d58161416d565b935060408701356146e58161418c565b92506060870135915060808701356146fc816141ac565b809150509295509295509295565b5f6020828403121561471a575f80fd5b813567ffffffffffffffff811115614730575f80fd5b612bca848285016144a0565b5f805f6040848603121561474e575f80fd5b833567ffffffffffffffff811115614764575f80fd5b614770868287016141d8565b909790965060209590950135949350505050565b5f60208284031215614794575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff8281168282160390808211156147e9576147e961479b565b5092915050565b5f82614823577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c9082168061483c57607f821691505b602082108103614873577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b8082018082111561488c5761488c61479b565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f608082840312156148cf575f80fd5b6148d76143e3565b823581526020830135602082015260408301356148f38161418c565b60408201526060928301359281019290925250919050565b5f67ffffffffffffffff8083168181036149275761492761479b565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149615761496161479b565b5060010190565b8181038181111561488c5761488c61479b565b808202811582820484141761488c5761488c61479b565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b838152604060208201525f6149f2604083018486614992565b95945050505050565b5f60208284031215614a0b575f80fd5b81516141668161418c565b5f60208284031215614a26575f80fd5b8151614166816142ef565b601f821115613331575f81815260208120601f850160051c81016020861015614a575750805b601f850160051c820191505b81811015612cfd57828155600101614a63565b815167ffffffffffffffff811115614a9057614a906143b6565b614aa481614a9e8454614828565b84614a31565b602080601f831160018114614af6575f8415614ac05750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612cfd565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614b4257888601518255948401946001909101908401614b23565b5085821015614b7e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f614ba0606083018661410b565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff8181168382160190808211156147e9576147e961479b565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614c1f575f80fd5b9190910192915050565b5f60808236031215614c39575f80fd5b614c416143e3565b823567ffffffffffffffff811115614c57575f80fd5b614c63368286016144a0565b825250602083013560208201526040830135614c7e8161418c565b6040820152606092830135928101929092525090565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a0830152614cea60c083018461410b565b98975050505050505050565b61ffff8181168382160190808211156147e9576147e961479b565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751614d79816003860160208c016140e9565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651614dbc816017840160208b016140e9565b808201915050818660f81b16601782015284519150614de28260188301602088016140e9565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b1660018401528751614e5b816003860160208c016140e9565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651614e9e816017840160208b016140e9565b808201915050818660f01b16601782015284519150614ec48260198301602088016140e9565b016019019998505050505050505050565b5f8651614ee6818460208b016140e9565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201525f614f74606083018486614992565b9695505050505050565b5f60208284031215614f8e575f80fd5b815167ffffffffffffffff811115614fa4575f80fd5b8201601f81018413614fb4575f80fd5b8051614fc26144bd8261445b565b818152856020838501011115614fd6575f80fd5b6149f28260208301602086016140e9565b5f8060408385031215614ff8575f80fd5b82516150038161416d565b6020840151909250615014816141ac565b809150509250929050565b5f8251614c1f8184602087016140e956fea26469706673582212208f14e95d711e34ab8ce58024a58ae32be4d80a1ebbc48bf76219efb04a89124264736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610319575f3560e01c80636ff512cc116101a8578063b910e0f9116100f3578063d7bc90ff1161009e578063e7a7ed0211610079578063e7a7ed0214610850578063eaeb077b14610864578063f35dda4714610877578063f851a4401461087f575f80fd5b8063d7bc90ff146107fe578063e46761c414610809578063e57a0b4c14610830575f80fd5b8063c89e42df116100ce578063c89e42df146107a4578063cfa8ed47146107b7578063d02103ca146107d7575f80fd5b8063b910e0f914610761578063c754c7ed14610774578063c7fffd4b1461079c575f80fd5b80639e00187711610153578063a652f26c1161012e578063a652f26c1461072f578063ada8f91914610742578063b0afe15414610755575f80fd5b80639e001877146106da5780639f26f840146106f5578063a3c573eb14610708575f80fd5b80637cd76b8b116101835780637cd76b8b146106ac5780638c3d7301146106bf57806391cafe32146106c7575f80fd5b80636ff512cc1461064a578063712570221461065d5780637a5460c514610670575f80fd5b806340b5de6c1161026857806352bdeb6d11610213578063676870d2116101ee578063676870d21461061a5780636b8616ce146106225780636e05d2cd14610641575f80fd5b806352bdeb6d146105c3578063542028d5146105ff578063669adece14610607575f80fd5b806349b7b8021161024357806349b7b802146105545780634c21fef31461057b5780634e487706146105b0575f80fd5b806340b5de6c146104bb57806342308fab14610513578063456052671461051b575f80fd5b806326782247116102c857806332c2d153116102a357806332c2d1531461044b5780633c351e101461045e5780633cbc795b1461047e575f80fd5b806326782247146103d35780632acdc2b6146104185780632c111c061461042b575f80fd5b8063107bf28c116102f8578063107bf28c1461039c57806311e892d4146103a4578063165e8a8d146103be575f80fd5b8062d0295d1461031d578063035089631461033857806305835f3714610353575b5f80fd5b6103256108a4565b6040519081526020015b60405180910390f35b610340602081565b60405161ffff909116815260200161032f565b61038f6040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b60405161032f9190614154565b61038f6109aa565b6103ac60f981565b60405160ff909116815260200161032f565b6103d16103cc36600461421d565b610a36565b005b6001546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161032f565b6103d16104263660046142fc565b6113bb565b6008546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b6103d1610459366004614317565b6114d9565b6009546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b6009546104a69074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff909116815260200161032f565b6104e27fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff00000000000000000000000000000000000000000000000000000000000000909116815260200161032f565b610325602481565b60075461053b9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161032f565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b603c546105a09074010000000000000000000000000000000000000000900460ff1681565b604051901515815260200161032f565b6103d16105be366004614356565b6115a8565b61038f6040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b61038f6117b7565b6103d1610615366004614371565b6117c4565b610340601f81565b610325610630366004614356565b60066020525f908152604090205481565b61032560055481565b6103d161065836600461439b565b61187b565b6103d161066b3660046144f2565b611944565b61038f6040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b6103d16106ba36600461439b565b611efd565b6103d1611fc6565b6103d16106d536600461439b565b612098565b6103f373a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b6103d16107033660046145da565b6121b0565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b61038f61073d366004614619565b6127f4565b6103d161075036600461439b565b612bd2565b6103256405ca1ab1e081565b6103d161076f36600461468a565b612c9b565b60075461053b90700100000000000000000000000000000000900467ffffffffffffffff1681565b6103ac60e481565b6103d16107b236600461470a565b612d05565b6002546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b610325635ca1ab1e81565b6103f37f000000000000000000000000000000000000000000000000000000000000000081565b603c546103f39073ffffffffffffffffffffffffffffffffffffffff1681565b60075461053b9067ffffffffffffffff1681565b6103d161087236600461473c565b612d97565b6103ac601b81565b5f546103f39062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015610930573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109549190614784565b6007549091505f9061097e9067ffffffffffffffff680100000000000000008204811691166147c8565b67ffffffffffffffff169050805f03610999575f9250505090565b6109a381836147f0565b9250505090565b600480546109b790614828565b80601f01602080910402602001604051908101604052809291908181526020018280546109e390614828565b8015610a2e5780601f10610a0557610100808354040283529160200191610a2e565b820191905f5260205f20905b815481529060010190602001808311610a1157829003601f168201915b505050505081565b60025473ffffffffffffffffffffffffffffffffffffffff163314610a87576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865f819003610ac2576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115610afe576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b09602442614879565b8667ffffffffffffffff161115610b4c576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610bb1575f80fd5b505af1158015610bc3573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff8a1660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa158015610c57573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7b9190614784565b905080610cb4576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b85811015610f9a575f8e8e83818110610cf057610cf0614892565b905060800201803603810190610d0691906148bf565b604081015190915067ffffffffffffffff1615610ef35784610d278161490b565b9550505f815f0151826020015183604001518460600151604051602001610d8c9493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f90815260069093529120549091508114610e14576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84825f0151836020015184604001518e8660600151604051602001610ead969594939291909586526020860194909452604085019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060808501919091521b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166068830152607c820152609c0190565b60405160208183030381529060405280519060200120945060065f8767ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550610f87565b8051604080516020810187905290810191909152606080820188905260c08e901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012093505b5080610f9281614931565b915050610cd5565b5060075467ffffffffffffffff9081169084161115610fe5576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff848116908316146110e2575f61100a83866147c8565b905061102067ffffffffffffffff821683614968565b91506110a17f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff166110596108a4565b611063919061497b565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919061325d565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b801561126b576111e4337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa158015611177573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061119b9190614784565b6111a5919061497b565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190613336565b603c546040517f3b51be4b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911690633b51be4b9061123e908d908c908c906004016149d9565b5f6040518083038186803b158015611254575f80fd5b505afa158015611266573d5f803e3d5ffd5b505050505b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015611307573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061132b91906149fb565b90508a8414611366576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e766876040516113a291815260200190565b60405180910390a2505050505050505050505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611411576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c5474010000000000000000000000000000000000000000900460ff1615158115150361146b576040517f5f0e7abe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c80547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000831515021790556040517ff32a0473f809a720a4f8af1e50d353f1caf7452030626fdaac4273f5e6587f41905f90a150565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314611548576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f59668460405161159b91815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146115fe576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611645576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116ae573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116d29190614a16565b6117335760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610611733576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546109b790614828565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314611833576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581905560405181815267ffffffffffffffff8316907f1125aaf62d132d8e2d02005114f8fc360ff204c3105e4f1a700a1340dc55d5b19060200160405180910390a25050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146118d1576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0906020016117ac565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146119b3576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff16158080156119d157505f54600160ff909116105b806119ea5750303b1580156119ea57505f5460ff166001145b611a7b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015611ad7575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f611ae18561339a565b6009549091505f90611b2b90889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff16856127f4565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ba6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bca9190614784565b90505f808483858f611bdd600143614968565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015611d23573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d4791906149fb565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508860039081611dd79190614a76565b506004611de48982614a76565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e604051611e8493929190614b8e565b60405180910390a15050505050508015611ef4575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611f53576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603c80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fd331bd4c4cd1afecb94a225184bded161ff3213624ba4fb58c4f30c5a861144a906020016117ac565b60015473ffffffffffffffffffffffffffffffffffffffff163314612017576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146120ee576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff1661213d576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb906020016117ac565b60085473ffffffffffffffffffffffffffffffffffffffff1680158015906121ee575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612225576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612293573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122b791906149fb565b6122c19190614bcc565b67ffffffffffffffff161115612303576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81900361233e576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e881111561237a576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff808216916123a291849168010000000000000000900416614879565b11156123da576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b83811015612675575f87878381811061241557612415614892565b90506020028101906124279190614bed565b61243090614c29565b90508361243c8161490b565b825180516020918201208185015160408087015160608801519151959a509295505f946124a8948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f90815260069093529120549091508114612530576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f90815260066020526040812055612554600188614968565b84036125c35742600760109054906101000a900467ffffffffffffffff1684604001516125819190614bcc565b67ffffffffffffffff1611156125c3576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc01604051602081830303815290604052805190602001209450505050808061266d90614931565b9150506123fa565b506126a37f0000000000000000000000000000000000000000000000000000000000000000846110596108a4565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e7390612774908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015612790573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127b491906149fb565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f8760405160240161282696959493929190614c94565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f036129765760f9601f83516128ba9190614cf6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e4876040516020016129609796959493929190614d11565b6040516020818303038152906040529050612a7a565b815161ffff10156129b3576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f96129c2602083614cf6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b90000000000000000000000000000000000000000000000000000000000008152508588604051602001612a679796959493929190614df3565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa158015612ad8573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612b50576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f90612b959084906405ca1ab1e090635ca1ab1e90601b907fff0000000000000000000000000000000000000000000000000000000000000090602001614ed5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612c28576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce6906020016117ac565b603c5474010000000000000000000000000000000000000000900460ff16612cef576040517f821935b400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612cfd8686868686866135fc565b505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612d5b576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003612d678282614a76565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20816040516117ac9190614154565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590612dd5575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612e0c576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e75573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e999190614a16565b15612ed0576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f3a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f5e9190614784565b905082811115612f9a576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115612fd6576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61301873ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084613336565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613082573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130a69190614784565b6007805491925067ffffffffffffffff909116905f6130c48361490b565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055505085856040516130fb929190614f30565b6040519081900390208142613111600143614968565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303613207576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2612cfd565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319061324d90849033908b908b90614f3f565b60405180910390a2505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526133319084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613e73565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526133949085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016132af565b50505050565b606073ffffffffffffffffffffffffffffffffffffffff8216156135f7576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015613441573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526134869190810190614f7e565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa158015613518573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061353c9190614fe7565b915091508163ffffffff165f146135b3576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff8416171790556135f4565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60025473ffffffffffffffffffffffffffffffffffffffff16331461364d576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f819003613688576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156136c4576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6136cf602442614879565b8467ffffffffffffffff161115613712576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015613777575f80fd5b505af1158015613789573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff881660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa15801561381d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138419190614784565b90508061387a576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b85811015613b96575f8c8c838181106138b6576138b6614892565b90506020028101906138c89190614bed565b6138d190614c29565b8051805160209091012060408201519192509067ffffffffffffffff1615613ab157856138fd8161490b565b9650505f8183602001518460400151856060015160405160200161395f9493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f908152600690935291205490915081146139e7576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550613b81565b8151516201d4c01015613af0576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b50508080613b8e90614931565b91505061389b565b5060075467ffffffffffffffff9081169084161115613be1576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff84811690831614613c96575f613c0683866147c8565b9050613c1c67ffffffffffffffff821683614968565b9150613c557f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff166110596108a4565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b613d25337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa158015611177573d5f803e3d5ffd5b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015613dc1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613de591906149fb565b9050888414613e20576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e76687604051613e5c91815260200190565b60405180910390a250505050505050505050505050565b5f613ed4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613f7e9092919063ffffffff16565b8051909150156133315780806020019051810190613ef29190614a16565b613331576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611a72565b6060612bca84845f85855f808673ffffffffffffffffffffffffffffffffffffffff168587604051613fb0919061501f565b5f6040518083038185875af1925050503d805f8114613fea576040519150601f19603f3d011682016040523d82523d5f602084013e613fef565b606091505b50915091506140008783838761400b565b979650505050505050565b606083156140a05782515f036140995773ffffffffffffffffffffffffffffffffffffffff85163b614099576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611a72565b5081612bca565b612bca83838151156140b55781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a729190614154565b5f5b838110156141035781810151838201526020016140eb565b50505f910152565b5f81518084526141228160208601602086016140e9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f614166602083018461410b565b9392505050565b63ffffffff8116811461417e575f80fd5b50565b80356135f78161416d565b67ffffffffffffffff8116811461417e575f80fd5b80356135f78161418c565b73ffffffffffffffffffffffffffffffffffffffff8116811461417e575f80fd5b80356135f7816141ac565b5f8083601f8401126141e8575f80fd5b50813567ffffffffffffffff8111156141ff575f80fd5b602083019150836020828501011115614216575f80fd5b9250929050565b5f805f805f805f8060c0898b031215614234575f80fd5b883567ffffffffffffffff8082111561424b575f80fd5b818b0191508b601f83011261425e575f80fd5b81358181111561426c575f80fd5b8c60208260071b8501011115614280575f80fd5b602083019a508099505061429660208c01614181565b97506142a460408c016141a1565b965060608b013595506142b960808c016141cd565b945060a08b01359150808211156142ce575f80fd5b506142db8b828c016141d8565b999c989b5096995094979396929594505050565b801515811461417e575f80fd5b5f6020828403121561430c575f80fd5b8135614166816142ef565b5f805f60608486031215614329575f80fd5b83356143348161418c565b925060208401359150604084013561434b816141ac565b809150509250925092565b5f60208284031215614366575f80fd5b81356141668161418c565b5f8060408385031215614382575f80fd5b823561438d8161418c565b946020939093013593505050565b5f602082840312156143ab575f80fd5b8135614166816141ac565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040516080810167ffffffffffffffff81118282101715614406576144066143b6565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614453576144536143b6565b604052919050565b5f67ffffffffffffffff821115614474576144746143b6565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f8301126144af575f80fd5b81356144c26144bd8261445b565b61440c565b8181528460208386010111156144d6575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060c08789031215614507575f80fd5b8635614512816141ac565b95506020870135614522816141ac565b945060408701356145328161416d565b93506060870135614542816141ac565b9250608087013567ffffffffffffffff8082111561455e575f80fd5b61456a8a838b016144a0565b935060a089013591508082111561457f575f80fd5b5061458c89828a016144a0565b9150509295509295509295565b5f8083601f8401126145a9575f80fd5b50813567ffffffffffffffff8111156145c0575f80fd5b6020830191508360208260051b8501011115614216575f80fd5b5f80602083850312156145eb575f80fd5b823567ffffffffffffffff811115614601575f80fd5b61460d85828601614599565b90969095509350505050565b5f805f806080858703121561462c575f80fd5b84356146378161416d565b93506020850135614647816141ac565b925060408501356146578161416d565b9150606085013567ffffffffffffffff811115614672575f80fd5b61467e878288016144a0565b91505092959194509250565b5f805f805f8060a0878903121561469f575f80fd5b863567ffffffffffffffff8111156146b5575f80fd5b6146c189828a01614599565b90975095505060208701356146d58161416d565b935060408701356146e58161418c565b92506060870135915060808701356146fc816141ac565b809150509295509295509295565b5f6020828403121561471a575f80fd5b813567ffffffffffffffff811115614730575f80fd5b612bca848285016144a0565b5f805f6040848603121561474e575f80fd5b833567ffffffffffffffff811115614764575f80fd5b614770868287016141d8565b909790965060209590950135949350505050565b5f60208284031215614794575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff8281168282160390808211156147e9576147e961479b565b5092915050565b5f82614823577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c9082168061483c57607f821691505b602082108103614873577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b8082018082111561488c5761488c61479b565b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f608082840312156148cf575f80fd5b6148d76143e3565b823581526020830135602082015260408301356148f38161418c565b60408201526060928301359281019290925250919050565b5f67ffffffffffffffff8083168181036149275761492761479b565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036149615761496161479b565b5060010190565b8181038181111561488c5761488c61479b565b808202811582820484141761488c5761488c61479b565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b838152604060208201525f6149f2604083018486614992565b95945050505050565b5f60208284031215614a0b575f80fd5b81516141668161418c565b5f60208284031215614a26575f80fd5b8151614166816142ef565b601f821115613331575f81815260208120601f850160051c81016020861015614a575750805b601f850160051c820191505b81811015612cfd57828155600101614a63565b815167ffffffffffffffff811115614a9057614a906143b6565b614aa481614a9e8454614828565b84614a31565b602080601f831160018114614af6575f8415614ac05750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612cfd565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614b4257888601518255948401946001909101908401614b23565b5085821015614b7e57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f614ba0606083018661410b565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff8181168382160190808211156147e9576147e961479b565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614c1f575f80fd5b9190910192915050565b5f60808236031215614c39575f80fd5b614c416143e3565b823567ffffffffffffffff811115614c57575f80fd5b614c63368286016144a0565b825250602083013560208201526040830135614c7e8161418c565b6040820152606092830135928101929092525090565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a0830152614cea60c083018461410b565b98975050505050505050565b61ffff8181168382160190808211156147e9576147e961479b565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751614d79816003860160208c016140e9565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651614dbc816017840160208b016140e9565b808201915050818660f81b16601782015284519150614de28260188301602088016140e9565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b1660018401528751614e5b816003860160208c016140e9565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651614e9e816017840160208b016140e9565b808201915050818660f01b16601782015284519150614ec48260198301602088016140e9565b016019019998505050505050505050565b5f8651614ee6818460208b016140e9565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201525f614f74606083018486614992565b9695505050505050565b5f60208284031215614f8e575f80fd5b815167ffffffffffffffff811115614fa4575f80fd5b8201601f81018413614fb4575f80fd5b8051614fc26144bd8261445b565b818152856020838501011115614fd6575f80fd5b6149f28260208301602086016140e9565b5f8060408385031215614ff8575f80fd5b82516150038161416d565b6020840151909250615014816141ac565b809150509250929050565b5f8251614c1f8184602087016140e956fea26469706673582212208f14e95d711e34ab8ce58024a58ae32be4d80a1ebbc48bf76219efb04a89124264736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVM.json b/compiled-contracts/PolygonZkEVM.json index 4e967a181..73789aacc 100644 --- a/compiled-contracts/PolygonZkEVM.json +++ b/compiled-contracts/PolygonZkEVM.json @@ -1711,8 +1711,8 @@ "type": "function" } ], - "bytecode": "0x61014060405234801562000011575f80fd5b5060405162005f6438038062005f648339810160408190526200003491620000a2565b6001600160a01b0395861660c05293851660805291841660a05290921660e0526001600160401b039182166101005216610120526200012a565b6001600160a01b038116811462000083575f80fd5b50565b80516001600160401b03811681146200009d575f80fd5b919050565b5f805f805f8060c08789031215620000b8575f80fd5b8651620000c5816200006e565b6020880151909650620000d8816200006e565b6040880151909550620000eb816200006e565b6060880151909450620000fe816200006e565b92506200010e6080880162000086565b91506200011e60a0880162000086565b90509295509295509295565b60805160a05160c05160e0516101005161012051615d74620001f05f395f818161068201528181610dd3015261311d01525f81816107ee0152610da901525f81816107b401528181611d60015281816137ae0152614c0001525f818161095901528181610f45015281816111100152818161196d0152818161212e0152818161398f01526146d801525f8181610a0601528181614041015261448f01525f81816108a901528181611d2e0152818161261301528181613964015261412d0152615d745ff3fe608060405234801561000f575f80fd5b50600436106103a9575f3560e01c8063841b24d7116101ea578063c754c7ed11610114578063e7a7ed02116100a9578063f14916d611610079578063f14916d614610a68578063f2fde38b14610a7b578063f851a44014610a8e578063f8b823e414610aae575f80fd5b8063e7a7ed02146109d1578063e8bf92ed14610a01578063eaeb077b14610a28578063ed6b010414610a3b575f80fd5b8063d2e129f9116100e4578063d2e129f91461097b578063d8d1091b1461098e578063d939b315146109a1578063dbc16976146109c9575f80fd5b8063c754c7ed146108e6578063c89e42df14610912578063cfa8ed4714610925578063d02103ca14610954575f80fd5b8063a3c573eb1161018a578063b4d63f581161015a578063b4d63f581461083e578063b6b0b097146108a4578063ba58ae39146108cb578063c0ed84e0146108de575f80fd5b8063a3c573eb146107af578063ada8f919146107d6578063adc879e9146107e9578063afd23cbe14610810575f80fd5b806399f5634e116101c557806399f5634e1461076e5780639aa972a3146107765780639c9f3dfe14610789578063a066215c1461079c575f80fd5b8063841b24d7146107185780638c3d7301146107485780638da5cb5b14610750575f80fd5b80634a1a89a7116102d6578063621dd4111161026b5780637215541a1161023b5780637215541a146106565780637fcb365314610669578063831c7ead1461067d578063837a4738146106a4575f80fd5b8063621dd411146106095780636b8616ce1461061c5780636ff512cc1461063b578063715018a61461064e575f80fd5b8063542028d5116102a6578063542028d5146105de5780635e9145c9146105e65780635ec91958146105f95780636046916914610601575f80fd5b80634a1a89a71461056b5780634a910e6a1461058b5780634e4877061461059e5780635392c5e0146105b1575f80fd5b8063298789831161034c578063394218e91161031c578063394218e9146104fc578063423fa8561461050f578063456052671461052f578063458c047714610557575f80fd5b806329878983146104975780632b0006fa146104c35780632c1f816a146104d6578063383b3be8146104e9575f80fd5b80631816b7e5116103875780631816b7e51461041657806319d8ac611461042b578063220d78991461043f5780632678224714610452575f80fd5b80630a0d9fbe146103ad578063107bf28c146103e457806315064c96146103f9575b5f80fd5b606f546103c690610100900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6103ec610ab7565b6040516103db919061521a565b606f546104069060ff1681565b60405190151581526020016103db565b610429610424366004615233565b610b43565b005b6073546103c69067ffffffffffffffff1681565b6103ec61044d36600461526b565b610c5b565b607b546104729073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103db565b6074546104729068010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104296104d13660046152cb565b610e31565b6104296104e436600461532f565b610ffb565b6104066104f73660046153a4565b611203565b61042961050a3660046153a4565b611258565b6073546103c69068010000000000000000900467ffffffffffffffff1681565b6073546103c690700100000000000000000000000000000000900467ffffffffffffffff1681565b6079546103c69067ffffffffffffffff1681565b6079546103c69068010000000000000000900467ffffffffffffffff1681565b6104296105993660046153a4565b6113dc565b6104296105ac3660046153a4565b61148f565b6105d06105bf3660046153a4565b60756020525f908152604090205481565b6040519081526020016103db565b6103ec611613565b6104296105f4366004615428565b611620565b610429611e19565b6105d0611f18565b6104296106173660046152cb565b611f2d565b6105d061062a3660046153a4565b60716020525f908152604090205481565b610429610649366004615478565b6122ab565b610429612380565b6104296106643660046153a4565b612393565b6074546103c69067ffffffffffffffff1681565b6103c67f000000000000000000000000000000000000000000000000000000000000000081565b6106ec6106b2366004615491565b60786020525f908152604090208054600182015460029092015467ffffffffffffffff808316936801000000000000000090930416919084565b6040805167ffffffffffffffff95861681529490931660208501529183015260608201526080016103db565b6079546103c6907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b610429612500565b60335473ffffffffffffffffffffffffffffffffffffffff16610472565b6105d06125cc565b61042961078436600461532f565b61271f565b6104296107973660046153a4565b6127cf565b6104296107aa3660046153a4565b61294b565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b6104296107e4366004615478565b612a51565b6103c67f000000000000000000000000000000000000000000000000000000000000000081565b606f5461082b906901000000000000000000900461ffff1681565b60405161ffff90911681526020016103db565b61087e61084c3660046153a4565b60726020525f90815260409020805460019091015467ffffffffffffffff808216916801000000000000000090041683565b6040805193845267ffffffffffffffff92831660208501529116908201526060016103db565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b6104066108d9366004615491565b612b15565b6103c6612b9d565b607b546103c69074010000000000000000000000000000000000000000900467ffffffffffffffff1681565b61042961092036600461557c565b612bf0565b606f54610472906b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b6104296109893660046155ec565b612c7d565b61042961099c366004615697565b6131c0565b6079546103c690700100000000000000000000000000000000900467ffffffffffffffff1681565b61042961375b565b6073546103c6907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b610429610a363660046156d6565b61382f565b607b54610406907c0100000000000000000000000000000000000000000000000000000000900460ff1681565b610429610a76366004615478565b613c1f565b610429610a89366004615478565b613cf1565b607a546104729073ffffffffffffffffffffffffffffffffffffffff1681565b6105d060705481565b60778054610ac49061571e565b80601f0160208091040260200160405190810160405280929190818152602001828054610af09061571e565b8015610b3b5780601f10610b1257610100808354040283529160200191610b3b565b820191905f5260205f20905b815481529060010190602001808311610b1e57829003601f168201915b505050505081565b607a5473ffffffffffffffffffffffffffffffffffffffff163314610b94576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88161ffff161080610bad57506103ff8161ffff16115b15610be4576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffff16690100000000000000000061ffff8416908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a150565b67ffffffffffffffff8086165f818152607260205260408082205493881682529020546060929115801590610c8e575081155b15610cc5576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610cfc576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0584612b15565b610d3b576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b166020820152603481019690965260548601929092527fffffffffffffffff00000000000000000000000000000000000000000000000060c098891b811660748701527f0000000000000000000000000000000000000000000000000000000000000000891b8116607c8701527f0000000000000000000000000000000000000000000000000000000000000000891b81166084870152608c86019490945260ac85015260cc840194909452509290931b90911660ec830152805180830360d401815260f4909201905290565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610e8e576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e9c868686868686613da5565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615610f1657607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015610f9b575f80fd5b505af1158015610fad573d5f803e3d5ffd5b505060405184815233925067ffffffffffffffff871691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe906020015b60405180910390a3505050505050565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611058576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61106787878787878787614160565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f90815260756020526040902083905560795416156110e157607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611166575f80fd5b505af1158015611178573d5f803e3d5ffd5b50506079805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a800000000000000000000000000000000000000000000000001790555050604051828152339067ffffffffffffffff8616907fcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf729060200160405180910390a350505050505050565b60795467ffffffffffffffff8281165f9081526078602052604081205490924292611246927001000000000000000000000000000000009092048116911661579c565b67ffffffffffffffff16111592915050565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146112a9576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff821611156112f0576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661135f5760795467ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169082161061135f576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a190602001610c50565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461148357606f5460ff1615611444576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61144d81611203565b611483576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61148c8161458f565b50565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146114e0576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611527576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661159257607b5467ffffffffffffffff74010000000000000000000000000000000000000000909104811690821610611592576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b90602001610c50565b60768054610ac49061571e565b606f5460ff161561165d576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1633146116bd576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f8190036116f8576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611734576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f81815260726020526040812054838516949293700100000000000000000000000000000000909304909216919082905b86811015611b7c575f8a8a8381811061179a5761179a6157c4565b90506020028101906117ac91906157f1565b6117b59061582d565b8051805160209091012060608201519192509067ffffffffffffffff161561192a57856117e1816158b7565b9650505f818360200151846060015160405160200161183893929190928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f908152607190935291205490915081146118c0576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8088165f908152607160205260408082209190915560608501519085015190821691161015611924576040517f7f7ab87200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611a64565b6020820151158015906119ee575060208201516040517f257b363200000000000000000000000000000000000000000000000000000000815260048101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063257b3632906024016020604051808303815f875af11580156119c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ec91906158dd565b155b15611a25576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516201d4c01015611a64576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8767ffffffffffffffff16826040015167ffffffffffffffff161080611a97575042826040015167ffffffffffffffff16115b15611ace576040517fea82791600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602082810151604080850151815193840189905290830184905260608084019290925260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c016040516020818303038152906040528051906020012094508160400151975050508080611b74906158f4565b91505061177f565b50611b87868561579c565b60735490945067ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169084161115611bf0576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611bfb828561592b565b611c0f9067ffffffffffffffff168861594c565b604080516060810182528581524267ffffffffffffffff908116602080840191825260738054680100000000000000009081900485168688019081528d86165f8181526072909552979093209551865592516001909501805492519585167fffffffffffffffffffffffffffffffff000000000000000000000000000000009384161795851684029590951790945583548c8416911617930292909217905590915082811690851614611d0457607380547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8716021790555b611d56333083607054611d17919061595f565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692919061479c565b611d5e61487e565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611dc3575f80fd5b505af1158015611dd5573d5f803e3d5ffd5b505060405167ffffffffffffffff881692507f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce91505f90a250505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611e6a576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b547c0100000000000000000000000000000000000000000000000000000000900460ff16611ec6576040517ff6ba91a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690556040517f854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f905f90a1565b5f6070546064611f28919061595f565b905090565b606f5460ff1615611f6a576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff8581165f908152607260205260409020600101544292611fb69278010000000000000000000000000000000000000000000000009091048116911661579c565b67ffffffffffffffff161115611ff8576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8612005868661592b565b67ffffffffffffffff161115612047576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612055868686868686613da5565b61205e8461492d565b607954700100000000000000000000000000000000900467ffffffffffffffff165f0361219f57607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f90815260756020526040902083905560795416156120ff57607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015612184575f80fd5b505af1158015612196573d5f803e3d5ffd5b5050505061226d565b6121a761487e565b6079805467ffffffffffffffff16905f6121c0836158b7565b825467ffffffffffffffff9182166101009390930a92830292820219169190911790915560408051608081018252428316815287831660208083019182528284018981526060840189815260795487165f908152607890935294909120925183549251861668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169516949094171781559151600183015551600290910155505b604051828152339067ffffffffffffffff8616907f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596690602001610feb565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146122fc576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fff0000000000000000000000000000000000000000ffffffffffffffffffffff166b01000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c50565b612388614b07565b6123915f614b88565b565b60335473ffffffffffffffffffffffffffffffffffffffff1633146124f8575f6123bb612b9d565b90508067ffffffffffffffff168267ffffffffffffffff161161240a576040517f812a372d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff680100000000000000009091048116908316118061244f575067ffffffffffffffff8083165f9081526072602052604090206001015416155b15612486576040517f98c5c01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8083165f9081526072602052604090206001015442916124b49162093a80911661579c565b67ffffffffffffffff1611156124f6576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b61148c614bfe565b607b5473ffffffffffffffffffffffffffffffffffffffff163314612551576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b54607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691821790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612658573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061267c91906158dd565b90505f612687612b9d565b60735467ffffffffffffffff6801000000000000000082048116916126df917001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041661592b565b6126e9919061579c565b6126f3919061592b565b67ffffffffffffffff169050805f0361270e575f9250505090565b61271881836159a3565b9250505090565b606f5460ff161561275c576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61276b87878787878787614160565b67ffffffffffffffff84165f908152607560209081526040918290205482519081529081018490527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a16127c6614bfe565b50505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612820576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115612867576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff166128ce5760795467ffffffffffffffff7001000000000000000000000000000000009091048116908216106128ce576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607980547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c7590602001610c50565b607a5473ffffffffffffffffffffffffffffffffffffffff16331461299c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620151808167ffffffffffffffff1611156129e3576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1661010067ffffffffffffffff8416908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c2890602001610c50565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612aa2576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c50565b5f67ffffffff0000000167ffffffffffffffff8316108015612b4c575067ffffffff00000001604083901c67ffffffffffffffff16105b8015612b6d575067ffffffff00000001608083901c67ffffffffffffffff16105b8015612b84575067ffffffff0000000160c083901c105b15612b9157506001919050565b505f919050565b919050565b6079545f9067ffffffffffffffff1615612bdf575060795467ffffffffffffffff9081165f908152607860205260409020546801000000000000000090041690565b5060745467ffffffffffffffff1690565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612c41576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6076612c4d8282615a03565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c50919061521a565b5f54610100900460ff1615808015612c9b57505f54600160ff909116105b80612cb45750303b158015612cb457505f5460ff166001145b612d45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015612da1575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b612dae6020880188615478565b607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055612e036040880160208901615478565b606f805473ffffffffffffffffffffffffffffffffffffffff929092166b010000000000000000000000027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055612e686080880160608901615478565b6074805473ffffffffffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9092169190911790555f805260756020527ff9e3fbf150b7a0077118526f473c53cb4734f166167e2c6213e3567dd390b4ad8690556076612ef28682615a03565b506077612eff8582615a03565b5062093a80612f146060890160408a016153a4565b67ffffffffffffffff161115612f56576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612f6660608801604089016153a4565b6079805467ffffffffffffffff92909216700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905562093a80612fc860a0890160808a016153a4565b67ffffffffffffffff16111561300a576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61301a60a08801608089016153a4565b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff939093169290920291909117905567016345785d8a0000607055606f80547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff166a03ea000000000000070800179055607b80547fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff167c01000000000006978000000000000000000000000000000000000000001790556130f9614c81565b7fed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd65f7f0000000000000000000000000000000000000000000000000000000000000000858560405161314e9493929190615b62565b60405180910390a180156127c6575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff161561321d576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff161561325a576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f819003613295576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156132d1576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff7801000000000000000000000000000000000000000000000000820481169161331c918491700100000000000000000000000000000000900416615b99565b1115613354576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f8181526072602052604081205491937001000000000000000000000000000000009004909216915b848110156135f9575f8787838181106133b2576133b26157c4565b90506020028101906133c49190615bac565b6133cd90615bde565b9050836133d9816158b7565b825180516020918201208185015160408087015190519499509194505f9361343a9386939101928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f908152607190935291205490915081146134c2576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f908152607160205260408120556134e660018961594c565b84036135555742607b60149054906101000a900467ffffffffffffffff168460400151613513919061579c565b67ffffffffffffffff161115613555576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020838101516040805192830188905282018490526060808301919091524260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016608083015233901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c0160405160208183030381529060405280519060200120945050505080806135f1906158f4565b915050613397565b50613604848461579c565b6073805467ffffffffffffffff4281167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217808455604080516060810182528781526020808201958652680100000000000000009384900485168284019081528589165f818152607290935284832093518455965160019390930180549151871686027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921693871693909317179091558554938916700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff938602939093167fffffffffffffffff00000000000000000000000000000000ffffffffffffffff90941693909317919091179093559151929550917f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a49190a2505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146137ac576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dbc169766040518163ffffffff1660e01b81526004015f604051808303815f87803b158015613811575f80fd5b505af1158015613823573d5f803e3d5ffd5b50505050612391614d20565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff161561388c576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff16156138c9576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6138d2611f18565b90508181111561390e576040517f4732fdb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61138883111561394a576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61398c73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633308461479c565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156139f6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613a1a91906158dd565b60738054919250780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16906018613a54836158b7565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508484604051613a8b929190615c57565b60408051918290038220602083015281018290527fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b166060820152606801604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206073547801000000000000000000000000000000000000000000000000900467ffffffffffffffff165f9081526071909352912055323303613bb9576073546040805183815233602082015260609181018290525f91810191909152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319060800160405180910390a2613c18565b607360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93182338888604051613c0f9493929190615c66565b60405180910390a25b5050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314613c70576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607480547fffffffff0000000000000000000000000000000000000000ffffffffffffffff166801000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527f61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca90602001610c50565b613cf9614b07565b73ffffffffffffffffffffffffffffffffffffffff8116613d9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401612d3c565b61148c81614b88565b5f80613daf612b9d565b905067ffffffffffffffff881615613e7e5760795467ffffffffffffffff9081169089161115613e0b576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8089165f908152607860205260409020600281015481549094509091898116680100000000000000009092041614613e78576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50613f1e565b67ffffffffffffffff87165f90815260756020526040902054915081613ed0576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff161115613f1e576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168667ffffffffffffffff1611613f6b576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f613f798888888689610c5b565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051613fad9190615c9b565b602060405180830381855afa158015613fc8573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190613feb91906158dd565b613ff59190615cac565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a9161407791899190600401615cbf565b602060405180830381865afa158015614092573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906140b69190615cf9565b6140ec576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614154336140fa858b61592b565b67ffffffffffffffff1661410c6125cc565b614116919061595f565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190614dae565b50505050505050505050565b5f67ffffffffffffffff88161561422c5760795467ffffffffffffffff90811690891611156141bb576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5067ffffffffffffffff8088165f908152607860205260409020600281015481549092888116680100000000000000009092041614614226576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506142c7565b5067ffffffffffffffff85165f908152607560205260409020548061427d576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60745467ffffffffffffffff90811690871611156142c7576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff90811690881611806142f957508767ffffffffffffffff168767ffffffffffffffff1611155b80614320575060795467ffffffffffffffff68010000000000000000909104811690881611155b15614357576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8781165f908152607860205260409020546801000000000000000090048116908616146143b9576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6143c78787878588610c5b565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516143fb9190615c9b565b602060405180830381855afa158015614416573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061443991906158dd565b6144439190615cac565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a916144c591889190600401615cbf565b602060405180830381865afa1580156144e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906145049190615cf9565b61453a576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff89165f90815260786020526040902060020154859003614154576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff6801000000000000000090910481169082161115806145c9575060795467ffffffffffffffff908116908216115b15614600576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8181165f81815260786020908152604080832080546074805468010000000000000000928390049098167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090981688179055600282015487865260759094529382902092909255607980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff169390940292909217909255600182015490517f33d6247d00000000000000000000000000000000000000000000000000000000815260048101919091529091907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b15801561472e575f80fd5b505af1158015614740573d5f803e3d5ffd5b505050508267ffffffffffffffff168167ffffffffffffffff167f328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e846002015460405161478f91815260200190565b60405180910390a3505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526148789085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614e09565b50505050565b60795467ffffffffffffffff680100000000000000008204811691161115612391576079545f906148c69068010000000000000000900467ffffffffffffffff16600161579c565b90506148d181611203565b1561148c576079545f906002906148f390849067ffffffffffffffff1661592b565b6148fd9190615d18565b614907908361579c565b905061491281611203565b15614924576149208161458f565b5050565b6149208261458f565b5f614936612b9d565b9050815f80614945848461592b565b606f5467ffffffffffffffff91821692505f91614968916101009004164261594c565b90505b8467ffffffffffffffff168467ffffffffffffffff16146149f25767ffffffffffffffff8085165f90815260726020526040902060018101549091168210156149d057600181015468010000000000000000900467ffffffffffffffff1694506149ec565b6149da868661592b565b67ffffffffffffffff169350506149f2565b5061496b565b5f6149fd848461594c565b905083811015614a5457808403600c8111614a185780614a1b565b600c5b9050806103e80a81606f60099054906101000a900461ffff1661ffff160a6070540281614a4a57614a4a615976565b0460705550614ac3565b838103600c8111614a655780614a68565b600c5b90505f816103e80a82606f60099054906101000a900461ffff1661ffff160a670de0b6b3a76400000281614a9e57614a9e615976565b04905080607054670de0b6b3a76400000281614abc57614abc615976565b0460705550505b683635c9adc5dea000006070541115614ae857683635c9adc5dea000006070556127c6565b633b9aca0060705410156127c657633b9aca0060705550505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314612391576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401612d3c565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b158015614c63575f80fd5b505af1158015614c75573d5f803e3d5ffd5b50505050612391614f14565b5f54610100900460ff16614d17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401612d3c565b61239133614b88565b606f5460ff16614d5c576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052614e049084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016147f6565b505050565b5f614e6a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16614fa69092919063ffffffff16565b805190915015614e045780806020019051810190614e889190615cf9565b614e04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401612d3c565b606f5460ff1615614f51576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b6060614fb484845f85614fbc565b949350505050565b60608247101561504e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401612d3c565b5f808673ffffffffffffffffffffffffffffffffffffffff1685876040516150769190615c9b565b5f6040518083038185875af1925050503d805f81146150b0576040519150601f19603f3d011682016040523d82523d5f602084013e6150b5565b606091505b50915091506150c6878383876150d1565b979650505050505050565b606083156151665782515f0361515f5773ffffffffffffffffffffffffffffffffffffffff85163b61515f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612d3c565b5081614fb4565b614fb4838381511561517b5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d3c919061521a565b5f5b838110156151c95781810151838201526020016151b1565b50505f910152565b5f81518084526151e88160208601602086016151af565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61522c60208301846151d1565b9392505050565b5f60208284031215615243575f80fd5b813561ffff8116811461522c575f80fd5b803567ffffffffffffffff81168114612b98575f80fd5b5f805f805f60a0868803121561527f575f80fd5b61528886615254565b945061529660208701615254565b94979496505050506040830135926060810135926080909101359150565b8061030081018310156152c5575f80fd5b92915050565b5f805f805f806103a087890312156152e1575f80fd5b6152ea87615254565b95506152f860208801615254565b945061530660408801615254565b935060608701359250608087013591506153238860a089016152b4565b90509295509295509295565b5f805f805f805f6103c0888a031215615346575f80fd5b61534f88615254565b965061535d60208901615254565b955061536b60408901615254565b945061537960608901615254565b93506080880135925060a088013591506153968960c08a016152b4565b905092959891949750929550565b5f602082840312156153b4575f80fd5b61522c82615254565b5f8083601f8401126153cd575f80fd5b50813567ffffffffffffffff8111156153e4575f80fd5b6020830191508360208260051b85010111156153fe575f80fd5b9250929050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612b98575f80fd5b5f805f6040848603121561543a575f80fd5b833567ffffffffffffffff811115615450575f80fd5b61545c868287016153bd565b909450925061546f905060208501615405565b90509250925092565b5f60208284031215615488575f80fd5b61522c82615405565b5f602082840312156154a1575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f8301126154e4575f80fd5b813567ffffffffffffffff808211156154ff576154ff6154a8565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715615545576155456154a8565b8160405283815286602085880101111561555d575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f6020828403121561558c575f80fd5b813567ffffffffffffffff8111156155a2575f80fd5b614fb4848285016154d5565b5f8083601f8401126155be575f80fd5b50813567ffffffffffffffff8111156155d5575f80fd5b6020830191508360208285010111156153fe575f80fd5b5f805f805f80868803610120811215615603575f80fd5b60a0811215615610575f80fd5b5086955060a0870135945060c087013567ffffffffffffffff80821115615635575f80fd5b6156418a838b016154d5565b955060e0890135915080821115615656575f80fd5b6156628a838b016154d5565b9450610100890135915080821115615678575f80fd5b5061568589828a016155ae565b979a9699509497509295939492505050565b5f80602083850312156156a8575f80fd5b823567ffffffffffffffff8111156156be575f80fd5b6156ca858286016153bd565b90969095509350505050565b5f805f604084860312156156e8575f80fd5b833567ffffffffffffffff8111156156fe575f80fd5b61570a868287016155ae565b909790965060209590950135949350505050565b600181811c9082168061573257607f821691505b602082108103615769577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff8181168382160190808211156157bd576157bd61576f565b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112615823575f80fd5b9190910192915050565b5f6080823603121561583d575f80fd5b6040516080810167ffffffffffffffff8282108183111715615861576158616154a8565b816040528435915080821115615875575f80fd5b50615882368286016154d5565b8252506020830135602082015261589b60408401615254565b60408201526158ac60608401615254565b606082015292915050565b5f67ffffffffffffffff8083168181036158d3576158d361576f565b6001019392505050565b5f602082840312156158ed575f80fd5b5051919050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036159245761592461576f565b5060010190565b67ffffffffffffffff8281168282160390808211156157bd576157bd61576f565b818103818111156152c5576152c561576f565b80820281158282048414176152c5576152c561576f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f826159b1576159b1615976565b500490565b601f821115614e04575f81815260208120601f850160051c810160208610156159dc5750805b601f850160051c820191505b818110156159fb578281556001016159e8565b505050505050565b815167ffffffffffffffff811115615a1d57615a1d6154a8565b615a3181615a2b845461571e565b846159b6565b602080601f831160018114615a83575f8415615a4d5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556159fb565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015615acf57888601518255948401946001909101908401615ab0565b5085821015615b0b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f67ffffffffffffffff808716835280861660208401525060606040830152615b8f606083018486615b1b565b9695505050505050565b808201808211156152c5576152c561576f565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112615823575f80fd5b5f60608236031215615bee575f80fd5b6040516060810167ffffffffffffffff8282108183111715615c1257615c126154a8565b816040528435915080821115615c26575f80fd5b50615c33368286016154d5565b82525060208301356020820152615c4c60408401615254565b604082015292915050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201525f615b8f606083018486615b1b565b5f82516158238184602087016151af565b5f82615cba57615cba615976565b500690565b6103208101610300808584378201835f5b6001811015615cef578151835260209283019290910190600101615cd0565b5050509392505050565b5f60208284031215615d09575f80fd5b8151801515811461522c575f80fd5b5f67ffffffffffffffff80841680615d3257615d32615976565b9216919091049291505056fea2646970667358221220037883250178a4dbbb3550eba18a465d36ff27719a1da48e547cafff0383598464736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106103a9575f3560e01c8063841b24d7116101ea578063c754c7ed11610114578063e7a7ed02116100a9578063f14916d611610079578063f14916d614610a68578063f2fde38b14610a7b578063f851a44014610a8e578063f8b823e414610aae575f80fd5b8063e7a7ed02146109d1578063e8bf92ed14610a01578063eaeb077b14610a28578063ed6b010414610a3b575f80fd5b8063d2e129f9116100e4578063d2e129f91461097b578063d8d1091b1461098e578063d939b315146109a1578063dbc16976146109c9575f80fd5b8063c754c7ed146108e6578063c89e42df14610912578063cfa8ed4714610925578063d02103ca14610954575f80fd5b8063a3c573eb1161018a578063b4d63f581161015a578063b4d63f581461083e578063b6b0b097146108a4578063ba58ae39146108cb578063c0ed84e0146108de575f80fd5b8063a3c573eb146107af578063ada8f919146107d6578063adc879e9146107e9578063afd23cbe14610810575f80fd5b806399f5634e116101c557806399f5634e1461076e5780639aa972a3146107765780639c9f3dfe14610789578063a066215c1461079c575f80fd5b8063841b24d7146107185780638c3d7301146107485780638da5cb5b14610750575f80fd5b80634a1a89a7116102d6578063621dd4111161026b5780637215541a1161023b5780637215541a146106565780637fcb365314610669578063831c7ead1461067d578063837a4738146106a4575f80fd5b8063621dd411146106095780636b8616ce1461061c5780636ff512cc1461063b578063715018a61461064e575f80fd5b8063542028d5116102a6578063542028d5146105de5780635e9145c9146105e65780635ec91958146105f95780636046916914610601575f80fd5b80634a1a89a71461056b5780634a910e6a1461058b5780634e4877061461059e5780635392c5e0146105b1575f80fd5b8063298789831161034c578063394218e91161031c578063394218e9146104fc578063423fa8561461050f578063456052671461052f578063458c047714610557575f80fd5b806329878983146104975780632b0006fa146104c35780632c1f816a146104d6578063383b3be8146104e9575f80fd5b80631816b7e5116103875780631816b7e51461041657806319d8ac611461042b578063220d78991461043f5780632678224714610452575f80fd5b80630a0d9fbe146103ad578063107bf28c146103e457806315064c96146103f9575b5f80fd5b606f546103c690610100900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6103ec610ab7565b6040516103db919061521a565b606f546104069060ff1681565b60405190151581526020016103db565b610429610424366004615233565b610b43565b005b6073546103c69067ffffffffffffffff1681565b6103ec61044d36600461526b565b610c5b565b607b546104729073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103db565b6074546104729068010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104296104d13660046152cb565b610e31565b6104296104e436600461532f565b610ffb565b6104066104f73660046153a4565b611203565b61042961050a3660046153a4565b611258565b6073546103c69068010000000000000000900467ffffffffffffffff1681565b6073546103c690700100000000000000000000000000000000900467ffffffffffffffff1681565b6079546103c69067ffffffffffffffff1681565b6079546103c69068010000000000000000900467ffffffffffffffff1681565b6104296105993660046153a4565b6113dc565b6104296105ac3660046153a4565b61148f565b6105d06105bf3660046153a4565b60756020525f908152604090205481565b6040519081526020016103db565b6103ec611613565b6104296105f4366004615428565b611620565b610429611e19565b6105d0611f18565b6104296106173660046152cb565b611f2d565b6105d061062a3660046153a4565b60716020525f908152604090205481565b610429610649366004615478565b6122ab565b610429612380565b6104296106643660046153a4565b612393565b6074546103c69067ffffffffffffffff1681565b6103c67f000000000000000000000000000000000000000000000000000000000000000081565b6106ec6106b2366004615491565b60786020525f908152604090208054600182015460029092015467ffffffffffffffff808316936801000000000000000090930416919084565b6040805167ffffffffffffffff95861681529490931660208501529183015260608201526080016103db565b6079546103c6907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b610429612500565b60335473ffffffffffffffffffffffffffffffffffffffff16610472565b6105d06125cc565b61042961078436600461532f565b61271f565b6104296107973660046153a4565b6127cf565b6104296107aa3660046153a4565b61294b565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b6104296107e4366004615478565b612a51565b6103c67f000000000000000000000000000000000000000000000000000000000000000081565b606f5461082b906901000000000000000000900461ffff1681565b60405161ffff90911681526020016103db565b61087e61084c3660046153a4565b60726020525f90815260409020805460019091015467ffffffffffffffff808216916801000000000000000090041683565b6040805193845267ffffffffffffffff92831660208501529116908201526060016103db565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b6104066108d9366004615491565b612b15565b6103c6612b9d565b607b546103c69074010000000000000000000000000000000000000000900467ffffffffffffffff1681565b61042961092036600461557c565b612bf0565b606f54610472906b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b6104296109893660046155ec565b612c7d565b61042961099c366004615697565b6131c0565b6079546103c690700100000000000000000000000000000000900467ffffffffffffffff1681565b61042961375b565b6073546103c6907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b610429610a363660046156d6565b61382f565b607b54610406907c0100000000000000000000000000000000000000000000000000000000900460ff1681565b610429610a76366004615478565b613c1f565b610429610a89366004615478565b613cf1565b607a546104729073ffffffffffffffffffffffffffffffffffffffff1681565b6105d060705481565b60778054610ac49061571e565b80601f0160208091040260200160405190810160405280929190818152602001828054610af09061571e565b8015610b3b5780601f10610b1257610100808354040283529160200191610b3b565b820191905f5260205f20905b815481529060010190602001808311610b1e57829003601f168201915b505050505081565b607a5473ffffffffffffffffffffffffffffffffffffffff163314610b94576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88161ffff161080610bad57506103ff8161ffff16115b15610be4576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffff16690100000000000000000061ffff8416908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a150565b67ffffffffffffffff8086165f818152607260205260408082205493881682529020546060929115801590610c8e575081155b15610cc5576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610cfc576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0584612b15565b610d3b576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b166020820152603481019690965260548601929092527fffffffffffffffff00000000000000000000000000000000000000000000000060c098891b811660748701527f0000000000000000000000000000000000000000000000000000000000000000891b8116607c8701527f0000000000000000000000000000000000000000000000000000000000000000891b81166084870152608c86019490945260ac85015260cc840194909452509290931b90911660ec830152805180830360d401815260f4909201905290565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610e8e576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e9c868686868686613da5565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615610f1657607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015610f9b575f80fd5b505af1158015610fad573d5f803e3d5ffd5b505060405184815233925067ffffffffffffffff871691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe906020015b60405180910390a3505050505050565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611058576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61106787878787878787614160565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f90815260756020526040902083905560795416156110e157607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611166575f80fd5b505af1158015611178573d5f803e3d5ffd5b50506079805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a800000000000000000000000000000000000000000000000001790555050604051828152339067ffffffffffffffff8616907fcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf729060200160405180910390a350505050505050565b60795467ffffffffffffffff8281165f9081526078602052604081205490924292611246927001000000000000000000000000000000009092048116911661579c565b67ffffffffffffffff16111592915050565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146112a9576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff821611156112f0576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661135f5760795467ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169082161061135f576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a190602001610c50565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461148357606f5460ff1615611444576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61144d81611203565b611483576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61148c8161458f565b50565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146114e0576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611527576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661159257607b5467ffffffffffffffff74010000000000000000000000000000000000000000909104811690821610611592576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b90602001610c50565b60768054610ac49061571e565b606f5460ff161561165d576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1633146116bd576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f8190036116f8576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611734576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f81815260726020526040812054838516949293700100000000000000000000000000000000909304909216919082905b86811015611b7c575f8a8a8381811061179a5761179a6157c4565b90506020028101906117ac91906157f1565b6117b59061582d565b8051805160209091012060608201519192509067ffffffffffffffff161561192a57856117e1816158b7565b9650505f818360200151846060015160405160200161183893929190928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f908152607190935291205490915081146118c0576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8088165f908152607160205260408082209190915560608501519085015190821691161015611924576040517f7f7ab87200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611a64565b6020820151158015906119ee575060208201516040517f257b363200000000000000000000000000000000000000000000000000000000815260048101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063257b3632906024016020604051808303815f875af11580156119c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ec91906158dd565b155b15611a25576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516201d4c01015611a64576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8767ffffffffffffffff16826040015167ffffffffffffffff161080611a97575042826040015167ffffffffffffffff16115b15611ace576040517fea82791600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602082810151604080850151815193840189905290830184905260608084019290925260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c016040516020818303038152906040528051906020012094508160400151975050508080611b74906158f4565b91505061177f565b50611b87868561579c565b60735490945067ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169084161115611bf0576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611bfb828561592b565b611c0f9067ffffffffffffffff168861594c565b604080516060810182528581524267ffffffffffffffff908116602080840191825260738054680100000000000000009081900485168688019081528d86165f8181526072909552979093209551865592516001909501805492519585167fffffffffffffffffffffffffffffffff000000000000000000000000000000009384161795851684029590951790945583548c8416911617930292909217905590915082811690851614611d0457607380547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8716021790555b611d56333083607054611d17919061595f565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692919061479c565b611d5e61487e565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611dc3575f80fd5b505af1158015611dd5573d5f803e3d5ffd5b505060405167ffffffffffffffff881692507f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce91505f90a250505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611e6a576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b547c0100000000000000000000000000000000000000000000000000000000900460ff16611ec6576040517ff6ba91a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690556040517f854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f905f90a1565b5f6070546064611f28919061595f565b905090565b606f5460ff1615611f6a576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff8581165f908152607260205260409020600101544292611fb69278010000000000000000000000000000000000000000000000009091048116911661579c565b67ffffffffffffffff161115611ff8576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8612005868661592b565b67ffffffffffffffff161115612047576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612055868686868686613da5565b61205e8461492d565b607954700100000000000000000000000000000000900467ffffffffffffffff165f0361219f57607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f90815260756020526040902083905560795416156120ff57607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015612184575f80fd5b505af1158015612196573d5f803e3d5ffd5b5050505061226d565b6121a761487e565b6079805467ffffffffffffffff16905f6121c0836158b7565b825467ffffffffffffffff9182166101009390930a92830292820219169190911790915560408051608081018252428316815287831660208083019182528284018981526060840189815260795487165f908152607890935294909120925183549251861668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169516949094171781559151600183015551600290910155505b604051828152339067ffffffffffffffff8616907f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596690602001610feb565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146122fc576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fff0000000000000000000000000000000000000000ffffffffffffffffffffff166b01000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c50565b612388614b07565b6123915f614b88565b565b60335473ffffffffffffffffffffffffffffffffffffffff1633146124f8575f6123bb612b9d565b90508067ffffffffffffffff168267ffffffffffffffff161161240a576040517f812a372d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff680100000000000000009091048116908316118061244f575067ffffffffffffffff8083165f9081526072602052604090206001015416155b15612486576040517f98c5c01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8083165f9081526072602052604090206001015442916124b49162093a80911661579c565b67ffffffffffffffff1611156124f6576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b61148c614bfe565b607b5473ffffffffffffffffffffffffffffffffffffffff163314612551576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b54607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691821790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612658573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061267c91906158dd565b90505f612687612b9d565b60735467ffffffffffffffff6801000000000000000082048116916126df917001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041661592b565b6126e9919061579c565b6126f3919061592b565b67ffffffffffffffff169050805f0361270e575f9250505090565b61271881836159a3565b9250505090565b606f5460ff161561275c576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61276b87878787878787614160565b67ffffffffffffffff84165f908152607560209081526040918290205482519081529081018490527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a16127c6614bfe565b50505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612820576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115612867576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff166128ce5760795467ffffffffffffffff7001000000000000000000000000000000009091048116908216106128ce576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607980547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c7590602001610c50565b607a5473ffffffffffffffffffffffffffffffffffffffff16331461299c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620151808167ffffffffffffffff1611156129e3576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1661010067ffffffffffffffff8416908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c2890602001610c50565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612aa2576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c50565b5f67ffffffff0000000167ffffffffffffffff8316108015612b4c575067ffffffff00000001604083901c67ffffffffffffffff16105b8015612b6d575067ffffffff00000001608083901c67ffffffffffffffff16105b8015612b84575067ffffffff0000000160c083901c105b15612b9157506001919050565b505f919050565b919050565b6079545f9067ffffffffffffffff1615612bdf575060795467ffffffffffffffff9081165f908152607860205260409020546801000000000000000090041690565b5060745467ffffffffffffffff1690565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612c41576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6076612c4d8282615a03565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c50919061521a565b5f54610100900460ff1615808015612c9b57505f54600160ff909116105b80612cb45750303b158015612cb457505f5460ff166001145b612d45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015612da1575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b612dae6020880188615478565b607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055612e036040880160208901615478565b606f805473ffffffffffffffffffffffffffffffffffffffff929092166b010000000000000000000000027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055612e686080880160608901615478565b6074805473ffffffffffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9092169190911790555f805260756020527ff9e3fbf150b7a0077118526f473c53cb4734f166167e2c6213e3567dd390b4ad8690556076612ef28682615a03565b506077612eff8582615a03565b5062093a80612f146060890160408a016153a4565b67ffffffffffffffff161115612f56576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612f6660608801604089016153a4565b6079805467ffffffffffffffff92909216700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905562093a80612fc860a0890160808a016153a4565b67ffffffffffffffff16111561300a576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61301a60a08801608089016153a4565b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff939093169290920291909117905567016345785d8a0000607055606f80547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff166a03ea000000000000070800179055607b80547fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff167c01000000000006978000000000000000000000000000000000000000001790556130f9614c81565b7fed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd65f7f0000000000000000000000000000000000000000000000000000000000000000858560405161314e9493929190615b62565b60405180910390a180156127c6575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff161561321d576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff161561325a576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f819003613295576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156132d1576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff7801000000000000000000000000000000000000000000000000820481169161331c918491700100000000000000000000000000000000900416615b99565b1115613354576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f8181526072602052604081205491937001000000000000000000000000000000009004909216915b848110156135f9575f8787838181106133b2576133b26157c4565b90506020028101906133c49190615bac565b6133cd90615bde565b9050836133d9816158b7565b825180516020918201208185015160408087015190519499509194505f9361343a9386939101928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f908152607190935291205490915081146134c2576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f908152607160205260408120556134e660018961594c565b84036135555742607b60149054906101000a900467ffffffffffffffff168460400151613513919061579c565b67ffffffffffffffff161115613555576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020838101516040805192830188905282018490526060808301919091524260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016608083015233901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c0160405160208183030381529060405280519060200120945050505080806135f1906158f4565b915050613397565b50613604848461579c565b6073805467ffffffffffffffff4281167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217808455604080516060810182528781526020808201958652680100000000000000009384900485168284019081528589165f818152607290935284832093518455965160019390930180549151871686027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921693871693909317179091558554938916700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff938602939093167fffffffffffffffff00000000000000000000000000000000ffffffffffffffff90941693909317919091179093559151929550917f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a49190a2505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146137ac576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dbc169766040518163ffffffff1660e01b81526004015f604051808303815f87803b158015613811575f80fd5b505af1158015613823573d5f803e3d5ffd5b50505050612391614d20565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff161561388c576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff16156138c9576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6138d2611f18565b90508181111561390e576040517f4732fdb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61138883111561394a576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61398c73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633308461479c565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156139f6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613a1a91906158dd565b60738054919250780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16906018613a54836158b7565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508484604051613a8b929190615c57565b60408051918290038220602083015281018290527fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b166060820152606801604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206073547801000000000000000000000000000000000000000000000000900467ffffffffffffffff165f9081526071909352912055323303613bb9576073546040805183815233602082015260609181018290525f91810191909152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319060800160405180910390a2613c18565b607360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93182338888604051613c0f9493929190615c66565b60405180910390a25b5050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314613c70576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607480547fffffffff0000000000000000000000000000000000000000ffffffffffffffff166801000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527f61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca90602001610c50565b613cf9614b07565b73ffffffffffffffffffffffffffffffffffffffff8116613d9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401612d3c565b61148c81614b88565b5f80613daf612b9d565b905067ffffffffffffffff881615613e7e5760795467ffffffffffffffff9081169089161115613e0b576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8089165f908152607860205260409020600281015481549094509091898116680100000000000000009092041614613e78576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50613f1e565b67ffffffffffffffff87165f90815260756020526040902054915081613ed0576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff161115613f1e576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168667ffffffffffffffff1611613f6b576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f613f798888888689610c5b565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051613fad9190615c9b565b602060405180830381855afa158015613fc8573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190613feb91906158dd565b613ff59190615cac565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a9161407791899190600401615cbf565b602060405180830381865afa158015614092573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906140b69190615cf9565b6140ec576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614154336140fa858b61592b565b67ffffffffffffffff1661410c6125cc565b614116919061595f565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190614dae565b50505050505050505050565b5f67ffffffffffffffff88161561422c5760795467ffffffffffffffff90811690891611156141bb576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5067ffffffffffffffff8088165f908152607860205260409020600281015481549092888116680100000000000000009092041614614226576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506142c7565b5067ffffffffffffffff85165f908152607560205260409020548061427d576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60745467ffffffffffffffff90811690871611156142c7576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff90811690881611806142f957508767ffffffffffffffff168767ffffffffffffffff1611155b80614320575060795467ffffffffffffffff68010000000000000000909104811690881611155b15614357576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8781165f908152607860205260409020546801000000000000000090048116908616146143b9576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6143c78787878588610c5b565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516143fb9190615c9b565b602060405180830381855afa158015614416573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061443991906158dd565b6144439190615cac565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a916144c591889190600401615cbf565b602060405180830381865afa1580156144e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906145049190615cf9565b61453a576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff89165f90815260786020526040902060020154859003614154576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff6801000000000000000090910481169082161115806145c9575060795467ffffffffffffffff908116908216115b15614600576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8181165f81815260786020908152604080832080546074805468010000000000000000928390049098167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090981688179055600282015487865260759094529382902092909255607980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff169390940292909217909255600182015490517f33d6247d00000000000000000000000000000000000000000000000000000000815260048101919091529091907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b15801561472e575f80fd5b505af1158015614740573d5f803e3d5ffd5b505050508267ffffffffffffffff168167ffffffffffffffff167f328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e846002015460405161478f91815260200190565b60405180910390a3505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526148789085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614e09565b50505050565b60795467ffffffffffffffff680100000000000000008204811691161115612391576079545f906148c69068010000000000000000900467ffffffffffffffff16600161579c565b90506148d181611203565b1561148c576079545f906002906148f390849067ffffffffffffffff1661592b565b6148fd9190615d18565b614907908361579c565b905061491281611203565b15614924576149208161458f565b5050565b6149208261458f565b5f614936612b9d565b9050815f80614945848461592b565b606f5467ffffffffffffffff91821692505f91614968916101009004164261594c565b90505b8467ffffffffffffffff168467ffffffffffffffff16146149f25767ffffffffffffffff8085165f90815260726020526040902060018101549091168210156149d057600181015468010000000000000000900467ffffffffffffffff1694506149ec565b6149da868661592b565b67ffffffffffffffff169350506149f2565b5061496b565b5f6149fd848461594c565b905083811015614a5457808403600c8111614a185780614a1b565b600c5b9050806103e80a81606f60099054906101000a900461ffff1661ffff160a6070540281614a4a57614a4a615976565b0460705550614ac3565b838103600c8111614a655780614a68565b600c5b90505f816103e80a82606f60099054906101000a900461ffff1661ffff160a670de0b6b3a76400000281614a9e57614a9e615976565b04905080607054670de0b6b3a76400000281614abc57614abc615976565b0460705550505b683635c9adc5dea000006070541115614ae857683635c9adc5dea000006070556127c6565b633b9aca0060705410156127c657633b9aca0060705550505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314612391576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401612d3c565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b158015614c63575f80fd5b505af1158015614c75573d5f803e3d5ffd5b50505050612391614f14565b5f54610100900460ff16614d17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401612d3c565b61239133614b88565b606f5460ff16614d5c576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052614e049084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016147f6565b505050565b5f614e6a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16614fa69092919063ffffffff16565b805190915015614e045780806020019051810190614e889190615cf9565b614e04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401612d3c565b606f5460ff1615614f51576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b6060614fb484845f85614fbc565b949350505050565b60608247101561504e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401612d3c565b5f808673ffffffffffffffffffffffffffffffffffffffff1685876040516150769190615c9b565b5f6040518083038185875af1925050503d805f81146150b0576040519150601f19603f3d011682016040523d82523d5f602084013e6150b5565b606091505b50915091506150c6878383876150d1565b979650505050505050565b606083156151665782515f0361515f5773ffffffffffffffffffffffffffffffffffffffff85163b61515f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612d3c565b5081614fb4565b614fb4838381511561517b5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d3c919061521a565b5f5b838110156151c95781810151838201526020016151b1565b50505f910152565b5f81518084526151e88160208601602086016151af565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61522c60208301846151d1565b9392505050565b5f60208284031215615243575f80fd5b813561ffff8116811461522c575f80fd5b803567ffffffffffffffff81168114612b98575f80fd5b5f805f805f60a0868803121561527f575f80fd5b61528886615254565b945061529660208701615254565b94979496505050506040830135926060810135926080909101359150565b8061030081018310156152c5575f80fd5b92915050565b5f805f805f806103a087890312156152e1575f80fd5b6152ea87615254565b95506152f860208801615254565b945061530660408801615254565b935060608701359250608087013591506153238860a089016152b4565b90509295509295509295565b5f805f805f805f6103c0888a031215615346575f80fd5b61534f88615254565b965061535d60208901615254565b955061536b60408901615254565b945061537960608901615254565b93506080880135925060a088013591506153968960c08a016152b4565b905092959891949750929550565b5f602082840312156153b4575f80fd5b61522c82615254565b5f8083601f8401126153cd575f80fd5b50813567ffffffffffffffff8111156153e4575f80fd5b6020830191508360208260051b85010111156153fe575f80fd5b9250929050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612b98575f80fd5b5f805f6040848603121561543a575f80fd5b833567ffffffffffffffff811115615450575f80fd5b61545c868287016153bd565b909450925061546f905060208501615405565b90509250925092565b5f60208284031215615488575f80fd5b61522c82615405565b5f602082840312156154a1575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f8301126154e4575f80fd5b813567ffffffffffffffff808211156154ff576154ff6154a8565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715615545576155456154a8565b8160405283815286602085880101111561555d575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f6020828403121561558c575f80fd5b813567ffffffffffffffff8111156155a2575f80fd5b614fb4848285016154d5565b5f8083601f8401126155be575f80fd5b50813567ffffffffffffffff8111156155d5575f80fd5b6020830191508360208285010111156153fe575f80fd5b5f805f805f80868803610120811215615603575f80fd5b60a0811215615610575f80fd5b5086955060a0870135945060c087013567ffffffffffffffff80821115615635575f80fd5b6156418a838b016154d5565b955060e0890135915080821115615656575f80fd5b6156628a838b016154d5565b9450610100890135915080821115615678575f80fd5b5061568589828a016155ae565b979a9699509497509295939492505050565b5f80602083850312156156a8575f80fd5b823567ffffffffffffffff8111156156be575f80fd5b6156ca858286016153bd565b90969095509350505050565b5f805f604084860312156156e8575f80fd5b833567ffffffffffffffff8111156156fe575f80fd5b61570a868287016155ae565b909790965060209590950135949350505050565b600181811c9082168061573257607f821691505b602082108103615769577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff8181168382160190808211156157bd576157bd61576f565b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112615823575f80fd5b9190910192915050565b5f6080823603121561583d575f80fd5b6040516080810167ffffffffffffffff8282108183111715615861576158616154a8565b816040528435915080821115615875575f80fd5b50615882368286016154d5565b8252506020830135602082015261589b60408401615254565b60408201526158ac60608401615254565b606082015292915050565b5f67ffffffffffffffff8083168181036158d3576158d361576f565b6001019392505050565b5f602082840312156158ed575f80fd5b5051919050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036159245761592461576f565b5060010190565b67ffffffffffffffff8281168282160390808211156157bd576157bd61576f565b818103818111156152c5576152c561576f565b80820281158282048414176152c5576152c561576f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f826159b1576159b1615976565b500490565b601f821115614e04575f81815260208120601f850160051c810160208610156159dc5750805b601f850160051c820191505b818110156159fb578281556001016159e8565b505050505050565b815167ffffffffffffffff811115615a1d57615a1d6154a8565b615a3181615a2b845461571e565b846159b6565b602080601f831160018114615a83575f8415615a4d5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556159fb565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015615acf57888601518255948401946001909101908401615ab0565b5085821015615b0b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f67ffffffffffffffff808716835280861660208401525060606040830152615b8f606083018486615b1b565b9695505050505050565b808201808211156152c5576152c561576f565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112615823575f80fd5b5f60608236031215615bee575f80fd5b6040516060810167ffffffffffffffff8282108183111715615c1257615c126154a8565b816040528435915080821115615c26575f80fd5b50615c33368286016154d5565b82525060208301356020820152615c4c60408401615254565b604082015292915050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201525f615b8f606083018486615b1b565b5f82516158238184602087016151af565b5f82615cba57615cba615976565b500690565b6103208101610300808584378201835f5b6001811015615cef578151835260209283019290910190600101615cd0565b5050509392505050565b5f60208284031215615d09575f80fd5b8151801515811461522c575f80fd5b5f67ffffffffffffffff80841680615d3257615d32615976565b9216919091049291505056fea2646970667358221220037883250178a4dbbb3550eba18a465d36ff27719a1da48e547cafff0383598464736f6c63430008140033", + "bytecode": "0x61014060405234801562000011575f80fd5b5060405162005f6438038062005f648339810160408190526200003491620000a2565b6001600160a01b0395861660c05293851660805291841660a05290921660e0526001600160401b039182166101005216610120526200012a565b6001600160a01b038116811462000083575f80fd5b50565b80516001600160401b03811681146200009d575f80fd5b919050565b5f805f805f8060c08789031215620000b8575f80fd5b8651620000c5816200006e565b6020880151909650620000d8816200006e565b6040880151909550620000eb816200006e565b6060880151909450620000fe816200006e565b92506200010e6080880162000086565b91506200011e60a0880162000086565b90509295509295509295565b60805160a05160c05160e0516101005161012051615d74620001f05f395f818161068201528181610dd3015261311d01525f81816107ee0152610da901525f81816107b401528181611d60015281816137ae0152614c0001525f818161095901528181610f45015281816111100152818161196d0152818161212e0152818161398f01526146d801525f8181610a0601528181614041015261448f01525f81816108a901528181611d2e0152818161261301528181613964015261412d0152615d745ff3fe608060405234801561000f575f80fd5b50600436106103a9575f3560e01c8063841b24d7116101ea578063c754c7ed11610114578063e7a7ed02116100a9578063f14916d611610079578063f14916d614610a68578063f2fde38b14610a7b578063f851a44014610a8e578063f8b823e414610aae575f80fd5b8063e7a7ed02146109d1578063e8bf92ed14610a01578063eaeb077b14610a28578063ed6b010414610a3b575f80fd5b8063d2e129f9116100e4578063d2e129f91461097b578063d8d1091b1461098e578063d939b315146109a1578063dbc16976146109c9575f80fd5b8063c754c7ed146108e6578063c89e42df14610912578063cfa8ed4714610925578063d02103ca14610954575f80fd5b8063a3c573eb1161018a578063b4d63f581161015a578063b4d63f581461083e578063b6b0b097146108a4578063ba58ae39146108cb578063c0ed84e0146108de575f80fd5b8063a3c573eb146107af578063ada8f919146107d6578063adc879e9146107e9578063afd23cbe14610810575f80fd5b806399f5634e116101c557806399f5634e1461076e5780639aa972a3146107765780639c9f3dfe14610789578063a066215c1461079c575f80fd5b8063841b24d7146107185780638c3d7301146107485780638da5cb5b14610750575f80fd5b80634a1a89a7116102d6578063621dd4111161026b5780637215541a1161023b5780637215541a146106565780637fcb365314610669578063831c7ead1461067d578063837a4738146106a4575f80fd5b8063621dd411146106095780636b8616ce1461061c5780636ff512cc1461063b578063715018a61461064e575f80fd5b8063542028d5116102a6578063542028d5146105de5780635e9145c9146105e65780635ec91958146105f95780636046916914610601575f80fd5b80634a1a89a71461056b5780634a910e6a1461058b5780634e4877061461059e5780635392c5e0146105b1575f80fd5b8063298789831161034c578063394218e91161031c578063394218e9146104fc578063423fa8561461050f578063456052671461052f578063458c047714610557575f80fd5b806329878983146104975780632b0006fa146104c35780632c1f816a146104d6578063383b3be8146104e9575f80fd5b80631816b7e5116103875780631816b7e51461041657806319d8ac611461042b578063220d78991461043f5780632678224714610452575f80fd5b80630a0d9fbe146103ad578063107bf28c146103e457806315064c96146103f9575b5f80fd5b606f546103c690610100900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6103ec610ab7565b6040516103db919061521a565b606f546104069060ff1681565b60405190151581526020016103db565b610429610424366004615233565b610b43565b005b6073546103c69067ffffffffffffffff1681565b6103ec61044d36600461526b565b610c5b565b607b546104729073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103db565b6074546104729068010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104296104d13660046152cb565b610e31565b6104296104e436600461532f565b610ffb565b6104066104f73660046153a4565b611203565b61042961050a3660046153a4565b611258565b6073546103c69068010000000000000000900467ffffffffffffffff1681565b6073546103c690700100000000000000000000000000000000900467ffffffffffffffff1681565b6079546103c69067ffffffffffffffff1681565b6079546103c69068010000000000000000900467ffffffffffffffff1681565b6104296105993660046153a4565b6113dc565b6104296105ac3660046153a4565b61148f565b6105d06105bf3660046153a4565b60756020525f908152604090205481565b6040519081526020016103db565b6103ec611613565b6104296105f4366004615428565b611620565b610429611e19565b6105d0611f18565b6104296106173660046152cb565b611f2d565b6105d061062a3660046153a4565b60716020525f908152604090205481565b610429610649366004615478565b6122ab565b610429612380565b6104296106643660046153a4565b612393565b6074546103c69067ffffffffffffffff1681565b6103c67f000000000000000000000000000000000000000000000000000000000000000081565b6106ec6106b2366004615491565b60786020525f908152604090208054600182015460029092015467ffffffffffffffff808316936801000000000000000090930416919084565b6040805167ffffffffffffffff95861681529490931660208501529183015260608201526080016103db565b6079546103c6907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b610429612500565b60335473ffffffffffffffffffffffffffffffffffffffff16610472565b6105d06125cc565b61042961078436600461532f565b61271f565b6104296107973660046153a4565b6127cf565b6104296107aa3660046153a4565b61294b565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b6104296107e4366004615478565b612a51565b6103c67f000000000000000000000000000000000000000000000000000000000000000081565b606f5461082b906901000000000000000000900461ffff1681565b60405161ffff90911681526020016103db565b61087e61084c3660046153a4565b60726020525f90815260409020805460019091015467ffffffffffffffff808216916801000000000000000090041683565b6040805193845267ffffffffffffffff92831660208501529116908201526060016103db565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b6104066108d9366004615491565b612b15565b6103c6612b9d565b607b546103c69074010000000000000000000000000000000000000000900467ffffffffffffffff1681565b61042961092036600461557c565b612bf0565b606f54610472906b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b6104296109893660046155ec565b612c7d565b61042961099c366004615697565b6131c0565b6079546103c690700100000000000000000000000000000000900467ffffffffffffffff1681565b61042961375b565b6073546103c6907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b610429610a363660046156d6565b61382f565b607b54610406907c0100000000000000000000000000000000000000000000000000000000900460ff1681565b610429610a76366004615478565b613c1f565b610429610a89366004615478565b613cf1565b607a546104729073ffffffffffffffffffffffffffffffffffffffff1681565b6105d060705481565b60778054610ac49061571e565b80601f0160208091040260200160405190810160405280929190818152602001828054610af09061571e565b8015610b3b5780601f10610b1257610100808354040283529160200191610b3b565b820191905f5260205f20905b815481529060010190602001808311610b1e57829003601f168201915b505050505081565b607a5473ffffffffffffffffffffffffffffffffffffffff163314610b94576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88161ffff161080610bad57506103ff8161ffff16115b15610be4576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffff16690100000000000000000061ffff8416908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a150565b67ffffffffffffffff8086165f818152607260205260408082205493881682529020546060929115801590610c8e575081155b15610cc5576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610cfc576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0584612b15565b610d3b576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b166020820152603481019690965260548601929092527fffffffffffffffff00000000000000000000000000000000000000000000000060c098891b811660748701527f0000000000000000000000000000000000000000000000000000000000000000891b8116607c8701527f0000000000000000000000000000000000000000000000000000000000000000891b81166084870152608c86019490945260ac85015260cc840194909452509290931b90911660ec830152805180830360d401815260f4909201905290565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610e8e576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e9c868686868686613da5565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615610f1657607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015610f9b575f80fd5b505af1158015610fad573d5f803e3d5ffd5b505060405184815233925067ffffffffffffffff871691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe906020015b60405180910390a3505050505050565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611058576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61106787878787878787614160565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f90815260756020526040902083905560795416156110e157607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611166575f80fd5b505af1158015611178573d5f803e3d5ffd5b50506079805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a800000000000000000000000000000000000000000000000001790555050604051828152339067ffffffffffffffff8616907fcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf729060200160405180910390a350505050505050565b60795467ffffffffffffffff8281165f9081526078602052604081205490924292611246927001000000000000000000000000000000009092048116911661579c565b67ffffffffffffffff16111592915050565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146112a9576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff821611156112f0576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661135f5760795467ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169082161061135f576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a190602001610c50565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461148357606f5460ff1615611444576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61144d81611203565b611483576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61148c8161458f565b50565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146114e0576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611527576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661159257607b5467ffffffffffffffff74010000000000000000000000000000000000000000909104811690821610611592576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b90602001610c50565b60768054610ac49061571e565b606f5460ff161561165d576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1633146116bd576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f8190036116f8576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611734576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f81815260726020526040812054838516949293700100000000000000000000000000000000909304909216919082905b86811015611b7c575f8a8a8381811061179a5761179a6157c4565b90506020028101906117ac91906157f1565b6117b59061582d565b8051805160209091012060608201519192509067ffffffffffffffff161561192a57856117e1816158b7565b9650505f818360200151846060015160405160200161183893929190928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f908152607190935291205490915081146118c0576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8088165f908152607160205260408082209190915560608501519085015190821691161015611924576040517f7f7ab87200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611a64565b6020820151158015906119ee575060208201516040517f257b363200000000000000000000000000000000000000000000000000000000815260048101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063257b3632906024016020604051808303815f875af11580156119c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ec91906158dd565b155b15611a25576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516201d4c01015611a64576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8767ffffffffffffffff16826040015167ffffffffffffffff161080611a97575042826040015167ffffffffffffffff16115b15611ace576040517fea82791600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602082810151604080850151815193840189905290830184905260608084019290925260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c016040516020818303038152906040528051906020012094508160400151975050508080611b74906158f4565b91505061177f565b50611b87868561579c565b60735490945067ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169084161115611bf0576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611bfb828561592b565b611c0f9067ffffffffffffffff168861594c565b604080516060810182528581524267ffffffffffffffff908116602080840191825260738054680100000000000000009081900485168688019081528d86165f8181526072909552979093209551865592516001909501805492519585167fffffffffffffffffffffffffffffffff000000000000000000000000000000009384161795851684029590951790945583548c8416911617930292909217905590915082811690851614611d0457607380547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8716021790555b611d56333083607054611d17919061595f565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692919061479c565b611d5e61487e565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611dc3575f80fd5b505af1158015611dd5573d5f803e3d5ffd5b505060405167ffffffffffffffff881692507f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce91505f90a250505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611e6a576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b547c0100000000000000000000000000000000000000000000000000000000900460ff16611ec6576040517ff6ba91a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690556040517f854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f905f90a1565b5f6070546064611f28919061595f565b905090565b606f5460ff1615611f6a576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff8581165f908152607260205260409020600101544292611fb69278010000000000000000000000000000000000000000000000009091048116911661579c565b67ffffffffffffffff161115611ff8576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8612005868661592b565b67ffffffffffffffff161115612047576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612055868686868686613da5565b61205e8461492d565b607954700100000000000000000000000000000000900467ffffffffffffffff165f0361219f57607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f90815260756020526040902083905560795416156120ff57607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015612184575f80fd5b505af1158015612196573d5f803e3d5ffd5b5050505061226d565b6121a761487e565b6079805467ffffffffffffffff16905f6121c0836158b7565b825467ffffffffffffffff9182166101009390930a92830292820219169190911790915560408051608081018252428316815287831660208083019182528284018981526060840189815260795487165f908152607890935294909120925183549251861668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169516949094171781559151600183015551600290910155505b604051828152339067ffffffffffffffff8616907f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596690602001610feb565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146122fc576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fff0000000000000000000000000000000000000000ffffffffffffffffffffff166b01000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c50565b612388614b07565b6123915f614b88565b565b60335473ffffffffffffffffffffffffffffffffffffffff1633146124f8575f6123bb612b9d565b90508067ffffffffffffffff168267ffffffffffffffff161161240a576040517f812a372d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff680100000000000000009091048116908316118061244f575067ffffffffffffffff8083165f9081526072602052604090206001015416155b15612486576040517f98c5c01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8083165f9081526072602052604090206001015442916124b49162093a80911661579c565b67ffffffffffffffff1611156124f6576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b61148c614bfe565b607b5473ffffffffffffffffffffffffffffffffffffffff163314612551576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b54607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691821790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612658573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061267c91906158dd565b90505f612687612b9d565b60735467ffffffffffffffff6801000000000000000082048116916126df917001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041661592b565b6126e9919061579c565b6126f3919061592b565b67ffffffffffffffff169050805f0361270e575f9250505090565b61271881836159a3565b9250505090565b606f5460ff161561275c576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61276b87878787878787614160565b67ffffffffffffffff84165f908152607560209081526040918290205482519081529081018490527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a16127c6614bfe565b50505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612820576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115612867576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff166128ce5760795467ffffffffffffffff7001000000000000000000000000000000009091048116908216106128ce576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607980547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c7590602001610c50565b607a5473ffffffffffffffffffffffffffffffffffffffff16331461299c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620151808167ffffffffffffffff1611156129e3576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1661010067ffffffffffffffff8416908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c2890602001610c50565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612aa2576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c50565b5f67ffffffff0000000167ffffffffffffffff8316108015612b4c575067ffffffff00000001604083901c67ffffffffffffffff16105b8015612b6d575067ffffffff00000001608083901c67ffffffffffffffff16105b8015612b84575067ffffffff0000000160c083901c105b15612b9157506001919050565b505f919050565b919050565b6079545f9067ffffffffffffffff1615612bdf575060795467ffffffffffffffff9081165f908152607860205260409020546801000000000000000090041690565b5060745467ffffffffffffffff1690565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612c41576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6076612c4d8282615a03565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c50919061521a565b5f54610100900460ff1615808015612c9b57505f54600160ff909116105b80612cb45750303b158015612cb457505f5460ff166001145b612d45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015612da1575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b612dae6020880188615478565b607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055612e036040880160208901615478565b606f805473ffffffffffffffffffffffffffffffffffffffff929092166b010000000000000000000000027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055612e686080880160608901615478565b6074805473ffffffffffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9092169190911790555f805260756020527ff9e3fbf150b7a0077118526f473c53cb4734f166167e2c6213e3567dd390b4ad8690556076612ef28682615a03565b506077612eff8582615a03565b5062093a80612f146060890160408a016153a4565b67ffffffffffffffff161115612f56576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612f6660608801604089016153a4565b6079805467ffffffffffffffff92909216700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905562093a80612fc860a0890160808a016153a4565b67ffffffffffffffff16111561300a576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61301a60a08801608089016153a4565b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff939093169290920291909117905567016345785d8a0000607055606f80547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff166a03ea000000000000070800179055607b80547fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff167c01000000000006978000000000000000000000000000000000000000001790556130f9614c81565b7fed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd65f7f0000000000000000000000000000000000000000000000000000000000000000858560405161314e9493929190615b62565b60405180910390a180156127c6575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff161561321d576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff161561325a576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f819003613295576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156132d1576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff7801000000000000000000000000000000000000000000000000820481169161331c918491700100000000000000000000000000000000900416615b99565b1115613354576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f8181526072602052604081205491937001000000000000000000000000000000009004909216915b848110156135f9575f8787838181106133b2576133b26157c4565b90506020028101906133c49190615bac565b6133cd90615bde565b9050836133d9816158b7565b825180516020918201208185015160408087015190519499509194505f9361343a9386939101928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f908152607190935291205490915081146134c2576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f908152607160205260408120556134e660018961594c565b84036135555742607b60149054906101000a900467ffffffffffffffff168460400151613513919061579c565b67ffffffffffffffff161115613555576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020838101516040805192830188905282018490526060808301919091524260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016608083015233901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c0160405160208183030381529060405280519060200120945050505080806135f1906158f4565b915050613397565b50613604848461579c565b6073805467ffffffffffffffff4281167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217808455604080516060810182528781526020808201958652680100000000000000009384900485168284019081528589165f818152607290935284832093518455965160019390930180549151871686027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921693871693909317179091558554938916700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff938602939093167fffffffffffffffff00000000000000000000000000000000ffffffffffffffff90941693909317919091179093559151929550917f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a49190a2505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146137ac576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dbc169766040518163ffffffff1660e01b81526004015f604051808303815f87803b158015613811575f80fd5b505af1158015613823573d5f803e3d5ffd5b50505050612391614d20565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff161561388c576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff16156138c9576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6138d2611f18565b90508181111561390e576040517f4732fdb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61138883111561394a576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61398c73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633308461479c565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156139f6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613a1a91906158dd565b60738054919250780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16906018613a54836158b7565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508484604051613a8b929190615c57565b60408051918290038220602083015281018290527fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b166060820152606801604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206073547801000000000000000000000000000000000000000000000000900467ffffffffffffffff165f9081526071909352912055323303613bb9576073546040805183815233602082015260609181018290525f91810191909152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319060800160405180910390a2613c18565b607360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93182338888604051613c0f9493929190615c66565b60405180910390a25b5050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314613c70576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607480547fffffffff0000000000000000000000000000000000000000ffffffffffffffff166801000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527f61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca90602001610c50565b613cf9614b07565b73ffffffffffffffffffffffffffffffffffffffff8116613d9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401612d3c565b61148c81614b88565b5f80613daf612b9d565b905067ffffffffffffffff881615613e7e5760795467ffffffffffffffff9081169089161115613e0b576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8089165f908152607860205260409020600281015481549094509091898116680100000000000000009092041614613e78576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50613f1e565b67ffffffffffffffff87165f90815260756020526040902054915081613ed0576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff161115613f1e576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168667ffffffffffffffff1611613f6b576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f613f798888888689610c5b565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051613fad9190615c9b565b602060405180830381855afa158015613fc8573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190613feb91906158dd565b613ff59190615cac565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a9161407791899190600401615cbf565b602060405180830381865afa158015614092573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906140b69190615cf9565b6140ec576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614154336140fa858b61592b565b67ffffffffffffffff1661410c6125cc565b614116919061595f565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190614dae565b50505050505050505050565b5f67ffffffffffffffff88161561422c5760795467ffffffffffffffff90811690891611156141bb576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5067ffffffffffffffff8088165f908152607860205260409020600281015481549092888116680100000000000000009092041614614226576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506142c7565b5067ffffffffffffffff85165f908152607560205260409020548061427d576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60745467ffffffffffffffff90811690871611156142c7576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff90811690881611806142f957508767ffffffffffffffff168767ffffffffffffffff1611155b80614320575060795467ffffffffffffffff68010000000000000000909104811690881611155b15614357576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8781165f908152607860205260409020546801000000000000000090048116908616146143b9576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6143c78787878588610c5b565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516143fb9190615c9b565b602060405180830381855afa158015614416573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061443991906158dd565b6144439190615cac565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a916144c591889190600401615cbf565b602060405180830381865afa1580156144e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906145049190615cf9565b61453a576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff89165f90815260786020526040902060020154859003614154576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff6801000000000000000090910481169082161115806145c9575060795467ffffffffffffffff908116908216115b15614600576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8181165f81815260786020908152604080832080546074805468010000000000000000928390049098167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090981688179055600282015487865260759094529382902092909255607980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff169390940292909217909255600182015490517f33d6247d00000000000000000000000000000000000000000000000000000000815260048101919091529091907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b15801561472e575f80fd5b505af1158015614740573d5f803e3d5ffd5b505050508267ffffffffffffffff168167ffffffffffffffff167f328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e846002015460405161478f91815260200190565b60405180910390a3505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526148789085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614e09565b50505050565b60795467ffffffffffffffff680100000000000000008204811691161115612391576079545f906148c69068010000000000000000900467ffffffffffffffff16600161579c565b90506148d181611203565b1561148c576079545f906002906148f390849067ffffffffffffffff1661592b565b6148fd9190615d18565b614907908361579c565b905061491281611203565b15614924576149208161458f565b5050565b6149208261458f565b5f614936612b9d565b9050815f80614945848461592b565b606f5467ffffffffffffffff91821692505f91614968916101009004164261594c565b90505b8467ffffffffffffffff168467ffffffffffffffff16146149f25767ffffffffffffffff8085165f90815260726020526040902060018101549091168210156149d057600181015468010000000000000000900467ffffffffffffffff1694506149ec565b6149da868661592b565b67ffffffffffffffff169350506149f2565b5061496b565b5f6149fd848461594c565b905083811015614a5457808403600c8111614a185780614a1b565b600c5b9050806103e80a81606f60099054906101000a900461ffff1661ffff160a6070540281614a4a57614a4a615976565b0460705550614ac3565b838103600c8111614a655780614a68565b600c5b90505f816103e80a82606f60099054906101000a900461ffff1661ffff160a670de0b6b3a76400000281614a9e57614a9e615976565b04905080607054670de0b6b3a76400000281614abc57614abc615976565b0460705550505b683635c9adc5dea000006070541115614ae857683635c9adc5dea000006070556127c6565b633b9aca0060705410156127c657633b9aca0060705550505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314612391576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401612d3c565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b158015614c63575f80fd5b505af1158015614c75573d5f803e3d5ffd5b50505050612391614f14565b5f54610100900460ff16614d17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401612d3c565b61239133614b88565b606f5460ff16614d5c576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052614e049084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016147f6565b505050565b5f614e6a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16614fa69092919063ffffffff16565b805190915015614e045780806020019051810190614e889190615cf9565b614e04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401612d3c565b606f5460ff1615614f51576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b6060614fb484845f85614fbc565b949350505050565b60608247101561504e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401612d3c565b5f808673ffffffffffffffffffffffffffffffffffffffff1685876040516150769190615c9b565b5f6040518083038185875af1925050503d805f81146150b0576040519150601f19603f3d011682016040523d82523d5f602084013e6150b5565b606091505b50915091506150c6878383876150d1565b979650505050505050565b606083156151665782515f0361515f5773ffffffffffffffffffffffffffffffffffffffff85163b61515f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612d3c565b5081614fb4565b614fb4838381511561517b5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d3c919061521a565b5f5b838110156151c95781810151838201526020016151b1565b50505f910152565b5f81518084526151e88160208601602086016151af565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61522c60208301846151d1565b9392505050565b5f60208284031215615243575f80fd5b813561ffff8116811461522c575f80fd5b803567ffffffffffffffff81168114612b98575f80fd5b5f805f805f60a0868803121561527f575f80fd5b61528886615254565b945061529660208701615254565b94979496505050506040830135926060810135926080909101359150565b8061030081018310156152c5575f80fd5b92915050565b5f805f805f806103a087890312156152e1575f80fd5b6152ea87615254565b95506152f860208801615254565b945061530660408801615254565b935060608701359250608087013591506153238860a089016152b4565b90509295509295509295565b5f805f805f805f6103c0888a031215615346575f80fd5b61534f88615254565b965061535d60208901615254565b955061536b60408901615254565b945061537960608901615254565b93506080880135925060a088013591506153968960c08a016152b4565b905092959891949750929550565b5f602082840312156153b4575f80fd5b61522c82615254565b5f8083601f8401126153cd575f80fd5b50813567ffffffffffffffff8111156153e4575f80fd5b6020830191508360208260051b85010111156153fe575f80fd5b9250929050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612b98575f80fd5b5f805f6040848603121561543a575f80fd5b833567ffffffffffffffff811115615450575f80fd5b61545c868287016153bd565b909450925061546f905060208501615405565b90509250925092565b5f60208284031215615488575f80fd5b61522c82615405565b5f602082840312156154a1575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f8301126154e4575f80fd5b813567ffffffffffffffff808211156154ff576154ff6154a8565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715615545576155456154a8565b8160405283815286602085880101111561555d575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f6020828403121561558c575f80fd5b813567ffffffffffffffff8111156155a2575f80fd5b614fb4848285016154d5565b5f8083601f8401126155be575f80fd5b50813567ffffffffffffffff8111156155d5575f80fd5b6020830191508360208285010111156153fe575f80fd5b5f805f805f80868803610120811215615603575f80fd5b60a0811215615610575f80fd5b5086955060a0870135945060c087013567ffffffffffffffff80821115615635575f80fd5b6156418a838b016154d5565b955060e0890135915080821115615656575f80fd5b6156628a838b016154d5565b9450610100890135915080821115615678575f80fd5b5061568589828a016155ae565b979a9699509497509295939492505050565b5f80602083850312156156a8575f80fd5b823567ffffffffffffffff8111156156be575f80fd5b6156ca858286016153bd565b90969095509350505050565b5f805f604084860312156156e8575f80fd5b833567ffffffffffffffff8111156156fe575f80fd5b61570a868287016155ae565b909790965060209590950135949350505050565b600181811c9082168061573257607f821691505b602082108103615769577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff8181168382160190808211156157bd576157bd61576f565b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112615823575f80fd5b9190910192915050565b5f6080823603121561583d575f80fd5b6040516080810167ffffffffffffffff8282108183111715615861576158616154a8565b816040528435915080821115615875575f80fd5b50615882368286016154d5565b8252506020830135602082015261589b60408401615254565b60408201526158ac60608401615254565b606082015292915050565b5f67ffffffffffffffff8083168181036158d3576158d361576f565b6001019392505050565b5f602082840312156158ed575f80fd5b5051919050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036159245761592461576f565b5060010190565b67ffffffffffffffff8281168282160390808211156157bd576157bd61576f565b818103818111156152c5576152c561576f565b80820281158282048414176152c5576152c561576f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f826159b1576159b1615976565b500490565b601f821115614e04575f81815260208120601f850160051c810160208610156159dc5750805b601f850160051c820191505b818110156159fb578281556001016159e8565b505050505050565b815167ffffffffffffffff811115615a1d57615a1d6154a8565b615a3181615a2b845461571e565b846159b6565b602080601f831160018114615a83575f8415615a4d5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556159fb565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015615acf57888601518255948401946001909101908401615ab0565b5085821015615b0b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f67ffffffffffffffff808716835280861660208401525060606040830152615b8f606083018486615b1b565b9695505050505050565b808201808211156152c5576152c561576f565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112615823575f80fd5b5f60608236031215615bee575f80fd5b6040516060810167ffffffffffffffff8282108183111715615c1257615c126154a8565b816040528435915080821115615c26575f80fd5b50615c33368286016154d5565b82525060208301356020820152615c4c60408401615254565b604082015292915050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201525f615b8f606083018486615b1b565b5f82516158238184602087016151af565b5f82615cba57615cba615976565b500690565b6103208101610300808584378201835f5b6001811015615cef578151835260209283019290910190600101615cd0565b5050509392505050565b5f60208284031215615d09575f80fd5b8151801515811461522c575f80fd5b5f67ffffffffffffffff80841680615d3257615d32615976565b9216919091049291505056fea26469706673582212207601237f211900340462d308ec23f21cf56fdd8a6a63dd46586a4037175deeee64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106103a9575f3560e01c8063841b24d7116101ea578063c754c7ed11610114578063e7a7ed02116100a9578063f14916d611610079578063f14916d614610a68578063f2fde38b14610a7b578063f851a44014610a8e578063f8b823e414610aae575f80fd5b8063e7a7ed02146109d1578063e8bf92ed14610a01578063eaeb077b14610a28578063ed6b010414610a3b575f80fd5b8063d2e129f9116100e4578063d2e129f91461097b578063d8d1091b1461098e578063d939b315146109a1578063dbc16976146109c9575f80fd5b8063c754c7ed146108e6578063c89e42df14610912578063cfa8ed4714610925578063d02103ca14610954575f80fd5b8063a3c573eb1161018a578063b4d63f581161015a578063b4d63f581461083e578063b6b0b097146108a4578063ba58ae39146108cb578063c0ed84e0146108de575f80fd5b8063a3c573eb146107af578063ada8f919146107d6578063adc879e9146107e9578063afd23cbe14610810575f80fd5b806399f5634e116101c557806399f5634e1461076e5780639aa972a3146107765780639c9f3dfe14610789578063a066215c1461079c575f80fd5b8063841b24d7146107185780638c3d7301146107485780638da5cb5b14610750575f80fd5b80634a1a89a7116102d6578063621dd4111161026b5780637215541a1161023b5780637215541a146106565780637fcb365314610669578063831c7ead1461067d578063837a4738146106a4575f80fd5b8063621dd411146106095780636b8616ce1461061c5780636ff512cc1461063b578063715018a61461064e575f80fd5b8063542028d5116102a6578063542028d5146105de5780635e9145c9146105e65780635ec91958146105f95780636046916914610601575f80fd5b80634a1a89a71461056b5780634a910e6a1461058b5780634e4877061461059e5780635392c5e0146105b1575f80fd5b8063298789831161034c578063394218e91161031c578063394218e9146104fc578063423fa8561461050f578063456052671461052f578063458c047714610557575f80fd5b806329878983146104975780632b0006fa146104c35780632c1f816a146104d6578063383b3be8146104e9575f80fd5b80631816b7e5116103875780631816b7e51461041657806319d8ac611461042b578063220d78991461043f5780632678224714610452575f80fd5b80630a0d9fbe146103ad578063107bf28c146103e457806315064c96146103f9575b5f80fd5b606f546103c690610100900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6103ec610ab7565b6040516103db919061521a565b606f546104069060ff1681565b60405190151581526020016103db565b610429610424366004615233565b610b43565b005b6073546103c69067ffffffffffffffff1681565b6103ec61044d36600461526b565b610c5b565b607b546104729073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103db565b6074546104729068010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104296104d13660046152cb565b610e31565b6104296104e436600461532f565b610ffb565b6104066104f73660046153a4565b611203565b61042961050a3660046153a4565b611258565b6073546103c69068010000000000000000900467ffffffffffffffff1681565b6073546103c690700100000000000000000000000000000000900467ffffffffffffffff1681565b6079546103c69067ffffffffffffffff1681565b6079546103c69068010000000000000000900467ffffffffffffffff1681565b6104296105993660046153a4565b6113dc565b6104296105ac3660046153a4565b61148f565b6105d06105bf3660046153a4565b60756020525f908152604090205481565b6040519081526020016103db565b6103ec611613565b6104296105f4366004615428565b611620565b610429611e19565b6105d0611f18565b6104296106173660046152cb565b611f2d565b6105d061062a3660046153a4565b60716020525f908152604090205481565b610429610649366004615478565b6122ab565b610429612380565b6104296106643660046153a4565b612393565b6074546103c69067ffffffffffffffff1681565b6103c67f000000000000000000000000000000000000000000000000000000000000000081565b6106ec6106b2366004615491565b60786020525f908152604090208054600182015460029092015467ffffffffffffffff808316936801000000000000000090930416919084565b6040805167ffffffffffffffff95861681529490931660208501529183015260608201526080016103db565b6079546103c6907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b610429612500565b60335473ffffffffffffffffffffffffffffffffffffffff16610472565b6105d06125cc565b61042961078436600461532f565b61271f565b6104296107973660046153a4565b6127cf565b6104296107aa3660046153a4565b61294b565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b6104296107e4366004615478565b612a51565b6103c67f000000000000000000000000000000000000000000000000000000000000000081565b606f5461082b906901000000000000000000900461ffff1681565b60405161ffff90911681526020016103db565b61087e61084c3660046153a4565b60726020525f90815260409020805460019091015467ffffffffffffffff808216916801000000000000000090041683565b6040805193845267ffffffffffffffff92831660208501529116908201526060016103db565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b6104066108d9366004615491565b612b15565b6103c6612b9d565b607b546103c69074010000000000000000000000000000000000000000900467ffffffffffffffff1681565b61042961092036600461557c565b612bf0565b606f54610472906b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b6104296109893660046155ec565b612c7d565b61042961099c366004615697565b6131c0565b6079546103c690700100000000000000000000000000000000900467ffffffffffffffff1681565b61042961375b565b6073546103c6907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104727f000000000000000000000000000000000000000000000000000000000000000081565b610429610a363660046156d6565b61382f565b607b54610406907c0100000000000000000000000000000000000000000000000000000000900460ff1681565b610429610a76366004615478565b613c1f565b610429610a89366004615478565b613cf1565b607a546104729073ffffffffffffffffffffffffffffffffffffffff1681565b6105d060705481565b60778054610ac49061571e565b80601f0160208091040260200160405190810160405280929190818152602001828054610af09061571e565b8015610b3b5780601f10610b1257610100808354040283529160200191610b3b565b820191905f5260205f20905b815481529060010190602001808311610b1e57829003601f168201915b505050505081565b607a5473ffffffffffffffffffffffffffffffffffffffff163314610b94576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88161ffff161080610bad57506103ff8161ffff16115b15610be4576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffff16690100000000000000000061ffff8416908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a150565b67ffffffffffffffff8086165f818152607260205260408082205493881682529020546060929115801590610c8e575081155b15610cc5576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610cfc576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d0584612b15565b610d3b576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b166020820152603481019690965260548601929092527fffffffffffffffff00000000000000000000000000000000000000000000000060c098891b811660748701527f0000000000000000000000000000000000000000000000000000000000000000891b8116607c8701527f0000000000000000000000000000000000000000000000000000000000000000891b81166084870152608c86019490945260ac85015260cc840194909452509290931b90911660ec830152805180830360d401815260f4909201905290565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610e8e576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e9c868686868686613da5565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615610f1657607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015610f9b575f80fd5b505af1158015610fad573d5f803e3d5ffd5b505060405184815233925067ffffffffffffffff871691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe906020015b60405180910390a3505050505050565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611058576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61106787878787878787614160565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f90815260756020526040902083905560795416156110e157607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611166575f80fd5b505af1158015611178573d5f803e3d5ffd5b50506079805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a800000000000000000000000000000000000000000000000001790555050604051828152339067ffffffffffffffff8616907fcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf729060200160405180910390a350505050505050565b60795467ffffffffffffffff8281165f9081526078602052604081205490924292611246927001000000000000000000000000000000009092048116911661579c565b67ffffffffffffffff16111592915050565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146112a9576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff821611156112f0576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661135f5760795467ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169082161061135f576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a190602001610c50565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461148357606f5460ff1615611444576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61144d81611203565b611483576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61148c8161458f565b50565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146114e0576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611527576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661159257607b5467ffffffffffffffff74010000000000000000000000000000000000000000909104811690821610611592576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b90602001610c50565b60768054610ac49061571e565b606f5460ff161561165d576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1633146116bd576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f8190036116f8576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611734576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f81815260726020526040812054838516949293700100000000000000000000000000000000909304909216919082905b86811015611b7c575f8a8a8381811061179a5761179a6157c4565b90506020028101906117ac91906157f1565b6117b59061582d565b8051805160209091012060608201519192509067ffffffffffffffff161561192a57856117e1816158b7565b9650505f818360200151846060015160405160200161183893929190928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f908152607190935291205490915081146118c0576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8088165f908152607160205260408082209190915560608501519085015190821691161015611924576040517f7f7ab87200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611a64565b6020820151158015906119ee575060208201516040517f257b363200000000000000000000000000000000000000000000000000000000815260048101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063257b3632906024016020604051808303815f875af11580156119c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ec91906158dd565b155b15611a25576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516201d4c01015611a64576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8767ffffffffffffffff16826040015167ffffffffffffffff161080611a97575042826040015167ffffffffffffffff16115b15611ace576040517fea82791600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602082810151604080850151815193840189905290830184905260608084019290925260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c016040516020818303038152906040528051906020012094508160400151975050508080611b74906158f4565b91505061177f565b50611b87868561579c565b60735490945067ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169084161115611bf0576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f611bfb828561592b565b611c0f9067ffffffffffffffff168861594c565b604080516060810182528581524267ffffffffffffffff908116602080840191825260738054680100000000000000009081900485168688019081528d86165f8181526072909552979093209551865592516001909501805492519585167fffffffffffffffffffffffffffffffff000000000000000000000000000000009384161795851684029590951790945583548c8416911617930292909217905590915082811690851614611d0457607380547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8716021790555b611d56333083607054611d17919061595f565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692919061479c565b611d5e61487e565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015611dc3575f80fd5b505af1158015611dd5573d5f803e3d5ffd5b505060405167ffffffffffffffff881692507f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce91505f90a250505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611e6a576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b547c0100000000000000000000000000000000000000000000000000000000900460ff16611ec6576040517ff6ba91a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690556040517f854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f905f90a1565b5f6070546064611f28919061595f565b905090565b606f5460ff1615611f6a576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff8581165f908152607260205260409020600101544292611fb69278010000000000000000000000000000000000000000000000009091048116911661579c565b67ffffffffffffffff161115611ff8576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8612005868661592b565b67ffffffffffffffff161115612047576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612055868686868686613da5565b61205e8461492d565b607954700100000000000000000000000000000000900467ffffffffffffffff165f0361219f57607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f90815260756020526040902083905560795416156120ff57607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015612184575f80fd5b505af1158015612196573d5f803e3d5ffd5b5050505061226d565b6121a761487e565b6079805467ffffffffffffffff16905f6121c0836158b7565b825467ffffffffffffffff9182166101009390930a92830292820219169190911790915560408051608081018252428316815287831660208083019182528284018981526060840189815260795487165f908152607890935294909120925183549251861668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169516949094171781559151600183015551600290910155505b604051828152339067ffffffffffffffff8616907f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596690602001610feb565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146122fc576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fff0000000000000000000000000000000000000000ffffffffffffffffffffff166b01000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c50565b612388614b07565b6123915f614b88565b565b60335473ffffffffffffffffffffffffffffffffffffffff1633146124f8575f6123bb612b9d565b90508067ffffffffffffffff168267ffffffffffffffff161161240a576040517f812a372d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff680100000000000000009091048116908316118061244f575067ffffffffffffffff8083165f9081526072602052604090206001015416155b15612486576040517f98c5c01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8083165f9081526072602052604090206001015442916124b49162093a80911661579c565b67ffffffffffffffff1611156124f6576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b61148c614bfe565b607b5473ffffffffffffffffffffffffffffffffffffffff163314612551576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b54607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691821790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa158015612658573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061267c91906158dd565b90505f612687612b9d565b60735467ffffffffffffffff6801000000000000000082048116916126df917001000000000000000000000000000000008204811691780100000000000000000000000000000000000000000000000090041661592b565b6126e9919061579c565b6126f3919061592b565b67ffffffffffffffff169050805f0361270e575f9250505090565b61271881836159a3565b9250505090565b606f5460ff161561275c576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61276b87878787878787614160565b67ffffffffffffffff84165f908152607560209081526040918290205482519081529081018490527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a16127c6614bfe565b50505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612820576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115612867576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff166128ce5760795467ffffffffffffffff7001000000000000000000000000000000009091048116908216106128ce576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607980547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c7590602001610c50565b607a5473ffffffffffffffffffffffffffffffffffffffff16331461299c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620151808167ffffffffffffffff1611156129e3576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1661010067ffffffffffffffff8416908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c2890602001610c50565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612aa2576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c50565b5f67ffffffff0000000167ffffffffffffffff8316108015612b4c575067ffffffff00000001604083901c67ffffffffffffffff16105b8015612b6d575067ffffffff00000001608083901c67ffffffffffffffff16105b8015612b84575067ffffffff0000000160c083901c105b15612b9157506001919050565b505f919050565b919050565b6079545f9067ffffffffffffffff1615612bdf575060795467ffffffffffffffff9081165f908152607860205260409020546801000000000000000090041690565b5060745467ffffffffffffffff1690565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612c41576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6076612c4d8282615a03565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c50919061521a565b5f54610100900460ff1615808015612c9b57505f54600160ff909116105b80612cb45750303b158015612cb457505f5460ff166001145b612d45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015612da1575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b612dae6020880188615478565b607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055612e036040880160208901615478565b606f805473ffffffffffffffffffffffffffffffffffffffff929092166b010000000000000000000000027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055612e686080880160608901615478565b6074805473ffffffffffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9092169190911790555f805260756020527ff9e3fbf150b7a0077118526f473c53cb4734f166167e2c6213e3567dd390b4ad8690556076612ef28682615a03565b506077612eff8582615a03565b5062093a80612f146060890160408a016153a4565b67ffffffffffffffff161115612f56576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612f6660608801604089016153a4565b6079805467ffffffffffffffff92909216700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905562093a80612fc860a0890160808a016153a4565b67ffffffffffffffff16111561300a576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61301a60a08801608089016153a4565b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff939093169290920291909117905567016345785d8a0000607055606f80547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff166a03ea000000000000070800179055607b80547fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff167c01000000000006978000000000000000000000000000000000000000001790556130f9614c81565b7fed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd65f7f0000000000000000000000000000000000000000000000000000000000000000858560405161314e9493929190615b62565b60405180910390a180156127c6575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff161561321d576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff161561325a576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f819003613295576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156132d1576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff7801000000000000000000000000000000000000000000000000820481169161331c918491700100000000000000000000000000000000900416615b99565b1115613354576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f8181526072602052604081205491937001000000000000000000000000000000009004909216915b848110156135f9575f8787838181106133b2576133b26157c4565b90506020028101906133c49190615bac565b6133cd90615bde565b9050836133d9816158b7565b825180516020918201208185015160408087015190519499509194505f9361343a9386939101928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f908152607190935291205490915081146134c2576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f908152607160205260408120556134e660018961594c565b84036135555742607b60149054906101000a900467ffffffffffffffff168460400151613513919061579c565b67ffffffffffffffff161115613555576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020838101516040805192830188905282018490526060808301919091524260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016608083015233901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c0160405160208183030381529060405280519060200120945050505080806135f1906158f4565b915050613397565b50613604848461579c565b6073805467ffffffffffffffff4281167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217808455604080516060810182528781526020808201958652680100000000000000009384900485168284019081528589165f818152607290935284832093518455965160019390930180549151871686027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921693871693909317179091558554938916700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff938602939093167fffffffffffffffff00000000000000000000000000000000ffffffffffffffff90941693909317919091179093559151929550917f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a49190a2505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146137ac576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dbc169766040518163ffffffff1660e01b81526004015f604051808303815f87803b158015613811575f80fd5b505af1158015613823573d5f803e3d5ffd5b50505050612391614d20565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff161561388c576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff16156138c9576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6138d2611f18565b90508181111561390e576040517f4732fdb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61138883111561394a576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61398c73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633308461479c565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156139f6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613a1a91906158dd565b60738054919250780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16906018613a54836158b7565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508484604051613a8b929190615c57565b60408051918290038220602083015281018290527fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b166060820152606801604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206073547801000000000000000000000000000000000000000000000000900467ffffffffffffffff165f9081526071909352912055323303613bb9576073546040805183815233602082015260609181018290525f91810191909152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319060800160405180910390a2613c18565b607360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93182338888604051613c0f9493929190615c66565b60405180910390a25b5050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314613c70576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607480547fffffffff0000000000000000000000000000000000000000ffffffffffffffff166801000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527f61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca90602001610c50565b613cf9614b07565b73ffffffffffffffffffffffffffffffffffffffff8116613d9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401612d3c565b61148c81614b88565b5f80613daf612b9d565b905067ffffffffffffffff881615613e7e5760795467ffffffffffffffff9081169089161115613e0b576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8089165f908152607860205260409020600281015481549094509091898116680100000000000000009092041614613e78576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50613f1e565b67ffffffffffffffff87165f90815260756020526040902054915081613ed0576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff161115613f1e576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168667ffffffffffffffff1611613f6b576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f613f798888888689610c5b565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051613fad9190615c9b565b602060405180830381855afa158015613fc8573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190613feb91906158dd565b613ff59190615cac565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a9161407791899190600401615cbf565b602060405180830381865afa158015614092573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906140b69190615cf9565b6140ec576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614154336140fa858b61592b565b67ffffffffffffffff1661410c6125cc565b614116919061595f565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190614dae565b50505050505050505050565b5f67ffffffffffffffff88161561422c5760795467ffffffffffffffff90811690891611156141bb576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5067ffffffffffffffff8088165f908152607860205260409020600281015481549092888116680100000000000000009092041614614226576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506142c7565b5067ffffffffffffffff85165f908152607560205260409020548061427d576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60745467ffffffffffffffff90811690871611156142c7576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff90811690881611806142f957508767ffffffffffffffff168767ffffffffffffffff1611155b80614320575060795467ffffffffffffffff68010000000000000000909104811690881611155b15614357576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8781165f908152607860205260409020546801000000000000000090048116908616146143b9576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f6143c78787878588610c5b565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016002836040516143fb9190615c9b565b602060405180830381855afa158015614416573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061443991906158dd565b6144439190615cac565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a916144c591889190600401615cbf565b602060405180830381865afa1580156144e0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906145049190615cf9565b61453a576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff89165f90815260786020526040902060020154859003614154576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff6801000000000000000090910481169082161115806145c9575060795467ffffffffffffffff908116908216115b15614600576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8181165f81815260786020908152604080832080546074805468010000000000000000928390049098167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090981688179055600282015487865260759094529382902092909255607980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff169390940292909217909255600182015490517f33d6247d00000000000000000000000000000000000000000000000000000000815260048101919091529091907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b15801561472e575f80fd5b505af1158015614740573d5f803e3d5ffd5b505050508267ffffffffffffffff168167ffffffffffffffff167f328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e846002015460405161478f91815260200190565b60405180910390a3505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526148789085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152614e09565b50505050565b60795467ffffffffffffffff680100000000000000008204811691161115612391576079545f906148c69068010000000000000000900467ffffffffffffffff16600161579c565b90506148d181611203565b1561148c576079545f906002906148f390849067ffffffffffffffff1661592b565b6148fd9190615d18565b614907908361579c565b905061491281611203565b15614924576149208161458f565b5050565b6149208261458f565b5f614936612b9d565b9050815f80614945848461592b565b606f5467ffffffffffffffff91821692505f91614968916101009004164261594c565b90505b8467ffffffffffffffff168467ffffffffffffffff16146149f25767ffffffffffffffff8085165f90815260726020526040902060018101549091168210156149d057600181015468010000000000000000900467ffffffffffffffff1694506149ec565b6149da868661592b565b67ffffffffffffffff169350506149f2565b5061496b565b5f6149fd848461594c565b905083811015614a5457808403600c8111614a185780614a1b565b600c5b9050806103e80a81606f60099054906101000a900461ffff1661ffff160a6070540281614a4a57614a4a615976565b0460705550614ac3565b838103600c8111614a655780614a68565b600c5b90505f816103e80a82606f60099054906101000a900461ffff1661ffff160a670de0b6b3a76400000281614a9e57614a9e615976565b04905080607054670de0b6b3a76400000281614abc57614abc615976565b0460705550505b683635c9adc5dea000006070541115614ae857683635c9adc5dea000006070556127c6565b633b9aca0060705410156127c657633b9aca0060705550505050505050565b60335473ffffffffffffffffffffffffffffffffffffffff163314612391576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401612d3c565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b158015614c63575f80fd5b505af1158015614c75573d5f803e3d5ffd5b50505050612391614f14565b5f54610100900460ff16614d17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401612d3c565b61239133614b88565b606f5460ff16614d5c576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052614e049084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064016147f6565b505050565b5f614e6a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16614fa69092919063ffffffff16565b805190915015614e045780806020019051810190614e889190615cf9565b614e04576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401612d3c565b606f5460ff1615614f51576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b6060614fb484845f85614fbc565b949350505050565b60608247101561504e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401612d3c565b5f808673ffffffffffffffffffffffffffffffffffffffff1685876040516150769190615c9b565b5f6040518083038185875af1925050503d805f81146150b0576040519150601f19603f3d011682016040523d82523d5f602084013e6150b5565b606091505b50915091506150c6878383876150d1565b979650505050505050565b606083156151665782515f0361515f5773ffffffffffffffffffffffffffffffffffffffff85163b61515f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401612d3c565b5081614fb4565b614fb4838381511561517b5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d3c919061521a565b5f5b838110156151c95781810151838201526020016151b1565b50505f910152565b5f81518084526151e88160208601602086016151af565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61522c60208301846151d1565b9392505050565b5f60208284031215615243575f80fd5b813561ffff8116811461522c575f80fd5b803567ffffffffffffffff81168114612b98575f80fd5b5f805f805f60a0868803121561527f575f80fd5b61528886615254565b945061529660208701615254565b94979496505050506040830135926060810135926080909101359150565b8061030081018310156152c5575f80fd5b92915050565b5f805f805f806103a087890312156152e1575f80fd5b6152ea87615254565b95506152f860208801615254565b945061530660408801615254565b935060608701359250608087013591506153238860a089016152b4565b90509295509295509295565b5f805f805f805f6103c0888a031215615346575f80fd5b61534f88615254565b965061535d60208901615254565b955061536b60408901615254565b945061537960608901615254565b93506080880135925060a088013591506153968960c08a016152b4565b905092959891949750929550565b5f602082840312156153b4575f80fd5b61522c82615254565b5f8083601f8401126153cd575f80fd5b50813567ffffffffffffffff8111156153e4575f80fd5b6020830191508360208260051b85010111156153fe575f80fd5b9250929050565b803573ffffffffffffffffffffffffffffffffffffffff81168114612b98575f80fd5b5f805f6040848603121561543a575f80fd5b833567ffffffffffffffff811115615450575f80fd5b61545c868287016153bd565b909450925061546f905060208501615405565b90509250925092565b5f60208284031215615488575f80fd5b61522c82615405565b5f602082840312156154a1575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f8301126154e4575f80fd5b813567ffffffffffffffff808211156154ff576154ff6154a8565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715615545576155456154a8565b8160405283815286602085880101111561555d575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f6020828403121561558c575f80fd5b813567ffffffffffffffff8111156155a2575f80fd5b614fb4848285016154d5565b5f8083601f8401126155be575f80fd5b50813567ffffffffffffffff8111156155d5575f80fd5b6020830191508360208285010111156153fe575f80fd5b5f805f805f80868803610120811215615603575f80fd5b60a0811215615610575f80fd5b5086955060a0870135945060c087013567ffffffffffffffff80821115615635575f80fd5b6156418a838b016154d5565b955060e0890135915080821115615656575f80fd5b6156628a838b016154d5565b9450610100890135915080821115615678575f80fd5b5061568589828a016155ae565b979a9699509497509295939492505050565b5f80602083850312156156a8575f80fd5b823567ffffffffffffffff8111156156be575f80fd5b6156ca858286016153bd565b90969095509350505050565b5f805f604084860312156156e8575f80fd5b833567ffffffffffffffff8111156156fe575f80fd5b61570a868287016155ae565b909790965060209590950135949350505050565b600181811c9082168061573257607f821691505b602082108103615769577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff8181168382160190808211156157bd576157bd61576f565b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112615823575f80fd5b9190910192915050565b5f6080823603121561583d575f80fd5b6040516080810167ffffffffffffffff8282108183111715615861576158616154a8565b816040528435915080821115615875575f80fd5b50615882368286016154d5565b8252506020830135602082015261589b60408401615254565b60408201526158ac60608401615254565b606082015292915050565b5f67ffffffffffffffff8083168181036158d3576158d361576f565b6001019392505050565b5f602082840312156158ed575f80fd5b5051919050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036159245761592461576f565b5060010190565b67ffffffffffffffff8281168282160390808211156157bd576157bd61576f565b818103818111156152c5576152c561576f565b80820281158282048414176152c5576152c561576f565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f826159b1576159b1615976565b500490565b601f821115614e04575f81815260208120601f850160051c810160208610156159dc5750805b601f850160051c820191505b818110156159fb578281556001016159e8565b505050505050565b815167ffffffffffffffff811115615a1d57615a1d6154a8565b615a3181615a2b845461571e565b846159b6565b602080601f831160018114615a83575f8415615a4d5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556159fb565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015615acf57888601518255948401946001909101908401615ab0565b5085821015615b0b57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f67ffffffffffffffff808716835280861660208401525060606040830152615b8f606083018486615b1b565b9695505050505050565b808201808211156152c5576152c561576f565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112615823575f80fd5b5f60608236031215615bee575f80fd5b6040516060810167ffffffffffffffff8282108183111715615c1257615c126154a8565b816040528435915080821115615c26575f80fd5b50615c33368286016154d5565b82525060208301356020820152615c4c60408401615254565b604082015292915050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201525f615b8f606083018486615b1b565b5f82516158238184602087016151af565b5f82615cba57615cba615976565b500690565b6103208101610300808584378201835f5b6001811015615cef578151835260209283019290910190600101615cd0565b5050509392505050565b5f60208284031215615d09575f80fd5b8151801515811461522c575f80fd5b5f67ffffffffffffffff80841680615d3257615d32615976565b9216919091049291505056fea26469706673582212207601237f211900340462d308ec23f21cf56fdd8a6a63dd46586a4037175deeee64736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMBridge.json b/compiled-contracts/PolygonZkEVMBridge.json index 0a1bcd5c1..99a0e3182 100644 --- a/compiled-contracts/PolygonZkEVMBridge.json +++ b/compiled-contracts/PolygonZkEVMBridge.json @@ -776,8 +776,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561000f575f80fd5b50615b1f8061001d5f395ff3fe60806040526004361062000197575f3560e01c8063647c576c11620000e2578063be5831c71162000086578063dbc16976116200005e578063dbc16976146200061a578063ee25560b1462000631578063fb5708341462000660575f80fd5b8063be5831c71462000591578063cd58657914620005cc578063d02103ca14620005e3575f80fd5b80639e34070f11620000ba5780639e34070f14620004f1578063aaa13cc21462000534578063bab161bf1462000558575f80fd5b8063647c576c146200047157806379e2cf97146200049557806381b1c17414620004ac575f80fd5b80632d2c9d94116200014a57806334ac9cf2116200012257806334ac9cf2146200033a5780633ae0504714620003685780633e197043146200037f575f80fd5b80632d2c9d9414620002695780632dfdf0b5146200028d578063318aee3d14620002b3575f80fd5b806322e95f2c116200017e57806322e95f2c14620001e4578063240ff378146200022e5780632cffd02e1462000245575f80fd5b806315064c96146200019b5780632072f6c514620001cb575b5f80fd5b348015620001a7575f80fd5b50606854620001b69060ff1681565b60405190151581526020015b60405180910390f35b348015620001d7575f80fd5b50620001e262000684565b005b348015620001f0575f80fd5b5062000208620002023660046200323f565b620006e2565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620001c2565b620001e26200023f366004620032cf565b62000784565b34801562000251575f80fd5b50620001e26200026336600462003360565b620009ab565b34801562000275575f80fd5b50620001e26200028736600462003360565b62000f30565b34801562000299575f80fd5b50620002a460535481565b604051908152602001620001c2565b348015620002bf575f80fd5b5062000308620002d13660046200343e565b606b6020525f908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff909116602083015201620001c2565b34801562000346575f80fd5b50606c54620002089073ffffffffffffffffffffffffffffffffffffffff1681565b34801562000374575f80fd5b50620002a462001130565b3480156200038b575f80fd5b50620002a46200039d36600462003472565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b3480156200047d575f80fd5b50620001e26200048f366004620034f7565b62001215565b348015620004a1575f80fd5b50620001e26200145e565b348015620004b8575f80fd5b5062000208620004ca36600462003544565b606a6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015620004fd575f80fd5b50620001b66200050f36600462003544565b600881901c5f90815260696020526040902054600160ff9092169190911b9081161490565b34801562000540575f80fd5b5062000208620005523660046200355c565b62001498565b34801562000564575f80fd5b506068546200057b90610100900463ffffffff1681565b60405163ffffffff9091168152602001620001c2565b3480156200059d575f80fd5b506068546200057b90790100000000000000000000000000000000000000000000000000900463ffffffff1681565b620001e2620005dd36600462003609565b62001682565b348015620005ef575f80fd5b50606854620002089065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b34801562000626575f80fd5b50620001e262001bd4565b3480156200063d575f80fd5b50620002a46200064f36600462003544565b60696020525f908152604090205481565b3480156200066c575f80fd5b50620001b66200067e366004620036a5565b62001c30565b606c5473ffffffffffffffffffffffffffffffffffffffff163314620006d6576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620006e062001d18565b565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602483015282516018818403018152603890920183528151918101919091205f908152606a909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b60685460ff1615620007c2576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff868116610100909204161480620007e85750600263ffffffff861610155b1562000820576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338888348888605354604051620008769998979695949392919062003736565b60405180910390a1620009936200098d6001606860019054906101000a900463ffffffff16338989348989604051620008b1929190620037b0565b60405180910390206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b62001dab565b8215620009a457620009a462001ebf565b5050505050565b60685460ff1615620009e9576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620009ff8b8b8b8b8b8b8b8b8b8b8b5f62001f8f565b73ffffffffffffffffffffffffffffffffffffffff861662000ad757604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff861690859060405162000a53919062003810565b5f6040518083038185875af1925050503d805f811462000a8f576040519150601f19603f3d011682016040523d82523d5f602084013e62000a94565b606091505b505090508062000ad0576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5062000eb8565b60685463ffffffff61010090910481169088160362000b195762000b1373ffffffffffffffffffffffffffffffffffffffff871685856200217a565b62000eb8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f90603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301205f818152606a90935291205490915073ffffffffffffffffffffffffffffffffffffffff168062000e2f575f808062000beb868801886200391f565b9250925092505f8584848460405162000c0490620031f8565b62000c1293929190620039db565b8190604051809103905ff590508015801562000c30573d5f803e3d5ffd5b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81166004830152602482018c9052919250908216906340c10f19906044015f604051808303815f87803b15801562000ca3575f80fd5b505af115801562000cb6573d5f803e3d5ffd5b5050505080606a5f8881526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808e63ffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815250606b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000e1d95949392919062003a17565b60405180910390a15050505062000eb5565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801562000e9d575f80fd5b505af115801562000eb0573d5f803e3d5ffd5b505050505b50505b6040805163ffffffff8c811682528916602082015273ffffffffffffffffffffffffffffffffffffffff88811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff161562000f6e576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000f858b8b8b8b8b8b8b8b8b8b8b600162001f8f565b5f8473ffffffffffffffffffffffffffffffffffffffff1684888a868660405160240162000fb7949392919062003a5e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1806b5f200000000000000000000000000000000000000000000000000000000179052516200103a919062003810565b5f6040518083038185875af1925050503d805f811462001076576040519150601f19603f3d011682016040523d82523d5f602084013e6200107b565b606091505b5050905080620010b7576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a16602082015273ffffffffffffffffffffffffffffffffffffffff89811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b6053545f90819081805b60208110156200120c578083901c6001166001036200119d576033816020811062001169576200116962003aa5565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350620011ca565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080620012039062003aff565b9150506200113a565b50919392505050565b5f54610100900460ff16158080156200123457505f54600160ff909116105b806200124f5750303b1580156200124f57505f5460ff166001145b620012e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200133e575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff16176501000000000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155606c80547fffffffffffffffffffffffff000000000000000000000000000000000000000016918416919091179055620013f562002250565b801562001458575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b605354606854790100000000000000000000000000000000000000000000000000900463ffffffff161015620006e057620006e062001ebf565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b3083604051806020016200152c90620031f8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081905262001577908d908d908d908d908d9060200162003b39565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052620015b5929160200162003b79565b604051602081830303815290604052805190602001206040516020016200163e94939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101209a9950505050505050505050565b60685460ff1615620016c0576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620016ca620022f2565b60685463ffffffff888116610100909204161480620016f05750600263ffffffff881610155b1562001728576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8060608773ffffffffffffffffffffffffffffffffffffffff88166200178c5788341462001783576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f925062001a79565b3415620017c5576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8089165f908152606b602090815260409182902082518084019093525463ffffffff8116835264010000000090049092169181018290529015620018ae576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b905273ffffffffffffffffffffffffffffffffffffffff8a1690639dc29fac906044015f604051808303815f87803b15801562001884575f80fd5b505af115801562001897573d5f803e3d5ffd5b5050505080602001519450805f0151935062001a77565b8515620018c357620018c3898b898962002367565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8b16906370a0823190602401602060405180830381865afa1580156200192e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001954919062003bab565b90506200197a73ffffffffffffffffffffffffffffffffffffffff8b1633308e6200287a565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa158015620019e5573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001a0b919062003bab565b905062001a19828262003bc3565b6068548c9850610100900463ffffffff169650935062001a3987620028da565b62001a448c620029ee565b62001a4f8d62002af7565b60405160200162001a6393929190620039db565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e868860535460405162001aba98979695949392919062003bd9565b60405180910390a162001bac6200098d5f85878f8f8789805190602001206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b861562001bbd5762001bbd62001ebf565b5050505062001bcb60018055565b50505050505050565b606c5473ffffffffffffffffffffffffffffffffffffffff16331462001c26576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620006e062002bf5565b5f84815b602081101562001d0a57600163ffffffff8616821c8116900362001ca65785816020811062001c675762001c6762003aa5565b60200201358260405160200162001c88929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001cf5565b8186826020811062001cbc5762001cbc62003aa5565b602002013560405160200162001cdc929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001d018162003aff565b91505062001c34565b50821490505b949350505050565b60685460ff161562001d56576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b80600162001dbc6020600262003d88565b62001dc8919062003bc3565b6053541062001e03576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f815462001e149062003aff565b918290555090505f5b602081101562001eaf578082901c60011660010362001e5557826033826020811062001e4d5762001e4d62003aa5565b015550505050565b6033816020811062001e6b5762001e6b62003aa5565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808062001ea69062003aff565b91505062001e1d565b5062001eba62003d95565b505050565b6053546068805463ffffffff909216790100000000000000000000000000000000000000000000000000027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179081905573ffffffffffffffffffffffffffffffffffffffff65010000000000909104166333d6247d62001f4562001130565b6040518263ffffffff1660e01b815260040162001f6491815260200190565b5f604051808303815f87803b15801562001f7c575f80fd5b505af115801562001458573d5f803e3d5ffd5b62001fa08b63ffffffff1662002c84565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f9165010000000000900473ffffffffffffffffffffffffffffffffffffffff169063257b3632906084016020604051808303815f875af11580156200203f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002065919062003bab565b9050805f03620020a0576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff8881166101009092041614620020ea576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068545f90610100900463ffffffff16620021075750896200210a565b508a5b620021336200212a848c8c8c8c8c8c8c604051620008b1929190620037b0565b8f8f8462001c30565b6200216a576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001eba9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915262002ce8565b5f54610100900460ff16620022e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620012d8565b620006e062002dfa565b60026001540362002360576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401620012d8565b6002600155565b5f62002377600482848662003dc2565b620023829162003deb565b90507f2afa5331000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000821601620025fc575f808080808080620023e4896004818d62003dc2565b810190620023f3919062003e34565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462002467576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff86163014620024b7576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a8514620024f1576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e1691620025ac919062003810565b5f604051808303815f865af19150503d805f8114620025e7576040519150601f19603f3d011682016040523d82523d5f602084013e620025ec565b606091505b50505050505050505050620009a4565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f8fcbaf0c000000000000000000000000000000000000000000000000000000001462002678576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806200268f8a6004818e62003dc2565b8101906200269e919062003e8a565b975097509750975097509750975097503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161462002714576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8716301462002764576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8fcbaf0c000000000000000000000000000000000000000000000000000000001790529151918f169162002828919062003810565b5f604051808303815f865af19150503d805f811462002863576040519150601f19603f3d011682016040523d82523d5f602084013e62002868565b606091505b50505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620014589085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401620021cd565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff8616916200295d919062003810565b5f60405180830381855afa9150503d805f811462002997576040519150601f19603f3d011682016040523d82523d5f602084013e6200299c565b606091505b509150915081620029e3576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525062001d10565b62001d108162002e92565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff86169162002a71919062003810565b5f60405180830381855afa9150503d805f811462002aab576040519150601f19603f3d011682016040523d82523d5f602084013e62002ab0565b606091505b509150915081620029e3576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525062001d10565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f918291829173ffffffffffffffffffffffffffffffffffffffff86169162002b79919062003810565b5f60405180830381855afa9150503d805f811462002bb3576040519150601f19603f3d011682016040523d82523d5f602084013e62002bb8565b606091505b509150915081801562002bcc575080516020145b62002bd957601262001d10565b8080602001905181019062001d10919062003f11565b60018055565b60685460ff1662002c32576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003620009a4576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62002d4b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166200307d9092919063ffffffff16565b80519091501562001eba578080602001905181019062002d6c919062003f2f565b62001eba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401620012d8565b5f54610100900460ff1662002bef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620012d8565b6060604082511062002eb457818060200190518101906200077e919062003f4d565b81516020036200303f575f5b60208110801562002f0b575082818151811062002ee15762002ee162003aa5565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b1562002f26578062002f1d8162003aff565b91505062002ec0565b805f0362002f6957505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff81111562002f865762002f86620037bf565b6040519080825280601f01601f19166020018201604052801562002fb1576020820181803683370190505b5090505f5b82811015620030375784818151811062002fd45762002fd462003aa5565b602001015160f81c60f81b82828151811062002ff45762002ff462003aa5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350806200302e8162003aff565b91505062002fb6565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b606062001d1084845f85855f808673ffffffffffffffffffffffffffffffffffffffff168587604051620030b2919062003810565b5f6040518083038185875af1925050503d805f8114620030ee576040519150601f19603f3d011682016040523d82523d5f602084013e620030f3565b606091505b5091509150620031068783838762003111565b979650505050505050565b60608315620031ab5782515f03620031a35773ffffffffffffffffffffffffffffffffffffffff85163b620031a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620012d8565b508162001d10565b62001d108383815115620031c25781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620012d8919062003fc8565b611b0d8062003fdd83390190565b803563ffffffff8116811462003078575f80fd5b73ffffffffffffffffffffffffffffffffffffffff811681146200323c575f80fd5b50565b5f806040838503121562003251575f80fd5b6200325c8362003206565b915060208301356200326e816200321a565b809150509250929050565b80151581146200323c575f80fd5b5f8083601f84011262003298575f80fd5b50813567ffffffffffffffff811115620032b0575f80fd5b602083019150836020828501011115620032c8575f80fd5b9250929050565b5f805f805f60808688031215620032e4575f80fd5b620032ef8662003206565b9450602086013562003301816200321a565b93506040860135620033138162003279565b9250606086013567ffffffffffffffff8111156200332f575f80fd5b6200333d8882890162003287565b969995985093965092949392505050565b8061040081018310156200077e575f80fd5b5f805f805f805f805f805f6105208c8e0312156200337c575f80fd5b620033888d8d6200334e565b9a50620033996104008d0162003206565b99506104208c013598506104408c01359750620033ba6104608d0162003206565b96506104808c0135620033cd816200321a565b9550620033de6104a08d0162003206565b94506104c08c0135620033f1816200321a565b93506104e08c013592506105008c013567ffffffffffffffff81111562003416575f80fd5b620034248e828f0162003287565b915080935050809150509295989b509295989b9093969950565b5f602082840312156200344f575f80fd5b81356200345c816200321a565b9392505050565b60ff811681146200323c575f80fd5b5f805f805f805f60e0888a03121562003489575f80fd5b8735620034968162003463565b9650620034a66020890162003206565b95506040880135620034b8816200321a565b9450620034c86060890162003206565b93506080880135620034da816200321a565b9699959850939692959460a0840135945060c09093013592915050565b5f805f606084860312156200350a575f80fd5b620035158462003206565b9250602084013562003527816200321a565b9150604084013562003539816200321a565b809150509250925092565b5f6020828403121562003555575f80fd5b5035919050565b5f805f805f805f60a0888a03121562003573575f80fd5b6200357e8862003206565b9650602088013562003590816200321a565b9550604088013567ffffffffffffffff80821115620035ad575f80fd5b620035bb8b838c0162003287565b909750955060608a0135915080821115620035d4575f80fd5b50620035e38a828b0162003287565b9094509250506080880135620035f98162003463565b8091505092959891949750929550565b5f805f805f805f60c0888a03121562003620575f80fd5b6200362b8862003206565b965060208801356200363d816200321a565b955060408801359450606088013562003656816200321a565b93506080880135620036688162003279565b925060a088013567ffffffffffffffff81111562003684575f80fd5b620036928a828b0162003287565b989b979a50959850939692959293505050565b5f805f806104608587031215620036ba575f80fd5b84359350620036cd86602087016200334e565b9250620036de610420860162003206565b939692955092936104400135925050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f61010060ff8c16835263ffffffff808c16602085015273ffffffffffffffffffffffffffffffffffffffff808c166040860152818b166060860152808a166080860152508760a08501528160c0850152620037968285018789620036ef565b925080851660e085015250509a9950505050505050505050565b818382375f9101908152919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5b8381101562003808578181015183820152602001620037ee565b50505f910152565b5f825162003823818460208701620037ec565b9190910192915050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715620038775762003877620037bf565b604052919050565b5f67ffffffffffffffff8211156200389b576200389b620037bf565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112620038d7575f80fd5b8135620038ee620038e8826200387f565b6200382d565b81815284602083860101111562003903575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f6060848603121562003932575f80fd5b833567ffffffffffffffff808211156200394a575f80fd5b6200395887838801620038c7565b945060208601359150808211156200396e575f80fd5b506200397d86828701620038c7565b9250506040840135620035398162003463565b5f8151808452620039a9816020860160208601620037ec565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606081525f620039ef606083018662003990565b828103602084015262003a03818662003990565b91505060ff83166040830152949350505050565b63ffffffff861681525f73ffffffffffffffffffffffffffffffffffffffff80871660208401528086166040840152506080606083015262003106608083018486620036ef565b73ffffffffffffffffffffffffffffffffffffffff8516815263ffffffff84166020820152606060408201525f62003a9b606083018486620036ef565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003b325762003b3262003ad2565b5060010190565b606081525f62003b4e606083018789620036ef565b828103602084015262003b63818688620036ef565b91505060ff831660408301529695505050505050565b5f835162003b8c818460208801620037ec565b83519083019062003ba2818360208801620037ec565b01949350505050565b5f6020828403121562003bbc575f80fd5b5051919050565b818103818111156200077e576200077e62003ad2565b5f61010060ff8b16835263ffffffff808b16602085015273ffffffffffffffffffffffffffffffffffffffff808b166040860152818a1660608601528089166080860152508660a08501528160c085015262003c388285018762003990565b925080851660e085015250509998505050505050505050565b600181815b8085111562003cb057817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003c945762003c9462003ad2565b8085161562003ca257918102915b93841c939080029062003c56565b509250929050565b5f8262003cc8575060016200077e565b8162003cd657505f6200077e565b816001811462003cef576002811462003cfa5762003d1a565b60019150506200077e565b60ff84111562003d0e5762003d0e62003ad2565b50506001821b6200077e565b5060208310610133831016604e8410600b841016171562003d3f575081810a6200077e565b62003d4b838362003c51565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003d805762003d8062003ad2565b029392505050565b5f6200345c838362003cb8565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b5f808585111562003dd1575f80fd5b8386111562003dde575f80fd5b5050820193919092039150565b7fffffffff00000000000000000000000000000000000000000000000000000000813581811691600485101562003e2c5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a03121562003e4b575f80fd5b873562003e58816200321a565b9650602088013562003e6a816200321a565b955060408801359450606088013593506080880135620034da8162003463565b5f805f805f805f80610100898b03121562003ea3575f80fd5b883562003eb0816200321a565b9750602089013562003ec2816200321a565b96506040890135955060608901359450608089013562003ee28162003279565b935060a089013562003ef48162003463565b979a969950949793969295929450505060c08201359160e0013590565b5f6020828403121562003f22575f80fd5b81516200345c8162003463565b5f6020828403121562003f40575f80fd5b81516200345c8162003279565b5f6020828403121562003f5e575f80fd5b815167ffffffffffffffff81111562003f75575f80fd5b8201601f8101841362003f86575f80fd5b805162003f97620038e8826200387f565b81815285602083850101111562003fac575f80fd5b62003fbf826020830160208601620037ec565b95945050505050565b602081525f6200345c60208301846200399056fe61010060405234801562000011575f80fd5b5060405162001b0d38038062001b0d833981016040819052620000349162000282565b828260036200004483826200038d565b5060046200005382826200038d565b50503360c0525060ff811660e05246608081905262000072906200007f565b60a0525062000455915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ab6200012c565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013d9062000301565b80601f01602080910402602001604051908101604052809291908181526020018280546200016b9062000301565b8015620001ba5780601f106200019057610100808354040283529160200191620001ba565b820191905f5260205f20905b8154815290600101906020018083116200019c57829003601f168201915b5050505050905090565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112620001e8575f80fd5b81516001600160401b0380821115620002055762000205620001c4565b604051601f8301601f19908116603f01168101908282118183101715620002305762000230620001c4565b816040528381526020925086838588010111156200024c575f80fd5b5f91505b838210156200026f578582018301518183018401529082019062000250565b5f93810190920192909252949350505050565b5f805f6060848603121562000295575f80fd5b83516001600160401b0380821115620002ac575f80fd5b620002ba87838801620001d8565b94506020860151915080821115620002d0575f80fd5b50620002df86828701620001d8565b925050604084015160ff81168114620002f6575f80fd5b809150509250925092565b600181811c908216806200031657607f821691505b6020821081036200033557634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000388575f81815260208120601f850160051c81016020861015620003635750805b601f850160051c820191505b8181101562000384578281556001016200036f565b5050505b505050565b81516001600160401b03811115620003a957620003a9620001c4565b620003c181620003ba845462000301565b846200033b565b602080601f831160018114620003f7575f8415620003df5750858301515b5f19600386901b1c1916600185901b17855562000384565b5f85815260208120601f198616915b82811015620004275788860151825594840194600190910190840162000406565b50858210156200044557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161166f6200049e5f395f61022d01525f81816102fb015281816105ad015261069401525f61052801525f818161036d01526104f2015261166f5ff3fe608060405234801561000f575f80fd5b506004361061016e575f3560e01c806370a08231116100d2578063a457c2d711610088578063d505accf11610063578063d505accf1461038f578063dd62ed3e146103a2578063ffa1ad74146103e7575f80fd5b8063a457c2d714610342578063a9059cbb14610355578063cd0d009614610368575f80fd5b806395d89b41116100b857806395d89b41146102db5780639dc29fac146102e3578063a3c573eb146102f6575f80fd5b806370a08231146102875780637ecebe00146102bc575f80fd5b806330adf81f116101275780633644e5151161010d5780633644e51514610257578063395093511461025f57806340c10f1914610272575f80fd5b806330adf81f146101ff578063313ce56714610226575f80fd5b806318160ddd1161015757806318160ddd146101b357806320606b70146101c557806323b872dd146101ec575f80fd5b806306fdde0314610172578063095ea7b314610190575b5f80fd5b61017a610423565b60405161018791906113c1565b60405180910390f35b6101a361019e366004611452565b6104b3565b6040519015158152602001610187565b6002545b604051908152602001610187565b6101b77f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101a36101fa36600461147a565b6104cc565b6101b77f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610187565b6101b76104ef565b6101a361026d366004611452565b61054a565b610285610280366004611452565b610595565b005b6101b76102953660046114b3565b73ffffffffffffffffffffffffffffffffffffffff165f9081526020819052604090205490565b6101b76102ca3660046114b3565b60056020525f908152604090205481565b61017a61066d565b6102856102f1366004611452565b61067c565b61031d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610187565b6101a3610350366004611452565b61074b565b6101a3610363366004611452565b61081b565b6101b77f000000000000000000000000000000000000000000000000000000000000000081565b61028561039d3660046114d3565b610828565b6101b76103b0366004611540565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260016020908152604080832093909416825291909152205490565b61017a6040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043290611571565b80601f016020809104026020016040519081016040528092919081815260200182805461045e90611571565b80156104a95780601f10610480576101008083540402835291602001916104a9565b820191905f5260205f20905b81548152906001019060200180831161048c57829003601f168201915b5050505050905090565b5f336104c0818585610b59565b60019150505b92915050565b5f336104d9858285610d0c565b6104e4858585610de2565b506001949350505050565b5f7f00000000000000000000000000000000000000000000000000000000000000004614610525576105204661104f565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104c090829086906105909087906115ef565b610b59565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461065f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b6106698282611116565b5050565b60606004805461043290611571565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610741576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610656565b6106698282611207565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561080e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610656565b6104e48286868403610b59565b5f336104c0818585610de2565b834211156108b7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff87165f90815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a91908661091083611602565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f61097a6104ef565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f80855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a3b573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ab657508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610656565b610b4d8a8a8a610b59565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610c9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381165f908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610ddc5781811015610dcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610656565b610ddc8484848403610b59565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610e85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610f28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f9081526020819052604090205481811015610fdd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610ddc565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611079610423565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff8216611193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610656565b8060025f8282546111a491906115ef565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff82165f908152602081905260409020548181101561135f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610cff565b5f6020808352835180828501525f5b818110156113ec578581018301518582016040015282016113d0565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461144d575f80fd5b919050565b5f8060408385031215611463575f80fd5b61146c8361142a565b946020939093013593505050565b5f805f6060848603121561148c575f80fd5b6114958461142a565b92506114a36020850161142a565b9150604084013590509250925092565b5f602082840312156114c3575f80fd5b6114cc8261142a565b9392505050565b5f805f805f805f60e0888a0312156114e9575f80fd5b6114f28861142a565b96506115006020890161142a565b95506040880135945060608801359350608088013560ff81168114611523575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611551575f80fd5b61155a8361142a565b91506115686020840161142a565b90509250929050565b600181811c9082168061158557607f821691505b6020821081036115bc577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156104c6576104c66115c2565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611632576116326115c2565b506001019056fea2646970667358221220a04a4613834006222ac539b942dfe3284c1163f5082f3bafb302007d825cd7ff64736f6c63430008140033a26469706673582212204bf5435ffe476836b9a1ac833105603f477cc35a320609487acf64f513eae07564736f6c63430008140033", - "deployedBytecode": "0x60806040526004361062000197575f3560e01c8063647c576c11620000e2578063be5831c71162000086578063dbc16976116200005e578063dbc16976146200061a578063ee25560b1462000631578063fb5708341462000660575f80fd5b8063be5831c71462000591578063cd58657914620005cc578063d02103ca14620005e3575f80fd5b80639e34070f11620000ba5780639e34070f14620004f1578063aaa13cc21462000534578063bab161bf1462000558575f80fd5b8063647c576c146200047157806379e2cf97146200049557806381b1c17414620004ac575f80fd5b80632d2c9d94116200014a57806334ac9cf2116200012257806334ac9cf2146200033a5780633ae0504714620003685780633e197043146200037f575f80fd5b80632d2c9d9414620002695780632dfdf0b5146200028d578063318aee3d14620002b3575f80fd5b806322e95f2c116200017e57806322e95f2c14620001e4578063240ff378146200022e5780632cffd02e1462000245575f80fd5b806315064c96146200019b5780632072f6c514620001cb575b5f80fd5b348015620001a7575f80fd5b50606854620001b69060ff1681565b60405190151581526020015b60405180910390f35b348015620001d7575f80fd5b50620001e262000684565b005b348015620001f0575f80fd5b5062000208620002023660046200323f565b620006e2565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620001c2565b620001e26200023f366004620032cf565b62000784565b34801562000251575f80fd5b50620001e26200026336600462003360565b620009ab565b34801562000275575f80fd5b50620001e26200028736600462003360565b62000f30565b34801562000299575f80fd5b50620002a460535481565b604051908152602001620001c2565b348015620002bf575f80fd5b5062000308620002d13660046200343e565b606b6020525f908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff909116602083015201620001c2565b34801562000346575f80fd5b50606c54620002089073ffffffffffffffffffffffffffffffffffffffff1681565b34801562000374575f80fd5b50620002a462001130565b3480156200038b575f80fd5b50620002a46200039d36600462003472565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b3480156200047d575f80fd5b50620001e26200048f366004620034f7565b62001215565b348015620004a1575f80fd5b50620001e26200145e565b348015620004b8575f80fd5b5062000208620004ca36600462003544565b606a6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015620004fd575f80fd5b50620001b66200050f36600462003544565b600881901c5f90815260696020526040902054600160ff9092169190911b9081161490565b34801562000540575f80fd5b5062000208620005523660046200355c565b62001498565b34801562000564575f80fd5b506068546200057b90610100900463ffffffff1681565b60405163ffffffff9091168152602001620001c2565b3480156200059d575f80fd5b506068546200057b90790100000000000000000000000000000000000000000000000000900463ffffffff1681565b620001e2620005dd36600462003609565b62001682565b348015620005ef575f80fd5b50606854620002089065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b34801562000626575f80fd5b50620001e262001bd4565b3480156200063d575f80fd5b50620002a46200064f36600462003544565b60696020525f908152604090205481565b3480156200066c575f80fd5b50620001b66200067e366004620036a5565b62001c30565b606c5473ffffffffffffffffffffffffffffffffffffffff163314620006d6576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620006e062001d18565b565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602483015282516018818403018152603890920183528151918101919091205f908152606a909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b60685460ff1615620007c2576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff868116610100909204161480620007e85750600263ffffffff861610155b1562000820576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338888348888605354604051620008769998979695949392919062003736565b60405180910390a1620009936200098d6001606860019054906101000a900463ffffffff16338989348989604051620008b1929190620037b0565b60405180910390206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b62001dab565b8215620009a457620009a462001ebf565b5050505050565b60685460ff1615620009e9576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620009ff8b8b8b8b8b8b8b8b8b8b8b5f62001f8f565b73ffffffffffffffffffffffffffffffffffffffff861662000ad757604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff861690859060405162000a53919062003810565b5f6040518083038185875af1925050503d805f811462000a8f576040519150601f19603f3d011682016040523d82523d5f602084013e62000a94565b606091505b505090508062000ad0576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5062000eb8565b60685463ffffffff61010090910481169088160362000b195762000b1373ffffffffffffffffffffffffffffffffffffffff871685856200217a565b62000eb8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f90603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301205f818152606a90935291205490915073ffffffffffffffffffffffffffffffffffffffff168062000e2f575f808062000beb868801886200391f565b9250925092505f8584848460405162000c0490620031f8565b62000c1293929190620039db565b8190604051809103905ff590508015801562000c30573d5f803e3d5ffd5b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81166004830152602482018c9052919250908216906340c10f19906044015f604051808303815f87803b15801562000ca3575f80fd5b505af115801562000cb6573d5f803e3d5ffd5b5050505080606a5f8881526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808e63ffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815250606b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000e1d95949392919062003a17565b60405180910390a15050505062000eb5565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801562000e9d575f80fd5b505af115801562000eb0573d5f803e3d5ffd5b505050505b50505b6040805163ffffffff8c811682528916602082015273ffffffffffffffffffffffffffffffffffffffff88811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff161562000f6e576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000f858b8b8b8b8b8b8b8b8b8b8b600162001f8f565b5f8473ffffffffffffffffffffffffffffffffffffffff1684888a868660405160240162000fb7949392919062003a5e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1806b5f200000000000000000000000000000000000000000000000000000000179052516200103a919062003810565b5f6040518083038185875af1925050503d805f811462001076576040519150601f19603f3d011682016040523d82523d5f602084013e6200107b565b606091505b5050905080620010b7576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a16602082015273ffffffffffffffffffffffffffffffffffffffff89811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b6053545f90819081805b60208110156200120c578083901c6001166001036200119d576033816020811062001169576200116962003aa5565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350620011ca565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080620012039062003aff565b9150506200113a565b50919392505050565b5f54610100900460ff16158080156200123457505f54600160ff909116105b806200124f5750303b1580156200124f57505f5460ff166001145b620012e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200133e575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff16176501000000000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155606c80547fffffffffffffffffffffffff000000000000000000000000000000000000000016918416919091179055620013f562002250565b801562001458575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b605354606854790100000000000000000000000000000000000000000000000000900463ffffffff161015620006e057620006e062001ebf565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b3083604051806020016200152c90620031f8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081905262001577908d908d908d908d908d9060200162003b39565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052620015b5929160200162003b79565b604051602081830303815290604052805190602001206040516020016200163e94939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101209a9950505050505050505050565b60685460ff1615620016c0576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620016ca620022f2565b60685463ffffffff888116610100909204161480620016f05750600263ffffffff881610155b1562001728576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8060608773ffffffffffffffffffffffffffffffffffffffff88166200178c5788341462001783576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f925062001a79565b3415620017c5576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8089165f908152606b602090815260409182902082518084019093525463ffffffff8116835264010000000090049092169181018290529015620018ae576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b905273ffffffffffffffffffffffffffffffffffffffff8a1690639dc29fac906044015f604051808303815f87803b15801562001884575f80fd5b505af115801562001897573d5f803e3d5ffd5b5050505080602001519450805f0151935062001a77565b8515620018c357620018c3898b898962002367565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8b16906370a0823190602401602060405180830381865afa1580156200192e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001954919062003bab565b90506200197a73ffffffffffffffffffffffffffffffffffffffff8b1633308e6200287a565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa158015620019e5573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001a0b919062003bab565b905062001a19828262003bc3565b6068548c9850610100900463ffffffff169650935062001a3987620028da565b62001a448c620029ee565b62001a4f8d62002af7565b60405160200162001a6393929190620039db565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e868860535460405162001aba98979695949392919062003bd9565b60405180910390a162001bac6200098d5f85878f8f8789805190602001206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b861562001bbd5762001bbd62001ebf565b5050505062001bcb60018055565b50505050505050565b606c5473ffffffffffffffffffffffffffffffffffffffff16331462001c26576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620006e062002bf5565b5f84815b602081101562001d0a57600163ffffffff8616821c8116900362001ca65785816020811062001c675762001c6762003aa5565b60200201358260405160200162001c88929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001cf5565b8186826020811062001cbc5762001cbc62003aa5565b602002013560405160200162001cdc929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001d018162003aff565b91505062001c34565b50821490505b949350505050565b60685460ff161562001d56576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b80600162001dbc6020600262003d88565b62001dc8919062003bc3565b6053541062001e03576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f815462001e149062003aff565b918290555090505f5b602081101562001eaf578082901c60011660010362001e5557826033826020811062001e4d5762001e4d62003aa5565b015550505050565b6033816020811062001e6b5762001e6b62003aa5565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808062001ea69062003aff565b91505062001e1d565b5062001eba62003d95565b505050565b6053546068805463ffffffff909216790100000000000000000000000000000000000000000000000000027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179081905573ffffffffffffffffffffffffffffffffffffffff65010000000000909104166333d6247d62001f4562001130565b6040518263ffffffff1660e01b815260040162001f6491815260200190565b5f604051808303815f87803b15801562001f7c575f80fd5b505af115801562001458573d5f803e3d5ffd5b62001fa08b63ffffffff1662002c84565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f9165010000000000900473ffffffffffffffffffffffffffffffffffffffff169063257b3632906084016020604051808303815f875af11580156200203f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002065919062003bab565b9050805f03620020a0576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff8881166101009092041614620020ea576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068545f90610100900463ffffffff16620021075750896200210a565b508a5b620021336200212a848c8c8c8c8c8c8c604051620008b1929190620037b0565b8f8f8462001c30565b6200216a576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001eba9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915262002ce8565b5f54610100900460ff16620022e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620012d8565b620006e062002dfa565b60026001540362002360576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401620012d8565b6002600155565b5f62002377600482848662003dc2565b620023829162003deb565b90507f2afa5331000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000821601620025fc575f808080808080620023e4896004818d62003dc2565b810190620023f3919062003e34565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462002467576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff86163014620024b7576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a8514620024f1576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e1691620025ac919062003810565b5f604051808303815f865af19150503d805f8114620025e7576040519150601f19603f3d011682016040523d82523d5f602084013e620025ec565b606091505b50505050505050505050620009a4565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f8fcbaf0c000000000000000000000000000000000000000000000000000000001462002678576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806200268f8a6004818e62003dc2565b8101906200269e919062003e8a565b975097509750975097509750975097503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161462002714576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8716301462002764576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8fcbaf0c000000000000000000000000000000000000000000000000000000001790529151918f169162002828919062003810565b5f604051808303815f865af19150503d805f811462002863576040519150601f19603f3d011682016040523d82523d5f602084013e62002868565b606091505b50505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620014589085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401620021cd565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff8616916200295d919062003810565b5f60405180830381855afa9150503d805f811462002997576040519150601f19603f3d011682016040523d82523d5f602084013e6200299c565b606091505b509150915081620029e3576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525062001d10565b62001d108162002e92565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff86169162002a71919062003810565b5f60405180830381855afa9150503d805f811462002aab576040519150601f19603f3d011682016040523d82523d5f602084013e62002ab0565b606091505b509150915081620029e3576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525062001d10565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f918291829173ffffffffffffffffffffffffffffffffffffffff86169162002b79919062003810565b5f60405180830381855afa9150503d805f811462002bb3576040519150601f19603f3d011682016040523d82523d5f602084013e62002bb8565b606091505b509150915081801562002bcc575080516020145b62002bd957601262001d10565b8080602001905181019062001d10919062003f11565b60018055565b60685460ff1662002c32576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003620009a4576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62002d4b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166200307d9092919063ffffffff16565b80519091501562001eba578080602001905181019062002d6c919062003f2f565b62001eba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401620012d8565b5f54610100900460ff1662002bef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620012d8565b6060604082511062002eb457818060200190518101906200077e919062003f4d565b81516020036200303f575f5b60208110801562002f0b575082818151811062002ee15762002ee162003aa5565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b1562002f26578062002f1d8162003aff565b91505062002ec0565b805f0362002f6957505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff81111562002f865762002f86620037bf565b6040519080825280601f01601f19166020018201604052801562002fb1576020820181803683370190505b5090505f5b82811015620030375784818151811062002fd45762002fd462003aa5565b602001015160f81c60f81b82828151811062002ff45762002ff462003aa5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350806200302e8162003aff565b91505062002fb6565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b606062001d1084845f85855f808673ffffffffffffffffffffffffffffffffffffffff168587604051620030b2919062003810565b5f6040518083038185875af1925050503d805f8114620030ee576040519150601f19603f3d011682016040523d82523d5f602084013e620030f3565b606091505b5091509150620031068783838762003111565b979650505050505050565b60608315620031ab5782515f03620031a35773ffffffffffffffffffffffffffffffffffffffff85163b620031a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620012d8565b508162001d10565b62001d108383815115620031c25781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620012d8919062003fc8565b611b0d8062003fdd83390190565b803563ffffffff8116811462003078575f80fd5b73ffffffffffffffffffffffffffffffffffffffff811681146200323c575f80fd5b50565b5f806040838503121562003251575f80fd5b6200325c8362003206565b915060208301356200326e816200321a565b809150509250929050565b80151581146200323c575f80fd5b5f8083601f84011262003298575f80fd5b50813567ffffffffffffffff811115620032b0575f80fd5b602083019150836020828501011115620032c8575f80fd5b9250929050565b5f805f805f60808688031215620032e4575f80fd5b620032ef8662003206565b9450602086013562003301816200321a565b93506040860135620033138162003279565b9250606086013567ffffffffffffffff8111156200332f575f80fd5b6200333d8882890162003287565b969995985093965092949392505050565b8061040081018310156200077e575f80fd5b5f805f805f805f805f805f6105208c8e0312156200337c575f80fd5b620033888d8d6200334e565b9a50620033996104008d0162003206565b99506104208c013598506104408c01359750620033ba6104608d0162003206565b96506104808c0135620033cd816200321a565b9550620033de6104a08d0162003206565b94506104c08c0135620033f1816200321a565b93506104e08c013592506105008c013567ffffffffffffffff81111562003416575f80fd5b620034248e828f0162003287565b915080935050809150509295989b509295989b9093969950565b5f602082840312156200344f575f80fd5b81356200345c816200321a565b9392505050565b60ff811681146200323c575f80fd5b5f805f805f805f60e0888a03121562003489575f80fd5b8735620034968162003463565b9650620034a66020890162003206565b95506040880135620034b8816200321a565b9450620034c86060890162003206565b93506080880135620034da816200321a565b9699959850939692959460a0840135945060c09093013592915050565b5f805f606084860312156200350a575f80fd5b620035158462003206565b9250602084013562003527816200321a565b9150604084013562003539816200321a565b809150509250925092565b5f6020828403121562003555575f80fd5b5035919050565b5f805f805f805f60a0888a03121562003573575f80fd5b6200357e8862003206565b9650602088013562003590816200321a565b9550604088013567ffffffffffffffff80821115620035ad575f80fd5b620035bb8b838c0162003287565b909750955060608a0135915080821115620035d4575f80fd5b50620035e38a828b0162003287565b9094509250506080880135620035f98162003463565b8091505092959891949750929550565b5f805f805f805f60c0888a03121562003620575f80fd5b6200362b8862003206565b965060208801356200363d816200321a565b955060408801359450606088013562003656816200321a565b93506080880135620036688162003279565b925060a088013567ffffffffffffffff81111562003684575f80fd5b620036928a828b0162003287565b989b979a50959850939692959293505050565b5f805f806104608587031215620036ba575f80fd5b84359350620036cd86602087016200334e565b9250620036de610420860162003206565b939692955092936104400135925050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f61010060ff8c16835263ffffffff808c16602085015273ffffffffffffffffffffffffffffffffffffffff808c166040860152818b166060860152808a166080860152508760a08501528160c0850152620037968285018789620036ef565b925080851660e085015250509a9950505050505050505050565b818382375f9101908152919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5b8381101562003808578181015183820152602001620037ee565b50505f910152565b5f825162003823818460208701620037ec565b9190910192915050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715620038775762003877620037bf565b604052919050565b5f67ffffffffffffffff8211156200389b576200389b620037bf565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112620038d7575f80fd5b8135620038ee620038e8826200387f565b6200382d565b81815284602083860101111562003903575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f6060848603121562003932575f80fd5b833567ffffffffffffffff808211156200394a575f80fd5b6200395887838801620038c7565b945060208601359150808211156200396e575f80fd5b506200397d86828701620038c7565b9250506040840135620035398162003463565b5f8151808452620039a9816020860160208601620037ec565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606081525f620039ef606083018662003990565b828103602084015262003a03818662003990565b91505060ff83166040830152949350505050565b63ffffffff861681525f73ffffffffffffffffffffffffffffffffffffffff80871660208401528086166040840152506080606083015262003106608083018486620036ef565b73ffffffffffffffffffffffffffffffffffffffff8516815263ffffffff84166020820152606060408201525f62003a9b606083018486620036ef565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003b325762003b3262003ad2565b5060010190565b606081525f62003b4e606083018789620036ef565b828103602084015262003b63818688620036ef565b91505060ff831660408301529695505050505050565b5f835162003b8c818460208801620037ec565b83519083019062003ba2818360208801620037ec565b01949350505050565b5f6020828403121562003bbc575f80fd5b5051919050565b818103818111156200077e576200077e62003ad2565b5f61010060ff8b16835263ffffffff808b16602085015273ffffffffffffffffffffffffffffffffffffffff808b166040860152818a1660608601528089166080860152508660a08501528160c085015262003c388285018762003990565b925080851660e085015250509998505050505050505050565b600181815b8085111562003cb057817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003c945762003c9462003ad2565b8085161562003ca257918102915b93841c939080029062003c56565b509250929050565b5f8262003cc8575060016200077e565b8162003cd657505f6200077e565b816001811462003cef576002811462003cfa5762003d1a565b60019150506200077e565b60ff84111562003d0e5762003d0e62003ad2565b50506001821b6200077e565b5060208310610133831016604e8410600b841016171562003d3f575081810a6200077e565b62003d4b838362003c51565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003d805762003d8062003ad2565b029392505050565b5f6200345c838362003cb8565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b5f808585111562003dd1575f80fd5b8386111562003dde575f80fd5b5050820193919092039150565b7fffffffff00000000000000000000000000000000000000000000000000000000813581811691600485101562003e2c5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a03121562003e4b575f80fd5b873562003e58816200321a565b9650602088013562003e6a816200321a565b955060408801359450606088013593506080880135620034da8162003463565b5f805f805f805f80610100898b03121562003ea3575f80fd5b883562003eb0816200321a565b9750602089013562003ec2816200321a565b96506040890135955060608901359450608089013562003ee28162003279565b935060a089013562003ef48162003463565b979a969950949793969295929450505060c08201359160e0013590565b5f6020828403121562003f22575f80fd5b81516200345c8162003463565b5f6020828403121562003f40575f80fd5b81516200345c8162003279565b5f6020828403121562003f5e575f80fd5b815167ffffffffffffffff81111562003f75575f80fd5b8201601f8101841362003f86575f80fd5b805162003f97620038e8826200387f565b81815285602083850101111562003fac575f80fd5b62003fbf826020830160208601620037ec565b95945050505050565b602081525f6200345c60208301846200399056fe61010060405234801562000011575f80fd5b5060405162001b0d38038062001b0d833981016040819052620000349162000282565b828260036200004483826200038d565b5060046200005382826200038d565b50503360c0525060ff811660e05246608081905262000072906200007f565b60a0525062000455915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ab6200012c565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013d9062000301565b80601f01602080910402602001604051908101604052809291908181526020018280546200016b9062000301565b8015620001ba5780601f106200019057610100808354040283529160200191620001ba565b820191905f5260205f20905b8154815290600101906020018083116200019c57829003601f168201915b5050505050905090565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112620001e8575f80fd5b81516001600160401b0380821115620002055762000205620001c4565b604051601f8301601f19908116603f01168101908282118183101715620002305762000230620001c4565b816040528381526020925086838588010111156200024c575f80fd5b5f91505b838210156200026f578582018301518183018401529082019062000250565b5f93810190920192909252949350505050565b5f805f6060848603121562000295575f80fd5b83516001600160401b0380821115620002ac575f80fd5b620002ba87838801620001d8565b94506020860151915080821115620002d0575f80fd5b50620002df86828701620001d8565b925050604084015160ff81168114620002f6575f80fd5b809150509250925092565b600181811c908216806200031657607f821691505b6020821081036200033557634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000388575f81815260208120601f850160051c81016020861015620003635750805b601f850160051c820191505b8181101562000384578281556001016200036f565b5050505b505050565b81516001600160401b03811115620003a957620003a9620001c4565b620003c181620003ba845462000301565b846200033b565b602080601f831160018114620003f7575f8415620003df5750858301515b5f19600386901b1c1916600185901b17855562000384565b5f85815260208120601f198616915b82811015620004275788860151825594840194600190910190840162000406565b50858210156200044557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161166f6200049e5f395f61022d01525f81816102fb015281816105ad015261069401525f61052801525f818161036d01526104f2015261166f5ff3fe608060405234801561000f575f80fd5b506004361061016e575f3560e01c806370a08231116100d2578063a457c2d711610088578063d505accf11610063578063d505accf1461038f578063dd62ed3e146103a2578063ffa1ad74146103e7575f80fd5b8063a457c2d714610342578063a9059cbb14610355578063cd0d009614610368575f80fd5b806395d89b41116100b857806395d89b41146102db5780639dc29fac146102e3578063a3c573eb146102f6575f80fd5b806370a08231146102875780637ecebe00146102bc575f80fd5b806330adf81f116101275780633644e5151161010d5780633644e51514610257578063395093511461025f57806340c10f1914610272575f80fd5b806330adf81f146101ff578063313ce56714610226575f80fd5b806318160ddd1161015757806318160ddd146101b357806320606b70146101c557806323b872dd146101ec575f80fd5b806306fdde0314610172578063095ea7b314610190575b5f80fd5b61017a610423565b60405161018791906113c1565b60405180910390f35b6101a361019e366004611452565b6104b3565b6040519015158152602001610187565b6002545b604051908152602001610187565b6101b77f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101a36101fa36600461147a565b6104cc565b6101b77f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610187565b6101b76104ef565b6101a361026d366004611452565b61054a565b610285610280366004611452565b610595565b005b6101b76102953660046114b3565b73ffffffffffffffffffffffffffffffffffffffff165f9081526020819052604090205490565b6101b76102ca3660046114b3565b60056020525f908152604090205481565b61017a61066d565b6102856102f1366004611452565b61067c565b61031d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610187565b6101a3610350366004611452565b61074b565b6101a3610363366004611452565b61081b565b6101b77f000000000000000000000000000000000000000000000000000000000000000081565b61028561039d3660046114d3565b610828565b6101b76103b0366004611540565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260016020908152604080832093909416825291909152205490565b61017a6040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043290611571565b80601f016020809104026020016040519081016040528092919081815260200182805461045e90611571565b80156104a95780601f10610480576101008083540402835291602001916104a9565b820191905f5260205f20905b81548152906001019060200180831161048c57829003601f168201915b5050505050905090565b5f336104c0818585610b59565b60019150505b92915050565b5f336104d9858285610d0c565b6104e4858585610de2565b506001949350505050565b5f7f00000000000000000000000000000000000000000000000000000000000000004614610525576105204661104f565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104c090829086906105909087906115ef565b610b59565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461065f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b6106698282611116565b5050565b60606004805461043290611571565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610741576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610656565b6106698282611207565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561080e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610656565b6104e48286868403610b59565b5f336104c0818585610de2565b834211156108b7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff87165f90815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a91908661091083611602565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f61097a6104ef565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f80855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a3b573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ab657508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610656565b610b4d8a8a8a610b59565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610c9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381165f908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610ddc5781811015610dcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610656565b610ddc8484848403610b59565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610e85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610f28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f9081526020819052604090205481811015610fdd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610ddc565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611079610423565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff8216611193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610656565b8060025f8282546111a491906115ef565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff82165f908152602081905260409020548181101561135f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610cff565b5f6020808352835180828501525f5b818110156113ec578581018301518582016040015282016113d0565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461144d575f80fd5b919050565b5f8060408385031215611463575f80fd5b61146c8361142a565b946020939093013593505050565b5f805f6060848603121561148c575f80fd5b6114958461142a565b92506114a36020850161142a565b9150604084013590509250925092565b5f602082840312156114c3575f80fd5b6114cc8261142a565b9392505050565b5f805f805f805f60e0888a0312156114e9575f80fd5b6114f28861142a565b96506115006020890161142a565b95506040880135945060608801359350608088013560ff81168114611523575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611551575f80fd5b61155a8361142a565b91506115686020840161142a565b90509250929050565b600181811c9082168061158557607f821691505b6020821081036115bc577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156104c6576104c66115c2565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611632576116326115c2565b506001019056fea2646970667358221220a04a4613834006222ac539b942dfe3284c1163f5082f3bafb302007d825cd7ff64736f6c63430008140033a26469706673582212204bf5435ffe476836b9a1ac833105603f477cc35a320609487acf64f513eae07564736f6c63430008140033", + "bytecode": "0x608060405234801561000f575f80fd5b50615b1f8061001d5f395ff3fe60806040526004361062000197575f3560e01c8063647c576c11620000e2578063be5831c71162000086578063dbc16976116200005e578063dbc16976146200061a578063ee25560b1462000631578063fb5708341462000660575f80fd5b8063be5831c71462000591578063cd58657914620005cc578063d02103ca14620005e3575f80fd5b80639e34070f11620000ba5780639e34070f14620004f1578063aaa13cc21462000534578063bab161bf1462000558575f80fd5b8063647c576c146200047157806379e2cf97146200049557806381b1c17414620004ac575f80fd5b80632d2c9d94116200014a57806334ac9cf2116200012257806334ac9cf2146200033a5780633ae0504714620003685780633e197043146200037f575f80fd5b80632d2c9d9414620002695780632dfdf0b5146200028d578063318aee3d14620002b3575f80fd5b806322e95f2c116200017e57806322e95f2c14620001e4578063240ff378146200022e5780632cffd02e1462000245575f80fd5b806315064c96146200019b5780632072f6c514620001cb575b5f80fd5b348015620001a7575f80fd5b50606854620001b69060ff1681565b60405190151581526020015b60405180910390f35b348015620001d7575f80fd5b50620001e262000684565b005b348015620001f0575f80fd5b5062000208620002023660046200323f565b620006e2565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620001c2565b620001e26200023f366004620032cf565b62000784565b34801562000251575f80fd5b50620001e26200026336600462003360565b620009ab565b34801562000275575f80fd5b50620001e26200028736600462003360565b62000f30565b34801562000299575f80fd5b50620002a460535481565b604051908152602001620001c2565b348015620002bf575f80fd5b5062000308620002d13660046200343e565b606b6020525f908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff909116602083015201620001c2565b34801562000346575f80fd5b50606c54620002089073ffffffffffffffffffffffffffffffffffffffff1681565b34801562000374575f80fd5b50620002a462001130565b3480156200038b575f80fd5b50620002a46200039d36600462003472565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b3480156200047d575f80fd5b50620001e26200048f366004620034f7565b62001215565b348015620004a1575f80fd5b50620001e26200145e565b348015620004b8575f80fd5b5062000208620004ca36600462003544565b606a6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015620004fd575f80fd5b50620001b66200050f36600462003544565b600881901c5f90815260696020526040902054600160ff9092169190911b9081161490565b34801562000540575f80fd5b5062000208620005523660046200355c565b62001498565b34801562000564575f80fd5b506068546200057b90610100900463ffffffff1681565b60405163ffffffff9091168152602001620001c2565b3480156200059d575f80fd5b506068546200057b90790100000000000000000000000000000000000000000000000000900463ffffffff1681565b620001e2620005dd36600462003609565b62001682565b348015620005ef575f80fd5b50606854620002089065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b34801562000626575f80fd5b50620001e262001bd4565b3480156200063d575f80fd5b50620002a46200064f36600462003544565b60696020525f908152604090205481565b3480156200066c575f80fd5b50620001b66200067e366004620036a5565b62001c30565b606c5473ffffffffffffffffffffffffffffffffffffffff163314620006d6576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620006e062001d18565b565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602483015282516018818403018152603890920183528151918101919091205f908152606a909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b60685460ff1615620007c2576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff868116610100909204161480620007e85750600263ffffffff861610155b1562000820576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338888348888605354604051620008769998979695949392919062003736565b60405180910390a1620009936200098d6001606860019054906101000a900463ffffffff16338989348989604051620008b1929190620037b0565b60405180910390206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b62001dab565b8215620009a457620009a462001ebf565b5050505050565b60685460ff1615620009e9576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620009ff8b8b8b8b8b8b8b8b8b8b8b5f62001f8f565b73ffffffffffffffffffffffffffffffffffffffff861662000ad757604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff861690859060405162000a53919062003810565b5f6040518083038185875af1925050503d805f811462000a8f576040519150601f19603f3d011682016040523d82523d5f602084013e62000a94565b606091505b505090508062000ad0576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5062000eb8565b60685463ffffffff61010090910481169088160362000b195762000b1373ffffffffffffffffffffffffffffffffffffffff871685856200217a565b62000eb8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f90603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301205f818152606a90935291205490915073ffffffffffffffffffffffffffffffffffffffff168062000e2f575f808062000beb868801886200391f565b9250925092505f8584848460405162000c0490620031f8565b62000c1293929190620039db565b8190604051809103905ff590508015801562000c30573d5f803e3d5ffd5b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81166004830152602482018c9052919250908216906340c10f19906044015f604051808303815f87803b15801562000ca3575f80fd5b505af115801562000cb6573d5f803e3d5ffd5b5050505080606a5f8881526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808e63ffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815250606b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000e1d95949392919062003a17565b60405180910390a15050505062000eb5565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801562000e9d575f80fd5b505af115801562000eb0573d5f803e3d5ffd5b505050505b50505b6040805163ffffffff8c811682528916602082015273ffffffffffffffffffffffffffffffffffffffff88811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff161562000f6e576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000f858b8b8b8b8b8b8b8b8b8b8b600162001f8f565b5f8473ffffffffffffffffffffffffffffffffffffffff1684888a868660405160240162000fb7949392919062003a5e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1806b5f200000000000000000000000000000000000000000000000000000000179052516200103a919062003810565b5f6040518083038185875af1925050503d805f811462001076576040519150601f19603f3d011682016040523d82523d5f602084013e6200107b565b606091505b5050905080620010b7576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a16602082015273ffffffffffffffffffffffffffffffffffffffff89811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b6053545f90819081805b60208110156200120c578083901c6001166001036200119d576033816020811062001169576200116962003aa5565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350620011ca565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080620012039062003aff565b9150506200113a565b50919392505050565b5f54610100900460ff16158080156200123457505f54600160ff909116105b806200124f5750303b1580156200124f57505f5460ff166001145b620012e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200133e575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff16176501000000000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155606c80547fffffffffffffffffffffffff000000000000000000000000000000000000000016918416919091179055620013f562002250565b801562001458575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b605354606854790100000000000000000000000000000000000000000000000000900463ffffffff161015620006e057620006e062001ebf565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b3083604051806020016200152c90620031f8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081905262001577908d908d908d908d908d9060200162003b39565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052620015b5929160200162003b79565b604051602081830303815290604052805190602001206040516020016200163e94939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101209a9950505050505050505050565b60685460ff1615620016c0576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620016ca620022f2565b60685463ffffffff888116610100909204161480620016f05750600263ffffffff881610155b1562001728576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8060608773ffffffffffffffffffffffffffffffffffffffff88166200178c5788341462001783576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f925062001a79565b3415620017c5576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8089165f908152606b602090815260409182902082518084019093525463ffffffff8116835264010000000090049092169181018290529015620018ae576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b905273ffffffffffffffffffffffffffffffffffffffff8a1690639dc29fac906044015f604051808303815f87803b15801562001884575f80fd5b505af115801562001897573d5f803e3d5ffd5b5050505080602001519450805f0151935062001a77565b8515620018c357620018c3898b898962002367565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8b16906370a0823190602401602060405180830381865afa1580156200192e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001954919062003bab565b90506200197a73ffffffffffffffffffffffffffffffffffffffff8b1633308e6200287a565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa158015620019e5573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001a0b919062003bab565b905062001a19828262003bc3565b6068548c9850610100900463ffffffff169650935062001a3987620028da565b62001a448c620029ee565b62001a4f8d62002af7565b60405160200162001a6393929190620039db565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e868860535460405162001aba98979695949392919062003bd9565b60405180910390a162001bac6200098d5f85878f8f8789805190602001206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b861562001bbd5762001bbd62001ebf565b5050505062001bcb60018055565b50505050505050565b606c5473ffffffffffffffffffffffffffffffffffffffff16331462001c26576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620006e062002bf5565b5f84815b602081101562001d0a57600163ffffffff8616821c8116900362001ca65785816020811062001c675762001c6762003aa5565b60200201358260405160200162001c88929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001cf5565b8186826020811062001cbc5762001cbc62003aa5565b602002013560405160200162001cdc929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001d018162003aff565b91505062001c34565b50821490505b949350505050565b60685460ff161562001d56576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b80600162001dbc6020600262003d88565b62001dc8919062003bc3565b6053541062001e03576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f815462001e149062003aff565b918290555090505f5b602081101562001eaf578082901c60011660010362001e5557826033826020811062001e4d5762001e4d62003aa5565b015550505050565b6033816020811062001e6b5762001e6b62003aa5565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808062001ea69062003aff565b91505062001e1d565b5062001eba62003d95565b505050565b6053546068805463ffffffff909216790100000000000000000000000000000000000000000000000000027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179081905573ffffffffffffffffffffffffffffffffffffffff65010000000000909104166333d6247d62001f4562001130565b6040518263ffffffff1660e01b815260040162001f6491815260200190565b5f604051808303815f87803b15801562001f7c575f80fd5b505af115801562001458573d5f803e3d5ffd5b62001fa08b63ffffffff1662002c84565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f9165010000000000900473ffffffffffffffffffffffffffffffffffffffff169063257b3632906084016020604051808303815f875af11580156200203f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002065919062003bab565b9050805f03620020a0576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff8881166101009092041614620020ea576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068545f90610100900463ffffffff16620021075750896200210a565b508a5b620021336200212a848c8c8c8c8c8c8c604051620008b1929190620037b0565b8f8f8462001c30565b6200216a576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001eba9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915262002ce8565b5f54610100900460ff16620022e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620012d8565b620006e062002dfa565b60026001540362002360576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401620012d8565b6002600155565b5f62002377600482848662003dc2565b620023829162003deb565b90507f2afa5331000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000821601620025fc575f808080808080620023e4896004818d62003dc2565b810190620023f3919062003e34565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462002467576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff86163014620024b7576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a8514620024f1576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e1691620025ac919062003810565b5f604051808303815f865af19150503d805f8114620025e7576040519150601f19603f3d011682016040523d82523d5f602084013e620025ec565b606091505b50505050505050505050620009a4565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f8fcbaf0c000000000000000000000000000000000000000000000000000000001462002678576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806200268f8a6004818e62003dc2565b8101906200269e919062003e8a565b975097509750975097509750975097503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161462002714576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8716301462002764576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8fcbaf0c000000000000000000000000000000000000000000000000000000001790529151918f169162002828919062003810565b5f604051808303815f865af19150503d805f811462002863576040519150601f19603f3d011682016040523d82523d5f602084013e62002868565b606091505b50505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620014589085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401620021cd565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff8616916200295d919062003810565b5f60405180830381855afa9150503d805f811462002997576040519150601f19603f3d011682016040523d82523d5f602084013e6200299c565b606091505b509150915081620029e3576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525062001d10565b62001d108162002e92565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff86169162002a71919062003810565b5f60405180830381855afa9150503d805f811462002aab576040519150601f19603f3d011682016040523d82523d5f602084013e62002ab0565b606091505b509150915081620029e3576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525062001d10565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f918291829173ffffffffffffffffffffffffffffffffffffffff86169162002b79919062003810565b5f60405180830381855afa9150503d805f811462002bb3576040519150601f19603f3d011682016040523d82523d5f602084013e62002bb8565b606091505b509150915081801562002bcc575080516020145b62002bd957601262001d10565b8080602001905181019062001d10919062003f11565b60018055565b60685460ff1662002c32576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003620009a4576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62002d4b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166200307d9092919063ffffffff16565b80519091501562001eba578080602001905181019062002d6c919062003f2f565b62001eba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401620012d8565b5f54610100900460ff1662002bef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620012d8565b6060604082511062002eb457818060200190518101906200077e919062003f4d565b81516020036200303f575f5b60208110801562002f0b575082818151811062002ee15762002ee162003aa5565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b1562002f26578062002f1d8162003aff565b91505062002ec0565b805f0362002f6957505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff81111562002f865762002f86620037bf565b6040519080825280601f01601f19166020018201604052801562002fb1576020820181803683370190505b5090505f5b82811015620030375784818151811062002fd45762002fd462003aa5565b602001015160f81c60f81b82828151811062002ff45762002ff462003aa5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350806200302e8162003aff565b91505062002fb6565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b606062001d1084845f85855f808673ffffffffffffffffffffffffffffffffffffffff168587604051620030b2919062003810565b5f6040518083038185875af1925050503d805f8114620030ee576040519150601f19603f3d011682016040523d82523d5f602084013e620030f3565b606091505b5091509150620031068783838762003111565b979650505050505050565b60608315620031ab5782515f03620031a35773ffffffffffffffffffffffffffffffffffffffff85163b620031a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620012d8565b508162001d10565b62001d108383815115620031c25781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620012d8919062003fc8565b611b0d8062003fdd83390190565b803563ffffffff8116811462003078575f80fd5b73ffffffffffffffffffffffffffffffffffffffff811681146200323c575f80fd5b50565b5f806040838503121562003251575f80fd5b6200325c8362003206565b915060208301356200326e816200321a565b809150509250929050565b80151581146200323c575f80fd5b5f8083601f84011262003298575f80fd5b50813567ffffffffffffffff811115620032b0575f80fd5b602083019150836020828501011115620032c8575f80fd5b9250929050565b5f805f805f60808688031215620032e4575f80fd5b620032ef8662003206565b9450602086013562003301816200321a565b93506040860135620033138162003279565b9250606086013567ffffffffffffffff8111156200332f575f80fd5b6200333d8882890162003287565b969995985093965092949392505050565b8061040081018310156200077e575f80fd5b5f805f805f805f805f805f6105208c8e0312156200337c575f80fd5b620033888d8d6200334e565b9a50620033996104008d0162003206565b99506104208c013598506104408c01359750620033ba6104608d0162003206565b96506104808c0135620033cd816200321a565b9550620033de6104a08d0162003206565b94506104c08c0135620033f1816200321a565b93506104e08c013592506105008c013567ffffffffffffffff81111562003416575f80fd5b620034248e828f0162003287565b915080935050809150509295989b509295989b9093969950565b5f602082840312156200344f575f80fd5b81356200345c816200321a565b9392505050565b60ff811681146200323c575f80fd5b5f805f805f805f60e0888a03121562003489575f80fd5b8735620034968162003463565b9650620034a66020890162003206565b95506040880135620034b8816200321a565b9450620034c86060890162003206565b93506080880135620034da816200321a565b9699959850939692959460a0840135945060c09093013592915050565b5f805f606084860312156200350a575f80fd5b620035158462003206565b9250602084013562003527816200321a565b9150604084013562003539816200321a565b809150509250925092565b5f6020828403121562003555575f80fd5b5035919050565b5f805f805f805f60a0888a03121562003573575f80fd5b6200357e8862003206565b9650602088013562003590816200321a565b9550604088013567ffffffffffffffff80821115620035ad575f80fd5b620035bb8b838c0162003287565b909750955060608a0135915080821115620035d4575f80fd5b50620035e38a828b0162003287565b9094509250506080880135620035f98162003463565b8091505092959891949750929550565b5f805f805f805f60c0888a03121562003620575f80fd5b6200362b8862003206565b965060208801356200363d816200321a565b955060408801359450606088013562003656816200321a565b93506080880135620036688162003279565b925060a088013567ffffffffffffffff81111562003684575f80fd5b620036928a828b0162003287565b989b979a50959850939692959293505050565b5f805f806104608587031215620036ba575f80fd5b84359350620036cd86602087016200334e565b9250620036de610420860162003206565b939692955092936104400135925050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f61010060ff8c16835263ffffffff808c16602085015273ffffffffffffffffffffffffffffffffffffffff808c166040860152818b166060860152808a166080860152508760a08501528160c0850152620037968285018789620036ef565b925080851660e085015250509a9950505050505050505050565b818382375f9101908152919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5b8381101562003808578181015183820152602001620037ee565b50505f910152565b5f825162003823818460208701620037ec565b9190910192915050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715620038775762003877620037bf565b604052919050565b5f67ffffffffffffffff8211156200389b576200389b620037bf565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112620038d7575f80fd5b8135620038ee620038e8826200387f565b6200382d565b81815284602083860101111562003903575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f6060848603121562003932575f80fd5b833567ffffffffffffffff808211156200394a575f80fd5b6200395887838801620038c7565b945060208601359150808211156200396e575f80fd5b506200397d86828701620038c7565b9250506040840135620035398162003463565b5f8151808452620039a9816020860160208601620037ec565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606081525f620039ef606083018662003990565b828103602084015262003a03818662003990565b91505060ff83166040830152949350505050565b63ffffffff861681525f73ffffffffffffffffffffffffffffffffffffffff80871660208401528086166040840152506080606083015262003106608083018486620036ef565b73ffffffffffffffffffffffffffffffffffffffff8516815263ffffffff84166020820152606060408201525f62003a9b606083018486620036ef565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003b325762003b3262003ad2565b5060010190565b606081525f62003b4e606083018789620036ef565b828103602084015262003b63818688620036ef565b91505060ff831660408301529695505050505050565b5f835162003b8c818460208801620037ec565b83519083019062003ba2818360208801620037ec565b01949350505050565b5f6020828403121562003bbc575f80fd5b5051919050565b818103818111156200077e576200077e62003ad2565b5f61010060ff8b16835263ffffffff808b16602085015273ffffffffffffffffffffffffffffffffffffffff808b166040860152818a1660608601528089166080860152508660a08501528160c085015262003c388285018762003990565b925080851660e085015250509998505050505050505050565b600181815b8085111562003cb057817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003c945762003c9462003ad2565b8085161562003ca257918102915b93841c939080029062003c56565b509250929050565b5f8262003cc8575060016200077e565b8162003cd657505f6200077e565b816001811462003cef576002811462003cfa5762003d1a565b60019150506200077e565b60ff84111562003d0e5762003d0e62003ad2565b50506001821b6200077e565b5060208310610133831016604e8410600b841016171562003d3f575081810a6200077e565b62003d4b838362003c51565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003d805762003d8062003ad2565b029392505050565b5f6200345c838362003cb8565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b5f808585111562003dd1575f80fd5b8386111562003dde575f80fd5b5050820193919092039150565b7fffffffff00000000000000000000000000000000000000000000000000000000813581811691600485101562003e2c5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a03121562003e4b575f80fd5b873562003e58816200321a565b9650602088013562003e6a816200321a565b955060408801359450606088013593506080880135620034da8162003463565b5f805f805f805f80610100898b03121562003ea3575f80fd5b883562003eb0816200321a565b9750602089013562003ec2816200321a565b96506040890135955060608901359450608089013562003ee28162003279565b935060a089013562003ef48162003463565b979a969950949793969295929450505060c08201359160e0013590565b5f6020828403121562003f22575f80fd5b81516200345c8162003463565b5f6020828403121562003f40575f80fd5b81516200345c8162003279565b5f6020828403121562003f5e575f80fd5b815167ffffffffffffffff81111562003f75575f80fd5b8201601f8101841362003f86575f80fd5b805162003f97620038e8826200387f565b81815285602083850101111562003fac575f80fd5b62003fbf826020830160208601620037ec565b95945050505050565b602081525f6200345c60208301846200399056fe61010060405234801562000011575f80fd5b5060405162001b0d38038062001b0d833981016040819052620000349162000282565b828260036200004483826200038d565b5060046200005382826200038d565b50503360c0525060ff811660e05246608081905262000072906200007f565b60a0525062000455915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ab6200012c565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013d9062000301565b80601f01602080910402602001604051908101604052809291908181526020018280546200016b9062000301565b8015620001ba5780601f106200019057610100808354040283529160200191620001ba565b820191905f5260205f20905b8154815290600101906020018083116200019c57829003601f168201915b5050505050905090565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112620001e8575f80fd5b81516001600160401b0380821115620002055762000205620001c4565b604051601f8301601f19908116603f01168101908282118183101715620002305762000230620001c4565b816040528381526020925086838588010111156200024c575f80fd5b5f91505b838210156200026f578582018301518183018401529082019062000250565b5f93810190920192909252949350505050565b5f805f6060848603121562000295575f80fd5b83516001600160401b0380821115620002ac575f80fd5b620002ba87838801620001d8565b94506020860151915080821115620002d0575f80fd5b50620002df86828701620001d8565b925050604084015160ff81168114620002f6575f80fd5b809150509250925092565b600181811c908216806200031657607f821691505b6020821081036200033557634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000388575f81815260208120601f850160051c81016020861015620003635750805b601f850160051c820191505b8181101562000384578281556001016200036f565b5050505b505050565b81516001600160401b03811115620003a957620003a9620001c4565b620003c181620003ba845462000301565b846200033b565b602080601f831160018114620003f7575f8415620003df5750858301515b5f19600386901b1c1916600185901b17855562000384565b5f85815260208120601f198616915b82811015620004275788860151825594840194600190910190840162000406565b50858210156200044557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161166f6200049e5f395f61022d01525f81816102fb015281816105ad015261069401525f61052801525f818161036d01526104f2015261166f5ff3fe608060405234801561000f575f80fd5b506004361061016e575f3560e01c806370a08231116100d2578063a457c2d711610088578063d505accf11610063578063d505accf1461038f578063dd62ed3e146103a2578063ffa1ad74146103e7575f80fd5b8063a457c2d714610342578063a9059cbb14610355578063cd0d009614610368575f80fd5b806395d89b41116100b857806395d89b41146102db5780639dc29fac146102e3578063a3c573eb146102f6575f80fd5b806370a08231146102875780637ecebe00146102bc575f80fd5b806330adf81f116101275780633644e5151161010d5780633644e51514610257578063395093511461025f57806340c10f1914610272575f80fd5b806330adf81f146101ff578063313ce56714610226575f80fd5b806318160ddd1161015757806318160ddd146101b357806320606b70146101c557806323b872dd146101ec575f80fd5b806306fdde0314610172578063095ea7b314610190575b5f80fd5b61017a610423565b60405161018791906113c1565b60405180910390f35b6101a361019e366004611452565b6104b3565b6040519015158152602001610187565b6002545b604051908152602001610187565b6101b77f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101a36101fa36600461147a565b6104cc565b6101b77f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610187565b6101b76104ef565b6101a361026d366004611452565b61054a565b610285610280366004611452565b610595565b005b6101b76102953660046114b3565b73ffffffffffffffffffffffffffffffffffffffff165f9081526020819052604090205490565b6101b76102ca3660046114b3565b60056020525f908152604090205481565b61017a61066d565b6102856102f1366004611452565b61067c565b61031d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610187565b6101a3610350366004611452565b61074b565b6101a3610363366004611452565b61081b565b6101b77f000000000000000000000000000000000000000000000000000000000000000081565b61028561039d3660046114d3565b610828565b6101b76103b0366004611540565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260016020908152604080832093909416825291909152205490565b61017a6040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043290611571565b80601f016020809104026020016040519081016040528092919081815260200182805461045e90611571565b80156104a95780601f10610480576101008083540402835291602001916104a9565b820191905f5260205f20905b81548152906001019060200180831161048c57829003601f168201915b5050505050905090565b5f336104c0818585610b59565b60019150505b92915050565b5f336104d9858285610d0c565b6104e4858585610de2565b506001949350505050565b5f7f00000000000000000000000000000000000000000000000000000000000000004614610525576105204661104f565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104c090829086906105909087906115ef565b610b59565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461065f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b6106698282611116565b5050565b60606004805461043290611571565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610741576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610656565b6106698282611207565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561080e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610656565b6104e48286868403610b59565b5f336104c0818585610de2565b834211156108b7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff87165f90815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a91908661091083611602565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f61097a6104ef565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f80855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a3b573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ab657508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610656565b610b4d8a8a8a610b59565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610c9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381165f908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610ddc5781811015610dcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610656565b610ddc8484848403610b59565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610e85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610f28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f9081526020819052604090205481811015610fdd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610ddc565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611079610423565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff8216611193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610656565b8060025f8282546111a491906115ef565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff82165f908152602081905260409020548181101561135f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610cff565b5f6020808352835180828501525f5b818110156113ec578581018301518582016040015282016113d0565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461144d575f80fd5b919050565b5f8060408385031215611463575f80fd5b61146c8361142a565b946020939093013593505050565b5f805f6060848603121561148c575f80fd5b6114958461142a565b92506114a36020850161142a565b9150604084013590509250925092565b5f602082840312156114c3575f80fd5b6114cc8261142a565b9392505050565b5f805f805f805f60e0888a0312156114e9575f80fd5b6114f28861142a565b96506115006020890161142a565b95506040880135945060608801359350608088013560ff81168114611523575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611551575f80fd5b61155a8361142a565b91506115686020840161142a565b90509250929050565b600181811c9082168061158557607f821691505b6020821081036115bc577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156104c6576104c66115c2565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611632576116326115c2565b506001019056fea2646970667358221220a04a4613834006222ac539b942dfe3284c1163f5082f3bafb302007d825cd7ff64736f6c63430008140033a2646970667358221220991aea41966384d328d04f6fe159faeb7c73b2b4e1ff56268f8b5e388f63cf8064736f6c63430008140033", + "deployedBytecode": "0x60806040526004361062000197575f3560e01c8063647c576c11620000e2578063be5831c71162000086578063dbc16976116200005e578063dbc16976146200061a578063ee25560b1462000631578063fb5708341462000660575f80fd5b8063be5831c71462000591578063cd58657914620005cc578063d02103ca14620005e3575f80fd5b80639e34070f11620000ba5780639e34070f14620004f1578063aaa13cc21462000534578063bab161bf1462000558575f80fd5b8063647c576c146200047157806379e2cf97146200049557806381b1c17414620004ac575f80fd5b80632d2c9d94116200014a57806334ac9cf2116200012257806334ac9cf2146200033a5780633ae0504714620003685780633e197043146200037f575f80fd5b80632d2c9d9414620002695780632dfdf0b5146200028d578063318aee3d14620002b3575f80fd5b806322e95f2c116200017e57806322e95f2c14620001e4578063240ff378146200022e5780632cffd02e1462000245575f80fd5b806315064c96146200019b5780632072f6c514620001cb575b5f80fd5b348015620001a7575f80fd5b50606854620001b69060ff1681565b60405190151581526020015b60405180910390f35b348015620001d7575f80fd5b50620001e262000684565b005b348015620001f0575f80fd5b5062000208620002023660046200323f565b620006e2565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001620001c2565b620001e26200023f366004620032cf565b62000784565b34801562000251575f80fd5b50620001e26200026336600462003360565b620009ab565b34801562000275575f80fd5b50620001e26200028736600462003360565b62000f30565b34801562000299575f80fd5b50620002a460535481565b604051908152602001620001c2565b348015620002bf575f80fd5b5062000308620002d13660046200343e565b606b6020525f908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff909116602083015201620001c2565b34801562000346575f80fd5b50606c54620002089073ffffffffffffffffffffffffffffffffffffffff1681565b34801562000374575f80fd5b50620002a462001130565b3480156200038b575f80fd5b50620002a46200039d36600462003472565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b3480156200047d575f80fd5b50620001e26200048f366004620034f7565b62001215565b348015620004a1575f80fd5b50620001e26200145e565b348015620004b8575f80fd5b5062000208620004ca36600462003544565b606a6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015620004fd575f80fd5b50620001b66200050f36600462003544565b600881901c5f90815260696020526040902054600160ff9092169190911b9081161490565b34801562000540575f80fd5b5062000208620005523660046200355c565b62001498565b34801562000564575f80fd5b506068546200057b90610100900463ffffffff1681565b60405163ffffffff9091168152602001620001c2565b3480156200059d575f80fd5b506068546200057b90790100000000000000000000000000000000000000000000000000900463ffffffff1681565b620001e2620005dd36600462003609565b62001682565b348015620005ef575f80fd5b50606854620002089065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b34801562000626575f80fd5b50620001e262001bd4565b3480156200063d575f80fd5b50620002a46200064f36600462003544565b60696020525f908152604090205481565b3480156200066c575f80fd5b50620001b66200067e366004620036a5565b62001c30565b606c5473ffffffffffffffffffffffffffffffffffffffff163314620006d6576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620006e062001d18565b565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602483015282516018818403018152603890920183528151918101919091205f908152606a909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b60685460ff1615620007c2576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff868116610100909204161480620007e85750600263ffffffff861610155b1562000820576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338888348888605354604051620008769998979695949392919062003736565b60405180910390a1620009936200098d6001606860019054906101000a900463ffffffff16338989348989604051620008b1929190620037b0565b60405180910390206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b62001dab565b8215620009a457620009a462001ebf565b5050505050565b60685460ff1615620009e9576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620009ff8b8b8b8b8b8b8b8b8b8b8b5f62001f8f565b73ffffffffffffffffffffffffffffffffffffffff861662000ad757604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff861690859060405162000a53919062003810565b5f6040518083038185875af1925050503d805f811462000a8f576040519150601f19603f3d011682016040523d82523d5f602084013e62000a94565b606091505b505090508062000ad0576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5062000eb8565b60685463ffffffff61010090910481169088160362000b195762000b1373ffffffffffffffffffffffffffffffffffffffff871685856200217a565b62000eb8565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f90603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301205f818152606a90935291205490915073ffffffffffffffffffffffffffffffffffffffff168062000e2f575f808062000beb868801886200391f565b9250925092505f8584848460405162000c0490620031f8565b62000c1293929190620039db565b8190604051809103905ff590508015801562000c30573d5f803e3d5ffd5b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81166004830152602482018c9052919250908216906340c10f19906044015f604051808303815f87803b15801562000ca3575f80fd5b505af115801562000cb6573d5f803e3d5ffd5b5050505080606a5f8881526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808e63ffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815250606b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000e1d95949392919062003a17565b60405180910390a15050505062000eb5565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801562000e9d575f80fd5b505af115801562000eb0573d5f803e3d5ffd5b505050505b50505b6040805163ffffffff8c811682528916602082015273ffffffffffffffffffffffffffffffffffffffff88811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff161562000f6e576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000f858b8b8b8b8b8b8b8b8b8b8b600162001f8f565b5f8473ffffffffffffffffffffffffffffffffffffffff1684888a868660405160240162000fb7949392919062003a5e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1806b5f200000000000000000000000000000000000000000000000000000000179052516200103a919062003810565b5f6040518083038185875af1925050503d805f811462001076576040519150601f19603f3d011682016040523d82523d5f602084013e6200107b565b606091505b5050905080620010b7576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a16602082015273ffffffffffffffffffffffffffffffffffffffff89811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b6053545f90819081805b60208110156200120c578083901c6001166001036200119d576033816020811062001169576200116962003aa5565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350620011ca565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080620012039062003aff565b9150506200113a565b50919392505050565b5f54610100900460ff16158080156200123457505f54600160ff909116105b806200124f5750303b1580156200124f57505f5460ff166001145b620012e1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156200133e575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff16176501000000000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155606c80547fffffffffffffffffffffffff000000000000000000000000000000000000000016918416919091179055620013f562002250565b801562001458575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b605354606854790100000000000000000000000000000000000000000000000000900463ffffffff161015620006e057620006e062001ebf565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b3083604051806020016200152c90620031f8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081905262001577908d908d908d908d908d9060200162003b39565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052620015b5929160200162003b79565b604051602081830303815290604052805190602001206040516020016200163e94939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101209a9950505050505050505050565b60685460ff1615620016c0576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620016ca620022f2565b60685463ffffffff888116610100909204161480620016f05750600263ffffffff881610155b1562001728576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8060608773ffffffffffffffffffffffffffffffffffffffff88166200178c5788341462001783576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f925062001a79565b3415620017c5576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8089165f908152606b602090815260409182902082518084019093525463ffffffff8116835264010000000090049092169181018290529015620018ae576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b905273ffffffffffffffffffffffffffffffffffffffff8a1690639dc29fac906044015f604051808303815f87803b15801562001884575f80fd5b505af115801562001897573d5f803e3d5ffd5b5050505080602001519450805f0151935062001a77565b8515620018c357620018c3898b898962002367565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8b16906370a0823190602401602060405180830381865afa1580156200192e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001954919062003bab565b90506200197a73ffffffffffffffffffffffffffffffffffffffff8b1633308e6200287a565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa158015620019e5573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001a0b919062003bab565b905062001a19828262003bc3565b6068548c9850610100900463ffffffff169650935062001a3987620028da565b62001a448c620029ee565b62001a4f8d62002af7565b60405160200162001a6393929190620039db565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e868860535460405162001aba98979695949392919062003bd9565b60405180910390a162001bac6200098d5f85878f8f8789805190602001206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b861562001bbd5762001bbd62001ebf565b5050505062001bcb60018055565b50505050505050565b606c5473ffffffffffffffffffffffffffffffffffffffff16331462001c26576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620006e062002bf5565b5f84815b602081101562001d0a57600163ffffffff8616821c8116900362001ca65785816020811062001c675762001c6762003aa5565b60200201358260405160200162001c88929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001cf5565b8186826020811062001cbc5762001cbc62003aa5565b602002013560405160200162001cdc929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001d018162003aff565b91505062001c34565b50821490505b949350505050565b60685460ff161562001d56576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b80600162001dbc6020600262003d88565b62001dc8919062003bc3565b6053541062001e03576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f815462001e149062003aff565b918290555090505f5b602081101562001eaf578082901c60011660010362001e5557826033826020811062001e4d5762001e4d62003aa5565b015550505050565b6033816020811062001e6b5762001e6b62003aa5565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808062001ea69062003aff565b91505062001e1d565b5062001eba62003d95565b505050565b6053546068805463ffffffff909216790100000000000000000000000000000000000000000000000000027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179081905573ffffffffffffffffffffffffffffffffffffffff65010000000000909104166333d6247d62001f4562001130565b6040518263ffffffff1660e01b815260040162001f6491815260200190565b5f604051808303815f87803b15801562001f7c575f80fd5b505af115801562001458573d5f803e3d5ffd5b62001fa08b63ffffffff1662002c84565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f9165010000000000900473ffffffffffffffffffffffffffffffffffffffff169063257b3632906084016020604051808303815f875af11580156200203f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002065919062003bab565b9050805f03620020a0576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff8881166101009092041614620020ea576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068545f90610100900463ffffffff16620021075750896200210a565b508a5b620021336200212a848c8c8c8c8c8c8c604051620008b1929190620037b0565b8f8f8462001c30565b6200216a576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001eba9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915262002ce8565b5f54610100900460ff16620022e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620012d8565b620006e062002dfa565b60026001540362002360576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401620012d8565b6002600155565b5f62002377600482848662003dc2565b620023829162003deb565b90507f2afa5331000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000821601620025fc575f808080808080620023e4896004818d62003dc2565b810190620023f3919062003e34565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462002467576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff86163014620024b7576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a8514620024f1576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e1691620025ac919062003810565b5f604051808303815f865af19150503d805f8114620025e7576040519150601f19603f3d011682016040523d82523d5f602084013e620025ec565b606091505b50505050505050505050620009a4565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f8fcbaf0c000000000000000000000000000000000000000000000000000000001462002678576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806200268f8a6004818e62003dc2565b8101906200269e919062003e8a565b975097509750975097509750975097503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161462002714576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8716301462002764576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8fcbaf0c000000000000000000000000000000000000000000000000000000001790529151918f169162002828919062003810565b5f604051808303815f865af19150503d805f811462002863576040519150601f19603f3d011682016040523d82523d5f602084013e62002868565b606091505b50505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620014589085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401620021cd565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff8616916200295d919062003810565b5f60405180830381855afa9150503d805f811462002997576040519150601f19603f3d011682016040523d82523d5f602084013e6200299c565b606091505b509150915081620029e3576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525062001d10565b62001d108162002e92565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff86169162002a71919062003810565b5f60405180830381855afa9150503d805f811462002aab576040519150601f19603f3d011682016040523d82523d5f602084013e62002ab0565b606091505b509150915081620029e3576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525062001d10565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f918291829173ffffffffffffffffffffffffffffffffffffffff86169162002b79919062003810565b5f60405180830381855afa9150503d805f811462002bb3576040519150601f19603f3d011682016040523d82523d5f602084013e62002bb8565b606091505b509150915081801562002bcc575080516020145b62002bd957601262001d10565b8080602001905181019062001d10919062003f11565b60018055565b60685460ff1662002c32576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003620009a4576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62002d4b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166200307d9092919063ffffffff16565b80519091501562001eba578080602001905181019062002d6c919062003f2f565b62001eba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401620012d8565b5f54610100900460ff1662002bef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401620012d8565b6060604082511062002eb457818060200190518101906200077e919062003f4d565b81516020036200303f575f5b60208110801562002f0b575082818151811062002ee15762002ee162003aa5565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b1562002f26578062002f1d8162003aff565b91505062002ec0565b805f0362002f6957505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff81111562002f865762002f86620037bf565b6040519080825280601f01601f19166020018201604052801562002fb1576020820181803683370190505b5090505f5b82811015620030375784818151811062002fd45762002fd462003aa5565b602001015160f81c60f81b82828151811062002ff45762002ff462003aa5565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a905350806200302e8162003aff565b91505062002fb6565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b606062001d1084845f85855f808673ffffffffffffffffffffffffffffffffffffffff168587604051620030b2919062003810565b5f6040518083038185875af1925050503d805f8114620030ee576040519150601f19603f3d011682016040523d82523d5f602084013e620030f3565b606091505b5091509150620031068783838762003111565b979650505050505050565b60608315620031ab5782515f03620031a35773ffffffffffffffffffffffffffffffffffffffff85163b620031a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620012d8565b508162001d10565b62001d108383815115620031c25781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620012d8919062003fc8565b611b0d8062003fdd83390190565b803563ffffffff8116811462003078575f80fd5b73ffffffffffffffffffffffffffffffffffffffff811681146200323c575f80fd5b50565b5f806040838503121562003251575f80fd5b6200325c8362003206565b915060208301356200326e816200321a565b809150509250929050565b80151581146200323c575f80fd5b5f8083601f84011262003298575f80fd5b50813567ffffffffffffffff811115620032b0575f80fd5b602083019150836020828501011115620032c8575f80fd5b9250929050565b5f805f805f60808688031215620032e4575f80fd5b620032ef8662003206565b9450602086013562003301816200321a565b93506040860135620033138162003279565b9250606086013567ffffffffffffffff8111156200332f575f80fd5b6200333d8882890162003287565b969995985093965092949392505050565b8061040081018310156200077e575f80fd5b5f805f805f805f805f805f6105208c8e0312156200337c575f80fd5b620033888d8d6200334e565b9a50620033996104008d0162003206565b99506104208c013598506104408c01359750620033ba6104608d0162003206565b96506104808c0135620033cd816200321a565b9550620033de6104a08d0162003206565b94506104c08c0135620033f1816200321a565b93506104e08c013592506105008c013567ffffffffffffffff81111562003416575f80fd5b620034248e828f0162003287565b915080935050809150509295989b509295989b9093969950565b5f602082840312156200344f575f80fd5b81356200345c816200321a565b9392505050565b60ff811681146200323c575f80fd5b5f805f805f805f60e0888a03121562003489575f80fd5b8735620034968162003463565b9650620034a66020890162003206565b95506040880135620034b8816200321a565b9450620034c86060890162003206565b93506080880135620034da816200321a565b9699959850939692959460a0840135945060c09093013592915050565b5f805f606084860312156200350a575f80fd5b620035158462003206565b9250602084013562003527816200321a565b9150604084013562003539816200321a565b809150509250925092565b5f6020828403121562003555575f80fd5b5035919050565b5f805f805f805f60a0888a03121562003573575f80fd5b6200357e8862003206565b9650602088013562003590816200321a565b9550604088013567ffffffffffffffff80821115620035ad575f80fd5b620035bb8b838c0162003287565b909750955060608a0135915080821115620035d4575f80fd5b50620035e38a828b0162003287565b9094509250506080880135620035f98162003463565b8091505092959891949750929550565b5f805f805f805f60c0888a03121562003620575f80fd5b6200362b8862003206565b965060208801356200363d816200321a565b955060408801359450606088013562003656816200321a565b93506080880135620036688162003279565b925060a088013567ffffffffffffffff81111562003684575f80fd5b620036928a828b0162003287565b989b979a50959850939692959293505050565b5f805f806104608587031215620036ba575f80fd5b84359350620036cd86602087016200334e565b9250620036de610420860162003206565b939692955092936104400135925050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f61010060ff8c16835263ffffffff808c16602085015273ffffffffffffffffffffffffffffffffffffffff808c166040860152818b166060860152808a166080860152508760a08501528160c0850152620037968285018789620036ef565b925080851660e085015250509a9950505050505050505050565b818382375f9101908152919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5b8381101562003808578181015183820152602001620037ee565b50505f910152565b5f825162003823818460208701620037ec565b9190910192915050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715620038775762003877620037bf565b604052919050565b5f67ffffffffffffffff8211156200389b576200389b620037bf565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112620038d7575f80fd5b8135620038ee620038e8826200387f565b6200382d565b81815284602083860101111562003903575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f6060848603121562003932575f80fd5b833567ffffffffffffffff808211156200394a575f80fd5b6200395887838801620038c7565b945060208601359150808211156200396e575f80fd5b506200397d86828701620038c7565b9250506040840135620035398162003463565b5f8151808452620039a9816020860160208601620037ec565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606081525f620039ef606083018662003990565b828103602084015262003a03818662003990565b91505060ff83166040830152949350505050565b63ffffffff861681525f73ffffffffffffffffffffffffffffffffffffffff80871660208401528086166040840152506080606083015262003106608083018486620036ef565b73ffffffffffffffffffffffffffffffffffffffff8516815263ffffffff84166020820152606060408201525f62003a9b606083018486620036ef565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003b325762003b3262003ad2565b5060010190565b606081525f62003b4e606083018789620036ef565b828103602084015262003b63818688620036ef565b91505060ff831660408301529695505050505050565b5f835162003b8c818460208801620037ec565b83519083019062003ba2818360208801620037ec565b01949350505050565b5f6020828403121562003bbc575f80fd5b5051919050565b818103818111156200077e576200077e62003ad2565b5f61010060ff8b16835263ffffffff808b16602085015273ffffffffffffffffffffffffffffffffffffffff808b166040860152818a1660608601528089166080860152508660a08501528160c085015262003c388285018762003990565b925080851660e085015250509998505050505050505050565b600181815b8085111562003cb057817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003c945762003c9462003ad2565b8085161562003ca257918102915b93841c939080029062003c56565b509250929050565b5f8262003cc8575060016200077e565b8162003cd657505f6200077e565b816001811462003cef576002811462003cfa5762003d1a565b60019150506200077e565b60ff84111562003d0e5762003d0e62003ad2565b50506001821b6200077e565b5060208310610133831016604e8410600b841016171562003d3f575081810a6200077e565b62003d4b838362003c51565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562003d805762003d8062003ad2565b029392505050565b5f6200345c838362003cb8565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b5f808585111562003dd1575f80fd5b8386111562003dde575f80fd5b5050820193919092039150565b7fffffffff00000000000000000000000000000000000000000000000000000000813581811691600485101562003e2c5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a03121562003e4b575f80fd5b873562003e58816200321a565b9650602088013562003e6a816200321a565b955060408801359450606088013593506080880135620034da8162003463565b5f805f805f805f80610100898b03121562003ea3575f80fd5b883562003eb0816200321a565b9750602089013562003ec2816200321a565b96506040890135955060608901359450608089013562003ee28162003279565b935060a089013562003ef48162003463565b979a969950949793969295929450505060c08201359160e0013590565b5f6020828403121562003f22575f80fd5b81516200345c8162003463565b5f6020828403121562003f40575f80fd5b81516200345c8162003279565b5f6020828403121562003f5e575f80fd5b815167ffffffffffffffff81111562003f75575f80fd5b8201601f8101841362003f86575f80fd5b805162003f97620038e8826200387f565b81815285602083850101111562003fac575f80fd5b62003fbf826020830160208601620037ec565b95945050505050565b602081525f6200345c60208301846200399056fe61010060405234801562000011575f80fd5b5060405162001b0d38038062001b0d833981016040819052620000349162000282565b828260036200004483826200038d565b5060046200005382826200038d565b50503360c0525060ff811660e05246608081905262000072906200007f565b60a0525062000455915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ab6200012c565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013d9062000301565b80601f01602080910402602001604051908101604052809291908181526020018280546200016b9062000301565b8015620001ba5780601f106200019057610100808354040283529160200191620001ba565b820191905f5260205f20905b8154815290600101906020018083116200019c57829003601f168201915b5050505050905090565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112620001e8575f80fd5b81516001600160401b0380821115620002055762000205620001c4565b604051601f8301601f19908116603f01168101908282118183101715620002305762000230620001c4565b816040528381526020925086838588010111156200024c575f80fd5b5f91505b838210156200026f578582018301518183018401529082019062000250565b5f93810190920192909252949350505050565b5f805f6060848603121562000295575f80fd5b83516001600160401b0380821115620002ac575f80fd5b620002ba87838801620001d8565b94506020860151915080821115620002d0575f80fd5b50620002df86828701620001d8565b925050604084015160ff81168114620002f6575f80fd5b809150509250925092565b600181811c908216806200031657607f821691505b6020821081036200033557634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000388575f81815260208120601f850160051c81016020861015620003635750805b601f850160051c820191505b8181101562000384578281556001016200036f565b5050505b505050565b81516001600160401b03811115620003a957620003a9620001c4565b620003c181620003ba845462000301565b846200033b565b602080601f831160018114620003f7575f8415620003df5750858301515b5f19600386901b1c1916600185901b17855562000384565b5f85815260208120601f198616915b82811015620004275788860151825594840194600190910190840162000406565b50858210156200044557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161166f6200049e5f395f61022d01525f81816102fb015281816105ad015261069401525f61052801525f818161036d01526104f2015261166f5ff3fe608060405234801561000f575f80fd5b506004361061016e575f3560e01c806370a08231116100d2578063a457c2d711610088578063d505accf11610063578063d505accf1461038f578063dd62ed3e146103a2578063ffa1ad74146103e7575f80fd5b8063a457c2d714610342578063a9059cbb14610355578063cd0d009614610368575f80fd5b806395d89b41116100b857806395d89b41146102db5780639dc29fac146102e3578063a3c573eb146102f6575f80fd5b806370a08231146102875780637ecebe00146102bc575f80fd5b806330adf81f116101275780633644e5151161010d5780633644e51514610257578063395093511461025f57806340c10f1914610272575f80fd5b806330adf81f146101ff578063313ce56714610226575f80fd5b806318160ddd1161015757806318160ddd146101b357806320606b70146101c557806323b872dd146101ec575f80fd5b806306fdde0314610172578063095ea7b314610190575b5f80fd5b61017a610423565b60405161018791906113c1565b60405180910390f35b6101a361019e366004611452565b6104b3565b6040519015158152602001610187565b6002545b604051908152602001610187565b6101b77f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101a36101fa36600461147a565b6104cc565b6101b77f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610187565b6101b76104ef565b6101a361026d366004611452565b61054a565b610285610280366004611452565b610595565b005b6101b76102953660046114b3565b73ffffffffffffffffffffffffffffffffffffffff165f9081526020819052604090205490565b6101b76102ca3660046114b3565b60056020525f908152604090205481565b61017a61066d565b6102856102f1366004611452565b61067c565b61031d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610187565b6101a3610350366004611452565b61074b565b6101a3610363366004611452565b61081b565b6101b77f000000000000000000000000000000000000000000000000000000000000000081565b61028561039d3660046114d3565b610828565b6101b76103b0366004611540565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260016020908152604080832093909416825291909152205490565b61017a6040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043290611571565b80601f016020809104026020016040519081016040528092919081815260200182805461045e90611571565b80156104a95780601f10610480576101008083540402835291602001916104a9565b820191905f5260205f20905b81548152906001019060200180831161048c57829003601f168201915b5050505050905090565b5f336104c0818585610b59565b60019150505b92915050565b5f336104d9858285610d0c565b6104e4858585610de2565b506001949350505050565b5f7f00000000000000000000000000000000000000000000000000000000000000004614610525576105204661104f565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104c090829086906105909087906115ef565b610b59565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461065f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b6106698282611116565b5050565b60606004805461043290611571565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610741576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610656565b6106698282611207565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561080e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610656565b6104e48286868403610b59565b5f336104c0818585610de2565b834211156108b7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff87165f90815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a91908661091083611602565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f61097a6104ef565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f80855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a3b573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ab657508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610656565b610b4d8a8a8a610b59565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610c9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381165f908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610ddc5781811015610dcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610656565b610ddc8484848403610b59565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610e85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610f28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f9081526020819052604090205481811015610fdd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610ddc565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611079610423565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff8216611193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610656565b8060025f8282546111a491906115ef565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff82165f908152602081905260409020548181101561135f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610cff565b5f6020808352835180828501525f5b818110156113ec578581018301518582016040015282016113d0565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461144d575f80fd5b919050565b5f8060408385031215611463575f80fd5b61146c8361142a565b946020939093013593505050565b5f805f6060848603121561148c575f80fd5b6114958461142a565b92506114a36020850161142a565b9150604084013590509250925092565b5f602082840312156114c3575f80fd5b6114cc8261142a565b9392505050565b5f805f805f805f60e0888a0312156114e9575f80fd5b6114f28861142a565b96506115006020890161142a565b95506040880135945060608801359350608088013560ff81168114611523575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611551575f80fd5b61155a8361142a565b91506115686020840161142a565b90509250929050565b600181811c9082168061158557607f821691505b6020821081036115bc577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156104c6576104c66115c2565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611632576116326115c2565b506001019056fea2646970667358221220a04a4613834006222ac539b942dfe3284c1163f5082f3bafb302007d825cd7ff64736f6c63430008140033a2646970667358221220991aea41966384d328d04f6fe159faeb7c73b2b4e1ff56268f8b5e388f63cf8064736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMBridgeMock.json b/compiled-contracts/PolygonZkEVMBridgeMock.json index a39dd33d9..3f80587a0 100644 --- a/compiled-contracts/PolygonZkEVMBridgeMock.json +++ b/compiled-contracts/PolygonZkEVMBridgeMock.json @@ -867,8 +867,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561000f575f80fd5b50615f348061001d5f395ff3fe608060405260043610620001df575f3560e01c8063715018a61162000106578063bab161bf116200009e578063dbc16976116200006a578063dbc169761462000704578063ee25560b146200071b578063f2fde38b146200074a578063fb570834146200076e575f80fd5b8063bab161bf1462000642578063be5831c7146200067b578063cd58657914620006b6578063d02103ca14620006cd575f80fd5b80638da5cb5b11620000de5780638da5cb5b146200059857806391e57e2d14620005c45780639e34070f14620005db578063aaa13cc2146200061e575f80fd5b8063715018a6146200052557806379e2cf97146200053c57806381b1c1741462000553575f80fd5b80632d2c9d94116200017a57806334ac9cf2116200015257806334ac9cf214620003ca5780633ae0504714620003f85780633e197043146200040f578063647c576c1462000501575f80fd5b80632d2c9d9414620002f95780632dfdf0b5146200031d578063318aee3d1462000343575f80fd5b8063240ff37811620001ba578063240ff37814620002765780632b5e42e7146200028d5780632c3f58cd14620002b15780632cffd02e14620002d5575f80fd5b806315064c9614620001e35780632072f6c5146200021357806322e95f2c146200022c575b5f80fd5b348015620001ef575f80fd5b50606854620001fe9060ff1681565b60405190151581526020015b60405180910390f35b3480156200021f575f80fd5b506200022a62000792565b005b34801562000238575f80fd5b50620002506200024a36600462003638565b620007f0565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016200020a565b6200022a62000287366004620036c8565b62000892565b34801562000299575f80fd5b506200022a620002ab36600462003747565b62000ab9565b348015620002bd575f80fd5b506200022a620002cf3660046200375f565b62000ac8565b348015620002e1575f80fd5b506200022a620002f336600462003794565b62000b0e565b34801562000305575f80fd5b506200022a6200031736600462003794565b62001093565b34801562000329575f80fd5b506200033460535481565b6040519081526020016200020a565b3480156200034f575f80fd5b50620003986200036136600462003872565b606b6020525f908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff9091166020830152016200020a565b348015620003d6575f80fd5b50606c54620002509073ffffffffffffffffffffffffffffffffffffffff1681565b34801562000404575f80fd5b506200033462001293565b3480156200041b575f80fd5b50620003346200042d3660046200389f565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b3480156200050d575f80fd5b506200022a6200051f36600462003924565b62001378565b34801562000531575f80fd5b506200022a620015cd565b34801562000548575f80fd5b506200022a620015e2565b3480156200055f575f80fd5b50620002506200057136600462003747565b606a6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015620005a4575f80fd5b50609f5473ffffffffffffffffffffffffffffffffffffffff1662000250565b348015620005d0575f80fd5b506200033460d15481565b348015620005e7575f80fd5b50620001fe620005f936600462003747565b600881901c5f90815260696020526040902054600160ff9092169190911b9081161490565b3480156200062a575f80fd5b50620002506200063c36600462003971565b6200161c565b3480156200064e575f80fd5b506068546200066590610100900463ffffffff1681565b60405163ffffffff90911681526020016200020a565b34801562000687575f80fd5b506068546200066590790100000000000000000000000000000000000000000000000000900463ffffffff1681565b6200022a620006c736600462003a1e565b62001806565b348015620006d9575f80fd5b50606854620002509065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b34801562000710575f80fd5b506200022a620018da565b34801562000727575f80fd5b50620003346200073936600462003747565b60696020525f908152604090205481565b34801562000756575f80fd5b506200022a6200076836600462003872565b62001936565b3480156200077a575f80fd5b50620001fe6200078c36600462003aba565b620019f3565b606c5473ffffffffffffffffffffffffffffffffffffffff163314620007e4576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620007ee62001adb565b565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602483015282516018818403018152603890920183528151918101919091205f908152606a909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b60685460ff1615620008d0576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff868116610100909204161480620008f65750600263ffffffff861610155b156200092e576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338888348888605354604051620009849998979695949392919062003b4b565b60405180910390a162000aa162000a9b6001606860019054906101000a900463ffffffff16338989348989604051620009bf92919062003bc5565b60405180910390206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b62001b6e565b821562000ab25762000ab262001c82565b5050505050565b62000ac362001d52565b60d155565b62000ad262001d52565b6068805463ffffffff909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff909216919091179055565b60685460ff161562000b4c576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000b628b8b8b8b8b8b8b8b8b8b8b5f62001dd5565b73ffffffffffffffffffffffffffffffffffffffff861662000c3a57604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff861690859060405162000bb6919062003c25565b5f6040518083038185875af1925050503d805f811462000bf2576040519150601f19603f3d011682016040523d82523d5f602084013e62000bf7565b606091505b505090508062000c33576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506200101b565b60685463ffffffff61010090910481169088160362000c7c5762000c7673ffffffffffffffffffffffffffffffffffffffff8716858562001fc0565b6200101b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f90603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301205f818152606a90935291205490915073ffffffffffffffffffffffffffffffffffffffff168062000f92575f808062000d4e8688018862003d34565b9250925092505f8584848460405162000d6790620035f4565b62000d759392919062003df0565b8190604051809103905ff590508015801562000d93573d5f803e3d5ffd5b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81166004830152602482018c9052919250908216906340c10f19906044015f604051808303815f87803b15801562000e06575f80fd5b505af115801562000e19573d5f803e3d5ffd5b5050505080606a5f8881526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808e63ffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815250606b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000f8095949392919062003e2c565b60405180910390a15050505062001018565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801562001000575f80fd5b505af115801562001013573d5f803e3d5ffd5b505050505b50505b6040805163ffffffff8c811682528916602082015273ffffffffffffffffffffffffffffffffffffffff88811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff1615620010d1576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620010e88b8b8b8b8b8b8b8b8b8b8b600162001dd5565b5f8473ffffffffffffffffffffffffffffffffffffffff1684888a86866040516024016200111a949392919062003e73565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1806b5f200000000000000000000000000000000000000000000000000000000179052516200119d919062003c25565b5f6040518083038185875af1925050503d805f8114620011d9576040519150601f19603f3d011682016040523d82523d5f602084013e620011de565b606091505b50509050806200121a576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a16602082015273ffffffffffffffffffffffffffffffffffffffff89811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b6053545f90819081805b60208110156200136f578083901c600116600103620013005760338160208110620012cc57620012cc62003eba565b015460408051602081019290925281018590526060016040516020818303038152906040528051906020012093506200132d565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080620013669062003f14565b9150506200129d565b50919392505050565b5f54610100900460ff16158080156200139757505f54600160ff909116105b80620013b25750303b158015620013b257505f5460ff166001145b62001444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015620014a1575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff16176501000000000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155606c80547fffffffffffffffffffffffff0000000000000000000000000000000000000000169184169190911790556703782dace9d9000060d1556200156462002096565b8015620015c7575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b620015d762001d52565b620007ee5f62002134565b605354606854790100000000000000000000000000000000000000000000000000900463ffffffff161015620007ee57620007ee62001c82565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180602001620016b090620035f4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052620016fb908d908d908d908d908d9060200162003f4e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905262001739929160200162003f8e565b60405160208183030381529060405280519060200120604051602001620017c294939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101209a9950505050505050505050565b60d154341115620018c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604760248201527f506f6c79676f6e5a6b45564d4272696467653a3a62726964676541737365743a60448201527f2043616e6e6f7420627269646765206d6f7265207468616e206d61784574686560648201527f7242726964676500000000000000000000000000000000000000000000000000608482015260a4016200143b565b620018d187878787878787620021aa565b50505050505050565b606c5473ffffffffffffffffffffffffffffffffffffffff1633146200192c576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620007ee620026f3565b6200194062001d52565b73ffffffffffffffffffffffffffffffffffffffff8116620019e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016200143b565b620019f08162002134565b50565b5f84815b602081101562001acd57600163ffffffff8616821c8116900362001a695785816020811062001a2a5762001a2a62003eba565b60200201358260405160200162001a4b929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001ab8565b8186826020811062001a7f5762001a7f62003eba565b602002013560405160200162001a9f929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001ac48162003f14565b915050620019f7565b50821490505b949350505050565b60685460ff161562001b19576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b80600162001b7f60206002620040f7565b62001b8b919062004104565b6053541062001bc6576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f815462001bd79062003f14565b918290555090505f5b602081101562001c72578082901c60011660010362001c1857826033826020811062001c105762001c1062003eba565b015550505050565b6033816020811062001c2e5762001c2e62003eba565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808062001c699062003f14565b91505062001be0565b5062001c7d6200411a565b505050565b6053546068805463ffffffff909216790100000000000000000000000000000000000000000000000000027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179081905573ffffffffffffffffffffffffffffffffffffffff65010000000000909104166333d6247d62001d0862001293565b6040518263ffffffff1660e01b815260040162001d2791815260200190565b5f604051808303815f87803b15801562001d3f575f80fd5b505af1158015620015c7573d5f803e3d5ffd5b609f5473ffffffffffffffffffffffffffffffffffffffff163314620007ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200143b565b62001de68b63ffffffff1662002782565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f9165010000000000900473ffffffffffffffffffffffffffffffffffffffff169063257b3632906084016020604051808303815f875af115801562001e85573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001eab919062004147565b9050805f0362001ee6576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff888116610100909204161462001f30576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068545f90610100900463ffffffff1662001f4d57508962001f50565b508a5b62001f7962001f70848c8c8c8c8c8c8c604051620009bf92919062003bc5565b8f8f84620019f3565b62001fb0576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001c7d9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152620027e6565b5f54610100900460ff166200212e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016200143b565b620007ee335b609f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60685460ff1615620021e8576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620021f2620028f8565b60685463ffffffff888116610100909204161480620022185750600263ffffffff881610155b1562002250576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8060608773ffffffffffffffffffffffffffffffffffffffff8816620022b457883414620022ab576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f9250620025a1565b3415620022ed576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8089165f908152606b602090815260409182902082518084019093525463ffffffff8116835264010000000090049092169181018290529015620023d6576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b905273ffffffffffffffffffffffffffffffffffffffff8a1690639dc29fac906044015f604051808303815f87803b158015620023ac575f80fd5b505af1158015620023bf573d5f803e3d5ffd5b5050505080602001519450805f015193506200259f565b8515620023eb57620023eb898b89896200296d565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8b16906370a0823190602401602060405180830381865afa15801562002456573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200247c919062004147565b9050620024a273ffffffffffffffffffffffffffffffffffffffff8b1633308e62002e80565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa1580156200250d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002533919062004147565b905062002541828262004104565b6068548c9850610100900463ffffffff1696509350620025618762002ee0565b6200256c8c62002ff4565b620025778d620030fd565b6040516020016200258b9392919062003df0565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e8688605354604051620025e29897969594939291906200415f565b60405180910390a1620026d462000a9b5f85878f8f8789805190602001206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b8615620026e557620026e562001c82565b50505050620018d160018055565b60685460ff1662002730576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b600881901c5f8181526069602052604081208054600160ff861690811b9182189283905592909190818316900362000ab2576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62002849826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620031f59092919063ffffffff16565b80519091501562001c7d57808060200190518101906200286a9190620041d7565b62001c7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016200143b565b60026001540362002966576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016200143b565b6002600155565b5f6200297d6004828486620041f5565b62002988916200421e565b90507f2afa5331000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160162002c02575f808080808080620029ea896004818d620041f5565b810190620029f9919062004267565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462002a6d576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8616301462002abd576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a851462002af7576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169162002bb2919062003c25565b5f604051808303815f865af19150503d805f811462002bed576040519150601f19603f3d011682016040523d82523d5f602084013e62002bf2565b606091505b5050505050505050505062000ab2565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f8fcbaf0c000000000000000000000000000000000000000000000000000000001462002c7e576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8080808080808062002c958a6004818e620041f5565b81019062002ca49190620042bd565b975097509750975097509750975097503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161462002d1a576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8716301462002d6a576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8fcbaf0c000000000000000000000000000000000000000000000000000000001790529151918f169162002e2e919062003c25565b5f604051808303815f865af19150503d805f811462002e69576040519150601f19603f3d011682016040523d82523d5f602084013e62002e6e565b606091505b50505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620015c79085907f23b872dd000000000000000000000000000000000000000000000000000000009060840162002013565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff86169162002f63919062003c25565b5f60405180830381855afa9150503d805f811462002f9d576040519150601f19603f3d011682016040523d82523d5f602084013e62002fa2565b606091505b50915091508162002fe9576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525062001ad3565b62001ad38162003205565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff86169162003077919062003c25565b5f60405180830381855afa9150503d805f8114620030b1576040519150601f19603f3d011682016040523d82523d5f602084013e620030b6565b606091505b50915091508162002fe9576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525062001ad3565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f918291829173ffffffffffffffffffffffffffffffffffffffff8616916200317f919062003c25565b5f60405180830381855afa9150503d805f8114620031b9576040519150601f19603f3d011682016040523d82523d5f602084013e620031be565b606091505b5091509150818015620031d2575080516020145b620031df57601262001ad3565b8080602001905181019062001ad3919062004344565b606062001ad384845f85620033f0565b606060408251106200322757818060200190518101906200088c919062004362565b8151602003620033b2575f5b6020811080156200327e575082818151811062003254576200325462003eba565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15620032995780620032908162003f14565b91505062003233565b805f03620032dc57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115620032f957620032f962003bd4565b6040519080825280601f01601f19166020018201604052801562003324576020820181803683370190505b5090505f5b82811015620033aa5784818151811062003347576200334762003eba565b602001015160f81c60f81b82828151811062003367576200336762003eba565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080620033a18162003f14565b91505062003329565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b60608247101562003484576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016200143b565b5f808673ffffffffffffffffffffffffffffffffffffffff168587604051620034ae919062003c25565b5f6040518083038185875af1925050503d805f8114620034ea576040519150601f19603f3d011682016040523d82523d5f602084013e620034ef565b606091505b509150915062003502878383876200350d565b979650505050505050565b60608315620035a75782515f036200359f5773ffffffffffffffffffffffffffffffffffffffff85163b6200359f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200143b565b508162001ad3565b62001ad38383815115620035be5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200143b9190620043dd565b611b0d80620043f283390190565b803563ffffffff81168114620033eb575f80fd5b73ffffffffffffffffffffffffffffffffffffffff81168114620019f0575f80fd5b5f80604083850312156200364a575f80fd5b620036558362003602565b91506020830135620036678162003616565b809150509250929050565b8015158114620019f0575f80fd5b5f8083601f84011262003691575f80fd5b50813567ffffffffffffffff811115620036a9575f80fd5b602083019150836020828501011115620036c1575f80fd5b9250929050565b5f805f805f60808688031215620036dd575f80fd5b620036e88662003602565b94506020860135620036fa8162003616565b935060408601356200370c8162003672565b9250606086013567ffffffffffffffff81111562003728575f80fd5b620037368882890162003680565b969995985093965092949392505050565b5f6020828403121562003758575f80fd5b5035919050565b5f6020828403121562003770575f80fd5b6200377b8262003602565b9392505050565b8061040081018310156200088c575f80fd5b5f805f805f805f805f805f6105208c8e031215620037b0575f80fd5b620037bc8d8d62003782565b9a50620037cd6104008d0162003602565b99506104208c013598506104408c01359750620037ee6104608d0162003602565b96506104808c0135620038018162003616565b9550620038126104a08d0162003602565b94506104c08c0135620038258162003616565b93506104e08c013592506105008c013567ffffffffffffffff8111156200384a575f80fd5b620038588e828f0162003680565b915080935050809150509295989b509295989b9093969950565b5f6020828403121562003883575f80fd5b81356200377b8162003616565b60ff81168114620019f0575f80fd5b5f805f805f805f60e0888a031215620038b6575f80fd5b8735620038c38162003890565b9650620038d36020890162003602565b95506040880135620038e58162003616565b9450620038f56060890162003602565b93506080880135620039078162003616565b9699959850939692959460a0840135945060c09093013592915050565b5f805f6060848603121562003937575f80fd5b620039428462003602565b92506020840135620039548162003616565b91506040840135620039668162003616565b809150509250925092565b5f805f805f805f60a0888a03121562003988575f80fd5b620039938862003602565b96506020880135620039a58162003616565b9550604088013567ffffffffffffffff80821115620039c2575f80fd5b620039d08b838c0162003680565b909750955060608a0135915080821115620039e9575f80fd5b50620039f88a828b0162003680565b909450925050608088013562003a0e8162003890565b8091505092959891949750929550565b5f805f805f805f60c0888a03121562003a35575f80fd5b62003a408862003602565b9650602088013562003a528162003616565b955060408801359450606088013562003a6b8162003616565b9350608088013562003a7d8162003672565b925060a088013567ffffffffffffffff81111562003a99575f80fd5b62003aa78a828b0162003680565b989b979a50959850939692959293505050565b5f805f80610460858703121562003acf575f80fd5b8435935062003ae2866020870162003782565b925062003af3610420860162003602565b939692955092936104400135925050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f61010060ff8c16835263ffffffff808c16602085015273ffffffffffffffffffffffffffffffffffffffff808c166040860152818b166060860152808a166080860152508760a08501528160c085015262003bab828501878962003b04565b925080851660e085015250509a9950505050505050505050565b818382375f9101908152919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5b8381101562003c1d57818101518382015260200162003c03565b50505f910152565b5f825162003c3881846020870162003c01565b9190910192915050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171562003c8c5762003c8c62003bd4565b604052919050565b5f67ffffffffffffffff82111562003cb05762003cb062003bd4565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f83011262003cec575f80fd5b813562003d0362003cfd8262003c94565b62003c42565b81815284602083860101111562003d18575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f6060848603121562003d47575f80fd5b833567ffffffffffffffff8082111562003d5f575f80fd5b62003d6d8783880162003cdc565b9450602086013591508082111562003d83575f80fd5b5062003d928682870162003cdc565b9250506040840135620039668162003890565b5f815180845262003dbe81602086016020860162003c01565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606081525f62003e04606083018662003da5565b828103602084015262003e18818662003da5565b91505060ff83166040830152949350505050565b63ffffffff861681525f73ffffffffffffffffffffffffffffffffffffffff8087166020840152808616604084015250608060608301526200350260808301848662003b04565b73ffffffffffffffffffffffffffffffffffffffff8516815263ffffffff84166020820152606060408201525f62003eb060608301848662003b04565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003f475762003f4762003ee7565b5060010190565b606081525f62003f6360608301878962003b04565b828103602084015262003f7881868862003b04565b91505060ff831660408301529695505050505050565b5f835162003fa181846020880162003c01565b83519083019062003fb781836020880162003c01565b01949350505050565b600181815b808511156200401f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562004003576200400362003ee7565b808516156200401157918102915b93841c939080029062003fc5565b509250929050565b5f8262004037575060016200088c565b816200404557505f6200088c565b81600181146200405e5760028114620040695762004089565b60019150506200088c565b60ff8411156200407d576200407d62003ee7565b50506001821b6200088c565b5060208310610133831016604e8410600b8410161715620040ae575081810a6200088c565b620040ba838362003fc0565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115620040ef57620040ef62003ee7565b029392505050565b5f6200377b838362004027565b818103818111156200088c576200088c62003ee7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b5f6020828403121562004158575f80fd5b5051919050565b5f61010060ff8b16835263ffffffff808b16602085015273ffffffffffffffffffffffffffffffffffffffff808b166040860152818a1660608601528089166080860152508660a08501528160c0850152620041be8285018762003da5565b925080851660e085015250509998505050505050505050565b5f60208284031215620041e8575f80fd5b81516200377b8162003672565b5f808585111562004204575f80fd5b8386111562004211575f80fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156200425f5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a0312156200427e575f80fd5b87356200428b8162003616565b965060208801356200429d8162003616565b955060408801359450606088013593506080880135620039078162003890565b5f805f805f805f80610100898b031215620042d6575f80fd5b8835620042e38162003616565b97506020890135620042f58162003616565b965060408901359550606089013594506080890135620043158162003672565b935060a0890135620043278162003890565b979a969950949793969295929450505060c08201359160e0013590565b5f6020828403121562004355575f80fd5b81516200377b8162003890565b5f6020828403121562004373575f80fd5b815167ffffffffffffffff8111156200438a575f80fd5b8201601f810184136200439b575f80fd5b8051620043ac62003cfd8262003c94565b818152856020838501011115620043c1575f80fd5b620043d482602083016020860162003c01565b95945050505050565b602081525f6200377b602083018462003da556fe61010060405234801562000011575f80fd5b5060405162001b0d38038062001b0d833981016040819052620000349162000282565b828260036200004483826200038d565b5060046200005382826200038d565b50503360c0525060ff811660e05246608081905262000072906200007f565b60a0525062000455915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ab6200012c565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013d9062000301565b80601f01602080910402602001604051908101604052809291908181526020018280546200016b9062000301565b8015620001ba5780601f106200019057610100808354040283529160200191620001ba565b820191905f5260205f20905b8154815290600101906020018083116200019c57829003601f168201915b5050505050905090565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112620001e8575f80fd5b81516001600160401b0380821115620002055762000205620001c4565b604051601f8301601f19908116603f01168101908282118183101715620002305762000230620001c4565b816040528381526020925086838588010111156200024c575f80fd5b5f91505b838210156200026f578582018301518183018401529082019062000250565b5f93810190920192909252949350505050565b5f805f6060848603121562000295575f80fd5b83516001600160401b0380821115620002ac575f80fd5b620002ba87838801620001d8565b94506020860151915080821115620002d0575f80fd5b50620002df86828701620001d8565b925050604084015160ff81168114620002f6575f80fd5b809150509250925092565b600181811c908216806200031657607f821691505b6020821081036200033557634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000388575f81815260208120601f850160051c81016020861015620003635750805b601f850160051c820191505b8181101562000384578281556001016200036f565b5050505b505050565b81516001600160401b03811115620003a957620003a9620001c4565b620003c181620003ba845462000301565b846200033b565b602080601f831160018114620003f7575f8415620003df5750858301515b5f19600386901b1c1916600185901b17855562000384565b5f85815260208120601f198616915b82811015620004275788860151825594840194600190910190840162000406565b50858210156200044557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161166f6200049e5f395f61022d01525f81816102fb015281816105ad015261069401525f61052801525f818161036d01526104f2015261166f5ff3fe608060405234801561000f575f80fd5b506004361061016e575f3560e01c806370a08231116100d2578063a457c2d711610088578063d505accf11610063578063d505accf1461038f578063dd62ed3e146103a2578063ffa1ad74146103e7575f80fd5b8063a457c2d714610342578063a9059cbb14610355578063cd0d009614610368575f80fd5b806395d89b41116100b857806395d89b41146102db5780639dc29fac146102e3578063a3c573eb146102f6575f80fd5b806370a08231146102875780637ecebe00146102bc575f80fd5b806330adf81f116101275780633644e5151161010d5780633644e51514610257578063395093511461025f57806340c10f1914610272575f80fd5b806330adf81f146101ff578063313ce56714610226575f80fd5b806318160ddd1161015757806318160ddd146101b357806320606b70146101c557806323b872dd146101ec575f80fd5b806306fdde0314610172578063095ea7b314610190575b5f80fd5b61017a610423565b60405161018791906113c1565b60405180910390f35b6101a361019e366004611452565b6104b3565b6040519015158152602001610187565b6002545b604051908152602001610187565b6101b77f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101a36101fa36600461147a565b6104cc565b6101b77f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610187565b6101b76104ef565b6101a361026d366004611452565b61054a565b610285610280366004611452565b610595565b005b6101b76102953660046114b3565b73ffffffffffffffffffffffffffffffffffffffff165f9081526020819052604090205490565b6101b76102ca3660046114b3565b60056020525f908152604090205481565b61017a61066d565b6102856102f1366004611452565b61067c565b61031d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610187565b6101a3610350366004611452565b61074b565b6101a3610363366004611452565b61081b565b6101b77f000000000000000000000000000000000000000000000000000000000000000081565b61028561039d3660046114d3565b610828565b6101b76103b0366004611540565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260016020908152604080832093909416825291909152205490565b61017a6040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043290611571565b80601f016020809104026020016040519081016040528092919081815260200182805461045e90611571565b80156104a95780601f10610480576101008083540402835291602001916104a9565b820191905f5260205f20905b81548152906001019060200180831161048c57829003601f168201915b5050505050905090565b5f336104c0818585610b59565b60019150505b92915050565b5f336104d9858285610d0c565b6104e4858585610de2565b506001949350505050565b5f7f00000000000000000000000000000000000000000000000000000000000000004614610525576105204661104f565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104c090829086906105909087906115ef565b610b59565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461065f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b6106698282611116565b5050565b60606004805461043290611571565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610741576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610656565b6106698282611207565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561080e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610656565b6104e48286868403610b59565b5f336104c0818585610de2565b834211156108b7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff87165f90815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a91908661091083611602565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f61097a6104ef565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f80855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a3b573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ab657508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610656565b610b4d8a8a8a610b59565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610c9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381165f908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610ddc5781811015610dcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610656565b610ddc8484848403610b59565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610e85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610f28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f9081526020819052604090205481811015610fdd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610ddc565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611079610423565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff8216611193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610656565b8060025f8282546111a491906115ef565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff82165f908152602081905260409020548181101561135f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610cff565b5f6020808352835180828501525f5b818110156113ec578581018301518582016040015282016113d0565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461144d575f80fd5b919050565b5f8060408385031215611463575f80fd5b61146c8361142a565b946020939093013593505050565b5f805f6060848603121561148c575f80fd5b6114958461142a565b92506114a36020850161142a565b9150604084013590509250925092565b5f602082840312156114c3575f80fd5b6114cc8261142a565b9392505050565b5f805f805f805f60e0888a0312156114e9575f80fd5b6114f28861142a565b96506115006020890161142a565b95506040880135945060608801359350608088013560ff81168114611523575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611551575f80fd5b61155a8361142a565b91506115686020840161142a565b90509250929050565b600181811c9082168061158557607f821691505b6020821081036115bc577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156104c6576104c66115c2565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611632576116326115c2565b506001019056fea2646970667358221220a04a4613834006222ac539b942dfe3284c1163f5082f3bafb302007d825cd7ff64736f6c63430008140033a26469706673582212205357fe4be099d7eba3ac721350adeffb75403935ecb3ea1a84747cf8b5f23c3564736f6c63430008140033", - "deployedBytecode": "0x608060405260043610620001df575f3560e01c8063715018a61162000106578063bab161bf116200009e578063dbc16976116200006a578063dbc169761462000704578063ee25560b146200071b578063f2fde38b146200074a578063fb570834146200076e575f80fd5b8063bab161bf1462000642578063be5831c7146200067b578063cd58657914620006b6578063d02103ca14620006cd575f80fd5b80638da5cb5b11620000de5780638da5cb5b146200059857806391e57e2d14620005c45780639e34070f14620005db578063aaa13cc2146200061e575f80fd5b8063715018a6146200052557806379e2cf97146200053c57806381b1c1741462000553575f80fd5b80632d2c9d94116200017a57806334ac9cf2116200015257806334ac9cf214620003ca5780633ae0504714620003f85780633e197043146200040f578063647c576c1462000501575f80fd5b80632d2c9d9414620002f95780632dfdf0b5146200031d578063318aee3d1462000343575f80fd5b8063240ff37811620001ba578063240ff37814620002765780632b5e42e7146200028d5780632c3f58cd14620002b15780632cffd02e14620002d5575f80fd5b806315064c9614620001e35780632072f6c5146200021357806322e95f2c146200022c575b5f80fd5b348015620001ef575f80fd5b50606854620001fe9060ff1681565b60405190151581526020015b60405180910390f35b3480156200021f575f80fd5b506200022a62000792565b005b34801562000238575f80fd5b50620002506200024a36600462003638565b620007f0565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016200020a565b6200022a62000287366004620036c8565b62000892565b34801562000299575f80fd5b506200022a620002ab36600462003747565b62000ab9565b348015620002bd575f80fd5b506200022a620002cf3660046200375f565b62000ac8565b348015620002e1575f80fd5b506200022a620002f336600462003794565b62000b0e565b34801562000305575f80fd5b506200022a6200031736600462003794565b62001093565b34801562000329575f80fd5b506200033460535481565b6040519081526020016200020a565b3480156200034f575f80fd5b50620003986200036136600462003872565b606b6020525f908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff9091166020830152016200020a565b348015620003d6575f80fd5b50606c54620002509073ffffffffffffffffffffffffffffffffffffffff1681565b34801562000404575f80fd5b506200033462001293565b3480156200041b575f80fd5b50620003346200042d3660046200389f565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b3480156200050d575f80fd5b506200022a6200051f36600462003924565b62001378565b34801562000531575f80fd5b506200022a620015cd565b34801562000548575f80fd5b506200022a620015e2565b3480156200055f575f80fd5b50620002506200057136600462003747565b606a6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015620005a4575f80fd5b50609f5473ffffffffffffffffffffffffffffffffffffffff1662000250565b348015620005d0575f80fd5b506200033460d15481565b348015620005e7575f80fd5b50620001fe620005f936600462003747565b600881901c5f90815260696020526040902054600160ff9092169190911b9081161490565b3480156200062a575f80fd5b50620002506200063c36600462003971565b6200161c565b3480156200064e575f80fd5b506068546200066590610100900463ffffffff1681565b60405163ffffffff90911681526020016200020a565b34801562000687575f80fd5b506068546200066590790100000000000000000000000000000000000000000000000000900463ffffffff1681565b6200022a620006c736600462003a1e565b62001806565b348015620006d9575f80fd5b50606854620002509065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b34801562000710575f80fd5b506200022a620018da565b34801562000727575f80fd5b50620003346200073936600462003747565b60696020525f908152604090205481565b34801562000756575f80fd5b506200022a6200076836600462003872565b62001936565b3480156200077a575f80fd5b50620001fe6200078c36600462003aba565b620019f3565b606c5473ffffffffffffffffffffffffffffffffffffffff163314620007e4576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620007ee62001adb565b565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602483015282516018818403018152603890920183528151918101919091205f908152606a909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b60685460ff1615620008d0576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff868116610100909204161480620008f65750600263ffffffff861610155b156200092e576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338888348888605354604051620009849998979695949392919062003b4b565b60405180910390a162000aa162000a9b6001606860019054906101000a900463ffffffff16338989348989604051620009bf92919062003bc5565b60405180910390206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b62001b6e565b821562000ab25762000ab262001c82565b5050505050565b62000ac362001d52565b60d155565b62000ad262001d52565b6068805463ffffffff909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff909216919091179055565b60685460ff161562000b4c576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000b628b8b8b8b8b8b8b8b8b8b8b5f62001dd5565b73ffffffffffffffffffffffffffffffffffffffff861662000c3a57604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff861690859060405162000bb6919062003c25565b5f6040518083038185875af1925050503d805f811462000bf2576040519150601f19603f3d011682016040523d82523d5f602084013e62000bf7565b606091505b505090508062000c33576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506200101b565b60685463ffffffff61010090910481169088160362000c7c5762000c7673ffffffffffffffffffffffffffffffffffffffff8716858562001fc0565b6200101b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f90603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301205f818152606a90935291205490915073ffffffffffffffffffffffffffffffffffffffff168062000f92575f808062000d4e8688018862003d34565b9250925092505f8584848460405162000d6790620035f4565b62000d759392919062003df0565b8190604051809103905ff590508015801562000d93573d5f803e3d5ffd5b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81166004830152602482018c9052919250908216906340c10f19906044015f604051808303815f87803b15801562000e06575f80fd5b505af115801562000e19573d5f803e3d5ffd5b5050505080606a5f8881526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808e63ffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815250606b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000f8095949392919062003e2c565b60405180910390a15050505062001018565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801562001000575f80fd5b505af115801562001013573d5f803e3d5ffd5b505050505b50505b6040805163ffffffff8c811682528916602082015273ffffffffffffffffffffffffffffffffffffffff88811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff1615620010d1576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620010e88b8b8b8b8b8b8b8b8b8b8b600162001dd5565b5f8473ffffffffffffffffffffffffffffffffffffffff1684888a86866040516024016200111a949392919062003e73565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1806b5f200000000000000000000000000000000000000000000000000000000179052516200119d919062003c25565b5f6040518083038185875af1925050503d805f8114620011d9576040519150601f19603f3d011682016040523d82523d5f602084013e620011de565b606091505b50509050806200121a576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a16602082015273ffffffffffffffffffffffffffffffffffffffff89811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b6053545f90819081805b60208110156200136f578083901c600116600103620013005760338160208110620012cc57620012cc62003eba565b015460408051602081019290925281018590526060016040516020818303038152906040528051906020012093506200132d565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080620013669062003f14565b9150506200129d565b50919392505050565b5f54610100900460ff16158080156200139757505f54600160ff909116105b80620013b25750303b158015620013b257505f5460ff166001145b62001444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015620014a1575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff16176501000000000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155606c80547fffffffffffffffffffffffff0000000000000000000000000000000000000000169184169190911790556703782dace9d9000060d1556200156462002096565b8015620015c7575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b620015d762001d52565b620007ee5f62002134565b605354606854790100000000000000000000000000000000000000000000000000900463ffffffff161015620007ee57620007ee62001c82565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180602001620016b090620035f4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052620016fb908d908d908d908d908d9060200162003f4e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905262001739929160200162003f8e565b60405160208183030381529060405280519060200120604051602001620017c294939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101209a9950505050505050505050565b60d154341115620018c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604760248201527f506f6c79676f6e5a6b45564d4272696467653a3a62726964676541737365743a60448201527f2043616e6e6f7420627269646765206d6f7265207468616e206d61784574686560648201527f7242726964676500000000000000000000000000000000000000000000000000608482015260a4016200143b565b620018d187878787878787620021aa565b50505050505050565b606c5473ffffffffffffffffffffffffffffffffffffffff1633146200192c576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620007ee620026f3565b6200194062001d52565b73ffffffffffffffffffffffffffffffffffffffff8116620019e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016200143b565b620019f08162002134565b50565b5f84815b602081101562001acd57600163ffffffff8616821c8116900362001a695785816020811062001a2a5762001a2a62003eba565b60200201358260405160200162001a4b929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001ab8565b8186826020811062001a7f5762001a7f62003eba565b602002013560405160200162001a9f929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001ac48162003f14565b915050620019f7565b50821490505b949350505050565b60685460ff161562001b19576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b80600162001b7f60206002620040f7565b62001b8b919062004104565b6053541062001bc6576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f815462001bd79062003f14565b918290555090505f5b602081101562001c72578082901c60011660010362001c1857826033826020811062001c105762001c1062003eba565b015550505050565b6033816020811062001c2e5762001c2e62003eba565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808062001c699062003f14565b91505062001be0565b5062001c7d6200411a565b505050565b6053546068805463ffffffff909216790100000000000000000000000000000000000000000000000000027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179081905573ffffffffffffffffffffffffffffffffffffffff65010000000000909104166333d6247d62001d0862001293565b6040518263ffffffff1660e01b815260040162001d2791815260200190565b5f604051808303815f87803b15801562001d3f575f80fd5b505af1158015620015c7573d5f803e3d5ffd5b609f5473ffffffffffffffffffffffffffffffffffffffff163314620007ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200143b565b62001de68b63ffffffff1662002782565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f9165010000000000900473ffffffffffffffffffffffffffffffffffffffff169063257b3632906084016020604051808303815f875af115801562001e85573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001eab919062004147565b9050805f0362001ee6576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff888116610100909204161462001f30576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068545f90610100900463ffffffff1662001f4d57508962001f50565b508a5b62001f7962001f70848c8c8c8c8c8c8c604051620009bf92919062003bc5565b8f8f84620019f3565b62001fb0576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001c7d9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152620027e6565b5f54610100900460ff166200212e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016200143b565b620007ee335b609f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60685460ff1615620021e8576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620021f2620028f8565b60685463ffffffff888116610100909204161480620022185750600263ffffffff881610155b1562002250576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8060608773ffffffffffffffffffffffffffffffffffffffff8816620022b457883414620022ab576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f9250620025a1565b3415620022ed576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8089165f908152606b602090815260409182902082518084019093525463ffffffff8116835264010000000090049092169181018290529015620023d6576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b905273ffffffffffffffffffffffffffffffffffffffff8a1690639dc29fac906044015f604051808303815f87803b158015620023ac575f80fd5b505af1158015620023bf573d5f803e3d5ffd5b5050505080602001519450805f015193506200259f565b8515620023eb57620023eb898b89896200296d565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8b16906370a0823190602401602060405180830381865afa15801562002456573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200247c919062004147565b9050620024a273ffffffffffffffffffffffffffffffffffffffff8b1633308e62002e80565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa1580156200250d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002533919062004147565b905062002541828262004104565b6068548c9850610100900463ffffffff1696509350620025618762002ee0565b6200256c8c62002ff4565b620025778d620030fd565b6040516020016200258b9392919062003df0565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e8688605354604051620025e29897969594939291906200415f565b60405180910390a1620026d462000a9b5f85878f8f8789805190602001206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b8615620026e557620026e562001c82565b50505050620018d160018055565b60685460ff1662002730576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b600881901c5f8181526069602052604081208054600160ff861690811b9182189283905592909190818316900362000ab2576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62002849826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620031f59092919063ffffffff16565b80519091501562001c7d57808060200190518101906200286a9190620041d7565b62001c7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016200143b565b60026001540362002966576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016200143b565b6002600155565b5f6200297d6004828486620041f5565b62002988916200421e565b90507f2afa5331000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160162002c02575f808080808080620029ea896004818d620041f5565b810190620029f9919062004267565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462002a6d576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8616301462002abd576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a851462002af7576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169162002bb2919062003c25565b5f604051808303815f865af19150503d805f811462002bed576040519150601f19603f3d011682016040523d82523d5f602084013e62002bf2565b606091505b5050505050505050505062000ab2565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f8fcbaf0c000000000000000000000000000000000000000000000000000000001462002c7e576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8080808080808062002c958a6004818e620041f5565b81019062002ca49190620042bd565b975097509750975097509750975097503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161462002d1a576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8716301462002d6a576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8fcbaf0c000000000000000000000000000000000000000000000000000000001790529151918f169162002e2e919062003c25565b5f604051808303815f865af19150503d805f811462002e69576040519150601f19603f3d011682016040523d82523d5f602084013e62002e6e565b606091505b50505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620015c79085907f23b872dd000000000000000000000000000000000000000000000000000000009060840162002013565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff86169162002f63919062003c25565b5f60405180830381855afa9150503d805f811462002f9d576040519150601f19603f3d011682016040523d82523d5f602084013e62002fa2565b606091505b50915091508162002fe9576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525062001ad3565b62001ad38162003205565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff86169162003077919062003c25565b5f60405180830381855afa9150503d805f8114620030b1576040519150601f19603f3d011682016040523d82523d5f602084013e620030b6565b606091505b50915091508162002fe9576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525062001ad3565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f918291829173ffffffffffffffffffffffffffffffffffffffff8616916200317f919062003c25565b5f60405180830381855afa9150503d805f8114620031b9576040519150601f19603f3d011682016040523d82523d5f602084013e620031be565b606091505b5091509150818015620031d2575080516020145b620031df57601262001ad3565b8080602001905181019062001ad3919062004344565b606062001ad384845f85620033f0565b606060408251106200322757818060200190518101906200088c919062004362565b8151602003620033b2575f5b6020811080156200327e575082818151811062003254576200325462003eba565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15620032995780620032908162003f14565b91505062003233565b805f03620032dc57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115620032f957620032f962003bd4565b6040519080825280601f01601f19166020018201604052801562003324576020820181803683370190505b5090505f5b82811015620033aa5784818151811062003347576200334762003eba565b602001015160f81c60f81b82828151811062003367576200336762003eba565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080620033a18162003f14565b91505062003329565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b60608247101562003484576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016200143b565b5f808673ffffffffffffffffffffffffffffffffffffffff168587604051620034ae919062003c25565b5f6040518083038185875af1925050503d805f8114620034ea576040519150601f19603f3d011682016040523d82523d5f602084013e620034ef565b606091505b509150915062003502878383876200350d565b979650505050505050565b60608315620035a75782515f036200359f5773ffffffffffffffffffffffffffffffffffffffff85163b6200359f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200143b565b508162001ad3565b62001ad38383815115620035be5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200143b9190620043dd565b611b0d80620043f283390190565b803563ffffffff81168114620033eb575f80fd5b73ffffffffffffffffffffffffffffffffffffffff81168114620019f0575f80fd5b5f80604083850312156200364a575f80fd5b620036558362003602565b91506020830135620036678162003616565b809150509250929050565b8015158114620019f0575f80fd5b5f8083601f84011262003691575f80fd5b50813567ffffffffffffffff811115620036a9575f80fd5b602083019150836020828501011115620036c1575f80fd5b9250929050565b5f805f805f60808688031215620036dd575f80fd5b620036e88662003602565b94506020860135620036fa8162003616565b935060408601356200370c8162003672565b9250606086013567ffffffffffffffff81111562003728575f80fd5b620037368882890162003680565b969995985093965092949392505050565b5f6020828403121562003758575f80fd5b5035919050565b5f6020828403121562003770575f80fd5b6200377b8262003602565b9392505050565b8061040081018310156200088c575f80fd5b5f805f805f805f805f805f6105208c8e031215620037b0575f80fd5b620037bc8d8d62003782565b9a50620037cd6104008d0162003602565b99506104208c013598506104408c01359750620037ee6104608d0162003602565b96506104808c0135620038018162003616565b9550620038126104a08d0162003602565b94506104c08c0135620038258162003616565b93506104e08c013592506105008c013567ffffffffffffffff8111156200384a575f80fd5b620038588e828f0162003680565b915080935050809150509295989b509295989b9093969950565b5f6020828403121562003883575f80fd5b81356200377b8162003616565b60ff81168114620019f0575f80fd5b5f805f805f805f60e0888a031215620038b6575f80fd5b8735620038c38162003890565b9650620038d36020890162003602565b95506040880135620038e58162003616565b9450620038f56060890162003602565b93506080880135620039078162003616565b9699959850939692959460a0840135945060c09093013592915050565b5f805f6060848603121562003937575f80fd5b620039428462003602565b92506020840135620039548162003616565b91506040840135620039668162003616565b809150509250925092565b5f805f805f805f60a0888a03121562003988575f80fd5b620039938862003602565b96506020880135620039a58162003616565b9550604088013567ffffffffffffffff80821115620039c2575f80fd5b620039d08b838c0162003680565b909750955060608a0135915080821115620039e9575f80fd5b50620039f88a828b0162003680565b909450925050608088013562003a0e8162003890565b8091505092959891949750929550565b5f805f805f805f60c0888a03121562003a35575f80fd5b62003a408862003602565b9650602088013562003a528162003616565b955060408801359450606088013562003a6b8162003616565b9350608088013562003a7d8162003672565b925060a088013567ffffffffffffffff81111562003a99575f80fd5b62003aa78a828b0162003680565b989b979a50959850939692959293505050565b5f805f80610460858703121562003acf575f80fd5b8435935062003ae2866020870162003782565b925062003af3610420860162003602565b939692955092936104400135925050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f61010060ff8c16835263ffffffff808c16602085015273ffffffffffffffffffffffffffffffffffffffff808c166040860152818b166060860152808a166080860152508760a08501528160c085015262003bab828501878962003b04565b925080851660e085015250509a9950505050505050505050565b818382375f9101908152919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5b8381101562003c1d57818101518382015260200162003c03565b50505f910152565b5f825162003c3881846020870162003c01565b9190910192915050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171562003c8c5762003c8c62003bd4565b604052919050565b5f67ffffffffffffffff82111562003cb05762003cb062003bd4565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f83011262003cec575f80fd5b813562003d0362003cfd8262003c94565b62003c42565b81815284602083860101111562003d18575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f6060848603121562003d47575f80fd5b833567ffffffffffffffff8082111562003d5f575f80fd5b62003d6d8783880162003cdc565b9450602086013591508082111562003d83575f80fd5b5062003d928682870162003cdc565b9250506040840135620039668162003890565b5f815180845262003dbe81602086016020860162003c01565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606081525f62003e04606083018662003da5565b828103602084015262003e18818662003da5565b91505060ff83166040830152949350505050565b63ffffffff861681525f73ffffffffffffffffffffffffffffffffffffffff8087166020840152808616604084015250608060608301526200350260808301848662003b04565b73ffffffffffffffffffffffffffffffffffffffff8516815263ffffffff84166020820152606060408201525f62003eb060608301848662003b04565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003f475762003f4762003ee7565b5060010190565b606081525f62003f6360608301878962003b04565b828103602084015262003f7881868862003b04565b91505060ff831660408301529695505050505050565b5f835162003fa181846020880162003c01565b83519083019062003fb781836020880162003c01565b01949350505050565b600181815b808511156200401f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562004003576200400362003ee7565b808516156200401157918102915b93841c939080029062003fc5565b509250929050565b5f8262004037575060016200088c565b816200404557505f6200088c565b81600181146200405e5760028114620040695762004089565b60019150506200088c565b60ff8411156200407d576200407d62003ee7565b50506001821b6200088c565b5060208310610133831016604e8410600b8410161715620040ae575081810a6200088c565b620040ba838362003fc0565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115620040ef57620040ef62003ee7565b029392505050565b5f6200377b838362004027565b818103818111156200088c576200088c62003ee7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b5f6020828403121562004158575f80fd5b5051919050565b5f61010060ff8b16835263ffffffff808b16602085015273ffffffffffffffffffffffffffffffffffffffff808b166040860152818a1660608601528089166080860152508660a08501528160c0850152620041be8285018762003da5565b925080851660e085015250509998505050505050505050565b5f60208284031215620041e8575f80fd5b81516200377b8162003672565b5f808585111562004204575f80fd5b8386111562004211575f80fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156200425f5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a0312156200427e575f80fd5b87356200428b8162003616565b965060208801356200429d8162003616565b955060408801359450606088013593506080880135620039078162003890565b5f805f805f805f80610100898b031215620042d6575f80fd5b8835620042e38162003616565b97506020890135620042f58162003616565b965060408901359550606089013594506080890135620043158162003672565b935060a0890135620043278162003890565b979a969950949793969295929450505060c08201359160e0013590565b5f6020828403121562004355575f80fd5b81516200377b8162003890565b5f6020828403121562004373575f80fd5b815167ffffffffffffffff8111156200438a575f80fd5b8201601f810184136200439b575f80fd5b8051620043ac62003cfd8262003c94565b818152856020838501011115620043c1575f80fd5b620043d482602083016020860162003c01565b95945050505050565b602081525f6200377b602083018462003da556fe61010060405234801562000011575f80fd5b5060405162001b0d38038062001b0d833981016040819052620000349162000282565b828260036200004483826200038d565b5060046200005382826200038d565b50503360c0525060ff811660e05246608081905262000072906200007f565b60a0525062000455915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ab6200012c565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013d9062000301565b80601f01602080910402602001604051908101604052809291908181526020018280546200016b9062000301565b8015620001ba5780601f106200019057610100808354040283529160200191620001ba565b820191905f5260205f20905b8154815290600101906020018083116200019c57829003601f168201915b5050505050905090565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112620001e8575f80fd5b81516001600160401b0380821115620002055762000205620001c4565b604051601f8301601f19908116603f01168101908282118183101715620002305762000230620001c4565b816040528381526020925086838588010111156200024c575f80fd5b5f91505b838210156200026f578582018301518183018401529082019062000250565b5f93810190920192909252949350505050565b5f805f6060848603121562000295575f80fd5b83516001600160401b0380821115620002ac575f80fd5b620002ba87838801620001d8565b94506020860151915080821115620002d0575f80fd5b50620002df86828701620001d8565b925050604084015160ff81168114620002f6575f80fd5b809150509250925092565b600181811c908216806200031657607f821691505b6020821081036200033557634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000388575f81815260208120601f850160051c81016020861015620003635750805b601f850160051c820191505b8181101562000384578281556001016200036f565b5050505b505050565b81516001600160401b03811115620003a957620003a9620001c4565b620003c181620003ba845462000301565b846200033b565b602080601f831160018114620003f7575f8415620003df5750858301515b5f19600386901b1c1916600185901b17855562000384565b5f85815260208120601f198616915b82811015620004275788860151825594840194600190910190840162000406565b50858210156200044557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161166f6200049e5f395f61022d01525f81816102fb015281816105ad015261069401525f61052801525f818161036d01526104f2015261166f5ff3fe608060405234801561000f575f80fd5b506004361061016e575f3560e01c806370a08231116100d2578063a457c2d711610088578063d505accf11610063578063d505accf1461038f578063dd62ed3e146103a2578063ffa1ad74146103e7575f80fd5b8063a457c2d714610342578063a9059cbb14610355578063cd0d009614610368575f80fd5b806395d89b41116100b857806395d89b41146102db5780639dc29fac146102e3578063a3c573eb146102f6575f80fd5b806370a08231146102875780637ecebe00146102bc575f80fd5b806330adf81f116101275780633644e5151161010d5780633644e51514610257578063395093511461025f57806340c10f1914610272575f80fd5b806330adf81f146101ff578063313ce56714610226575f80fd5b806318160ddd1161015757806318160ddd146101b357806320606b70146101c557806323b872dd146101ec575f80fd5b806306fdde0314610172578063095ea7b314610190575b5f80fd5b61017a610423565b60405161018791906113c1565b60405180910390f35b6101a361019e366004611452565b6104b3565b6040519015158152602001610187565b6002545b604051908152602001610187565b6101b77f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101a36101fa36600461147a565b6104cc565b6101b77f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610187565b6101b76104ef565b6101a361026d366004611452565b61054a565b610285610280366004611452565b610595565b005b6101b76102953660046114b3565b73ffffffffffffffffffffffffffffffffffffffff165f9081526020819052604090205490565b6101b76102ca3660046114b3565b60056020525f908152604090205481565b61017a61066d565b6102856102f1366004611452565b61067c565b61031d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610187565b6101a3610350366004611452565b61074b565b6101a3610363366004611452565b61081b565b6101b77f000000000000000000000000000000000000000000000000000000000000000081565b61028561039d3660046114d3565b610828565b6101b76103b0366004611540565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260016020908152604080832093909416825291909152205490565b61017a6040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043290611571565b80601f016020809104026020016040519081016040528092919081815260200182805461045e90611571565b80156104a95780601f10610480576101008083540402835291602001916104a9565b820191905f5260205f20905b81548152906001019060200180831161048c57829003601f168201915b5050505050905090565b5f336104c0818585610b59565b60019150505b92915050565b5f336104d9858285610d0c565b6104e4858585610de2565b506001949350505050565b5f7f00000000000000000000000000000000000000000000000000000000000000004614610525576105204661104f565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104c090829086906105909087906115ef565b610b59565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461065f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b6106698282611116565b5050565b60606004805461043290611571565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610741576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610656565b6106698282611207565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561080e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610656565b6104e48286868403610b59565b5f336104c0818585610de2565b834211156108b7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff87165f90815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a91908661091083611602565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f61097a6104ef565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f80855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a3b573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ab657508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610656565b610b4d8a8a8a610b59565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610c9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381165f908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610ddc5781811015610dcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610656565b610ddc8484848403610b59565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610e85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610f28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f9081526020819052604090205481811015610fdd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610ddc565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611079610423565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff8216611193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610656565b8060025f8282546111a491906115ef565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff82165f908152602081905260409020548181101561135f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610cff565b5f6020808352835180828501525f5b818110156113ec578581018301518582016040015282016113d0565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461144d575f80fd5b919050565b5f8060408385031215611463575f80fd5b61146c8361142a565b946020939093013593505050565b5f805f6060848603121561148c575f80fd5b6114958461142a565b92506114a36020850161142a565b9150604084013590509250925092565b5f602082840312156114c3575f80fd5b6114cc8261142a565b9392505050565b5f805f805f805f60e0888a0312156114e9575f80fd5b6114f28861142a565b96506115006020890161142a565b95506040880135945060608801359350608088013560ff81168114611523575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611551575f80fd5b61155a8361142a565b91506115686020840161142a565b90509250929050565b600181811c9082168061158557607f821691505b6020821081036115bc577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156104c6576104c66115c2565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611632576116326115c2565b506001019056fea2646970667358221220a04a4613834006222ac539b942dfe3284c1163f5082f3bafb302007d825cd7ff64736f6c63430008140033a26469706673582212205357fe4be099d7eba3ac721350adeffb75403935ecb3ea1a84747cf8b5f23c3564736f6c63430008140033", + "bytecode": "0x608060405234801561000f575f80fd5b50615f348061001d5f395ff3fe608060405260043610620001df575f3560e01c8063715018a61162000106578063bab161bf116200009e578063dbc16976116200006a578063dbc169761462000704578063ee25560b146200071b578063f2fde38b146200074a578063fb570834146200076e575f80fd5b8063bab161bf1462000642578063be5831c7146200067b578063cd58657914620006b6578063d02103ca14620006cd575f80fd5b80638da5cb5b11620000de5780638da5cb5b146200059857806391e57e2d14620005c45780639e34070f14620005db578063aaa13cc2146200061e575f80fd5b8063715018a6146200052557806379e2cf97146200053c57806381b1c1741462000553575f80fd5b80632d2c9d94116200017a57806334ac9cf2116200015257806334ac9cf214620003ca5780633ae0504714620003f85780633e197043146200040f578063647c576c1462000501575f80fd5b80632d2c9d9414620002f95780632dfdf0b5146200031d578063318aee3d1462000343575f80fd5b8063240ff37811620001ba578063240ff37814620002765780632b5e42e7146200028d5780632c3f58cd14620002b15780632cffd02e14620002d5575f80fd5b806315064c9614620001e35780632072f6c5146200021357806322e95f2c146200022c575b5f80fd5b348015620001ef575f80fd5b50606854620001fe9060ff1681565b60405190151581526020015b60405180910390f35b3480156200021f575f80fd5b506200022a62000792565b005b34801562000238575f80fd5b50620002506200024a36600462003638565b620007f0565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016200020a565b6200022a62000287366004620036c8565b62000892565b34801562000299575f80fd5b506200022a620002ab36600462003747565b62000ab9565b348015620002bd575f80fd5b506200022a620002cf3660046200375f565b62000ac8565b348015620002e1575f80fd5b506200022a620002f336600462003794565b62000b0e565b34801562000305575f80fd5b506200022a6200031736600462003794565b62001093565b34801562000329575f80fd5b506200033460535481565b6040519081526020016200020a565b3480156200034f575f80fd5b50620003986200036136600462003872565b606b6020525f908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff9091166020830152016200020a565b348015620003d6575f80fd5b50606c54620002509073ffffffffffffffffffffffffffffffffffffffff1681565b34801562000404575f80fd5b506200033462001293565b3480156200041b575f80fd5b50620003346200042d3660046200389f565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b3480156200050d575f80fd5b506200022a6200051f36600462003924565b62001378565b34801562000531575f80fd5b506200022a620015cd565b34801562000548575f80fd5b506200022a620015e2565b3480156200055f575f80fd5b50620002506200057136600462003747565b606a6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015620005a4575f80fd5b50609f5473ffffffffffffffffffffffffffffffffffffffff1662000250565b348015620005d0575f80fd5b506200033460d15481565b348015620005e7575f80fd5b50620001fe620005f936600462003747565b600881901c5f90815260696020526040902054600160ff9092169190911b9081161490565b3480156200062a575f80fd5b50620002506200063c36600462003971565b6200161c565b3480156200064e575f80fd5b506068546200066590610100900463ffffffff1681565b60405163ffffffff90911681526020016200020a565b34801562000687575f80fd5b506068546200066590790100000000000000000000000000000000000000000000000000900463ffffffff1681565b6200022a620006c736600462003a1e565b62001806565b348015620006d9575f80fd5b50606854620002509065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b34801562000710575f80fd5b506200022a620018da565b34801562000727575f80fd5b50620003346200073936600462003747565b60696020525f908152604090205481565b34801562000756575f80fd5b506200022a6200076836600462003872565b62001936565b3480156200077a575f80fd5b50620001fe6200078c36600462003aba565b620019f3565b606c5473ffffffffffffffffffffffffffffffffffffffff163314620007e4576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620007ee62001adb565b565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602483015282516018818403018152603890920183528151918101919091205f908152606a909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b60685460ff1615620008d0576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff868116610100909204161480620008f65750600263ffffffff861610155b156200092e576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338888348888605354604051620009849998979695949392919062003b4b565b60405180910390a162000aa162000a9b6001606860019054906101000a900463ffffffff16338989348989604051620009bf92919062003bc5565b60405180910390206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b62001b6e565b821562000ab25762000ab262001c82565b5050505050565b62000ac362001d52565b60d155565b62000ad262001d52565b6068805463ffffffff909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff909216919091179055565b60685460ff161562000b4c576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000b628b8b8b8b8b8b8b8b8b8b8b5f62001dd5565b73ffffffffffffffffffffffffffffffffffffffff861662000c3a57604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff861690859060405162000bb6919062003c25565b5f6040518083038185875af1925050503d805f811462000bf2576040519150601f19603f3d011682016040523d82523d5f602084013e62000bf7565b606091505b505090508062000c33576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506200101b565b60685463ffffffff61010090910481169088160362000c7c5762000c7673ffffffffffffffffffffffffffffffffffffffff8716858562001fc0565b6200101b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f90603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301205f818152606a90935291205490915073ffffffffffffffffffffffffffffffffffffffff168062000f92575f808062000d4e8688018862003d34565b9250925092505f8584848460405162000d6790620035f4565b62000d759392919062003df0565b8190604051809103905ff590508015801562000d93573d5f803e3d5ffd5b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81166004830152602482018c9052919250908216906340c10f19906044015f604051808303815f87803b15801562000e06575f80fd5b505af115801562000e19573d5f803e3d5ffd5b5050505080606a5f8881526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808e63ffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815250606b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000f8095949392919062003e2c565b60405180910390a15050505062001018565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801562001000575f80fd5b505af115801562001013573d5f803e3d5ffd5b505050505b50505b6040805163ffffffff8c811682528916602082015273ffffffffffffffffffffffffffffffffffffffff88811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff1615620010d1576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620010e88b8b8b8b8b8b8b8b8b8b8b600162001dd5565b5f8473ffffffffffffffffffffffffffffffffffffffff1684888a86866040516024016200111a949392919062003e73565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1806b5f200000000000000000000000000000000000000000000000000000000179052516200119d919062003c25565b5f6040518083038185875af1925050503d805f8114620011d9576040519150601f19603f3d011682016040523d82523d5f602084013e620011de565b606091505b50509050806200121a576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a16602082015273ffffffffffffffffffffffffffffffffffffffff89811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b6053545f90819081805b60208110156200136f578083901c600116600103620013005760338160208110620012cc57620012cc62003eba565b015460408051602081019290925281018590526060016040516020818303038152906040528051906020012093506200132d565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080620013669062003f14565b9150506200129d565b50919392505050565b5f54610100900460ff16158080156200139757505f54600160ff909116105b80620013b25750303b158015620013b257505f5460ff166001145b62001444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015620014a1575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff16176501000000000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155606c80547fffffffffffffffffffffffff0000000000000000000000000000000000000000169184169190911790556703782dace9d9000060d1556200156462002096565b8015620015c7575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b620015d762001d52565b620007ee5f62002134565b605354606854790100000000000000000000000000000000000000000000000000900463ffffffff161015620007ee57620007ee62001c82565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180602001620016b090620035f4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052620016fb908d908d908d908d908d9060200162003f4e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905262001739929160200162003f8e565b60405160208183030381529060405280519060200120604051602001620017c294939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101209a9950505050505050505050565b60d154341115620018c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604760248201527f506f6c79676f6e5a6b45564d4272696467653a3a62726964676541737365743a60448201527f2043616e6e6f7420627269646765206d6f7265207468616e206d61784574686560648201527f7242726964676500000000000000000000000000000000000000000000000000608482015260a4016200143b565b620018d187878787878787620021aa565b50505050505050565b606c5473ffffffffffffffffffffffffffffffffffffffff1633146200192c576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620007ee620026f3565b6200194062001d52565b73ffffffffffffffffffffffffffffffffffffffff8116620019e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016200143b565b620019f08162002134565b50565b5f84815b602081101562001acd57600163ffffffff8616821c8116900362001a695785816020811062001a2a5762001a2a62003eba565b60200201358260405160200162001a4b929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001ab8565b8186826020811062001a7f5762001a7f62003eba565b602002013560405160200162001a9f929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001ac48162003f14565b915050620019f7565b50821490505b949350505050565b60685460ff161562001b19576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b80600162001b7f60206002620040f7565b62001b8b919062004104565b6053541062001bc6576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f815462001bd79062003f14565b918290555090505f5b602081101562001c72578082901c60011660010362001c1857826033826020811062001c105762001c1062003eba565b015550505050565b6033816020811062001c2e5762001c2e62003eba565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808062001c699062003f14565b91505062001be0565b5062001c7d6200411a565b505050565b6053546068805463ffffffff909216790100000000000000000000000000000000000000000000000000027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179081905573ffffffffffffffffffffffffffffffffffffffff65010000000000909104166333d6247d62001d0862001293565b6040518263ffffffff1660e01b815260040162001d2791815260200190565b5f604051808303815f87803b15801562001d3f575f80fd5b505af1158015620015c7573d5f803e3d5ffd5b609f5473ffffffffffffffffffffffffffffffffffffffff163314620007ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200143b565b62001de68b63ffffffff1662002782565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f9165010000000000900473ffffffffffffffffffffffffffffffffffffffff169063257b3632906084016020604051808303815f875af115801562001e85573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001eab919062004147565b9050805f0362001ee6576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff888116610100909204161462001f30576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068545f90610100900463ffffffff1662001f4d57508962001f50565b508a5b62001f7962001f70848c8c8c8c8c8c8c604051620009bf92919062003bc5565b8f8f84620019f3565b62001fb0576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001c7d9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152620027e6565b5f54610100900460ff166200212e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016200143b565b620007ee335b609f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60685460ff1615620021e8576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620021f2620028f8565b60685463ffffffff888116610100909204161480620022185750600263ffffffff881610155b1562002250576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8060608773ffffffffffffffffffffffffffffffffffffffff8816620022b457883414620022ab576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f9250620025a1565b3415620022ed576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8089165f908152606b602090815260409182902082518084019093525463ffffffff8116835264010000000090049092169181018290529015620023d6576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b905273ffffffffffffffffffffffffffffffffffffffff8a1690639dc29fac906044015f604051808303815f87803b158015620023ac575f80fd5b505af1158015620023bf573d5f803e3d5ffd5b5050505080602001519450805f015193506200259f565b8515620023eb57620023eb898b89896200296d565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8b16906370a0823190602401602060405180830381865afa15801562002456573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200247c919062004147565b9050620024a273ffffffffffffffffffffffffffffffffffffffff8b1633308e62002e80565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa1580156200250d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002533919062004147565b905062002541828262004104565b6068548c9850610100900463ffffffff1696509350620025618762002ee0565b6200256c8c62002ff4565b620025778d620030fd565b6040516020016200258b9392919062003df0565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e8688605354604051620025e29897969594939291906200415f565b60405180910390a1620026d462000a9b5f85878f8f8789805190602001206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b8615620026e557620026e562001c82565b50505050620018d160018055565b60685460ff1662002730576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b600881901c5f8181526069602052604081208054600160ff861690811b9182189283905592909190818316900362000ab2576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62002849826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620031f59092919063ffffffff16565b80519091501562001c7d57808060200190518101906200286a9190620041d7565b62001c7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016200143b565b60026001540362002966576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016200143b565b6002600155565b5f6200297d6004828486620041f5565b62002988916200421e565b90507f2afa5331000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160162002c02575f808080808080620029ea896004818d620041f5565b810190620029f9919062004267565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462002a6d576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8616301462002abd576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a851462002af7576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169162002bb2919062003c25565b5f604051808303815f865af19150503d805f811462002bed576040519150601f19603f3d011682016040523d82523d5f602084013e62002bf2565b606091505b5050505050505050505062000ab2565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f8fcbaf0c000000000000000000000000000000000000000000000000000000001462002c7e576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8080808080808062002c958a6004818e620041f5565b81019062002ca49190620042bd565b975097509750975097509750975097503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161462002d1a576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8716301462002d6a576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8fcbaf0c000000000000000000000000000000000000000000000000000000001790529151918f169162002e2e919062003c25565b5f604051808303815f865af19150503d805f811462002e69576040519150601f19603f3d011682016040523d82523d5f602084013e62002e6e565b606091505b50505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620015c79085907f23b872dd000000000000000000000000000000000000000000000000000000009060840162002013565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff86169162002f63919062003c25565b5f60405180830381855afa9150503d805f811462002f9d576040519150601f19603f3d011682016040523d82523d5f602084013e62002fa2565b606091505b50915091508162002fe9576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525062001ad3565b62001ad38162003205565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff86169162003077919062003c25565b5f60405180830381855afa9150503d805f8114620030b1576040519150601f19603f3d011682016040523d82523d5f602084013e620030b6565b606091505b50915091508162002fe9576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525062001ad3565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f918291829173ffffffffffffffffffffffffffffffffffffffff8616916200317f919062003c25565b5f60405180830381855afa9150503d805f8114620031b9576040519150601f19603f3d011682016040523d82523d5f602084013e620031be565b606091505b5091509150818015620031d2575080516020145b620031df57601262001ad3565b8080602001905181019062001ad3919062004344565b606062001ad384845f85620033f0565b606060408251106200322757818060200190518101906200088c919062004362565b8151602003620033b2575f5b6020811080156200327e575082818151811062003254576200325462003eba565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15620032995780620032908162003f14565b91505062003233565b805f03620032dc57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115620032f957620032f962003bd4565b6040519080825280601f01601f19166020018201604052801562003324576020820181803683370190505b5090505f5b82811015620033aa5784818151811062003347576200334762003eba565b602001015160f81c60f81b82828151811062003367576200336762003eba565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080620033a18162003f14565b91505062003329565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b60608247101562003484576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016200143b565b5f808673ffffffffffffffffffffffffffffffffffffffff168587604051620034ae919062003c25565b5f6040518083038185875af1925050503d805f8114620034ea576040519150601f19603f3d011682016040523d82523d5f602084013e620034ef565b606091505b509150915062003502878383876200350d565b979650505050505050565b60608315620035a75782515f036200359f5773ffffffffffffffffffffffffffffffffffffffff85163b6200359f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200143b565b508162001ad3565b62001ad38383815115620035be5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200143b9190620043dd565b611b0d80620043f283390190565b803563ffffffff81168114620033eb575f80fd5b73ffffffffffffffffffffffffffffffffffffffff81168114620019f0575f80fd5b5f80604083850312156200364a575f80fd5b620036558362003602565b91506020830135620036678162003616565b809150509250929050565b8015158114620019f0575f80fd5b5f8083601f84011262003691575f80fd5b50813567ffffffffffffffff811115620036a9575f80fd5b602083019150836020828501011115620036c1575f80fd5b9250929050565b5f805f805f60808688031215620036dd575f80fd5b620036e88662003602565b94506020860135620036fa8162003616565b935060408601356200370c8162003672565b9250606086013567ffffffffffffffff81111562003728575f80fd5b620037368882890162003680565b969995985093965092949392505050565b5f6020828403121562003758575f80fd5b5035919050565b5f6020828403121562003770575f80fd5b6200377b8262003602565b9392505050565b8061040081018310156200088c575f80fd5b5f805f805f805f805f805f6105208c8e031215620037b0575f80fd5b620037bc8d8d62003782565b9a50620037cd6104008d0162003602565b99506104208c013598506104408c01359750620037ee6104608d0162003602565b96506104808c0135620038018162003616565b9550620038126104a08d0162003602565b94506104c08c0135620038258162003616565b93506104e08c013592506105008c013567ffffffffffffffff8111156200384a575f80fd5b620038588e828f0162003680565b915080935050809150509295989b509295989b9093969950565b5f6020828403121562003883575f80fd5b81356200377b8162003616565b60ff81168114620019f0575f80fd5b5f805f805f805f60e0888a031215620038b6575f80fd5b8735620038c38162003890565b9650620038d36020890162003602565b95506040880135620038e58162003616565b9450620038f56060890162003602565b93506080880135620039078162003616565b9699959850939692959460a0840135945060c09093013592915050565b5f805f6060848603121562003937575f80fd5b620039428462003602565b92506020840135620039548162003616565b91506040840135620039668162003616565b809150509250925092565b5f805f805f805f60a0888a03121562003988575f80fd5b620039938862003602565b96506020880135620039a58162003616565b9550604088013567ffffffffffffffff80821115620039c2575f80fd5b620039d08b838c0162003680565b909750955060608a0135915080821115620039e9575f80fd5b50620039f88a828b0162003680565b909450925050608088013562003a0e8162003890565b8091505092959891949750929550565b5f805f805f805f60c0888a03121562003a35575f80fd5b62003a408862003602565b9650602088013562003a528162003616565b955060408801359450606088013562003a6b8162003616565b9350608088013562003a7d8162003672565b925060a088013567ffffffffffffffff81111562003a99575f80fd5b62003aa78a828b0162003680565b989b979a50959850939692959293505050565b5f805f80610460858703121562003acf575f80fd5b8435935062003ae2866020870162003782565b925062003af3610420860162003602565b939692955092936104400135925050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f61010060ff8c16835263ffffffff808c16602085015273ffffffffffffffffffffffffffffffffffffffff808c166040860152818b166060860152808a166080860152508760a08501528160c085015262003bab828501878962003b04565b925080851660e085015250509a9950505050505050505050565b818382375f9101908152919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5b8381101562003c1d57818101518382015260200162003c03565b50505f910152565b5f825162003c3881846020870162003c01565b9190910192915050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171562003c8c5762003c8c62003bd4565b604052919050565b5f67ffffffffffffffff82111562003cb05762003cb062003bd4565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f83011262003cec575f80fd5b813562003d0362003cfd8262003c94565b62003c42565b81815284602083860101111562003d18575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f6060848603121562003d47575f80fd5b833567ffffffffffffffff8082111562003d5f575f80fd5b62003d6d8783880162003cdc565b9450602086013591508082111562003d83575f80fd5b5062003d928682870162003cdc565b9250506040840135620039668162003890565b5f815180845262003dbe81602086016020860162003c01565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606081525f62003e04606083018662003da5565b828103602084015262003e18818662003da5565b91505060ff83166040830152949350505050565b63ffffffff861681525f73ffffffffffffffffffffffffffffffffffffffff8087166020840152808616604084015250608060608301526200350260808301848662003b04565b73ffffffffffffffffffffffffffffffffffffffff8516815263ffffffff84166020820152606060408201525f62003eb060608301848662003b04565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003f475762003f4762003ee7565b5060010190565b606081525f62003f6360608301878962003b04565b828103602084015262003f7881868862003b04565b91505060ff831660408301529695505050505050565b5f835162003fa181846020880162003c01565b83519083019062003fb781836020880162003c01565b01949350505050565b600181815b808511156200401f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562004003576200400362003ee7565b808516156200401157918102915b93841c939080029062003fc5565b509250929050565b5f8262004037575060016200088c565b816200404557505f6200088c565b81600181146200405e5760028114620040695762004089565b60019150506200088c565b60ff8411156200407d576200407d62003ee7565b50506001821b6200088c565b5060208310610133831016604e8410600b8410161715620040ae575081810a6200088c565b620040ba838362003fc0565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115620040ef57620040ef62003ee7565b029392505050565b5f6200377b838362004027565b818103818111156200088c576200088c62003ee7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b5f6020828403121562004158575f80fd5b5051919050565b5f61010060ff8b16835263ffffffff808b16602085015273ffffffffffffffffffffffffffffffffffffffff808b166040860152818a1660608601528089166080860152508660a08501528160c0850152620041be8285018762003da5565b925080851660e085015250509998505050505050505050565b5f60208284031215620041e8575f80fd5b81516200377b8162003672565b5f808585111562004204575f80fd5b8386111562004211575f80fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156200425f5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a0312156200427e575f80fd5b87356200428b8162003616565b965060208801356200429d8162003616565b955060408801359450606088013593506080880135620039078162003890565b5f805f805f805f80610100898b031215620042d6575f80fd5b8835620042e38162003616565b97506020890135620042f58162003616565b965060408901359550606089013594506080890135620043158162003672565b935060a0890135620043278162003890565b979a969950949793969295929450505060c08201359160e0013590565b5f6020828403121562004355575f80fd5b81516200377b8162003890565b5f6020828403121562004373575f80fd5b815167ffffffffffffffff8111156200438a575f80fd5b8201601f810184136200439b575f80fd5b8051620043ac62003cfd8262003c94565b818152856020838501011115620043c1575f80fd5b620043d482602083016020860162003c01565b95945050505050565b602081525f6200377b602083018462003da556fe61010060405234801562000011575f80fd5b5060405162001b0d38038062001b0d833981016040819052620000349162000282565b828260036200004483826200038d565b5060046200005382826200038d565b50503360c0525060ff811660e05246608081905262000072906200007f565b60a0525062000455915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ab6200012c565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013d9062000301565b80601f01602080910402602001604051908101604052809291908181526020018280546200016b9062000301565b8015620001ba5780601f106200019057610100808354040283529160200191620001ba565b820191905f5260205f20905b8154815290600101906020018083116200019c57829003601f168201915b5050505050905090565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112620001e8575f80fd5b81516001600160401b0380821115620002055762000205620001c4565b604051601f8301601f19908116603f01168101908282118183101715620002305762000230620001c4565b816040528381526020925086838588010111156200024c575f80fd5b5f91505b838210156200026f578582018301518183018401529082019062000250565b5f93810190920192909252949350505050565b5f805f6060848603121562000295575f80fd5b83516001600160401b0380821115620002ac575f80fd5b620002ba87838801620001d8565b94506020860151915080821115620002d0575f80fd5b50620002df86828701620001d8565b925050604084015160ff81168114620002f6575f80fd5b809150509250925092565b600181811c908216806200031657607f821691505b6020821081036200033557634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000388575f81815260208120601f850160051c81016020861015620003635750805b601f850160051c820191505b8181101562000384578281556001016200036f565b5050505b505050565b81516001600160401b03811115620003a957620003a9620001c4565b620003c181620003ba845462000301565b846200033b565b602080601f831160018114620003f7575f8415620003df5750858301515b5f19600386901b1c1916600185901b17855562000384565b5f85815260208120601f198616915b82811015620004275788860151825594840194600190910190840162000406565b50858210156200044557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161166f6200049e5f395f61022d01525f81816102fb015281816105ad015261069401525f61052801525f818161036d01526104f2015261166f5ff3fe608060405234801561000f575f80fd5b506004361061016e575f3560e01c806370a08231116100d2578063a457c2d711610088578063d505accf11610063578063d505accf1461038f578063dd62ed3e146103a2578063ffa1ad74146103e7575f80fd5b8063a457c2d714610342578063a9059cbb14610355578063cd0d009614610368575f80fd5b806395d89b41116100b857806395d89b41146102db5780639dc29fac146102e3578063a3c573eb146102f6575f80fd5b806370a08231146102875780637ecebe00146102bc575f80fd5b806330adf81f116101275780633644e5151161010d5780633644e51514610257578063395093511461025f57806340c10f1914610272575f80fd5b806330adf81f146101ff578063313ce56714610226575f80fd5b806318160ddd1161015757806318160ddd146101b357806320606b70146101c557806323b872dd146101ec575f80fd5b806306fdde0314610172578063095ea7b314610190575b5f80fd5b61017a610423565b60405161018791906113c1565b60405180910390f35b6101a361019e366004611452565b6104b3565b6040519015158152602001610187565b6002545b604051908152602001610187565b6101b77f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101a36101fa36600461147a565b6104cc565b6101b77f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610187565b6101b76104ef565b6101a361026d366004611452565b61054a565b610285610280366004611452565b610595565b005b6101b76102953660046114b3565b73ffffffffffffffffffffffffffffffffffffffff165f9081526020819052604090205490565b6101b76102ca3660046114b3565b60056020525f908152604090205481565b61017a61066d565b6102856102f1366004611452565b61067c565b61031d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610187565b6101a3610350366004611452565b61074b565b6101a3610363366004611452565b61081b565b6101b77f000000000000000000000000000000000000000000000000000000000000000081565b61028561039d3660046114d3565b610828565b6101b76103b0366004611540565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260016020908152604080832093909416825291909152205490565b61017a6040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043290611571565b80601f016020809104026020016040519081016040528092919081815260200182805461045e90611571565b80156104a95780601f10610480576101008083540402835291602001916104a9565b820191905f5260205f20905b81548152906001019060200180831161048c57829003601f168201915b5050505050905090565b5f336104c0818585610b59565b60019150505b92915050565b5f336104d9858285610d0c565b6104e4858585610de2565b506001949350505050565b5f7f00000000000000000000000000000000000000000000000000000000000000004614610525576105204661104f565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104c090829086906105909087906115ef565b610b59565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461065f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b6106698282611116565b5050565b60606004805461043290611571565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610741576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610656565b6106698282611207565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561080e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610656565b6104e48286868403610b59565b5f336104c0818585610de2565b834211156108b7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff87165f90815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a91908661091083611602565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f61097a6104ef565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f80855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a3b573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ab657508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610656565b610b4d8a8a8a610b59565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610c9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381165f908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610ddc5781811015610dcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610656565b610ddc8484848403610b59565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610e85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610f28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f9081526020819052604090205481811015610fdd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610ddc565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611079610423565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff8216611193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610656565b8060025f8282546111a491906115ef565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff82165f908152602081905260409020548181101561135f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610cff565b5f6020808352835180828501525f5b818110156113ec578581018301518582016040015282016113d0565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461144d575f80fd5b919050565b5f8060408385031215611463575f80fd5b61146c8361142a565b946020939093013593505050565b5f805f6060848603121561148c575f80fd5b6114958461142a565b92506114a36020850161142a565b9150604084013590509250925092565b5f602082840312156114c3575f80fd5b6114cc8261142a565b9392505050565b5f805f805f805f60e0888a0312156114e9575f80fd5b6114f28861142a565b96506115006020890161142a565b95506040880135945060608801359350608088013560ff81168114611523575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611551575f80fd5b61155a8361142a565b91506115686020840161142a565b90509250929050565b600181811c9082168061158557607f821691505b6020821081036115bc577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156104c6576104c66115c2565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611632576116326115c2565b506001019056fea2646970667358221220a04a4613834006222ac539b942dfe3284c1163f5082f3bafb302007d825cd7ff64736f6c63430008140033a26469706673582212203eb4f60eaf973a04143dc808095d0bc352640e98fe76a4e0bfc37380215b023f64736f6c63430008140033", + "deployedBytecode": "0x608060405260043610620001df575f3560e01c8063715018a61162000106578063bab161bf116200009e578063dbc16976116200006a578063dbc169761462000704578063ee25560b146200071b578063f2fde38b146200074a578063fb570834146200076e575f80fd5b8063bab161bf1462000642578063be5831c7146200067b578063cd58657914620006b6578063d02103ca14620006cd575f80fd5b80638da5cb5b11620000de5780638da5cb5b146200059857806391e57e2d14620005c45780639e34070f14620005db578063aaa13cc2146200061e575f80fd5b8063715018a6146200052557806379e2cf97146200053c57806381b1c1741462000553575f80fd5b80632d2c9d94116200017a57806334ac9cf2116200015257806334ac9cf214620003ca5780633ae0504714620003f85780633e197043146200040f578063647c576c1462000501575f80fd5b80632d2c9d9414620002f95780632dfdf0b5146200031d578063318aee3d1462000343575f80fd5b8063240ff37811620001ba578063240ff37814620002765780632b5e42e7146200028d5780632c3f58cd14620002b15780632cffd02e14620002d5575f80fd5b806315064c9614620001e35780632072f6c5146200021357806322e95f2c146200022c575b5f80fd5b348015620001ef575f80fd5b50606854620001fe9060ff1681565b60405190151581526020015b60405180910390f35b3480156200021f575f80fd5b506200022a62000792565b005b34801562000238575f80fd5b50620002506200024a36600462003638565b620007f0565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016200020a565b6200022a62000287366004620036c8565b62000892565b34801562000299575f80fd5b506200022a620002ab36600462003747565b62000ab9565b348015620002bd575f80fd5b506200022a620002cf3660046200375f565b62000ac8565b348015620002e1575f80fd5b506200022a620002f336600462003794565b62000b0e565b34801562000305575f80fd5b506200022a6200031736600462003794565b62001093565b34801562000329575f80fd5b506200033460535481565b6040519081526020016200020a565b3480156200034f575f80fd5b50620003986200036136600462003872565b606b6020525f908152604090205463ffffffff811690640100000000900473ffffffffffffffffffffffffffffffffffffffff1682565b6040805163ffffffff909316835273ffffffffffffffffffffffffffffffffffffffff9091166020830152016200020a565b348015620003d6575f80fd5b50606c54620002509073ffffffffffffffffffffffffffffffffffffffff1681565b34801562000404575f80fd5b506200033462001293565b3480156200041b575f80fd5b50620003346200042d3660046200389f565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b3480156200050d575f80fd5b506200022a6200051f36600462003924565b62001378565b34801562000531575f80fd5b506200022a620015cd565b34801562000548575f80fd5b506200022a620015e2565b3480156200055f575f80fd5b50620002506200057136600462003747565b606a6020525f908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b348015620005a4575f80fd5b50609f5473ffffffffffffffffffffffffffffffffffffffff1662000250565b348015620005d0575f80fd5b506200033460d15481565b348015620005e7575f80fd5b50620001fe620005f936600462003747565b600881901c5f90815260696020526040902054600160ff9092169190911b9081161490565b3480156200062a575f80fd5b50620002506200063c36600462003971565b6200161c565b3480156200064e575f80fd5b506068546200066590610100900463ffffffff1681565b60405163ffffffff90911681526020016200020a565b34801562000687575f80fd5b506068546200066590790100000000000000000000000000000000000000000000000000900463ffffffff1681565b6200022a620006c736600462003a1e565b62001806565b348015620006d9575f80fd5b50606854620002509065010000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b34801562000710575f80fd5b506200022a620018da565b34801562000727575f80fd5b50620003346200073936600462003747565b60696020525f908152604090205481565b34801562000756575f80fd5b506200022a6200076836600462003872565b62001936565b3480156200077a575f80fd5b50620001fe6200078c36600462003aba565b620019f3565b606c5473ffffffffffffffffffffffffffffffffffffffff163314620007e4576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620007ee62001adb565b565b6040805160e084901b7fffffffff0000000000000000000000000000000000000000000000000000000016602080830191909152606084901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602483015282516018818403018152603890920183528151918101919091205f908152606a909152205473ffffffffffffffffffffffffffffffffffffffff165b92915050565b60685460ff1615620008d0576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff868116610100909204161480620008f65750600263ffffffff861610155b156200092e576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338888348888605354604051620009849998979695949392919062003b4b565b60405180910390a162000aa162000a9b6001606860019054906101000a900463ffffffff16338989348989604051620009bf92919062003bc5565b60405180910390206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b62001b6e565b821562000ab25762000ab262001c82565b5050505050565b62000ac362001d52565b60d155565b62000ad262001d52565b6068805463ffffffff909216610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff909216919091179055565b60685460ff161562000b4c576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62000b628b8b8b8b8b8b8b8b8b8b8b5f62001dd5565b73ffffffffffffffffffffffffffffffffffffffff861662000c3a57604080515f8082526020820190925273ffffffffffffffffffffffffffffffffffffffff861690859060405162000bb6919062003c25565b5f6040518083038185875af1925050503d805f811462000bf2576040519150601f19603f3d011682016040523d82523d5f602084013e62000bf7565b606091505b505090508062000c33576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506200101b565b60685463ffffffff61010090910481169088160362000c7c5762000c7673ffffffffffffffffffffffffffffffffffffffff8716858562001fc0565b6200101b565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f90603801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301205f818152606a90935291205490915073ffffffffffffffffffffffffffffffffffffffff168062000f92575f808062000d4e8688018862003d34565b9250925092505f8584848460405162000d6790620035f4565b62000d759392919062003df0565b8190604051809103905ff590508015801562000d93573d5f803e3d5ffd5b506040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8c81166004830152602482018c9052919250908216906340c10f19906044015f604051808303815f87803b15801562000e06575f80fd5b505af115801562000e19573d5f803e3d5ffd5b5050505080606a5f8881526020019081526020015f205f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180604001604052808e63ffffffff1681526020018d73ffffffffffffffffffffffffffffffffffffffff16815250606b5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398d8d838b8b60405162000f8095949392919062003e2c565b60405180910390a15050505062001018565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801562001000575f80fd5b505af115801562001013573d5f803e3d5ffd5b505050505b50505b6040805163ffffffff8c811682528916602082015273ffffffffffffffffffffffffffffffffffffffff88811682840152861660608201526080810185905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a15050505050505050505050565b60685460ff1615620010d1576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620010e88b8b8b8b8b8b8b8b8b8b8b600162001dd5565b5f8473ffffffffffffffffffffffffffffffffffffffff1684888a86866040516024016200111a949392919062003e73565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f1806b5f200000000000000000000000000000000000000000000000000000000179052516200119d919062003c25565b5f6040518083038185875af1925050503d805f8114620011d9576040519150601f19603f3d011682016040523d82523d5f602084013e620011de565b606091505b50509050806200121a576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805163ffffffff8d811682528a16602082015273ffffffffffffffffffffffffffffffffffffffff89811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b6053545f90819081805b60208110156200136f578083901c600116600103620013005760338160208110620012cc57620012cc62003eba565b015460408051602081019290925281018590526060016040516020818303038152906040528051906020012093506200132d565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080620013669062003f14565b9150506200129d565b50919392505050565b5f54610100900460ff16158080156200139757505f54600160ff909116105b80620013b25750303b158015620013b257505f5460ff166001145b62001444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015620014a1575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8716027fffffffffffffff0000000000000000000000000000000000000000ffffffffff16176501000000000073ffffffffffffffffffffffffffffffffffffffff8681169190910291909117909155606c80547fffffffffffffffffffffffff0000000000000000000000000000000000000000169184169190911790556703782dace9d9000060d1556200156462002096565b8015620015c7575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050565b620015d762001d52565b620007ee5f62002134565b605354606854790100000000000000000000000000000000000000000000000000900463ffffffff161015620007ee57620007ee62001c82565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b1660208201527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606088901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180602001620016b090620035f4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f909101166040819052620016fb908d908d908d908d908d9060200162003f4e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905262001739929160200162003f8e565b60405160208183030381529060405280519060200120604051602001620017c294939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830152603582015260550190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101209a9950505050505050505050565b60d154341115620018c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604760248201527f506f6c79676f6e5a6b45564d4272696467653a3a62726964676541737365743a60448201527f2043616e6e6f7420627269646765206d6f7265207468616e206d61784574686560648201527f7242726964676500000000000000000000000000000000000000000000000000608482015260a4016200143b565b620018d187878787878787620021aa565b50505050505050565b606c5473ffffffffffffffffffffffffffffffffffffffff1633146200192c576040517fe2e8106b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620007ee620026f3565b6200194062001d52565b73ffffffffffffffffffffffffffffffffffffffff8116620019e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016200143b565b620019f08162002134565b50565b5f84815b602081101562001acd57600163ffffffff8616821c8116900362001a695785816020811062001a2a5762001a2a62003eba565b60200201358260405160200162001a4b929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001ab8565b8186826020811062001a7f5762001a7f62003eba565b602002013560405160200162001a9f929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001ac48162003f14565b915050620019f7565b50821490505b949350505050565b60685460ff161562001b19576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b80600162001b7f60206002620040f7565b62001b8b919062004104565b6053541062001bc6576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f815462001bd79062003f14565b918290555090505f5b602081101562001c72578082901c60011660010362001c1857826033826020811062001c105762001c1062003eba565b015550505050565b6033816020811062001c2e5762001c2e62003eba565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808062001c699062003f14565b91505062001be0565b5062001c7d6200411a565b505050565b6053546068805463ffffffff909216790100000000000000000000000000000000000000000000000000027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179081905573ffffffffffffffffffffffffffffffffffffffff65010000000000909104166333d6247d62001d0862001293565b6040518263ffffffff1660e01b815260040162001d2791815260200190565b5f604051808303815f87803b15801562001d3f575f80fd5b505af1158015620015c7573d5f803e3d5ffd5b609f5473ffffffffffffffffffffffffffffffffffffffff163314620007ee576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016200143b565b62001de68b63ffffffff1662002782565b6068546040805160208082018e90528183018d9052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f9165010000000000900473ffffffffffffffffffffffffffffffffffffffff169063257b3632906084016020604051808303815f875af115801562001e85573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001eab919062004147565b9050805f0362001ee6576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60685463ffffffff888116610100909204161462001f30576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068545f90610100900463ffffffff1662001f4d57508962001f50565b508a5b62001f7962001f70848c8c8c8c8c8c8c604051620009bf92919062003bc5565b8f8f84620019f3565b62001fb0576040517fe0417cec00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905262001c7d9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152620027e6565b5f54610100900460ff166200212e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016200143b565b620007ee335b609f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60685460ff1615620021e8576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620021f2620028f8565b60685463ffffffff888116610100909204161480620022185750600263ffffffff881610155b1562002250576040517f0595ea2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8060608773ffffffffffffffffffffffffffffffffffffffff8816620022b457883414620022ab576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f9250620025a1565b3415620022ed576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8089165f908152606b602090815260409182902082518084019093525463ffffffff8116835264010000000090049092169181018290529015620023d6576040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018b905273ffffffffffffffffffffffffffffffffffffffff8a1690639dc29fac906044015f604051808303815f87803b158015620023ac575f80fd5b505af1158015620023bf573d5f803e3d5ffd5b5050505080602001519450805f015193506200259f565b8515620023eb57620023eb898b89896200296d565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8b16906370a0823190602401602060405180830381865afa15801562002456573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200247c919062004147565b9050620024a273ffffffffffffffffffffffffffffffffffffffff8b1633308e62002e80565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f9073ffffffffffffffffffffffffffffffffffffffff8c16906370a0823190602401602060405180830381865afa1580156200250d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062002533919062004147565b905062002541828262004104565b6068548c9850610100900463ffffffff1696509350620025618762002ee0565b6200256c8c62002ff4565b620025778d620030fd565b6040516020016200258b9392919062003df0565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e8688605354604051620025e29897969594939291906200415f565b60405180910390a1620026d462000a9b5f85878f8f8789805190602001206040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201527fffffffff0000000000000000000000000000000000000000000000000000000060e088811b821660218401527fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b8615620026e557620026e562001c82565b50505050620018d160018055565b60685460ff1662002730576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606880547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b600881901c5f8181526069602052604081208054600160ff861690811b9182189283905592909190818316900362000ab2576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f62002849826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16620031f59092919063ffffffff16565b80519091501562001c7d57808060200190518101906200286a9190620041d7565b62001c7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016200143b565b60026001540362002966576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016200143b565b6002600155565b5f6200297d6004828486620041f5565b62002988916200421e565b90507f2afa5331000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082160162002c02575f808080808080620029ea896004818d620041f5565b810190620029f9919062004267565b96509650965096509650965096503373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462002a6d576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8616301462002abd576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8a851462002af7576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff89811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169162002bb2919062003c25565b5f604051808303815f865af19150503d805f811462002bed576040519150601f19603f3d011682016040523d82523d5f602084013e62002bf2565b606091505b5050505050505050505062000ab2565b7fffffffff0000000000000000000000000000000000000000000000000000000081167f8fcbaf0c000000000000000000000000000000000000000000000000000000001462002c7e576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f8080808080808062002c958a6004818e620041f5565b81019062002ca49190620042bd565b975097509750975097509750975097503373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161462002d1a576040517f912ecce700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8716301462002d6a576040517f750643af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8fcbaf0c000000000000000000000000000000000000000000000000000000001790529151918f169162002e2e919062003c25565b5f604051808303815f865af19150503d805f811462002e69576040519150601f19603f3d011682016040523d82523d5f602084013e62002e6e565b606091505b50505050505050505050505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff80851660248301528316604482015260648101829052620015c79085907f23b872dd000000000000000000000000000000000000000000000000000000009060840162002013565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff86169162002f63919062003c25565b5f60405180830381855afa9150503d805f811462002f9d576040519150601f19603f3d011682016040523d82523d5f602084013e62002fa2565b606091505b50915091508162002fe9576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525062001ad3565b62001ad38162003205565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f91829173ffffffffffffffffffffffffffffffffffffffff86169162003077919062003c25565b5f60405180830381855afa9150503d805f8114620030b1576040519150601f19603f3d011682016040523d82523d5f602084013e620030b6565b606091505b50915091508162002fe9576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525062001ad3565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f918291829173ffffffffffffffffffffffffffffffffffffffff8616916200317f919062003c25565b5f60405180830381855afa9150503d805f8114620031b9576040519150601f19603f3d011682016040523d82523d5f602084013e620031be565b606091505b5091509150818015620031d2575080516020145b620031df57601262001ad3565b8080602001905181019062001ad3919062004344565b606062001ad384845f85620033f0565b606060408251106200322757818060200190518101906200088c919062004362565b8151602003620033b2575f5b6020811080156200327e575082818151811062003254576200325462003eba565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15620032995780620032908162003f14565b91505062003233565b805f03620032dc57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115620032f957620032f962003bd4565b6040519080825280601f01601f19166020018201604052801562003324576020820181803683370190505b5090505f5b82811015620033aa5784818151811062003347576200334762003eba565b602001015160f81c60f81b82828151811062003367576200336762003eba565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080620033a18162003f14565b91505062003329565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b60608247101562003484576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016200143b565b5f808673ffffffffffffffffffffffffffffffffffffffff168587604051620034ae919062003c25565b5f6040518083038185875af1925050503d805f8114620034ea576040519150601f19603f3d011682016040523d82523d5f602084013e620034ef565b606091505b509150915062003502878383876200350d565b979650505050505050565b60608315620035a75782515f036200359f5773ffffffffffffffffffffffffffffffffffffffff85163b6200359f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016200143b565b508162001ad3565b62001ad38383815115620035be5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200143b9190620043dd565b611b0d80620043f283390190565b803563ffffffff81168114620033eb575f80fd5b73ffffffffffffffffffffffffffffffffffffffff81168114620019f0575f80fd5b5f80604083850312156200364a575f80fd5b620036558362003602565b91506020830135620036678162003616565b809150509250929050565b8015158114620019f0575f80fd5b5f8083601f84011262003691575f80fd5b50813567ffffffffffffffff811115620036a9575f80fd5b602083019150836020828501011115620036c1575f80fd5b9250929050565b5f805f805f60808688031215620036dd575f80fd5b620036e88662003602565b94506020860135620036fa8162003616565b935060408601356200370c8162003672565b9250606086013567ffffffffffffffff81111562003728575f80fd5b620037368882890162003680565b969995985093965092949392505050565b5f6020828403121562003758575f80fd5b5035919050565b5f6020828403121562003770575f80fd5b6200377b8262003602565b9392505050565b8061040081018310156200088c575f80fd5b5f805f805f805f805f805f6105208c8e031215620037b0575f80fd5b620037bc8d8d62003782565b9a50620037cd6104008d0162003602565b99506104208c013598506104408c01359750620037ee6104608d0162003602565b96506104808c0135620038018162003616565b9550620038126104a08d0162003602565b94506104c08c0135620038258162003616565b93506104e08c013592506105008c013567ffffffffffffffff8111156200384a575f80fd5b620038588e828f0162003680565b915080935050809150509295989b509295989b9093969950565b5f6020828403121562003883575f80fd5b81356200377b8162003616565b60ff81168114620019f0575f80fd5b5f805f805f805f60e0888a031215620038b6575f80fd5b8735620038c38162003890565b9650620038d36020890162003602565b95506040880135620038e58162003616565b9450620038f56060890162003602565b93506080880135620039078162003616565b9699959850939692959460a0840135945060c09093013592915050565b5f805f6060848603121562003937575f80fd5b620039428462003602565b92506020840135620039548162003616565b91506040840135620039668162003616565b809150509250925092565b5f805f805f805f60a0888a03121562003988575f80fd5b620039938862003602565b96506020880135620039a58162003616565b9550604088013567ffffffffffffffff80821115620039c2575f80fd5b620039d08b838c0162003680565b909750955060608a0135915080821115620039e9575f80fd5b50620039f88a828b0162003680565b909450925050608088013562003a0e8162003890565b8091505092959891949750929550565b5f805f805f805f60c0888a03121562003a35575f80fd5b62003a408862003602565b9650602088013562003a528162003616565b955060408801359450606088013562003a6b8162003616565b9350608088013562003a7d8162003672565b925060a088013567ffffffffffffffff81111562003a99575f80fd5b62003aa78a828b0162003680565b989b979a50959850939692959293505050565b5f805f80610460858703121562003acf575f80fd5b8435935062003ae2866020870162003782565b925062003af3610420860162003602565b939692955092936104400135925050565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f61010060ff8c16835263ffffffff808c16602085015273ffffffffffffffffffffffffffffffffffffffff808c166040860152818b166060860152808a166080860152508760a08501528160c085015262003bab828501878962003b04565b925080851660e085015250509a9950505050505050505050565b818382375f9101908152919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f5b8381101562003c1d57818101518382015260200162003c03565b50505f910152565b5f825162003c3881846020870162003c01565b9190910192915050565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171562003c8c5762003c8c62003bd4565b604052919050565b5f67ffffffffffffffff82111562003cb05762003cb062003bd4565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f83011262003cec575f80fd5b813562003d0362003cfd8262003c94565b62003c42565b81815284602083860101111562003d18575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f6060848603121562003d47575f80fd5b833567ffffffffffffffff8082111562003d5f575f80fd5b62003d6d8783880162003cdc565b9450602086013591508082111562003d83575f80fd5b5062003d928682870162003cdc565b9250506040840135620039668162003890565b5f815180845262003dbe81602086016020860162003c01565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b606081525f62003e04606083018662003da5565b828103602084015262003e18818662003da5565b91505060ff83166040830152949350505050565b63ffffffff861681525f73ffffffffffffffffffffffffffffffffffffffff8087166020840152808616604084015250608060608301526200350260808301848662003b04565b73ffffffffffffffffffffffffffffffffffffffff8516815263ffffffff84166020820152606060408201525f62003eb060608301848662003b04565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820362003f475762003f4762003ee7565b5060010190565b606081525f62003f6360608301878962003b04565b828103602084015262003f7881868862003b04565b91505060ff831660408301529695505050505050565b5f835162003fa181846020880162003c01565b83519083019062003fb781836020880162003c01565b01949350505050565b600181815b808511156200401f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111562004003576200400362003ee7565b808516156200401157918102915b93841c939080029062003fc5565b509250929050565b5f8262004037575060016200088c565b816200404557505f6200088c565b81600181146200405e5760028114620040695762004089565b60019150506200088c565b60ff8411156200407d576200407d62003ee7565b50506001821b6200088c565b5060208310610133831016604e8410600b8410161715620040ae575081810a6200088c565b620040ba838362003fc0565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115620040ef57620040ef62003ee7565b029392505050565b5f6200377b838362004027565b818103818111156200088c576200088c62003ee7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffd5b5f6020828403121562004158575f80fd5b5051919050565b5f61010060ff8b16835263ffffffff808b16602085015273ffffffffffffffffffffffffffffffffffffffff808b166040860152818a1660608601528089166080860152508660a08501528160c0850152620041be8285018762003da5565b925080851660e085015250509998505050505050505050565b5f60208284031215620041e8575f80fd5b81516200377b8162003672565b5f808585111562004204575f80fd5b8386111562004211575f80fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156200425f5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a0312156200427e575f80fd5b87356200428b8162003616565b965060208801356200429d8162003616565b955060408801359450606088013593506080880135620039078162003890565b5f805f805f805f80610100898b031215620042d6575f80fd5b8835620042e38162003616565b97506020890135620042f58162003616565b965060408901359550606089013594506080890135620043158162003672565b935060a0890135620043278162003890565b979a969950949793969295929450505060c08201359160e0013590565b5f6020828403121562004355575f80fd5b81516200377b8162003890565b5f6020828403121562004373575f80fd5b815167ffffffffffffffff8111156200438a575f80fd5b8201601f810184136200439b575f80fd5b8051620043ac62003cfd8262003c94565b818152856020838501011115620043c1575f80fd5b620043d482602083016020860162003c01565b95945050505050565b602081525f6200377b602083018462003da556fe61010060405234801562000011575f80fd5b5060405162001b0d38038062001b0d833981016040819052620000349162000282565b828260036200004483826200038d565b5060046200005382826200038d565b50503360c0525060ff811660e05246608081905262000072906200007f565b60a0525062000455915050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ab6200012c565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013d9062000301565b80601f01602080910402602001604051908101604052809291908181526020018280546200016b9062000301565b8015620001ba5780601f106200019057610100808354040283529160200191620001ba565b820191905f5260205f20905b8154815290600101906020018083116200019c57829003601f168201915b5050505050905090565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112620001e8575f80fd5b81516001600160401b0380821115620002055762000205620001c4565b604051601f8301601f19908116603f01168101908282118183101715620002305762000230620001c4565b816040528381526020925086838588010111156200024c575f80fd5b5f91505b838210156200026f578582018301518183018401529082019062000250565b5f93810190920192909252949350505050565b5f805f6060848603121562000295575f80fd5b83516001600160401b0380821115620002ac575f80fd5b620002ba87838801620001d8565b94506020860151915080821115620002d0575f80fd5b50620002df86828701620001d8565b925050604084015160ff81168114620002f6575f80fd5b809150509250925092565b600181811c908216806200031657607f821691505b6020821081036200033557634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000388575f81815260208120601f850160051c81016020861015620003635750805b601f850160051c820191505b8181101562000384578281556001016200036f565b5050505b505050565b81516001600160401b03811115620003a957620003a9620001c4565b620003c181620003ba845462000301565b846200033b565b602080601f831160018114620003f7575f8415620003df5750858301515b5f19600386901b1c1916600185901b17855562000384565b5f85815260208120601f198616915b82811015620004275788860151825594840194600190910190840162000406565b50858210156200044557878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161166f6200049e5f395f61022d01525f81816102fb015281816105ad015261069401525f61052801525f818161036d01526104f2015261166f5ff3fe608060405234801561000f575f80fd5b506004361061016e575f3560e01c806370a08231116100d2578063a457c2d711610088578063d505accf11610063578063d505accf1461038f578063dd62ed3e146103a2578063ffa1ad74146103e7575f80fd5b8063a457c2d714610342578063a9059cbb14610355578063cd0d009614610368575f80fd5b806395d89b41116100b857806395d89b41146102db5780639dc29fac146102e3578063a3c573eb146102f6575f80fd5b806370a08231146102875780637ecebe00146102bc575f80fd5b806330adf81f116101275780633644e5151161010d5780633644e51514610257578063395093511461025f57806340c10f1914610272575f80fd5b806330adf81f146101ff578063313ce56714610226575f80fd5b806318160ddd1161015757806318160ddd146101b357806320606b70146101c557806323b872dd146101ec575f80fd5b806306fdde0314610172578063095ea7b314610190575b5f80fd5b61017a610423565b60405161018791906113c1565b60405180910390f35b6101a361019e366004611452565b6104b3565b6040519015158152602001610187565b6002545b604051908152602001610187565b6101b77f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101a36101fa36600461147a565b6104cc565b6101b77f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610187565b6101b76104ef565b6101a361026d366004611452565b61054a565b610285610280366004611452565b610595565b005b6101b76102953660046114b3565b73ffffffffffffffffffffffffffffffffffffffff165f9081526020819052604090205490565b6101b76102ca3660046114b3565b60056020525f908152604090205481565b61017a61066d565b6102856102f1366004611452565b61067c565b61031d7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610187565b6101a3610350366004611452565b61074b565b6101a3610363366004611452565b61081b565b6101b77f000000000000000000000000000000000000000000000000000000000000000081565b61028561039d3660046114d3565b610828565b6101b76103b0366004611540565b73ffffffffffffffffffffffffffffffffffffffff9182165f90815260016020908152604080832093909416825291909152205490565b61017a6040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043290611571565b80601f016020809104026020016040519081016040528092919081815260200182805461045e90611571565b80156104a95780601f10610480576101008083540402835291602001916104a9565b820191905f5260205f20905b81548152906001019060200180831161048c57829003601f168201915b5050505050905090565b5f336104c0818585610b59565b60019150505b92915050565b5f336104d9858285610d0c565b6104e4858585610de2565b506001949350505050565b5f7f00000000000000000000000000000000000000000000000000000000000000004614610525576105204661104f565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104c090829086906105909087906115ef565b610b59565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461065f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b6106698282611116565b5050565b60606004805461043290611571565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610741576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610656565b6106698282611207565b335f81815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561080e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610656565b6104e48286868403610b59565b5f336104c0818585610de2565b834211156108b7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff87165f90815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a91908661091083611602565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090505f61097a6104ef565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f80855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a3b573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ab657508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610656565b610b4d8a8a8a610b59565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610bfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610c9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381165f908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610ddc5781811015610dcf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610656565b610ddc8484848403610b59565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610e85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8216610f28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f9081526020819052604090205481811015610fdd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff8481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610ddc565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611079610423565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff8216611193576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610656565b8060025f8282546111a491906115ef565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff82165f908152602081905260409020548181101561135f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610656565b73ffffffffffffffffffffffffffffffffffffffff83165f818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610cff565b5f6020808352835180828501525f5b818110156113ec578581018301518582016040015282016113d0565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461144d575f80fd5b919050565b5f8060408385031215611463575f80fd5b61146c8361142a565b946020939093013593505050565b5f805f6060848603121561148c575f80fd5b6114958461142a565b92506114a36020850161142a565b9150604084013590509250925092565b5f602082840312156114c3575f80fd5b6114cc8261142a565b9392505050565b5f805f805f805f60e0888a0312156114e9575f80fd5b6114f28861142a565b96506115006020890161142a565b95506040880135945060608801359350608088013560ff81168114611523575f80fd5b9699959850939692959460a0840135945060c09093013592915050565b5f8060408385031215611551575f80fd5b61155a8361142a565b91506115686020840161142a565b90509250929050565b600181811c9082168061158557607f821691505b6020821081036115bc577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b808201808211156104c6576104c66115c2565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611632576116326115c2565b506001019056fea2646970667358221220a04a4613834006222ac539b942dfe3284c1163f5082f3bafb302007d825cd7ff64736f6c63430008140033a26469706673582212203eb4f60eaf973a04143dc808095d0bc352640e98fe76a4e0bfc37380215b023f64736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMBridgeV2.json b/compiled-contracts/PolygonZkEVMBridgeV2.json index 0fac2b1db..bfb88f28b 100644 --- a/compiled-contracts/PolygonZkEVMBridgeV2.json +++ b/compiled-contracts/PolygonZkEVMBridgeV2.json @@ -1006,8 +1006,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801562000010575f80fd5b506200001b62000021565b620000e0565b5f54610100900460ff16156200008d5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff9081161015620000de575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b61591b80620000ee5f395ff3fe6080604052600436106101db575f3560e01c806383f24403116100fd578063ccaa2d1111610092578063ee25560b11610062578063ee25560b146105a9578063f5efcd79146105d4578063f811bff7146105f3578063fb57083414610612575f80fd5b8063ccaa2d111461053b578063cd5865791461055a578063d02103ca1461056d578063dbc1697614610595575f80fd5b8063bab161bf116100cd578063bab161bf146104b9578063be5831c7146104da578063c00f14ab146104fd578063cc4616321461051c575f80fd5b806383f244031461043d5780638ed7e3f21461045c578063aaa13cc21461047b578063b8b284d01461049a575f80fd5b80633cbc795b116101735780637843298b116101435780637843298b146103c257806379e2cf97146103e157806381b1c174146103f557806383c43a5514610429575f80fd5b80633cbc795b146103385780633e197043146103705780634b2f336d1461038f5780635ca1e165146103ae575f80fd5b806327aef4e8116101ae57806327aef4e81461026d5780632dfdf0b51461028e578063318aee3d146102b15780633c351e1014610319575f80fd5b806315064c96146101df5780632072f6c51461020d57806322e95f2c14610223578063240ff3781461025a575b5f80fd5b3480156101ea575f80fd5b506068546101f89060ff1681565b60405190151581526020015b60405180910390f35b348015610218575f80fd5b50610221610631565b005b34801561022e575f80fd5b5061024261023d366004612fb9565b610666565b6040516001600160a01b039091168152602001610204565b610221610268366004613040565b6106d0565b348015610278575f80fd5b50610281610759565b6040516102049190613102565b348015610299575f80fd5b506102a360535481565b604051908152602001610204565b3480156102bc575f80fd5b506102f56102cb36600461311b565b606b6020525f908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201610204565b348015610324575f80fd5b50606d54610242906001600160a01b031681565b348015610343575f80fd5b50606d5461035b90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610204565b34801561037b575f80fd5b506102a361038a366004613144565b6107e5565b34801561039a575f80fd5b50606f54610242906001600160a01b031681565b3480156103b9575f80fd5b506102a361088e565b3480156103cd575f80fd5b506102426103dc3660046131be565b61096a565b3480156103ec575f80fd5b50610221610993565b348015610400575f80fd5b5061024261040f366004613204565b606a6020525f90815260409020546001600160a01b031681565b348015610434575f80fd5b506102816109b4565b348015610448575f80fd5b506102a361045736600461322c565b6109d3565b348015610467575f80fd5b50606c54610242906001600160a01b031681565b348015610486575f80fd5b5061024261049536600461332d565b610aa8565b3480156104a5575f80fd5b506102216104b43660046133c3565b610be7565b3480156104c4575f80fd5b5060685461035b90610100900463ffffffff1681565b3480156104e5575f80fd5b5060685461035b90600160c81b900463ffffffff1681565b348015610508575f80fd5b5061028161051736600461311b565b610cc2565b348015610527575f80fd5b506101f8610536366004613441565b610d07565b348015610546575f80fd5b50610221610555366004613472565b610d8f565b610221610568366004613556565b6112c0565b348015610578575f80fd5b50606854610242906501000000000090046001600160a01b031681565b3480156105a0575f80fd5b5061022161172c565b3480156105b4575f80fd5b506102a36105c3366004613204565b60696020525f908152604090205481565b3480156105df575f80fd5b506102216105ee366004613472565b61175f565b3480156105fe575f80fd5b5061022161060d3660046135e6565b611a25565b34801561061d575f80fd5b506101f861062c366004613689565b611d40565b606c546001600160a01b0316331461065c57604051631736745960e31b815260040160405180910390fd5b610664611d57565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091205f908152606a90915220546001600160a01b03165b92915050565b60685460ff16156106f457604051630bc011ff60e21b815260040160405180910390fd5b341580159061070d5750606f546001600160a01b031615155b15610744576040517f6f625c4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610752858534868686611db2565b5050505050565b606e8054610766906136ce565b80601f0160208091040260200160405190810160405280929190818152602001828054610792906136ce565b80156107dd5780601f106107b4576101008083540402835291602001916107dd565b820191905f5260205f20905b8154815290600101906020018083116107c057829003601f168201915b505050505081565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b6053545f90819081805b6020811015610961578083901c6001166001036108f557603381602081106108c2576108c2613706565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610922565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806109599061372e565b915050610898565b50919392505050565b5f61098b848461097985611e7c565b61098286611f66565b61049587612047565b949350505050565b605354606854600160c81b900463ffffffff16101561066457610664612114565b60405180611ba00160405280611b668152602001613d80611b66913981565b5f83815b6020811015610a9f57600163ffffffff8516821c81169003610a4257848160208110610a0557610a05613706565b602002013582604051602001610a25929190918252602082015260400190565b604051602081830303815290604052805190602001209150610a8d565b81858260208110610a5557610a55613706565b6020020135604051602001610a74929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80610a978161372e565b9150506109d7565b50949350505050565b6040516001600160e01b031960e087901b1660208201526bffffffffffffffffffffffff19606086901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180611ba00160405280611b668152602001613d80611b669139898989604051602001610b3093929190613746565b60408051601f1981840301815290829052610b4e929160200161377e565b60405160208183030381529060405280519060200120604051602001610bc394939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60685460ff1615610c0b57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b0316610c4d576040517fdde3cda700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f54604051632770a7eb60e21b8152336004820152602481018690526001600160a01b0390911690639dc29fac906044015f604051808303815f87803b158015610c96575f80fd5b505af1158015610ca8573d5f803e3d5ffd5b50505050610cba868686868686611db2565b505050505050565b6060610ccd82611e7c565b610cd683611f66565b610cdf84612047565b604051602001610cf193929190613746565b6040516020818303038152906040529050919050565b6068545f908190610100900463ffffffff16158015610d2c575063ffffffff83166001145b15610d3e575063ffffffff8316610d66565b610d5364010000000063ffffffff85166137ac565b610d639063ffffffff86166137c3565b90505b600881901c5f90815260696020526040902054600160ff9092169190911b908116149392505050565b60685460ff1615610db357604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614610de3576040516302caf51760e11b815260040160405180910390fd5b610e168c8c8c8c8c610e115f8e8e8e8e8e8e8e604051610e049291906137d6565b60405180910390206107e5565b6121c2565b6001600160a01b038616610f6057606f546001600160a01b0316610efa575f6001600160a01b03851684825b6040519080825280601f01601f191660200182016040528015610e6c576020820181803683370190505b50604051610e7a91906137e5565b5f6040518083038185875af1925050503d805f8114610eb4576040519150601f19603f3d011682016040523d82523d5f602084013e610eb9565b606091505b5050905080610ef4576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611256565b606f546040516340c10f1960e01b81526001600160a01b03868116600483015260248201869052909116906340c10f19906044015f604051808303815f87803b158015610f45575f80fd5b505af1158015610f57573d5f803e3d5ffd5b50505050611256565b606d546001600160a01b038781169116148015610f8e5750606d5463ffffffff888116600160a01b90920416145b15610fa5575f6001600160a01b0385168482610e42565b60685463ffffffff610100909104811690881603610fd657610fd16001600160a01b0387168585612354565b611256565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201525f9060380160408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b0316806111f5575f6110808386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506123d592505050565b6040516340c10f1960e01b81526001600160a01b03898116600483015260248201899052919250908216906340c10f19906044015f604051808303815f87803b1580156110cb575f80fd5b505af11580156110dd573d5f803e3d5ffd5b5050505080606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a8388886040516111e7959493929190613828565b60405180910390a150611253565b6040516340c10f1960e01b81526001600160a01b038781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801561123c575f80fd5b505af115801561124e573d5f803e3d5ffd5b505050505b50505b604080518b815263ffffffff891660208201526001600160a01b0388811682840152861660608201526080810185905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a1505050505050505050505050565b60685460ff16156112e457604051630bc011ff60e21b815260040160405180910390fd5b6112ec612468565b60685463ffffffff61010090910481169088160361131d576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b03881661141957883414611369576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff16945090611396906136ce565b80601f01602080910402602001604051908101604052809291908181526020018280546113c2906136ce565b801561140d5780601f106113e45761010080835404028352916020019161140d565b820191905f5260205f20905b8154815290600101906020018083116113f057829003601f168201915b505050505091506116a3565b3415611451576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546001600160a01b03908116908916036114c757604051632770a7eb60e21b8152336004820152602481018a90526001600160a01b03891690639dc29fac906044015f604051808303815f87803b1580156114ac575f80fd5b505af11580156114be573d5f803e3d5ffd5b505050506116a3565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901561157957604051632770a7eb60e21b8152336004820152602481018b90526001600160a01b038a1690639dc29fac906044015f604051808303815f87803b158015611551575f80fd5b505af1158015611563573d5f803e3d5ffd5b5050505080602001519450805f01519350611696565b851561158b5761158b898b89896124c1565b6040516370a0823160e01b81523060048201525f906001600160a01b038b16906370a0823190602401602060405180830381865afa1580156115cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f39190613860565b905061160a6001600160a01b038b1633308e612860565b6040516370a0823160e01b81523060048201525f906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561164e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116729190613860565b905061167e8282613877565b6068548c9850610100900463ffffffff169650935050505b61169f89610cc2565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e86886053546040516116e298979695949392919061388a565b60405180910390a16117086117035f85878f8f8789805190602001206107e5565b6128b1565b861561171657611716612114565b5050505061172360018055565b50505050505050565b606c546001600160a01b0316331461175757604051631736745960e31b815260040160405180910390fd5b6106646129b2565b60685460ff161561178357604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff86811661010090920416146117b3576040516302caf51760e11b815260040160405180910390fd5b6117d58c8c8c8c8c610e1160018e8e8e8e8e8e8e604051610e049291906137d6565b606f545f906001600160a01b031661188857846001600160a01b031684888a868660405160240161180994939291906138f3565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161183e91906137e5565b5f6040518083038185875af1925050503d805f8114611878576040519150601f19603f3d011682016040523d82523d5f602084013e61187d565b606091505b505080915050611983565b606f546040516340c10f1960e01b81526001600160a01b03878116600483015260248201879052909116906340c10f19906044015f604051808303815f87803b1580156118d3575f80fd5b505af11580156118e5573d5f803e3d5ffd5b50505050846001600160a01b03168789858560405160240161190a94939291906138f3565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161193f91906137e5565b5f604051808303815f865af19150503d805f8114611978576040519150601f19603f3d011682016040523d82523d5f602084013e61197d565b606091505b50909150505b806119ba576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518c815263ffffffff8a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a150505050505050505050505050565b5f54610100900460ff1615808015611a4357505f54600160ff909116105b80611a5c5750303b158015611a5c57505f5460ff166001145b611ad35760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805460ff191660011790558015611af4575f805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8a16027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038781169190910291909117909155606c805473ffffffffffffffffffffffffffffffffffffffff19168583161790558616611bcf5763ffffffff851615611bca576040517f1a874c1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ceb565b606d805463ffffffff8716600160a01b027fffffffffffffffff0000000000000000000000000000000000000000000000009091166001600160a01b03891617179055606e611c1e8382613970565b50611cbd5f801b6012604051602001611ca991906060808252600d908201527f5772617070656420457468657200000000000000000000000000000000000000608082015260a0602082018190526004908201527f574554480000000000000000000000000000000000000000000000000000000060c082015260ff91909116604082015260e00190565b6040516020818303038152906040526123d5565b606f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03929092169190911790555b611cf3612a22565b8015611723575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b5f81611d4d8686866109d3565b1495945050505050565b60685460ff1615611d7b57604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b60685463ffffffff610100909104811690871603611de3576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338989898888605354604051611e3799989796959493929190613a2c565b60405180910390a1611e6e6117036001606860019054906101000a900463ffffffff16338a8a8a8989604051610e049291906137d6565b8215610cba57610cba612114565b60408051600481526024810182526020810180516001600160e01b03167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611edb91906137e5565b5f60405180830381855afa9150503d805f8114611f13576040519150601f19603f3d011682016040523d82523d5f602084013e611f18565b606091505b509150915081611f5d576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525061098b565b61098b81612a94565b60408051600481526024810182526020810180516001600160e01b03167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611fc591906137e5565b5f60405180830381855afa9150503d805f8114611ffd576040519150601f19603f3d011682016040523d82523d5f602084013e612002565b606091505b509150915081611f5d576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525061098b565b60408051600481526024810182526020810180516001600160e01b03167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f91829182916001600160a01b038616916120a591906137e5565b5f60405180830381855afa9150503d805f81146120dd576040519150601f19603f3d011682016040523d82523d5f602084013e6120e2565b606091505b50915091508180156120f5575080516020145b61210057601261098b565b8080602001905181019061098b9190613a97565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d61217561088e565b6040518263ffffffff1660e01b815260040161219391815260200190565b5f604051808303815f87803b1580156121aa575f80fd5b505af11580156121bc573d5f803e3d5ffd5b50505050565b606854604080516020808201879052818301869052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f916501000000000090046001600160a01b03169063257b3632906084016020604051808303815f875af1158015612253573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122779190613860565b9050805f036122b1576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80680100000000000000008716156122f5578691506122d3848a8489611d40565b6122f0576040516338105f3b60e21b815260040160405180910390fd5b61233f565b602087901c612305816001613ab2565b9150879250612320612318868c866109d3565b8a8389611d40565b61233d576040516338105f3b60e21b815260040160405180910390fd5b505b6123498282612c64565b505050505050505050565b6040516001600160a01b0383166024820152604481018290526123d09084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612d24565b505050565b5f8060405180611ba00160405280611b668152602001613d80611b6691398360405160200161240592919061377e565b6040516020818303038152906040529050838151602083015ff591506001600160a01b038216612461576040517fbefb092000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092915050565b6002600154036124ba5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611aca565b6002600155565b5f6124cf6004828486613acf565b6124d891613af6565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b03198216016126b2575f80808080808061251f896004818d613acf565b81019061252c9190613b26565b9650965096509650965096509650336001600160a01b0316876001600160a01b03161461256c5760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03861630146125955760405163750643af60e01b815260040160405180910390fd5b8a85146125ce576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169161266591906137e5565b5f604051808303815f865af19150503d805f811461269e576040519150601f19603f3d011682016040523d82523d5f602084013e6126a3565b606091505b50505050505050505050610752565b6001600160e01b031981166323f2ebc360e21b146126fc576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806127118a6004818e613acf565b81019061271e9190613b75565b97509750975097509750975097509750336001600160a01b0316886001600160a01b0316146127605760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03871630146127895760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f169161281091906137e5565b5f604051808303815f865af19150503d805f8114612849576040519150601f19603f3d011682016040523d82523d5f602084013e61284e565b606091505b50505050505050505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526121bc9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612399565b8060016128c060206002613cd3565b6128ca9190613877565b60535410612904576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f81546129139061372e565b918290555090505f5b60208110156129a3578082901c60011660010361294f57826033826020811061294757612947613706565b015550505050565b6033816020811061296257612962613706565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808061299b9061372e565b91505061291c565b506123d0613cde565b60018055565b60685460ff166129ee576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f54610100900460ff16612a8c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611aca565b610664612e08565b60606040825110612ab357818060200190518101906106ca9190613cf2565b8151602003612c26575f5b602081108015612b055750828181518110612adb57612adb613706565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15612b1c5780612b148161372e565b915050612abe565b805f03612b5e57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115612b7857612b78613268565b6040519080825280601f01601f191660200182016040528015612ba2576020820181803683370190505b5090505f5b82811015612c1e57848181518110612bc157612bc1613706565b602001015160f81c60f81b828281518110612bde57612bde613706565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080612c168161372e565b915050612ba7565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b6068545f90610100900463ffffffff16158015612c87575063ffffffff82166001145b15612c99575063ffffffff8216612cc1565b612cae64010000000063ffffffff84166137ac565b612cbe9063ffffffff85166137c3565b90505b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003611723576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612d78826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612e729092919063ffffffff16565b8051909150156123d05780806020019051810190612d969190613d64565b6123d05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611aca565b5f54610100900460ff166129ac5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611aca565b606061098b84845f85855f80866001600160a01b03168587604051612e9791906137e5565b5f6040518083038185875af1925050503d805f8114612ed1576040519150601f19603f3d011682016040523d82523d5f602084013e612ed6565b606091505b5091509150612ee787838387612ef2565b979650505050505050565b60608315612f605782515f03612f59576001600160a01b0385163b612f595760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611aca565b508161098b565b61098b8383815115612f755781518083602001fd5b8060405162461bcd60e51b8152600401611aca9190613102565b803563ffffffff81168114612c5f575f80fd5b6001600160a01b0381168114612fb6575f80fd5b50565b5f8060408385031215612fca575f80fd5b612fd383612f8f565b91506020830135612fe381612fa2565b809150509250929050565b8015158114612fb6575f80fd5b5f8083601f84011261300b575f80fd5b50813567ffffffffffffffff811115613022575f80fd5b602083019150836020828501011115613039575f80fd5b9250929050565b5f805f805f60808688031215613054575f80fd5b61305d86612f8f565b9450602086013561306d81612fa2565b9350604086013561307d81612fee565b9250606086013567ffffffffffffffff811115613098575f80fd5b6130a488828901612ffb565b969995985093965092949392505050565b5f5b838110156130cf5781810151838201526020016130b7565b50505f910152565b5f81518084526130ee8160208601602086016130b5565b601f01601f19169290920160200192915050565b602081525f61311460208301846130d7565b9392505050565b5f6020828403121561312b575f80fd5b813561311481612fa2565b60ff81168114612fb6575f80fd5b5f805f805f805f60e0888a03121561315a575f80fd5b873561316581613136565b965061317360208901612f8f565b9550604088013561318381612fa2565b945061319160608901612f8f565b935060808801356131a181612fa2565b9699959850939692959460a0840135945060c09093013592915050565b5f805f606084860312156131d0575f80fd5b6131d984612f8f565b925060208401356131e981612fa2565b915060408401356131f981612fa2565b809150509250925092565b5f60208284031215613214575f80fd5b5035919050565b8061040081018310156106ca575f80fd5b5f805f610440848603121561323f575f80fd5b83359250613250856020860161321b565b915061325f6104208501612f8f565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156132a5576132a5613268565b604052919050565b5f67ffffffffffffffff8211156132c6576132c6613268565b50601f01601f191660200190565b5f6132e66132e1846132ad565b61327c565b90508281528383830111156132f9575f80fd5b828260208301375f602084830101529392505050565b5f82601f83011261331e575f80fd5b613114838335602085016132d4565b5f805f805f60a08688031215613341575f80fd5b61334a86612f8f565b9450602086013561335a81612fa2565b9350604086013567ffffffffffffffff80821115613376575f80fd5b61338289838a0161330f565b94506060880135915080821115613397575f80fd5b506133a48882890161330f565b92505060808601356133b581613136565b809150509295509295909350565b5f805f805f8060a087890312156133d8575f80fd5b6133e187612f8f565b955060208701356133f181612fa2565b945060408701359350606087013561340881612fee565b9250608087013567ffffffffffffffff811115613423575f80fd5b61342f89828a01612ffb565b979a9699509497509295939492505050565b5f8060408385031215613452575f80fd5b61345b83612f8f565b915061346960208401612f8f565b90509250929050565b5f805f805f805f805f805f806109208d8f03121561348e575f80fd5b6134988e8e61321b565b9b506134a88e6104008f0161321b565b9a506108008d013599506108208d013598506108408d013597506134cf6108608e01612f8f565b96506134df6108808e0135612fa2565b6108808d013595506134f46108a08e01612f8f565b94506135046108c08e0135612fa2565b6108c08d013593506108e08d0135925067ffffffffffffffff6109008e0135111561352d575f80fd5b61353e8e6109008f01358f01612ffb565b81935080925050509295989b509295989b509295989b565b5f805f805f805f60c0888a03121561356c575f80fd5b61357588612f8f565b9650602088013561358581612fa2565b955060408801359450606088013561359c81612fa2565b935060808801356135ac81612fee565b925060a088013567ffffffffffffffff8111156135c7575f80fd5b6135d38a828b01612ffb565b989b979a50959850939692959293505050565b5f805f805f8060c087890312156135fb575f80fd5b61360487612f8f565b9550602087013561361481612fa2565b945061362260408801612f8f565b9350606087013561363281612fa2565b9250608087013561364281612fa2565b915060a087013567ffffffffffffffff81111561365d575f80fd5b8701601f8101891361366d575f80fd5b61367c898235602084016132d4565b9150509295509295509295565b5f805f80610460858703121561369d575f80fd5b843593506136ae866020870161321b565b92506136bd6104208601612f8f565b939692955092936104400135925050565b600181811c908216806136e257607f821691505b60208210810361370057634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f6001820161373f5761373f61371a565b5060010190565b606081525f61375860608301866130d7565b828103602084015261376a81866130d7565b91505060ff83166040830152949350505050565b5f835161378f8184602088016130b5565b8351908301906137a38183602088016130b5565b01949350505050565b80820281158282048414176106ca576106ca61371a565b808201808211156106ca576106ca61371a565b818382375f9101908152919050565b5f82516137f68184602087016130b5565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681525f6001600160a01b03808716602084015280861660408401525060806060830152612ee7608083018486613800565b5f60208284031215613870575f80fd5b5051919050565b818103818111156106ca576106ca61371a565b5f61010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c08501526138da828501876130d7565b925080851660e085015250509998505050505050505050565b6001600160a01b038516815263ffffffff84166020820152606060408201525f613921606083018486613800565b9695505050505050565b601f8211156123d0575f81815260208120601f850160051c810160208610156139515750805b601f850160051c820191505b81811015610cba5782815560010161395d565b815167ffffffffffffffff81111561398a5761398a613268565b61399e8161399884546136ce565b8461392b565b602080601f8311600181146139d1575f84156139ba5750858301515b5f19600386901b1c1916600185901b178555610cba565b5f85815260208120601f198616915b828110156139ff578886015182559484019460019091019084016139e0565b5085821015613a1c57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f61010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c0850152613a7d8285018789613800565b925080851660e085015250509a9950505050505050505050565b5f60208284031215613aa7575f80fd5b815161311481613136565b63ffffffff8181168382160190808211156124615761246161371a565b5f8085851115613add575f80fd5b83861115613ae9575f80fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015613b1e5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a031215613b3c575f80fd5b8735613b4781612fa2565b96506020880135613b5781612fa2565b9550604088013594506060880135935060808801356131a181613136565b5f805f805f805f80610100898b031215613b8d575f80fd5b8835613b9881612fa2565b97506020890135613ba881612fa2565b965060408901359550606089013594506080890135613bc681612fee565b935060a0890135613bd681613136565b979a969950949793969295929450505060c08201359160e0013590565b600181815b80851115613c2d57815f1904821115613c1357613c1361371a565b80851615613c2057918102915b93841c9390800290613bf8565b509250929050565b5f82613c43575060016106ca565b81613c4f57505f6106ca565b8160018114613c655760028114613c6f57613c8b565b60019150506106ca565b60ff841115613c8057613c8061371a565b50506001821b6106ca565b5060208310610133831016604e8410600b8410161715613cae575081810a6106ca565b613cb88383613bf3565b805f1904821115613ccb57613ccb61371a565b029392505050565b5f6131148383613c35565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613d02575f80fd5b815167ffffffffffffffff811115613d18575f80fd5b8201601f81018413613d28575f80fd5b8051613d366132e1826132ad565b818152856020838501011115613d4a575f80fd5b613d5b8260208301602086016130b5565b95945050505050565b5f60208284031215613d74575f80fd5b815161311481612fee56fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220432f6d6b4446edbe1f73c19fd2115454d5c35d8b03b98a74fd46724151d7672264736f6c63430008140033", - "deployedBytecode": "0x6080604052600436106101db575f3560e01c806383f24403116100fd578063ccaa2d1111610092578063ee25560b11610062578063ee25560b146105a9578063f5efcd79146105d4578063f811bff7146105f3578063fb57083414610612575f80fd5b8063ccaa2d111461053b578063cd5865791461055a578063d02103ca1461056d578063dbc1697614610595575f80fd5b8063bab161bf116100cd578063bab161bf146104b9578063be5831c7146104da578063c00f14ab146104fd578063cc4616321461051c575f80fd5b806383f244031461043d5780638ed7e3f21461045c578063aaa13cc21461047b578063b8b284d01461049a575f80fd5b80633cbc795b116101735780637843298b116101435780637843298b146103c257806379e2cf97146103e157806381b1c174146103f557806383c43a5514610429575f80fd5b80633cbc795b146103385780633e197043146103705780634b2f336d1461038f5780635ca1e165146103ae575f80fd5b806327aef4e8116101ae57806327aef4e81461026d5780632dfdf0b51461028e578063318aee3d146102b15780633c351e1014610319575f80fd5b806315064c96146101df5780632072f6c51461020d57806322e95f2c14610223578063240ff3781461025a575b5f80fd5b3480156101ea575f80fd5b506068546101f89060ff1681565b60405190151581526020015b60405180910390f35b348015610218575f80fd5b50610221610631565b005b34801561022e575f80fd5b5061024261023d366004612fb9565b610666565b6040516001600160a01b039091168152602001610204565b610221610268366004613040565b6106d0565b348015610278575f80fd5b50610281610759565b6040516102049190613102565b348015610299575f80fd5b506102a360535481565b604051908152602001610204565b3480156102bc575f80fd5b506102f56102cb36600461311b565b606b6020525f908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201610204565b348015610324575f80fd5b50606d54610242906001600160a01b031681565b348015610343575f80fd5b50606d5461035b90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610204565b34801561037b575f80fd5b506102a361038a366004613144565b6107e5565b34801561039a575f80fd5b50606f54610242906001600160a01b031681565b3480156103b9575f80fd5b506102a361088e565b3480156103cd575f80fd5b506102426103dc3660046131be565b61096a565b3480156103ec575f80fd5b50610221610993565b348015610400575f80fd5b5061024261040f366004613204565b606a6020525f90815260409020546001600160a01b031681565b348015610434575f80fd5b506102816109b4565b348015610448575f80fd5b506102a361045736600461322c565b6109d3565b348015610467575f80fd5b50606c54610242906001600160a01b031681565b348015610486575f80fd5b5061024261049536600461332d565b610aa8565b3480156104a5575f80fd5b506102216104b43660046133c3565b610be7565b3480156104c4575f80fd5b5060685461035b90610100900463ffffffff1681565b3480156104e5575f80fd5b5060685461035b90600160c81b900463ffffffff1681565b348015610508575f80fd5b5061028161051736600461311b565b610cc2565b348015610527575f80fd5b506101f8610536366004613441565b610d07565b348015610546575f80fd5b50610221610555366004613472565b610d8f565b610221610568366004613556565b6112c0565b348015610578575f80fd5b50606854610242906501000000000090046001600160a01b031681565b3480156105a0575f80fd5b5061022161172c565b3480156105b4575f80fd5b506102a36105c3366004613204565b60696020525f908152604090205481565b3480156105df575f80fd5b506102216105ee366004613472565b61175f565b3480156105fe575f80fd5b5061022161060d3660046135e6565b611a25565b34801561061d575f80fd5b506101f861062c366004613689565b611d40565b606c546001600160a01b0316331461065c57604051631736745960e31b815260040160405180910390fd5b610664611d57565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091205f908152606a90915220546001600160a01b03165b92915050565b60685460ff16156106f457604051630bc011ff60e21b815260040160405180910390fd5b341580159061070d5750606f546001600160a01b031615155b15610744576040517f6f625c4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610752858534868686611db2565b5050505050565b606e8054610766906136ce565b80601f0160208091040260200160405190810160405280929190818152602001828054610792906136ce565b80156107dd5780601f106107b4576101008083540402835291602001916107dd565b820191905f5260205f20905b8154815290600101906020018083116107c057829003601f168201915b505050505081565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b6053545f90819081805b6020811015610961578083901c6001166001036108f557603381602081106108c2576108c2613706565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610922565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806109599061372e565b915050610898565b50919392505050565b5f61098b848461097985611e7c565b61098286611f66565b61049587612047565b949350505050565b605354606854600160c81b900463ffffffff16101561066457610664612114565b60405180611ba00160405280611b668152602001613d80611b66913981565b5f83815b6020811015610a9f57600163ffffffff8516821c81169003610a4257848160208110610a0557610a05613706565b602002013582604051602001610a25929190918252602082015260400190565b604051602081830303815290604052805190602001209150610a8d565b81858260208110610a5557610a55613706565b6020020135604051602001610a74929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80610a978161372e565b9150506109d7565b50949350505050565b6040516001600160e01b031960e087901b1660208201526bffffffffffffffffffffffff19606086901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180611ba00160405280611b668152602001613d80611b669139898989604051602001610b3093929190613746565b60408051601f1981840301815290829052610b4e929160200161377e565b60405160208183030381529060405280519060200120604051602001610bc394939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60685460ff1615610c0b57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b0316610c4d576040517fdde3cda700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f54604051632770a7eb60e21b8152336004820152602481018690526001600160a01b0390911690639dc29fac906044015f604051808303815f87803b158015610c96575f80fd5b505af1158015610ca8573d5f803e3d5ffd5b50505050610cba868686868686611db2565b505050505050565b6060610ccd82611e7c565b610cd683611f66565b610cdf84612047565b604051602001610cf193929190613746565b6040516020818303038152906040529050919050565b6068545f908190610100900463ffffffff16158015610d2c575063ffffffff83166001145b15610d3e575063ffffffff8316610d66565b610d5364010000000063ffffffff85166137ac565b610d639063ffffffff86166137c3565b90505b600881901c5f90815260696020526040902054600160ff9092169190911b908116149392505050565b60685460ff1615610db357604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614610de3576040516302caf51760e11b815260040160405180910390fd5b610e168c8c8c8c8c610e115f8e8e8e8e8e8e8e604051610e049291906137d6565b60405180910390206107e5565b6121c2565b6001600160a01b038616610f6057606f546001600160a01b0316610efa575f6001600160a01b03851684825b6040519080825280601f01601f191660200182016040528015610e6c576020820181803683370190505b50604051610e7a91906137e5565b5f6040518083038185875af1925050503d805f8114610eb4576040519150601f19603f3d011682016040523d82523d5f602084013e610eb9565b606091505b5050905080610ef4576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611256565b606f546040516340c10f1960e01b81526001600160a01b03868116600483015260248201869052909116906340c10f19906044015f604051808303815f87803b158015610f45575f80fd5b505af1158015610f57573d5f803e3d5ffd5b50505050611256565b606d546001600160a01b038781169116148015610f8e5750606d5463ffffffff888116600160a01b90920416145b15610fa5575f6001600160a01b0385168482610e42565b60685463ffffffff610100909104811690881603610fd657610fd16001600160a01b0387168585612354565b611256565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201525f9060380160408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b0316806111f5575f6110808386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506123d592505050565b6040516340c10f1960e01b81526001600160a01b03898116600483015260248201899052919250908216906340c10f19906044015f604051808303815f87803b1580156110cb575f80fd5b505af11580156110dd573d5f803e3d5ffd5b5050505080606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a8388886040516111e7959493929190613828565b60405180910390a150611253565b6040516340c10f1960e01b81526001600160a01b038781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801561123c575f80fd5b505af115801561124e573d5f803e3d5ffd5b505050505b50505b604080518b815263ffffffff891660208201526001600160a01b0388811682840152861660608201526080810185905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a1505050505050505050505050565b60685460ff16156112e457604051630bc011ff60e21b815260040160405180910390fd5b6112ec612468565b60685463ffffffff61010090910481169088160361131d576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b03881661141957883414611369576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff16945090611396906136ce565b80601f01602080910402602001604051908101604052809291908181526020018280546113c2906136ce565b801561140d5780601f106113e45761010080835404028352916020019161140d565b820191905f5260205f20905b8154815290600101906020018083116113f057829003601f168201915b505050505091506116a3565b3415611451576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546001600160a01b03908116908916036114c757604051632770a7eb60e21b8152336004820152602481018a90526001600160a01b03891690639dc29fac906044015f604051808303815f87803b1580156114ac575f80fd5b505af11580156114be573d5f803e3d5ffd5b505050506116a3565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901561157957604051632770a7eb60e21b8152336004820152602481018b90526001600160a01b038a1690639dc29fac906044015f604051808303815f87803b158015611551575f80fd5b505af1158015611563573d5f803e3d5ffd5b5050505080602001519450805f01519350611696565b851561158b5761158b898b89896124c1565b6040516370a0823160e01b81523060048201525f906001600160a01b038b16906370a0823190602401602060405180830381865afa1580156115cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f39190613860565b905061160a6001600160a01b038b1633308e612860565b6040516370a0823160e01b81523060048201525f906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561164e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116729190613860565b905061167e8282613877565b6068548c9850610100900463ffffffff169650935050505b61169f89610cc2565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e86886053546040516116e298979695949392919061388a565b60405180910390a16117086117035f85878f8f8789805190602001206107e5565b6128b1565b861561171657611716612114565b5050505061172360018055565b50505050505050565b606c546001600160a01b0316331461175757604051631736745960e31b815260040160405180910390fd5b6106646129b2565b60685460ff161561178357604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff86811661010090920416146117b3576040516302caf51760e11b815260040160405180910390fd5b6117d58c8c8c8c8c610e1160018e8e8e8e8e8e8e604051610e049291906137d6565b606f545f906001600160a01b031661188857846001600160a01b031684888a868660405160240161180994939291906138f3565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161183e91906137e5565b5f6040518083038185875af1925050503d805f8114611878576040519150601f19603f3d011682016040523d82523d5f602084013e61187d565b606091505b505080915050611983565b606f546040516340c10f1960e01b81526001600160a01b03878116600483015260248201879052909116906340c10f19906044015f604051808303815f87803b1580156118d3575f80fd5b505af11580156118e5573d5f803e3d5ffd5b50505050846001600160a01b03168789858560405160240161190a94939291906138f3565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161193f91906137e5565b5f604051808303815f865af19150503d805f8114611978576040519150601f19603f3d011682016040523d82523d5f602084013e61197d565b606091505b50909150505b806119ba576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518c815263ffffffff8a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a150505050505050505050505050565b5f54610100900460ff1615808015611a4357505f54600160ff909116105b80611a5c5750303b158015611a5c57505f5460ff166001145b611ad35760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805460ff191660011790558015611af4575f805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8a16027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038781169190910291909117909155606c805473ffffffffffffffffffffffffffffffffffffffff19168583161790558616611bcf5763ffffffff851615611bca576040517f1a874c1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ceb565b606d805463ffffffff8716600160a01b027fffffffffffffffff0000000000000000000000000000000000000000000000009091166001600160a01b03891617179055606e611c1e8382613970565b50611cbd5f801b6012604051602001611ca991906060808252600d908201527f5772617070656420457468657200000000000000000000000000000000000000608082015260a0602082018190526004908201527f574554480000000000000000000000000000000000000000000000000000000060c082015260ff91909116604082015260e00190565b6040516020818303038152906040526123d5565b606f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03929092169190911790555b611cf3612a22565b8015611723575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b5f81611d4d8686866109d3565b1495945050505050565b60685460ff1615611d7b57604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b60685463ffffffff610100909104811690871603611de3576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338989898888605354604051611e3799989796959493929190613a2c565b60405180910390a1611e6e6117036001606860019054906101000a900463ffffffff16338a8a8a8989604051610e049291906137d6565b8215610cba57610cba612114565b60408051600481526024810182526020810180516001600160e01b03167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611edb91906137e5565b5f60405180830381855afa9150503d805f8114611f13576040519150601f19603f3d011682016040523d82523d5f602084013e611f18565b606091505b509150915081611f5d576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525061098b565b61098b81612a94565b60408051600481526024810182526020810180516001600160e01b03167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611fc591906137e5565b5f60405180830381855afa9150503d805f8114611ffd576040519150601f19603f3d011682016040523d82523d5f602084013e612002565b606091505b509150915081611f5d576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525061098b565b60408051600481526024810182526020810180516001600160e01b03167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f91829182916001600160a01b038616916120a591906137e5565b5f60405180830381855afa9150503d805f81146120dd576040519150601f19603f3d011682016040523d82523d5f602084013e6120e2565b606091505b50915091508180156120f5575080516020145b61210057601261098b565b8080602001905181019061098b9190613a97565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d61217561088e565b6040518263ffffffff1660e01b815260040161219391815260200190565b5f604051808303815f87803b1580156121aa575f80fd5b505af11580156121bc573d5f803e3d5ffd5b50505050565b606854604080516020808201879052818301869052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f916501000000000090046001600160a01b03169063257b3632906084016020604051808303815f875af1158015612253573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122779190613860565b9050805f036122b1576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80680100000000000000008716156122f5578691506122d3848a8489611d40565b6122f0576040516338105f3b60e21b815260040160405180910390fd5b61233f565b602087901c612305816001613ab2565b9150879250612320612318868c866109d3565b8a8389611d40565b61233d576040516338105f3b60e21b815260040160405180910390fd5b505b6123498282612c64565b505050505050505050565b6040516001600160a01b0383166024820152604481018290526123d09084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612d24565b505050565b5f8060405180611ba00160405280611b668152602001613d80611b6691398360405160200161240592919061377e565b6040516020818303038152906040529050838151602083015ff591506001600160a01b038216612461576040517fbefb092000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092915050565b6002600154036124ba5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611aca565b6002600155565b5f6124cf6004828486613acf565b6124d891613af6565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b03198216016126b2575f80808080808061251f896004818d613acf565b81019061252c9190613b26565b9650965096509650965096509650336001600160a01b0316876001600160a01b03161461256c5760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03861630146125955760405163750643af60e01b815260040160405180910390fd5b8a85146125ce576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169161266591906137e5565b5f604051808303815f865af19150503d805f811461269e576040519150601f19603f3d011682016040523d82523d5f602084013e6126a3565b606091505b50505050505050505050610752565b6001600160e01b031981166323f2ebc360e21b146126fc576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806127118a6004818e613acf565b81019061271e9190613b75565b97509750975097509750975097509750336001600160a01b0316886001600160a01b0316146127605760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03871630146127895760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f169161281091906137e5565b5f604051808303815f865af19150503d805f8114612849576040519150601f19603f3d011682016040523d82523d5f602084013e61284e565b606091505b50505050505050505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526121bc9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612399565b8060016128c060206002613cd3565b6128ca9190613877565b60535410612904576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f81546129139061372e565b918290555090505f5b60208110156129a3578082901c60011660010361294f57826033826020811061294757612947613706565b015550505050565b6033816020811061296257612962613706565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808061299b9061372e565b91505061291c565b506123d0613cde565b60018055565b60685460ff166129ee576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f54610100900460ff16612a8c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611aca565b610664612e08565b60606040825110612ab357818060200190518101906106ca9190613cf2565b8151602003612c26575f5b602081108015612b055750828181518110612adb57612adb613706565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15612b1c5780612b148161372e565b915050612abe565b805f03612b5e57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115612b7857612b78613268565b6040519080825280601f01601f191660200182016040528015612ba2576020820181803683370190505b5090505f5b82811015612c1e57848181518110612bc157612bc1613706565b602001015160f81c60f81b828281518110612bde57612bde613706565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080612c168161372e565b915050612ba7565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b6068545f90610100900463ffffffff16158015612c87575063ffffffff82166001145b15612c99575063ffffffff8216612cc1565b612cae64010000000063ffffffff84166137ac565b612cbe9063ffffffff85166137c3565b90505b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003611723576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612d78826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612e729092919063ffffffff16565b8051909150156123d05780806020019051810190612d969190613d64565b6123d05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611aca565b5f54610100900460ff166129ac5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611aca565b606061098b84845f85855f80866001600160a01b03168587604051612e9791906137e5565b5f6040518083038185875af1925050503d805f8114612ed1576040519150601f19603f3d011682016040523d82523d5f602084013e612ed6565b606091505b5091509150612ee787838387612ef2565b979650505050505050565b60608315612f605782515f03612f59576001600160a01b0385163b612f595760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611aca565b508161098b565b61098b8383815115612f755781518083602001fd5b8060405162461bcd60e51b8152600401611aca9190613102565b803563ffffffff81168114612c5f575f80fd5b6001600160a01b0381168114612fb6575f80fd5b50565b5f8060408385031215612fca575f80fd5b612fd383612f8f565b91506020830135612fe381612fa2565b809150509250929050565b8015158114612fb6575f80fd5b5f8083601f84011261300b575f80fd5b50813567ffffffffffffffff811115613022575f80fd5b602083019150836020828501011115613039575f80fd5b9250929050565b5f805f805f60808688031215613054575f80fd5b61305d86612f8f565b9450602086013561306d81612fa2565b9350604086013561307d81612fee565b9250606086013567ffffffffffffffff811115613098575f80fd5b6130a488828901612ffb565b969995985093965092949392505050565b5f5b838110156130cf5781810151838201526020016130b7565b50505f910152565b5f81518084526130ee8160208601602086016130b5565b601f01601f19169290920160200192915050565b602081525f61311460208301846130d7565b9392505050565b5f6020828403121561312b575f80fd5b813561311481612fa2565b60ff81168114612fb6575f80fd5b5f805f805f805f60e0888a03121561315a575f80fd5b873561316581613136565b965061317360208901612f8f565b9550604088013561318381612fa2565b945061319160608901612f8f565b935060808801356131a181612fa2565b9699959850939692959460a0840135945060c09093013592915050565b5f805f606084860312156131d0575f80fd5b6131d984612f8f565b925060208401356131e981612fa2565b915060408401356131f981612fa2565b809150509250925092565b5f60208284031215613214575f80fd5b5035919050565b8061040081018310156106ca575f80fd5b5f805f610440848603121561323f575f80fd5b83359250613250856020860161321b565b915061325f6104208501612f8f565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156132a5576132a5613268565b604052919050565b5f67ffffffffffffffff8211156132c6576132c6613268565b50601f01601f191660200190565b5f6132e66132e1846132ad565b61327c565b90508281528383830111156132f9575f80fd5b828260208301375f602084830101529392505050565b5f82601f83011261331e575f80fd5b613114838335602085016132d4565b5f805f805f60a08688031215613341575f80fd5b61334a86612f8f565b9450602086013561335a81612fa2565b9350604086013567ffffffffffffffff80821115613376575f80fd5b61338289838a0161330f565b94506060880135915080821115613397575f80fd5b506133a48882890161330f565b92505060808601356133b581613136565b809150509295509295909350565b5f805f805f8060a087890312156133d8575f80fd5b6133e187612f8f565b955060208701356133f181612fa2565b945060408701359350606087013561340881612fee565b9250608087013567ffffffffffffffff811115613423575f80fd5b61342f89828a01612ffb565b979a9699509497509295939492505050565b5f8060408385031215613452575f80fd5b61345b83612f8f565b915061346960208401612f8f565b90509250929050565b5f805f805f805f805f805f806109208d8f03121561348e575f80fd5b6134988e8e61321b565b9b506134a88e6104008f0161321b565b9a506108008d013599506108208d013598506108408d013597506134cf6108608e01612f8f565b96506134df6108808e0135612fa2565b6108808d013595506134f46108a08e01612f8f565b94506135046108c08e0135612fa2565b6108c08d013593506108e08d0135925067ffffffffffffffff6109008e0135111561352d575f80fd5b61353e8e6109008f01358f01612ffb565b81935080925050509295989b509295989b509295989b565b5f805f805f805f60c0888a03121561356c575f80fd5b61357588612f8f565b9650602088013561358581612fa2565b955060408801359450606088013561359c81612fa2565b935060808801356135ac81612fee565b925060a088013567ffffffffffffffff8111156135c7575f80fd5b6135d38a828b01612ffb565b989b979a50959850939692959293505050565b5f805f805f8060c087890312156135fb575f80fd5b61360487612f8f565b9550602087013561361481612fa2565b945061362260408801612f8f565b9350606087013561363281612fa2565b9250608087013561364281612fa2565b915060a087013567ffffffffffffffff81111561365d575f80fd5b8701601f8101891361366d575f80fd5b61367c898235602084016132d4565b9150509295509295509295565b5f805f80610460858703121561369d575f80fd5b843593506136ae866020870161321b565b92506136bd6104208601612f8f565b939692955092936104400135925050565b600181811c908216806136e257607f821691505b60208210810361370057634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f6001820161373f5761373f61371a565b5060010190565b606081525f61375860608301866130d7565b828103602084015261376a81866130d7565b91505060ff83166040830152949350505050565b5f835161378f8184602088016130b5565b8351908301906137a38183602088016130b5565b01949350505050565b80820281158282048414176106ca576106ca61371a565b808201808211156106ca576106ca61371a565b818382375f9101908152919050565b5f82516137f68184602087016130b5565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681525f6001600160a01b03808716602084015280861660408401525060806060830152612ee7608083018486613800565b5f60208284031215613870575f80fd5b5051919050565b818103818111156106ca576106ca61371a565b5f61010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c08501526138da828501876130d7565b925080851660e085015250509998505050505050505050565b6001600160a01b038516815263ffffffff84166020820152606060408201525f613921606083018486613800565b9695505050505050565b601f8211156123d0575f81815260208120601f850160051c810160208610156139515750805b601f850160051c820191505b81811015610cba5782815560010161395d565b815167ffffffffffffffff81111561398a5761398a613268565b61399e8161399884546136ce565b8461392b565b602080601f8311600181146139d1575f84156139ba5750858301515b5f19600386901b1c1916600185901b178555610cba565b5f85815260208120601f198616915b828110156139ff578886015182559484019460019091019084016139e0565b5085821015613a1c57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f61010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c0850152613a7d8285018789613800565b925080851660e085015250509a9950505050505050505050565b5f60208284031215613aa7575f80fd5b815161311481613136565b63ffffffff8181168382160190808211156124615761246161371a565b5f8085851115613add575f80fd5b83861115613ae9575f80fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015613b1e5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a031215613b3c575f80fd5b8735613b4781612fa2565b96506020880135613b5781612fa2565b9550604088013594506060880135935060808801356131a181613136565b5f805f805f805f80610100898b031215613b8d575f80fd5b8835613b9881612fa2565b97506020890135613ba881612fa2565b965060408901359550606089013594506080890135613bc681612fee565b935060a0890135613bd681613136565b979a969950949793969295929450505060c08201359160e0013590565b600181815b80851115613c2d57815f1904821115613c1357613c1361371a565b80851615613c2057918102915b93841c9390800290613bf8565b509250929050565b5f82613c43575060016106ca565b81613c4f57505f6106ca565b8160018114613c655760028114613c6f57613c8b565b60019150506106ca565b60ff841115613c8057613c8061371a565b50506001821b6106ca565b5060208310610133831016604e8410600b8410161715613cae575081810a6106ca565b613cb88383613bf3565b805f1904821115613ccb57613ccb61371a565b029392505050565b5f6131148383613c35565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613d02575f80fd5b815167ffffffffffffffff811115613d18575f80fd5b8201601f81018413613d28575f80fd5b8051613d366132e1826132ad565b818152856020838501011115613d4a575f80fd5b613d5b8260208301602086016130b5565b95945050505050565b5f60208284031215613d74575f80fd5b815161311481612fee56fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220432f6d6b4446edbe1f73c19fd2115454d5c35d8b03b98a74fd46724151d7672264736f6c63430008140033", + "bytecode": "0x608060405234801562000010575f80fd5b506200001b62000021565b620000e0565b5f54610100900460ff16156200008d5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff9081161015620000de575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6157d180620000ee5f395ff3fe6080604052600436106101db575f3560e01c806383f24403116100fd578063ccaa2d1111610092578063ee25560b11610062578063ee25560b146105a9578063f5efcd79146105d4578063f811bff7146105f3578063fb57083414610612575f80fd5b8063ccaa2d111461053b578063cd5865791461055a578063d02103ca1461056d578063dbc1697614610595575f80fd5b8063bab161bf116100cd578063bab161bf146104b9578063be5831c7146104da578063c00f14ab146104fd578063cc4616321461051c575f80fd5b806383f244031461043d5780638ed7e3f21461045c578063aaa13cc21461047b578063b8b284d01461049a575f80fd5b80633cbc795b116101735780637843298b116101435780637843298b146103c257806379e2cf97146103e157806381b1c174146103f557806383c43a5514610429575f80fd5b80633cbc795b146103385780633e197043146103705780634b2f336d1461038f5780635ca1e165146103ae575f80fd5b806327aef4e8116101ae57806327aef4e81461026d5780632dfdf0b51461028e578063318aee3d146102b15780633c351e1014610319575f80fd5b806315064c96146101df5780632072f6c51461020d57806322e95f2c14610223578063240ff3781461025a575b5f80fd5b3480156101ea575f80fd5b506068546101f89060ff1681565b60405190151581526020015b60405180910390f35b348015610218575f80fd5b50610221610631565b005b34801561022e575f80fd5b5061024261023d366004612e6f565b610666565b6040516001600160a01b039091168152602001610204565b610221610268366004612ef6565b6106d0565b348015610278575f80fd5b50610281610759565b6040516102049190612fb8565b348015610299575f80fd5b506102a360535481565b604051908152602001610204565b3480156102bc575f80fd5b506102f56102cb366004612fd1565b606b6020525f908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201610204565b348015610324575f80fd5b50606d54610242906001600160a01b031681565b348015610343575f80fd5b50606d5461035b90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610204565b34801561037b575f80fd5b506102a361038a366004612ffa565b6107e5565b34801561039a575f80fd5b50606f54610242906001600160a01b031681565b3480156103b9575f80fd5b506102a361088e565b3480156103cd575f80fd5b506102426103dc366004613074565b61096a565b3480156103ec575f80fd5b50610221610993565b348015610400575f80fd5b5061024261040f3660046130ba565b606a6020525f90815260409020546001600160a01b031681565b348015610434575f80fd5b506102816109b4565b348015610448575f80fd5b506102a36104573660046130e2565b6109d3565b348015610467575f80fd5b50606c54610242906001600160a01b031681565b348015610486575f80fd5b506102426104953660046131e3565b610aa8565b3480156104a5575f80fd5b506102216104b4366004613279565b610be7565b3480156104c4575f80fd5b5060685461035b90610100900463ffffffff1681565b3480156104e5575f80fd5b5060685461035b90600160c81b900463ffffffff1681565b348015610508575f80fd5b50610281610517366004612fd1565b610c79565b348015610527575f80fd5b506101f86105363660046132f7565b610cbe565b348015610546575f80fd5b50610221610555366004613328565b610d46565b61022161056836600461340c565b611181565b348015610578575f80fd5b50606854610242906501000000000090046001600160a01b031681565b3480156105a0575f80fd5b5061022161154a565b3480156105b4575f80fd5b506102a36105c33660046130ba565b60696020525f908152604090205481565b3480156105df575f80fd5b506102216105ee366004613328565b61157d565b3480156105fe575f80fd5b5061022161060d36600461349c565b6117f9565b34801561061d575f80fd5b506101f861062c36600461353f565b611b14565b606c546001600160a01b0316331461065c57604051631736745960e31b815260040160405180910390fd5b610664611b2b565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091205f908152606a90915220546001600160a01b03165b92915050565b60685460ff16156106f457604051630bc011ff60e21b815260040160405180910390fd5b341580159061070d5750606f546001600160a01b031615155b15610744576040517f6f625c4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610752858534868686611b86565b5050505050565b606e805461076690613584565b80601f016020809104026020016040519081016040528092919081815260200182805461079290613584565b80156107dd5780601f106107b4576101008083540402835291602001916107dd565b820191905f5260205f20905b8154815290600101906020018083116107c057829003601f168201915b505050505081565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b6053545f90819081805b6020811015610961578083901c6001166001036108f557603381602081106108c2576108c26135bc565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610922565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080610959906135e4565b915050610898565b50919392505050565b5f61098b848461097985611c50565b61098286611d3a565b61049587611e1b565b949350505050565b605354606854600160c81b900463ffffffff16101561066457610664611ee8565b60405180611ba00160405280611b668152602001613c36611b66913981565b5f83815b6020811015610a9f57600163ffffffff8516821c81169003610a4257848160208110610a0557610a056135bc565b602002013582604051602001610a25929190918252602082015260400190565b604051602081830303815290604052805190602001209150610a8d565b81858260208110610a5557610a556135bc565b6020020135604051602001610a74929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80610a97816135e4565b9150506109d7565b50949350505050565b6040516001600160e01b031960e087901b1660208201526bffffffffffffffffffffffff19606086901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180611ba00160405280611b668152602001613c36611b669139898989604051602001610b30939291906135fc565b60408051601f1981840301815290829052610b4e9291602001613634565b60405160208183030381529060405280519060200120604051602001610bc394939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60685460ff1615610c0b57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b0316610c4d576040517fdde3cda700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f54610c63906001600160a01b031685611f96565b610c71868686868686611b86565b505050505050565b6060610c8482611c50565b610c8d83611d3a565b610c9684611e1b565b604051602001610ca8939291906135fc565b6040516020818303038152906040529050919050565b6068545f908190610100900463ffffffff16158015610ce3575063ffffffff83166001145b15610cf5575063ffffffff8316610d1d565b610d0a64010000000063ffffffff8516613662565b610d1a9063ffffffff8616613679565b90505b600881901c5f90815260696020526040902054600160ff9092169190911b908116149392505050565b60685460ff1615610d6a57604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614610d9a576040516302caf51760e11b815260040160405180910390fd5b610dcd8c8c8c8c8c610dc85f8e8e8e8e8e8e8e604051610dbb92919061368c565b60405180910390206107e5565b612006565b6001600160a01b038616610ecd57606f546001600160a01b0316610eb1575f6001600160a01b03851684825b6040519080825280601f01601f191660200182016040528015610e23576020820181803683370190505b50604051610e31919061369b565b5f6040518083038185875af1925050503d805f8114610e6b576040519150601f19603f3d011682016040523d82523d5f602084013e610e70565b606091505b5050905080610eab576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611117565b606f54610ec8906001600160a01b03168585612198565b611117565b606d546001600160a01b038781169116148015610efb5750606d5463ffffffff888116600160a01b90920416145b15610f12575f6001600160a01b0385168482610df9565b60685463ffffffff610100909104811690881603610f3e57610ec86001600160a01b038716858561220a565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201525f9060380160408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b031680611109575f610fe88386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061228b92505050565b9050610ff5818888612198565b80606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a8388886040516110fb9594939291906136de565b60405180910390a150611114565b611114818787612198565b50505b604080518b815263ffffffff891660208201526001600160a01b0388811682840152861660608201526080810185905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a1505050505050505050505050565b60685460ff16156111a557604051630bc011ff60e21b815260040160405180910390fd5b6111ad61231e565b60685463ffffffff6101009091048116908816036111de576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b0388166112da5788341461122a576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff1694509061125790613584565b80601f016020809104026020016040519081016040528092919081815260200182805461128390613584565b80156112ce5780601f106112a5576101008083540402835291602001916112ce565b820191905f5260205f20905b8154815290600101906020018083116112b157829003601f168201915b505050505091506114c1565b3415611312576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546001600160a01b039081169089160361133757611332888a611f96565b6114c1565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901561139757611386898b611f96565b6020810151815190955093506114b4565b85156113a9576113a9898b8989612377565b6040516370a0823160e01b81523060048201525f906001600160a01b038b16906370a0823190602401602060405180830381865afa1580156113ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114119190613716565b90506114286001600160a01b038b1633308e612716565b6040516370a0823160e01b81523060048201525f906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561146c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114909190613716565b905061149c828261372d565b6068548c9850610100900463ffffffff169650935050505b6114bd89610c79565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e8688605354604051611500989796959493929190613740565b60405180910390a16115266115215f85878f8f8789805190602001206107e5565b612767565b861561153457611534611ee8565b5050505061154160018055565b50505050505050565b606c546001600160a01b0316331461157557604051631736745960e31b815260040160405180910390fd5b610664612868565b60685460ff16156115a157604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff86811661010090920416146115d1576040516302caf51760e11b815260040160405180910390fd5b6115f38c8c8c8c8c610dc860018e8e8e8e8e8e8e604051610dbb92919061368c565b606f545f906001600160a01b03166116a657846001600160a01b031684888a868660405160240161162794939291906137a9565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161165c919061369b565b5f6040518083038185875af1925050503d805f8114611696576040519150601f19603f3d011682016040523d82523d5f602084013e61169b565b606091505b505080915050611757565b606f546116bd906001600160a01b03168686612198565b846001600160a01b0316878985856040516024016116de94939291906137a9565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b17905251611713919061369b565b5f604051808303815f865af19150503d805f811461174c576040519150601f19603f3d011682016040523d82523d5f602084013e611751565b606091505b50909150505b8061178e576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518c815263ffffffff8a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a150505050505050505050505050565b5f54610100900460ff161580801561181757505f54600160ff909116105b806118305750303b15801561183057505f5460ff166001145b6118a75760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805460ff1916600117905580156118c8575f805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8a16027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038781169190910291909117909155606c805473ffffffffffffffffffffffffffffffffffffffff191685831617905586166119a35763ffffffff85161561199e576040517f1a874c1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611abf565b606d805463ffffffff8716600160a01b027fffffffffffffffff0000000000000000000000000000000000000000000000009091166001600160a01b03891617179055606e6119f28382613826565b50611a915f801b6012604051602001611a7d91906060808252600d908201527f5772617070656420457468657200000000000000000000000000000000000000608082015260a0602082018190526004908201527f574554480000000000000000000000000000000000000000000000000000000060c082015260ff91909116604082015260e00190565b60405160208183030381529060405261228b565b606f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03929092169190911790555b611ac76128d8565b8015611541575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b5f81611b218686866109d3565b1495945050505050565b60685460ff1615611b4f57604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b60685463ffffffff610100909104811690871603611bb7576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338989898888605354604051611c0b999897969594939291906138e2565b60405180910390a1611c426115216001606860019054906101000a900463ffffffff16338a8a8a8989604051610dbb92919061368c565b8215610c7157610c71611ee8565b60408051600481526024810182526020810180516001600160e01b03167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611caf919061369b565b5f60405180830381855afa9150503d805f8114611ce7576040519150601f19603f3d011682016040523d82523d5f602084013e611cec565b606091505b509150915081611d31576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525061098b565b61098b8161294a565b60408051600481526024810182526020810180516001600160e01b03167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611d99919061369b565b5f60405180830381855afa9150503d805f8114611dd1576040519150601f19603f3d011682016040523d82523d5f602084013e611dd6565b606091505b509150915081611d31576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525061098b565b60408051600481526024810182526020810180516001600160e01b03167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f91829182916001600160a01b03861691611e79919061369b565b5f60405180830381855afa9150503d805f8114611eb1576040519150601f19603f3d011682016040523d82523d5f602084013e611eb6565b606091505b5091509150818015611ec9575080516020145b611ed457601261098b565b8080602001905181019061098b919061394d565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d611f4961088e565b6040518263ffffffff1660e01b8152600401611f6791815260200190565b5f604051808303815f87803b158015611f7e575f80fd5b505af1158015611f90573d5f803e3d5ffd5b50505050565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018290526001600160a01b03831690639dc29fac906044015f604051808303815f87803b158015611ff4575f80fd5b505af1158015610c71573d5f803e3d5ffd5b606854604080516020808201879052818301869052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f916501000000000090046001600160a01b03169063257b3632906084016020604051808303815f875af1158015612097573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120bb9190613716565b9050805f036120f5576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f806801000000000000000087161561213957869150612117848a8489611b14565b612134576040516338105f3b60e21b815260040160405180910390fd5b612183565b602087901c612149816001613968565b915087925061216461215c868c866109d3565b8a8389611b14565b612181576040516338105f3b60e21b815260040160405180910390fd5b505b61218d8282612b1a565b505050505050505050565b6040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018390528416906340c10f19906044015f604051808303815f87803b1580156121f8575f80fd5b505af1158015611541573d5f803e3d5ffd5b6040516001600160a01b0383166024820152604481018290526122869084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612bda565b505050565b5f8060405180611ba00160405280611b668152602001613c36611b669139836040516020016122bb929190613634565b6040516020818303038152906040529050838151602083015ff591506001600160a01b038216612317576040517fbefb092000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092915050565b6002600154036123705760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161189e565b6002600155565b5f6123856004828486613985565b61238e916139ac565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b0319821601612568575f8080808080806123d5896004818d613985565b8101906123e291906139dc565b9650965096509650965096509650336001600160a01b0316876001600160a01b0316146124225760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038616301461244b5760405163750643af60e01b815260040160405180910390fd5b8a8514612484576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169161251b919061369b565b5f604051808303815f865af19150503d805f8114612554576040519150601f19603f3d011682016040523d82523d5f602084013e612559565b606091505b50505050505050505050610752565b6001600160e01b031981166323f2ebc360e21b146125b2576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806125c78a6004818e613985565b8101906125d49190613a2b565b97509750975097509750975097509750336001600160a01b0316886001600160a01b0316146126165760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038716301461263f5760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f16916126c6919061369b565b5f604051808303815f865af19150503d805f81146126ff576040519150601f19603f3d011682016040523d82523d5f602084013e612704565b606091505b50505050505050505050505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611f909085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161224f565b80600161277660206002613b89565b612780919061372d565b605354106127ba576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f81546127c9906135e4565b918290555090505f5b6020811015612859578082901c6001166001036128055782603382602081106127fd576127fd6135bc565b015550505050565b60338160208110612818576128186135bc565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092508080612851906135e4565b9150506127d2565b50612286613b94565b60018055565b60685460ff166128a4576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f54610100900460ff166129425760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161189e565b610664612cbe565b6060604082511061296957818060200190518101906106ca9190613ba8565b8151602003612adc575f5b6020811080156129bb5750828181518110612991576129916135bc565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b156129d257806129ca816135e4565b915050612974565b805f03612a1457505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115612a2e57612a2e61311e565b6040519080825280601f01601f191660200182016040528015612a58576020820181803683370190505b5090505f5b82811015612ad457848181518110612a7757612a776135bc565b602001015160f81c60f81b828281518110612a9457612a946135bc565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080612acc816135e4565b915050612a5d565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b6068545f90610100900463ffffffff16158015612b3d575063ffffffff82166001145b15612b4f575063ffffffff8216612b77565b612b6464010000000063ffffffff8416613662565b612b749063ffffffff8516613679565b90505b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003611541576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612c2e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612d289092919063ffffffff16565b8051909150156122865780806020019051810190612c4c9190613c1a565b6122865760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161189e565b5f54610100900460ff166128625760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161189e565b606061098b84845f85855f80866001600160a01b03168587604051612d4d919061369b565b5f6040518083038185875af1925050503d805f8114612d87576040519150601f19603f3d011682016040523d82523d5f602084013e612d8c565b606091505b5091509150612d9d87838387612da8565b979650505050505050565b60608315612e165782515f03612e0f576001600160a01b0385163b612e0f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161189e565b508161098b565b61098b8383815115612e2b5781518083602001fd5b8060405162461bcd60e51b815260040161189e9190612fb8565b803563ffffffff81168114612b15575f80fd5b6001600160a01b0381168114612e6c575f80fd5b50565b5f8060408385031215612e80575f80fd5b612e8983612e45565b91506020830135612e9981612e58565b809150509250929050565b8015158114612e6c575f80fd5b5f8083601f840112612ec1575f80fd5b50813567ffffffffffffffff811115612ed8575f80fd5b602083019150836020828501011115612eef575f80fd5b9250929050565b5f805f805f60808688031215612f0a575f80fd5b612f1386612e45565b94506020860135612f2381612e58565b93506040860135612f3381612ea4565b9250606086013567ffffffffffffffff811115612f4e575f80fd5b612f5a88828901612eb1565b969995985093965092949392505050565b5f5b83811015612f85578181015183820152602001612f6d565b50505f910152565b5f8151808452612fa4816020860160208601612f6b565b601f01601f19169290920160200192915050565b602081525f612fca6020830184612f8d565b9392505050565b5f60208284031215612fe1575f80fd5b8135612fca81612e58565b60ff81168114612e6c575f80fd5b5f805f805f805f60e0888a031215613010575f80fd5b873561301b81612fec565b965061302960208901612e45565b9550604088013561303981612e58565b945061304760608901612e45565b9350608088013561305781612e58565b9699959850939692959460a0840135945060c09093013592915050565b5f805f60608486031215613086575f80fd5b61308f84612e45565b9250602084013561309f81612e58565b915060408401356130af81612e58565b809150509250925092565b5f602082840312156130ca575f80fd5b5035919050565b8061040081018310156106ca575f80fd5b5f805f61044084860312156130f5575f80fd5b8335925061310685602086016130d1565b91506131156104208501612e45565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561315b5761315b61311e565b604052919050565b5f67ffffffffffffffff82111561317c5761317c61311e565b50601f01601f191660200190565b5f61319c61319784613163565b613132565b90508281528383830111156131af575f80fd5b828260208301375f602084830101529392505050565b5f82601f8301126131d4575f80fd5b612fca8383356020850161318a565b5f805f805f60a086880312156131f7575f80fd5b61320086612e45565b9450602086013561321081612e58565b9350604086013567ffffffffffffffff8082111561322c575f80fd5b61323889838a016131c5565b9450606088013591508082111561324d575f80fd5b5061325a888289016131c5565b925050608086013561326b81612fec565b809150509295509295909350565b5f805f805f8060a0878903121561328e575f80fd5b61329787612e45565b955060208701356132a781612e58565b94506040870135935060608701356132be81612ea4565b9250608087013567ffffffffffffffff8111156132d9575f80fd5b6132e589828a01612eb1565b979a9699509497509295939492505050565b5f8060408385031215613308575f80fd5b61331183612e45565b915061331f60208401612e45565b90509250929050565b5f805f805f805f805f805f806109208d8f031215613344575f80fd5b61334e8e8e6130d1565b9b5061335e8e6104008f016130d1565b9a506108008d013599506108208d013598506108408d013597506133856108608e01612e45565b96506133956108808e0135612e58565b6108808d013595506133aa6108a08e01612e45565b94506133ba6108c08e0135612e58565b6108c08d013593506108e08d0135925067ffffffffffffffff6109008e013511156133e3575f80fd5b6133f48e6109008f01358f01612eb1565b81935080925050509295989b509295989b509295989b565b5f805f805f805f60c0888a031215613422575f80fd5b61342b88612e45565b9650602088013561343b81612e58565b955060408801359450606088013561345281612e58565b9350608088013561346281612ea4565b925060a088013567ffffffffffffffff81111561347d575f80fd5b6134898a828b01612eb1565b989b979a50959850939692959293505050565b5f805f805f8060c087890312156134b1575f80fd5b6134ba87612e45565b955060208701356134ca81612e58565b94506134d860408801612e45565b935060608701356134e881612e58565b925060808701356134f881612e58565b915060a087013567ffffffffffffffff811115613513575f80fd5b8701601f81018913613523575f80fd5b6135328982356020840161318a565b9150509295509295509295565b5f805f806104608587031215613553575f80fd5b8435935061356486602087016130d1565b92506135736104208601612e45565b939692955092936104400135925050565b600181811c9082168061359857607f821691505b6020821081036135b657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f600182016135f5576135f56135d0565b5060010190565b606081525f61360e6060830186612f8d565b82810360208401526136208186612f8d565b91505060ff83166040830152949350505050565b5f8351613645818460208801612f6b565b835190830190613659818360208801612f6b565b01949350505050565b80820281158282048414176106ca576106ca6135d0565b808201808211156106ca576106ca6135d0565b818382375f9101908152919050565b5f82516136ac818460208701612f6b565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681525f6001600160a01b03808716602084015280861660408401525060806060830152612d9d6080830184866136b6565b5f60208284031215613726575f80fd5b5051919050565b818103818111156106ca576106ca6135d0565b5f61010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c085015261379082850187612f8d565b925080851660e085015250509998505050505050505050565b6001600160a01b038516815263ffffffff84166020820152606060408201525f6137d76060830184866136b6565b9695505050505050565b601f821115612286575f81815260208120601f850160051c810160208610156138075750805b601f850160051c820191505b81811015610c7157828155600101613813565b815167ffffffffffffffff8111156138405761384061311e565b6138548161384e8454613584565b846137e1565b602080601f831160018114613887575f84156138705750858301515b5f19600386901b1c1916600185901b178555610c71565b5f85815260208120601f198616915b828110156138b557888601518255948401946001909101908401613896565b50858210156138d257878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f61010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c085015261393382850187896136b6565b925080851660e085015250509a9950505050505050505050565b5f6020828403121561395d575f80fd5b8151612fca81612fec565b63ffffffff818116838216019080821115612317576123176135d0565b5f8085851115613993575f80fd5b8386111561399f575f80fd5b5050820193919092039150565b6001600160e01b031981358181169160048510156139d45780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a0312156139f2575f80fd5b87356139fd81612e58565b96506020880135613a0d81612e58565b95506040880135945060608801359350608088013561305781612fec565b5f805f805f805f80610100898b031215613a43575f80fd5b8835613a4e81612e58565b97506020890135613a5e81612e58565b965060408901359550606089013594506080890135613a7c81612ea4565b935060a0890135613a8c81612fec565b979a969950949793969295929450505060c08201359160e0013590565b600181815b80851115613ae357815f1904821115613ac957613ac96135d0565b80851615613ad657918102915b93841c9390800290613aae565b509250929050565b5f82613af9575060016106ca565b81613b0557505f6106ca565b8160018114613b1b5760028114613b2557613b41565b60019150506106ca565b60ff841115613b3657613b366135d0565b50506001821b6106ca565b5060208310610133831016604e8410600b8410161715613b64575081810a6106ca565b613b6e8383613aa9565b805f1904821115613b8157613b816135d0565b029392505050565b5f612fca8383613aeb565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613bb8575f80fd5b815167ffffffffffffffff811115613bce575f80fd5b8201601f81018413613bde575f80fd5b8051613bec61319782613163565b818152856020838501011115613c00575f80fd5b613c11826020830160208601612f6b565b95945050505050565b5f60208284031215613c2a575f80fd5b8151612fca81612ea456fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220a78eddd2ec1bbf392884d4e37582400b71e4492a2a59eb380e2c913c347997b764736f6c63430008140033", + "deployedBytecode": "0x6080604052600436106101db575f3560e01c806383f24403116100fd578063ccaa2d1111610092578063ee25560b11610062578063ee25560b146105a9578063f5efcd79146105d4578063f811bff7146105f3578063fb57083414610612575f80fd5b8063ccaa2d111461053b578063cd5865791461055a578063d02103ca1461056d578063dbc1697614610595575f80fd5b8063bab161bf116100cd578063bab161bf146104b9578063be5831c7146104da578063c00f14ab146104fd578063cc4616321461051c575f80fd5b806383f244031461043d5780638ed7e3f21461045c578063aaa13cc21461047b578063b8b284d01461049a575f80fd5b80633cbc795b116101735780637843298b116101435780637843298b146103c257806379e2cf97146103e157806381b1c174146103f557806383c43a5514610429575f80fd5b80633cbc795b146103385780633e197043146103705780634b2f336d1461038f5780635ca1e165146103ae575f80fd5b806327aef4e8116101ae57806327aef4e81461026d5780632dfdf0b51461028e578063318aee3d146102b15780633c351e1014610319575f80fd5b806315064c96146101df5780632072f6c51461020d57806322e95f2c14610223578063240ff3781461025a575b5f80fd5b3480156101ea575f80fd5b506068546101f89060ff1681565b60405190151581526020015b60405180910390f35b348015610218575f80fd5b50610221610631565b005b34801561022e575f80fd5b5061024261023d366004612e6f565b610666565b6040516001600160a01b039091168152602001610204565b610221610268366004612ef6565b6106d0565b348015610278575f80fd5b50610281610759565b6040516102049190612fb8565b348015610299575f80fd5b506102a360535481565b604051908152602001610204565b3480156102bc575f80fd5b506102f56102cb366004612fd1565b606b6020525f908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201610204565b348015610324575f80fd5b50606d54610242906001600160a01b031681565b348015610343575f80fd5b50606d5461035b90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610204565b34801561037b575f80fd5b506102a361038a366004612ffa565b6107e5565b34801561039a575f80fd5b50606f54610242906001600160a01b031681565b3480156103b9575f80fd5b506102a361088e565b3480156103cd575f80fd5b506102426103dc366004613074565b61096a565b3480156103ec575f80fd5b50610221610993565b348015610400575f80fd5b5061024261040f3660046130ba565b606a6020525f90815260409020546001600160a01b031681565b348015610434575f80fd5b506102816109b4565b348015610448575f80fd5b506102a36104573660046130e2565b6109d3565b348015610467575f80fd5b50606c54610242906001600160a01b031681565b348015610486575f80fd5b506102426104953660046131e3565b610aa8565b3480156104a5575f80fd5b506102216104b4366004613279565b610be7565b3480156104c4575f80fd5b5060685461035b90610100900463ffffffff1681565b3480156104e5575f80fd5b5060685461035b90600160c81b900463ffffffff1681565b348015610508575f80fd5b50610281610517366004612fd1565b610c79565b348015610527575f80fd5b506101f86105363660046132f7565b610cbe565b348015610546575f80fd5b50610221610555366004613328565b610d46565b61022161056836600461340c565b611181565b348015610578575f80fd5b50606854610242906501000000000090046001600160a01b031681565b3480156105a0575f80fd5b5061022161154a565b3480156105b4575f80fd5b506102a36105c33660046130ba565b60696020525f908152604090205481565b3480156105df575f80fd5b506102216105ee366004613328565b61157d565b3480156105fe575f80fd5b5061022161060d36600461349c565b6117f9565b34801561061d575f80fd5b506101f861062c36600461353f565b611b14565b606c546001600160a01b0316331461065c57604051631736745960e31b815260040160405180910390fd5b610664611b2b565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091205f908152606a90915220546001600160a01b03165b92915050565b60685460ff16156106f457604051630bc011ff60e21b815260040160405180910390fd5b341580159061070d5750606f546001600160a01b031615155b15610744576040517f6f625c4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610752858534868686611b86565b5050505050565b606e805461076690613584565b80601f016020809104026020016040519081016040528092919081815260200182805461079290613584565b80156107dd5780601f106107b4576101008083540402835291602001916107dd565b820191905f5260205f20905b8154815290600101906020018083116107c057829003601f168201915b505050505081565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b6053545f90819081805b6020811015610961578083901c6001166001036108f557603381602081106108c2576108c26135bc565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610922565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080610959906135e4565b915050610898565b50919392505050565b5f61098b848461097985611c50565b61098286611d3a565b61049587611e1b565b949350505050565b605354606854600160c81b900463ffffffff16101561066457610664611ee8565b60405180611ba00160405280611b668152602001613c36611b66913981565b5f83815b6020811015610a9f57600163ffffffff8516821c81169003610a4257848160208110610a0557610a056135bc565b602002013582604051602001610a25929190918252602082015260400190565b604051602081830303815290604052805190602001209150610a8d565b81858260208110610a5557610a556135bc565b6020020135604051602001610a74929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80610a97816135e4565b9150506109d7565b50949350505050565b6040516001600160e01b031960e087901b1660208201526bffffffffffffffffffffffff19606086901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180611ba00160405280611b668152602001613c36611b669139898989604051602001610b30939291906135fc565b60408051601f1981840301815290829052610b4e9291602001613634565b60405160208183030381529060405280519060200120604051602001610bc394939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60685460ff1615610c0b57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b0316610c4d576040517fdde3cda700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f54610c63906001600160a01b031685611f96565b610c71868686868686611b86565b505050505050565b6060610c8482611c50565b610c8d83611d3a565b610c9684611e1b565b604051602001610ca8939291906135fc565b6040516020818303038152906040529050919050565b6068545f908190610100900463ffffffff16158015610ce3575063ffffffff83166001145b15610cf5575063ffffffff8316610d1d565b610d0a64010000000063ffffffff8516613662565b610d1a9063ffffffff8616613679565b90505b600881901c5f90815260696020526040902054600160ff9092169190911b908116149392505050565b60685460ff1615610d6a57604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614610d9a576040516302caf51760e11b815260040160405180910390fd5b610dcd8c8c8c8c8c610dc85f8e8e8e8e8e8e8e604051610dbb92919061368c565b60405180910390206107e5565b612006565b6001600160a01b038616610ecd57606f546001600160a01b0316610eb1575f6001600160a01b03851684825b6040519080825280601f01601f191660200182016040528015610e23576020820181803683370190505b50604051610e31919061369b565b5f6040518083038185875af1925050503d805f8114610e6b576040519150601f19603f3d011682016040523d82523d5f602084013e610e70565b606091505b5050905080610eab576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611117565b606f54610ec8906001600160a01b03168585612198565b611117565b606d546001600160a01b038781169116148015610efb5750606d5463ffffffff888116600160a01b90920416145b15610f12575f6001600160a01b0385168482610df9565b60685463ffffffff610100909104811690881603610f3e57610ec86001600160a01b038716858561220a565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201525f9060380160408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b031680611109575f610fe88386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061228b92505050565b9050610ff5818888612198565b80606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a8388886040516110fb9594939291906136de565b60405180910390a150611114565b611114818787612198565b50505b604080518b815263ffffffff891660208201526001600160a01b0388811682840152861660608201526080810185905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a1505050505050505050505050565b60685460ff16156111a557604051630bc011ff60e21b815260040160405180910390fd5b6111ad61231e565b60685463ffffffff6101009091048116908816036111de576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b0388166112da5788341461122a576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff1694509061125790613584565b80601f016020809104026020016040519081016040528092919081815260200182805461128390613584565b80156112ce5780601f106112a5576101008083540402835291602001916112ce565b820191905f5260205f20905b8154815290600101906020018083116112b157829003601f168201915b505050505091506114c1565b3415611312576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546001600160a01b039081169089160361133757611332888a611f96565b6114c1565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901561139757611386898b611f96565b6020810151815190955093506114b4565b85156113a9576113a9898b8989612377565b6040516370a0823160e01b81523060048201525f906001600160a01b038b16906370a0823190602401602060405180830381865afa1580156113ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114119190613716565b90506114286001600160a01b038b1633308e612716565b6040516370a0823160e01b81523060048201525f906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561146c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114909190613716565b905061149c828261372d565b6068548c9850610100900463ffffffff169650935050505b6114bd89610c79565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e8688605354604051611500989796959493929190613740565b60405180910390a16115266115215f85878f8f8789805190602001206107e5565b612767565b861561153457611534611ee8565b5050505061154160018055565b50505050505050565b606c546001600160a01b0316331461157557604051631736745960e31b815260040160405180910390fd5b610664612868565b60685460ff16156115a157604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff86811661010090920416146115d1576040516302caf51760e11b815260040160405180910390fd5b6115f38c8c8c8c8c610dc860018e8e8e8e8e8e8e604051610dbb92919061368c565b606f545f906001600160a01b03166116a657846001600160a01b031684888a868660405160240161162794939291906137a9565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161165c919061369b565b5f6040518083038185875af1925050503d805f8114611696576040519150601f19603f3d011682016040523d82523d5f602084013e61169b565b606091505b505080915050611757565b606f546116bd906001600160a01b03168686612198565b846001600160a01b0316878985856040516024016116de94939291906137a9565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b17905251611713919061369b565b5f604051808303815f865af19150503d805f811461174c576040519150601f19603f3d011682016040523d82523d5f602084013e611751565b606091505b50909150505b8061178e576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518c815263ffffffff8a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a150505050505050505050505050565b5f54610100900460ff161580801561181757505f54600160ff909116105b806118305750303b15801561183057505f5460ff166001145b6118a75760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805460ff1916600117905580156118c8575f805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8a16027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038781169190910291909117909155606c805473ffffffffffffffffffffffffffffffffffffffff191685831617905586166119a35763ffffffff85161561199e576040517f1a874c1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611abf565b606d805463ffffffff8716600160a01b027fffffffffffffffff0000000000000000000000000000000000000000000000009091166001600160a01b03891617179055606e6119f28382613826565b50611a915f801b6012604051602001611a7d91906060808252600d908201527f5772617070656420457468657200000000000000000000000000000000000000608082015260a0602082018190526004908201527f574554480000000000000000000000000000000000000000000000000000000060c082015260ff91909116604082015260e00190565b60405160208183030381529060405261228b565b606f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03929092169190911790555b611ac76128d8565b8015611541575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b5f81611b218686866109d3565b1495945050505050565b60685460ff1615611b4f57604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b60685463ffffffff610100909104811690871603611bb7576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338989898888605354604051611c0b999897969594939291906138e2565b60405180910390a1611c426115216001606860019054906101000a900463ffffffff16338a8a8a8989604051610dbb92919061368c565b8215610c7157610c71611ee8565b60408051600481526024810182526020810180516001600160e01b03167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611caf919061369b565b5f60405180830381855afa9150503d805f8114611ce7576040519150601f19603f3d011682016040523d82523d5f602084013e611cec565b606091505b509150915081611d31576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525061098b565b61098b8161294a565b60408051600481526024810182526020810180516001600160e01b03167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611d99919061369b565b5f60405180830381855afa9150503d805f8114611dd1576040519150601f19603f3d011682016040523d82523d5f602084013e611dd6565b606091505b509150915081611d31576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525061098b565b60408051600481526024810182526020810180516001600160e01b03167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f91829182916001600160a01b03861691611e79919061369b565b5f60405180830381855afa9150503d805f8114611eb1576040519150601f19603f3d011682016040523d82523d5f602084013e611eb6565b606091505b5091509150818015611ec9575080516020145b611ed457601261098b565b8080602001905181019061098b919061394d565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d611f4961088e565b6040518263ffffffff1660e01b8152600401611f6791815260200190565b5f604051808303815f87803b158015611f7e575f80fd5b505af1158015611f90573d5f803e3d5ffd5b50505050565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018290526001600160a01b03831690639dc29fac906044015f604051808303815f87803b158015611ff4575f80fd5b505af1158015610c71573d5f803e3d5ffd5b606854604080516020808201879052818301869052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f916501000000000090046001600160a01b03169063257b3632906084016020604051808303815f875af1158015612097573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120bb9190613716565b9050805f036120f5576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f806801000000000000000087161561213957869150612117848a8489611b14565b612134576040516338105f3b60e21b815260040160405180910390fd5b612183565b602087901c612149816001613968565b915087925061216461215c868c866109d3565b8a8389611b14565b612181576040516338105f3b60e21b815260040160405180910390fd5b505b61218d8282612b1a565b505050505050505050565b6040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018390528416906340c10f19906044015f604051808303815f87803b1580156121f8575f80fd5b505af1158015611541573d5f803e3d5ffd5b6040516001600160a01b0383166024820152604481018290526122869084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612bda565b505050565b5f8060405180611ba00160405280611b668152602001613c36611b669139836040516020016122bb929190613634565b6040516020818303038152906040529050838151602083015ff591506001600160a01b038216612317576040517fbefb092000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092915050565b6002600154036123705760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161189e565b6002600155565b5f6123856004828486613985565b61238e916139ac565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b0319821601612568575f8080808080806123d5896004818d613985565b8101906123e291906139dc565b9650965096509650965096509650336001600160a01b0316876001600160a01b0316146124225760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038616301461244b5760405163750643af60e01b815260040160405180910390fd5b8a8514612484576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169161251b919061369b565b5f604051808303815f865af19150503d805f8114612554576040519150601f19603f3d011682016040523d82523d5f602084013e612559565b606091505b50505050505050505050610752565b6001600160e01b031981166323f2ebc360e21b146125b2576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806125c78a6004818e613985565b8101906125d49190613a2b565b97509750975097509750975097509750336001600160a01b0316886001600160a01b0316146126165760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038716301461263f5760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f16916126c6919061369b565b5f604051808303815f865af19150503d805f81146126ff576040519150601f19603f3d011682016040523d82523d5f602084013e612704565b606091505b50505050505050505050505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611f909085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161224f565b80600161277660206002613b89565b612780919061372d565b605354106127ba576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f81546127c9906135e4565b918290555090505f5b6020811015612859578082901c6001166001036128055782603382602081106127fd576127fd6135bc565b015550505050565b60338160208110612818576128186135bc565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092508080612851906135e4565b9150506127d2565b50612286613b94565b60018055565b60685460ff166128a4576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f54610100900460ff166129425760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161189e565b610664612cbe565b6060604082511061296957818060200190518101906106ca9190613ba8565b8151602003612adc575f5b6020811080156129bb5750828181518110612991576129916135bc565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b156129d257806129ca816135e4565b915050612974565b805f03612a1457505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115612a2e57612a2e61311e565b6040519080825280601f01601f191660200182016040528015612a58576020820181803683370190505b5090505f5b82811015612ad457848181518110612a7757612a776135bc565b602001015160f81c60f81b828281518110612a9457612a946135bc565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080612acc816135e4565b915050612a5d565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b6068545f90610100900463ffffffff16158015612b3d575063ffffffff82166001145b15612b4f575063ffffffff8216612b77565b612b6464010000000063ffffffff8416613662565b612b749063ffffffff8516613679565b90505b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003611541576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612c2e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612d289092919063ffffffff16565b8051909150156122865780806020019051810190612c4c9190613c1a565b6122865760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161189e565b5f54610100900460ff166128625760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161189e565b606061098b84845f85855f80866001600160a01b03168587604051612d4d919061369b565b5f6040518083038185875af1925050503d805f8114612d87576040519150601f19603f3d011682016040523d82523d5f602084013e612d8c565b606091505b5091509150612d9d87838387612da8565b979650505050505050565b60608315612e165782515f03612e0f576001600160a01b0385163b612e0f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161189e565b508161098b565b61098b8383815115612e2b5781518083602001fd5b8060405162461bcd60e51b815260040161189e9190612fb8565b803563ffffffff81168114612b15575f80fd5b6001600160a01b0381168114612e6c575f80fd5b50565b5f8060408385031215612e80575f80fd5b612e8983612e45565b91506020830135612e9981612e58565b809150509250929050565b8015158114612e6c575f80fd5b5f8083601f840112612ec1575f80fd5b50813567ffffffffffffffff811115612ed8575f80fd5b602083019150836020828501011115612eef575f80fd5b9250929050565b5f805f805f60808688031215612f0a575f80fd5b612f1386612e45565b94506020860135612f2381612e58565b93506040860135612f3381612ea4565b9250606086013567ffffffffffffffff811115612f4e575f80fd5b612f5a88828901612eb1565b969995985093965092949392505050565b5f5b83811015612f85578181015183820152602001612f6d565b50505f910152565b5f8151808452612fa4816020860160208601612f6b565b601f01601f19169290920160200192915050565b602081525f612fca6020830184612f8d565b9392505050565b5f60208284031215612fe1575f80fd5b8135612fca81612e58565b60ff81168114612e6c575f80fd5b5f805f805f805f60e0888a031215613010575f80fd5b873561301b81612fec565b965061302960208901612e45565b9550604088013561303981612e58565b945061304760608901612e45565b9350608088013561305781612e58565b9699959850939692959460a0840135945060c09093013592915050565b5f805f60608486031215613086575f80fd5b61308f84612e45565b9250602084013561309f81612e58565b915060408401356130af81612e58565b809150509250925092565b5f602082840312156130ca575f80fd5b5035919050565b8061040081018310156106ca575f80fd5b5f805f61044084860312156130f5575f80fd5b8335925061310685602086016130d1565b91506131156104208501612e45565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561315b5761315b61311e565b604052919050565b5f67ffffffffffffffff82111561317c5761317c61311e565b50601f01601f191660200190565b5f61319c61319784613163565b613132565b90508281528383830111156131af575f80fd5b828260208301375f602084830101529392505050565b5f82601f8301126131d4575f80fd5b612fca8383356020850161318a565b5f805f805f60a086880312156131f7575f80fd5b61320086612e45565b9450602086013561321081612e58565b9350604086013567ffffffffffffffff8082111561322c575f80fd5b61323889838a016131c5565b9450606088013591508082111561324d575f80fd5b5061325a888289016131c5565b925050608086013561326b81612fec565b809150509295509295909350565b5f805f805f8060a0878903121561328e575f80fd5b61329787612e45565b955060208701356132a781612e58565b94506040870135935060608701356132be81612ea4565b9250608087013567ffffffffffffffff8111156132d9575f80fd5b6132e589828a01612eb1565b979a9699509497509295939492505050565b5f8060408385031215613308575f80fd5b61331183612e45565b915061331f60208401612e45565b90509250929050565b5f805f805f805f805f805f806109208d8f031215613344575f80fd5b61334e8e8e6130d1565b9b5061335e8e6104008f016130d1565b9a506108008d013599506108208d013598506108408d013597506133856108608e01612e45565b96506133956108808e0135612e58565b6108808d013595506133aa6108a08e01612e45565b94506133ba6108c08e0135612e58565b6108c08d013593506108e08d0135925067ffffffffffffffff6109008e013511156133e3575f80fd5b6133f48e6109008f01358f01612eb1565b81935080925050509295989b509295989b509295989b565b5f805f805f805f60c0888a031215613422575f80fd5b61342b88612e45565b9650602088013561343b81612e58565b955060408801359450606088013561345281612e58565b9350608088013561346281612ea4565b925060a088013567ffffffffffffffff81111561347d575f80fd5b6134898a828b01612eb1565b989b979a50959850939692959293505050565b5f805f805f8060c087890312156134b1575f80fd5b6134ba87612e45565b955060208701356134ca81612e58565b94506134d860408801612e45565b935060608701356134e881612e58565b925060808701356134f881612e58565b915060a087013567ffffffffffffffff811115613513575f80fd5b8701601f81018913613523575f80fd5b6135328982356020840161318a565b9150509295509295509295565b5f805f806104608587031215613553575f80fd5b8435935061356486602087016130d1565b92506135736104208601612e45565b939692955092936104400135925050565b600181811c9082168061359857607f821691505b6020821081036135b657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f600182016135f5576135f56135d0565b5060010190565b606081525f61360e6060830186612f8d565b82810360208401526136208186612f8d565b91505060ff83166040830152949350505050565b5f8351613645818460208801612f6b565b835190830190613659818360208801612f6b565b01949350505050565b80820281158282048414176106ca576106ca6135d0565b808201808211156106ca576106ca6135d0565b818382375f9101908152919050565b5f82516136ac818460208701612f6b565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681525f6001600160a01b03808716602084015280861660408401525060806060830152612d9d6080830184866136b6565b5f60208284031215613726575f80fd5b5051919050565b818103818111156106ca576106ca6135d0565b5f61010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c085015261379082850187612f8d565b925080851660e085015250509998505050505050505050565b6001600160a01b038516815263ffffffff84166020820152606060408201525f6137d76060830184866136b6565b9695505050505050565b601f821115612286575f81815260208120601f850160051c810160208610156138075750805b601f850160051c820191505b81811015610c7157828155600101613813565b815167ffffffffffffffff8111156138405761384061311e565b6138548161384e8454613584565b846137e1565b602080601f831160018114613887575f84156138705750858301515b5f19600386901b1c1916600185901b178555610c71565b5f85815260208120601f198616915b828110156138b557888601518255948401946001909101908401613896565b50858210156138d257878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f61010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c085015261393382850187896136b6565b925080851660e085015250509a9950505050505050505050565b5f6020828403121561395d575f80fd5b8151612fca81612fec565b63ffffffff818116838216019080821115612317576123176135d0565b5f8085851115613993575f80fd5b8386111561399f575f80fd5b5050820193919092039150565b6001600160e01b031981358181169160048510156139d45780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a0312156139f2575f80fd5b87356139fd81612e58565b96506020880135613a0d81612e58565b95506040880135945060608801359350608088013561305781612fec565b5f805f805f805f80610100898b031215613a43575f80fd5b8835613a4e81612e58565b97506020890135613a5e81612e58565b965060408901359550606089013594506080890135613a7c81612ea4565b935060a0890135613a8c81612fec565b979a969950949793969295929450505060c08201359160e0013590565b600181815b80851115613ae357815f1904821115613ac957613ac96135d0565b80851615613ad657918102915b93841c9390800290613aae565b509250929050565b5f82613af9575060016106ca565b81613b0557505f6106ca565b8160018114613b1b5760028114613b2557613b41565b60019150506106ca565b60ff841115613b3657613b366135d0565b50506001821b6106ca565b5060208310610133831016604e8410600b8410161715613b64575081810a6106ca565b613b6e8383613aa9565b805f1904821115613b8157613b816135d0565b029392505050565b5f612fca8383613aeb565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613bb8575f80fd5b815167ffffffffffffffff811115613bce575f80fd5b8201601f81018413613bde575f80fd5b8051613bec61319782613163565b818152856020838501011115613c00575f80fd5b613c11826020830160208601612f6b565b95945050505050565b5f60208284031215613c2a575f80fd5b8151612fca81612ea456fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220a78eddd2ec1bbf392884d4e37582400b71e4492a2a59eb380e2c913c347997b764736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMEtrog.json b/compiled-contracts/PolygonZkEVMEtrog.json index 1f516b57e..e9a81ec7f 100644 --- a/compiled-contracts/PolygonZkEVMEtrog.json +++ b/compiled-contracts/PolygonZkEVMEtrog.json @@ -1220,8 +1220,8 @@ "type": "function" } ], - "bytecode": "0x61010060405234801562000011575f80fd5b506040516200448a3803806200448a83398101604081905262000034916200006f565b6001600160a01b0393841660a052918316608052821660c0521660e052620000d4565b6001600160a01b03811681146200006c575f80fd5b50565b5f805f806080858703121562000083575f80fd5b8451620000908162000057565b6020860151909450620000a38162000057565b6040860151909350620000b68162000057565b6060860151909250620000c98162000057565b939692955090935050565b60805160a05160c05160e0516142cc620001be5f395f81816104fc0152818161097301528181610adf01528181610c5e01528181610dde01528181611160015281816115fb01528181611a4a01528181611b3f015281816126d901528181612752015281816127740152818161288901528181612a9f0152612b6401525f818161066801528181611d0901528181611e11015281816121ca01528181612f52015261302701525f818161073701528181610fd7015281816122780152612cac01525f81816107690152818161082601528181611a93015281816128200152612c8101526142cc5ff3fe608060405234801561000f575f80fd5b50600436106102e2575f3560e01c80637125702211610187578063c754c7ed116100dd578063d7bc90ff11610093578063eaeb077b1161006e578063eaeb077b1461079f578063f35dda47146107b2578063f851a440146107ba575f80fd5b8063d7bc90ff14610759578063e46761c414610764578063e7a7ed021461078b575f80fd5b8063c89e42df116100c3578063c89e42df146106ff578063cfa8ed4714610712578063d02103ca14610732575f80fd5b8063c754c7ed146106cf578063c7fffd4b146106f7575f80fd5b80639f26f8401161013d578063ada8f91911610118578063ada8f9191461069d578063b0afe154146106b0578063b910e0f9146106bc575f80fd5b80639f26f84014610650578063a3c573eb14610663578063a652f26c1461068a575f80fd5b80638c3d73011161016d5780638c3d73011461061a57806391cafe32146106225780639e00187714610635575f80fd5b806371257022146105cb5780637a5460c5146105de575f80fd5b806342308fab1161023c578063542028d5116101f25780636b8616ce116101cd5780636b8616ce146105905780636e05d2cd146105af5780636ff512cc146105b8575f80fd5b8063542028d51461056d578063669adece14610575578063676870d214610588575f80fd5b806349b7b8021161022257806349b7b802146104f75780634e4877061461051e57806352bdeb6d14610531575f80fd5b806342308fab146104b657806345605267146104be575f80fd5b8063267822471161029c5780633c351e10116102775780633c351e10146104015780633cbc795b1461042157806340b5de6c1461045e575f80fd5b806326782247146103875780632c111c06146103cc57806332c2d153146103ec575f80fd5b806305835f37116102cc57806305835f371461031c578063107bf28c1461036557806311e892d41461036d575f80fd5b8062d0295d146102e65780630350896314610301575b5f80fd5b6102ee6107df565b6040519081526020015b60405180910390f35b610309602081565b60405161ffff90911681526020016102f8565b6103586040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b6040516102f8919061356f565b6103586108e5565b61037560f981565b60405160ff90911681526020016102f8565b6001546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f8565b6008546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b6103ff6103fa3660046135c1565b610971565b005b6009546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b6009546104499074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f8565b6104857fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff0000000000000000000000000000000000000000000000000000000000000090911681526020016102f8565b6102ee602481565b6007546104de9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102f8565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6103ff61052c366004613600565b610a40565b6103586040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b610358610c4f565b6103ff61058336600461361b565b610c5c565b610309601f81565b6102ee61059e366004613600565b60066020525f908152604090205481565b6102ee60055481565b6103ff6105c6366004613645565b610d13565b6103ff6105d9366004613784565b610ddc565b6103586040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b6103ff611395565b6103ff610630366004613645565b611467565b6103a773a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b6103ff61065e366004613873565b61157f565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6103586106983660046138b2565b611c0b565b6103ff6106ab366004613645565b611fe9565b6102ee6405ca1ab1e081565b6103ff6106ca366004613923565b6120b2565b6007546104de90700100000000000000000000000000000000900467ffffffffffffffff1681565b61037560e481565b6103ff61070d3660046139a3565b612996565b6002546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6102ee635ca1ab1e81565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6007546104de9067ffffffffffffffff1681565b6103ff6107ad3660046139d5565b612a28565b610375601b81565b5f546103a79062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561086b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061088f9190613a46565b6007549091505f906108b99067ffffffffffffffff68010000000000000000820481169116613a8a565b67ffffffffffffffff169050805f036108d4575f9250505090565b6108de8183613ab2565b9250505090565b600480546108f290613aea565b80601f016020809104026020016040519081016040528092919081815260200182805461091e90613aea565b80156109695780601f1061094057610100808354040283529160200191610969565b820191905f5260205f20905b81548152906001019060200180831161094c57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146109e0576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596684604051610a3391815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610a96576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610add576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b6a9190613b3b565b610bcb5760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610610bcb576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546108f290613aea565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610ccb576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581905560405181815267ffffffffffffffff8316907f1125aaf62d132d8e2d02005114f8fc360ff204c3105e4f1a700a1340dc55d5b19060200160405180910390a25050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610d69576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c44565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610e4b576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff1615808015610e6957505f54600160ff909116105b80610e825750303b158015610e8257505f5460ff166001145b610f13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610f6f575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f610f7985612eef565b6009549091505f90610fc390889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff1685611c0b565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561103e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110629190613a46565b90505f808483858f611075600143613b5a565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af11580156111bb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111df9190613b73565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886003908161126f9190613bd3565b50600461127c8982613bd3565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e60405161131c93929190613ceb565b60405180910390a1505050505050801561138c575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146113e6576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146114bd576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff1661150c576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb90602001610c44565b60085473ffffffffffffffffffffffffffffffffffffffff1680158015906115bd575073ffffffffffffffffffffffffffffffffffffffff81163314155b156115f4576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611662573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116869190613b73565b6116909190613d29565b67ffffffffffffffff1611156116d2576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81900361170d576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611749576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff8082169161177191849168010000000000000000900416613d4a565b11156117a9576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b83811015611a44575f8787838181106117e4576117e4613d5d565b90506020028101906117f69190613d8a565b6117ff90613dc6565b90508361180b81613e4c565b825180516020918201208185015160408087015160608801519151959a509295505f94611877948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f908152600690935291205490915081146118ff576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f90815260066020526040812055611923600188613b5a565b84036119925742600760109054906101000a900467ffffffffffffffff1684604001516119509190613d29565b67ffffffffffffffff161115611992576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc016040516020818303038152906040528051906020012094505050508080611a3c90613e72565b9150506117c9565b50611aba7f000000000000000000000000000000000000000000000000000000000000000084611a726107df565b611a7c9190613ea9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190613151565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e7390611b8b908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015611ba7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bcb9190613b73565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f87604051602401611c3d96959493929190613ec0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f03611d8d5760f9601f8351611cd19190613f22565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e487604051602001611d779796959493929190613f3d565b6040516020818303038152906040529050611e91565b815161ffff1015611dca576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f9611dd9602083613f22565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b90000000000000000000000000000000000000000000000000000000000008152508588604051602001611e7e979695949392919061401f565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa158015611eef573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611f67576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f90611fac9084906405ca1ab1e090635ca1ab1e90601b907fff0000000000000000000000000000000000000000000000000000000000000090602001614101565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff16331461203f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c44565b60025473ffffffffffffffffffffffffffffffffffffffff163314612103576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f81900361213e576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e881111561217a576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612185602442613d4a565b8467ffffffffffffffff1611156121c8576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561222d575f80fd5b505af115801561223f573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff881660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa1580156122d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122f79190613a46565b905080612330576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b8581101561264c575f8c8c8381811061236c5761236c613d5d565b905060200281019061237e9190613d8a565b61238790613dc6565b8051805160209091012060408201519192509067ffffffffffffffff161561256757856123b381613e4c565b9650505f818360200151846040015185606001516040516020016124159493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f9081526006909352912054909150811461249d576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550612637565b8151516201d4c010156125a6576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b5050808061264490613e72565b915050612351565b5060075467ffffffffffffffff9081169084161115612697576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff8481169083161461274c575f6126bc8386613a8a565b90506126d267ffffffffffffffff821683613b5a565b915061270b7f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff16611a726107df565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b612848337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127ff9190613a46565b6128099190613ea9565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692919061322a565b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af11580156128e4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129089190613b73565b9050888414612943576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e7668760405161297f91815260200190565b60405180910390a250505050505050505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146129ec576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036129f88282613bd3565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c44919061356f565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590612a66575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612a9d576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b06573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b2a9190613b3b565b15612b61576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bcb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bef9190613a46565b905082811115612c2b576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115612c67576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612ca973ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633308461322a565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d379190613a46565b6007805491925067ffffffffffffffff909116905f612d5583613e4c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508585604051612d8c92919061415c565b6040519081900390208142612da2600143613b5a565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303612e98576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2612ee7565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93190612ede90849033908b908b9061416b565b60405180910390a25b505050505050565b606073ffffffffffffffffffffffffffffffffffffffff82161561314c576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015612f96573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612fdb91908101906141db565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa15801561306d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613091919061424d565b915091508163ffffffff165f14613108576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff841617179055613149565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526132259084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261328e565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526132889085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016131a3565b50505050565b5f6132ef826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166133999092919063ffffffff16565b805190915015613225578080602001905181019061330d9190613b3b565b613225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610f0a565b6060611fe184845f85855f808673ffffffffffffffffffffffffffffffffffffffff1685876040516133cb9190614285565b5f6040518083038185875af1925050503d805f8114613405576040519150601f19603f3d011682016040523d82523d5f602084013e61340a565b606091505b509150915061341b87838387613426565b979650505050505050565b606083156134bb5782515f036134b45773ffffffffffffffffffffffffffffffffffffffff85163b6134b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610f0a565b5081611fe1565b611fe183838151156134d05781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0a919061356f565b5f5b8381101561351e578181015183820152602001613506565b50505f910152565b5f815180845261353d816020860160208601613504565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f6135816020830184613526565b9392505050565b67ffffffffffffffff8116811461359d575f80fd5b50565b73ffffffffffffffffffffffffffffffffffffffff8116811461359d575f80fd5b5f805f606084860312156135d3575f80fd5b83356135de81613588565b92506020840135915060408401356135f5816135a0565b809150509250925092565b5f60208284031215613610575f80fd5b813561358181613588565b5f806040838503121561362c575f80fd5b823561363781613588565b946020939093013593505050565b5f60208284031215613655575f80fd5b8135613581816135a0565b63ffffffff8116811461359d575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156136e5576136e5613671565b604052919050565b5f67ffffffffffffffff82111561370657613706613671565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112613741575f80fd5b813561375461374f826136ed565b61369e565b818152846020838601011115613768575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060c08789031215613799575f80fd5b86356137a4816135a0565b955060208701356137b4816135a0565b945060408701356137c481613660565b935060608701356137d4816135a0565b9250608087013567ffffffffffffffff808211156137f0575f80fd5b6137fc8a838b01613732565b935060a0890135915080821115613811575f80fd5b5061381e89828a01613732565b9150509295509295509295565b5f8083601f84011261383b575f80fd5b50813567ffffffffffffffff811115613852575f80fd5b6020830191508360208260051b850101111561386c575f80fd5b9250929050565b5f8060208385031215613884575f80fd5b823567ffffffffffffffff81111561389a575f80fd5b6138a68582860161382b565b90969095509350505050565b5f805f80608085870312156138c5575f80fd5b84356138d081613660565b935060208501356138e0816135a0565b925060408501356138f081613660565b9150606085013567ffffffffffffffff81111561390b575f80fd5b61391787828801613732565b91505092959194509250565b5f805f805f8060a08789031215613938575f80fd5b863567ffffffffffffffff81111561394e575f80fd5b61395a89828a0161382b565b909750955050602087013561396e81613660565b9350604087013561397e81613588565b9250606087013591506080870135613995816135a0565b809150509295509295509295565b5f602082840312156139b3575f80fd5b813567ffffffffffffffff8111156139c9575f80fd5b611fe184828501613732565b5f805f604084860312156139e7575f80fd5b833567ffffffffffffffff808211156139fe575f80fd5b818601915086601f830112613a11575f80fd5b813581811115613a1f575f80fd5b876020828501011115613a30575f80fd5b6020928301989097509590910135949350505050565b5f60208284031215613a56575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff828116828216039080821115613aab57613aab613a5d565b5092915050565b5f82613ae5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c90821680613afe57607f821691505b602082108103613b35577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f60208284031215613b4b575f80fd5b81518015158114613581575f80fd5b81810381811115613b6d57613b6d613a5d565b92915050565b5f60208284031215613b83575f80fd5b815161358181613588565b601f821115613225575f81815260208120601f850160051c81016020861015613bb45750805b601f850160051c820191505b81811015612ee757828155600101613bc0565b815167ffffffffffffffff811115613bed57613bed613671565b613c0181613bfb8454613aea565b84613b8e565b602080601f831160018114613c53575f8415613c1d5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612ee7565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613c9f57888601518255948401946001909101908401613c80565b5085821015613cdb57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f613cfd6060830186613526565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff818116838216019080821115613aab57613aab613a5d565b80820180821115613b6d57613b6d613a5d565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112613dbc575f80fd5b9190910192915050565b5f60808236031215613dd6575f80fd5b6040516080810167ffffffffffffffff8282108183111715613dfa57613dfa613671565b816040528435915080821115613e0e575f80fd5b50613e1b36828601613732565b825250602083013560208201526040830135613e3681613588565b6040820152606092830135928101929092525090565b5f67ffffffffffffffff808316818103613e6857613e68613a5d565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613ea257613ea2613a5d565b5060010190565b8082028115828204841417613b6d57613b6d613a5d565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a0830152613f1660c0830184613526565b98975050505050505050565b61ffff818116838216019080821115613aab57613aab613a5d565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751613fa5816003860160208c01613504565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651613fe8816017840160208b01613504565b808201915050818660f81b1660178201528451915061400e826018830160208801613504565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b1660018401528751614087816003860160208c01613504565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b16600382015286516140ca816017840160208b01613504565b808201915050818660f01b166017820152845191506140f0826019830160208801613504565b016019019998505050505050505050565b5f8651614112818460208b01613504565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff8416602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b5f602082840312156141eb575f80fd5b815167ffffffffffffffff811115614201575f80fd5b8201601f81018413614211575f80fd5b805161421f61374f826136ed565b818152856020838501011115614233575f80fd5b614244826020830160208601613504565b95945050505050565b5f806040838503121561425e575f80fd5b825161426981613660565b602084015190925061427a816135a0565b809150509250929050565b5f8251613dbc81846020870161350456fea2646970667358221220e1b2a3530404a5d1a3c9fab3a211da5361432cb163ca402eebd128f30e6b490864736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102e2575f3560e01c80637125702211610187578063c754c7ed116100dd578063d7bc90ff11610093578063eaeb077b1161006e578063eaeb077b1461079f578063f35dda47146107b2578063f851a440146107ba575f80fd5b8063d7bc90ff14610759578063e46761c414610764578063e7a7ed021461078b575f80fd5b8063c89e42df116100c3578063c89e42df146106ff578063cfa8ed4714610712578063d02103ca14610732575f80fd5b8063c754c7ed146106cf578063c7fffd4b146106f7575f80fd5b80639f26f8401161013d578063ada8f91911610118578063ada8f9191461069d578063b0afe154146106b0578063b910e0f9146106bc575f80fd5b80639f26f84014610650578063a3c573eb14610663578063a652f26c1461068a575f80fd5b80638c3d73011161016d5780638c3d73011461061a57806391cafe32146106225780639e00187714610635575f80fd5b806371257022146105cb5780637a5460c5146105de575f80fd5b806342308fab1161023c578063542028d5116101f25780636b8616ce116101cd5780636b8616ce146105905780636e05d2cd146105af5780636ff512cc146105b8575f80fd5b8063542028d51461056d578063669adece14610575578063676870d214610588575f80fd5b806349b7b8021161022257806349b7b802146104f75780634e4877061461051e57806352bdeb6d14610531575f80fd5b806342308fab146104b657806345605267146104be575f80fd5b8063267822471161029c5780633c351e10116102775780633c351e10146104015780633cbc795b1461042157806340b5de6c1461045e575f80fd5b806326782247146103875780632c111c06146103cc57806332c2d153146103ec575f80fd5b806305835f37116102cc57806305835f371461031c578063107bf28c1461036557806311e892d41461036d575f80fd5b8062d0295d146102e65780630350896314610301575b5f80fd5b6102ee6107df565b6040519081526020015b60405180910390f35b610309602081565b60405161ffff90911681526020016102f8565b6103586040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b6040516102f8919061356f565b6103586108e5565b61037560f981565b60405160ff90911681526020016102f8565b6001546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f8565b6008546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b6103ff6103fa3660046135c1565b610971565b005b6009546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b6009546104499074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f8565b6104857fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff0000000000000000000000000000000000000000000000000000000000000090911681526020016102f8565b6102ee602481565b6007546104de9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102f8565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6103ff61052c366004613600565b610a40565b6103586040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b610358610c4f565b6103ff61058336600461361b565b610c5c565b610309601f81565b6102ee61059e366004613600565b60066020525f908152604090205481565b6102ee60055481565b6103ff6105c6366004613645565b610d13565b6103ff6105d9366004613784565b610ddc565b6103586040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b6103ff611395565b6103ff610630366004613645565b611467565b6103a773a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b6103ff61065e366004613873565b61157f565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6103586106983660046138b2565b611c0b565b6103ff6106ab366004613645565b611fe9565b6102ee6405ca1ab1e081565b6103ff6106ca366004613923565b6120b2565b6007546104de90700100000000000000000000000000000000900467ffffffffffffffff1681565b61037560e481565b6103ff61070d3660046139a3565b612996565b6002546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6102ee635ca1ab1e81565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6007546104de9067ffffffffffffffff1681565b6103ff6107ad3660046139d5565b612a28565b610375601b81565b5f546103a79062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561086b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061088f9190613a46565b6007549091505f906108b99067ffffffffffffffff68010000000000000000820481169116613a8a565b67ffffffffffffffff169050805f036108d4575f9250505090565b6108de8183613ab2565b9250505090565b600480546108f290613aea565b80601f016020809104026020016040519081016040528092919081815260200182805461091e90613aea565b80156109695780601f1061094057610100808354040283529160200191610969565b820191905f5260205f20905b81548152906001019060200180831161094c57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146109e0576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596684604051610a3391815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610a96576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610add576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b6a9190613b3b565b610bcb5760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610610bcb576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546108f290613aea565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610ccb576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581905560405181815267ffffffffffffffff8316907f1125aaf62d132d8e2d02005114f8fc360ff204c3105e4f1a700a1340dc55d5b19060200160405180910390a25050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610d69576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c44565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610e4b576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff1615808015610e6957505f54600160ff909116105b80610e825750303b158015610e8257505f5460ff166001145b610f13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610f6f575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f610f7985612eef565b6009549091505f90610fc390889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff1685611c0b565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561103e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110629190613a46565b90505f808483858f611075600143613b5a565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af11580156111bb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111df9190613b73565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886003908161126f9190613bd3565b50600461127c8982613bd3565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e60405161131c93929190613ceb565b60405180910390a1505050505050801561138c575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146113e6576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146114bd576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff1661150c576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb90602001610c44565b60085473ffffffffffffffffffffffffffffffffffffffff1680158015906115bd575073ffffffffffffffffffffffffffffffffffffffff81163314155b156115f4576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611662573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116869190613b73565b6116909190613d29565b67ffffffffffffffff1611156116d2576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81900361170d576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611749576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff8082169161177191849168010000000000000000900416613d4a565b11156117a9576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b83811015611a44575f8787838181106117e4576117e4613d5d565b90506020028101906117f69190613d8a565b6117ff90613dc6565b90508361180b81613e4c565b825180516020918201208185015160408087015160608801519151959a509295505f94611877948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f908152600690935291205490915081146118ff576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f90815260066020526040812055611923600188613b5a565b84036119925742600760109054906101000a900467ffffffffffffffff1684604001516119509190613d29565b67ffffffffffffffff161115611992576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc016040516020818303038152906040528051906020012094505050508080611a3c90613e72565b9150506117c9565b50611aba7f000000000000000000000000000000000000000000000000000000000000000084611a726107df565b611a7c9190613ea9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190613151565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e7390611b8b908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015611ba7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bcb9190613b73565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f87604051602401611c3d96959493929190613ec0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f03611d8d5760f9601f8351611cd19190613f22565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e487604051602001611d779796959493929190613f3d565b6040516020818303038152906040529050611e91565b815161ffff1015611dca576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f9611dd9602083613f22565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b90000000000000000000000000000000000000000000000000000000000008152508588604051602001611e7e979695949392919061401f565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa158015611eef573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611f67576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f90611fac9084906405ca1ab1e090635ca1ab1e90601b907fff0000000000000000000000000000000000000000000000000000000000000090602001614101565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff16331461203f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c44565b60025473ffffffffffffffffffffffffffffffffffffffff163314612103576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f81900361213e576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e881111561217a576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612185602442613d4a565b8467ffffffffffffffff1611156121c8576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561222d575f80fd5b505af115801561223f573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff881660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa1580156122d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122f79190613a46565b905080612330576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b8581101561264c575f8c8c8381811061236c5761236c613d5d565b905060200281019061237e9190613d8a565b61238790613dc6565b8051805160209091012060408201519192509067ffffffffffffffff161561256757856123b381613e4c565b9650505f818360200151846040015185606001516040516020016124159493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f9081526006909352912054909150811461249d576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550612637565b8151516201d4c010156125a6576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b5050808061264490613e72565b915050612351565b5060075467ffffffffffffffff9081169084161115612697576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff8481169083161461274c575f6126bc8386613a8a565b90506126d267ffffffffffffffff821683613b5a565b915061270b7f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff16611a726107df565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b612848337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127ff9190613a46565b6128099190613ea9565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692919061322a565b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af11580156128e4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129089190613b73565b9050888414612943576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e7668760405161297f91815260200190565b60405180910390a250505050505050505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146129ec576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036129f88282613bd3565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c44919061356f565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590612a66575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612a9d576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b06573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b2a9190613b3b565b15612b61576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bcb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bef9190613a46565b905082811115612c2b576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115612c67576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612ca973ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633308461322a565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d379190613a46565b6007805491925067ffffffffffffffff909116905f612d5583613e4c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508585604051612d8c92919061415c565b6040519081900390208142612da2600143613b5a565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303612e98576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2612ee7565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93190612ede90849033908b908b9061416b565b60405180910390a25b505050505050565b606073ffffffffffffffffffffffffffffffffffffffff82161561314c576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015612f96573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612fdb91908101906141db565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa15801561306d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613091919061424d565b915091508163ffffffff165f14613108576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff841617179055613149565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526132259084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261328e565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526132889085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016131a3565b50505050565b5f6132ef826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166133999092919063ffffffff16565b805190915015613225578080602001905181019061330d9190613b3b565b613225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610f0a565b6060611fe184845f85855f808673ffffffffffffffffffffffffffffffffffffffff1685876040516133cb9190614285565b5f6040518083038185875af1925050503d805f8114613405576040519150601f19603f3d011682016040523d82523d5f602084013e61340a565b606091505b509150915061341b87838387613426565b979650505050505050565b606083156134bb5782515f036134b45773ffffffffffffffffffffffffffffffffffffffff85163b6134b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610f0a565b5081611fe1565b611fe183838151156134d05781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0a919061356f565b5f5b8381101561351e578181015183820152602001613506565b50505f910152565b5f815180845261353d816020860160208601613504565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f6135816020830184613526565b9392505050565b67ffffffffffffffff8116811461359d575f80fd5b50565b73ffffffffffffffffffffffffffffffffffffffff8116811461359d575f80fd5b5f805f606084860312156135d3575f80fd5b83356135de81613588565b92506020840135915060408401356135f5816135a0565b809150509250925092565b5f60208284031215613610575f80fd5b813561358181613588565b5f806040838503121561362c575f80fd5b823561363781613588565b946020939093013593505050565b5f60208284031215613655575f80fd5b8135613581816135a0565b63ffffffff8116811461359d575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156136e5576136e5613671565b604052919050565b5f67ffffffffffffffff82111561370657613706613671565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112613741575f80fd5b813561375461374f826136ed565b61369e565b818152846020838601011115613768575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060c08789031215613799575f80fd5b86356137a4816135a0565b955060208701356137b4816135a0565b945060408701356137c481613660565b935060608701356137d4816135a0565b9250608087013567ffffffffffffffff808211156137f0575f80fd5b6137fc8a838b01613732565b935060a0890135915080821115613811575f80fd5b5061381e89828a01613732565b9150509295509295509295565b5f8083601f84011261383b575f80fd5b50813567ffffffffffffffff811115613852575f80fd5b6020830191508360208260051b850101111561386c575f80fd5b9250929050565b5f8060208385031215613884575f80fd5b823567ffffffffffffffff81111561389a575f80fd5b6138a68582860161382b565b90969095509350505050565b5f805f80608085870312156138c5575f80fd5b84356138d081613660565b935060208501356138e0816135a0565b925060408501356138f081613660565b9150606085013567ffffffffffffffff81111561390b575f80fd5b61391787828801613732565b91505092959194509250565b5f805f805f8060a08789031215613938575f80fd5b863567ffffffffffffffff81111561394e575f80fd5b61395a89828a0161382b565b909750955050602087013561396e81613660565b9350604087013561397e81613588565b9250606087013591506080870135613995816135a0565b809150509295509295509295565b5f602082840312156139b3575f80fd5b813567ffffffffffffffff8111156139c9575f80fd5b611fe184828501613732565b5f805f604084860312156139e7575f80fd5b833567ffffffffffffffff808211156139fe575f80fd5b818601915086601f830112613a11575f80fd5b813581811115613a1f575f80fd5b876020828501011115613a30575f80fd5b6020928301989097509590910135949350505050565b5f60208284031215613a56575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff828116828216039080821115613aab57613aab613a5d565b5092915050565b5f82613ae5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c90821680613afe57607f821691505b602082108103613b35577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f60208284031215613b4b575f80fd5b81518015158114613581575f80fd5b81810381811115613b6d57613b6d613a5d565b92915050565b5f60208284031215613b83575f80fd5b815161358181613588565b601f821115613225575f81815260208120601f850160051c81016020861015613bb45750805b601f850160051c820191505b81811015612ee757828155600101613bc0565b815167ffffffffffffffff811115613bed57613bed613671565b613c0181613bfb8454613aea565b84613b8e565b602080601f831160018114613c53575f8415613c1d5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612ee7565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613c9f57888601518255948401946001909101908401613c80565b5085821015613cdb57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f613cfd6060830186613526565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff818116838216019080821115613aab57613aab613a5d565b80820180821115613b6d57613b6d613a5d565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112613dbc575f80fd5b9190910192915050565b5f60808236031215613dd6575f80fd5b6040516080810167ffffffffffffffff8282108183111715613dfa57613dfa613671565b816040528435915080821115613e0e575f80fd5b50613e1b36828601613732565b825250602083013560208201526040830135613e3681613588565b6040820152606092830135928101929092525090565b5f67ffffffffffffffff808316818103613e6857613e68613a5d565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613ea257613ea2613a5d565b5060010190565b8082028115828204841417613b6d57613b6d613a5d565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a0830152613f1660c0830184613526565b98975050505050505050565b61ffff818116838216019080821115613aab57613aab613a5d565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751613fa5816003860160208c01613504565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651613fe8816017840160208b01613504565b808201915050818660f81b1660178201528451915061400e826018830160208801613504565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b1660018401528751614087816003860160208c01613504565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b16600382015286516140ca816017840160208b01613504565b808201915050818660f01b166017820152845191506140f0826019830160208801613504565b016019019998505050505050505050565b5f8651614112818460208b01613504565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff8416602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b5f602082840312156141eb575f80fd5b815167ffffffffffffffff811115614201575f80fd5b8201601f81018413614211575f80fd5b805161421f61374f826136ed565b818152856020838501011115614233575f80fd5b614244826020830160208601613504565b95945050505050565b5f806040838503121561425e575f80fd5b825161426981613660565b602084015190925061427a816135a0565b809150509250929050565b5f8251613dbc81846020870161350456fea2646970667358221220e1b2a3530404a5d1a3c9fab3a211da5361432cb163ca402eebd128f30e6b490864736f6c63430008140033", + "bytecode": "0x61010060405234801562000011575f80fd5b50604051620045693803806200456983398101604081905262000034916200014e565b6001600160a01b0380851660a05280841660805280831660c052811660e05283838383838383836200006562000077565b505050505050505050505050620001b3565b5f54610100900460ff1615620000e35760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116101562000134575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b03811681146200014b575f80fd5b50565b5f805f806080858703121562000162575f80fd5b84516200016f8162000136565b6020860151909450620001828162000136565b6040860151909350620001958162000136565b6060860151909250620001a88162000136565b939692955090935050565b60805160a05160c05160e0516142cc6200029d5f395f81816104fc0152818161097301528181610adf01528181610c5e01528181610dde01528181611160015281816115fb01528181611a4a01528181611b3f015281816126d901528181612752015281816127740152818161288901528181612a9f0152612b6401525f818161066801528181611d0901528181611e11015281816121ca01528181612f52015261302701525f818161073701528181610fd7015281816122780152612cac01525f81816107690152818161082601528181611a93015281816128200152612c8101526142cc5ff3fe608060405234801561000f575f80fd5b50600436106102e2575f3560e01c80637125702211610187578063c754c7ed116100dd578063d7bc90ff11610093578063eaeb077b1161006e578063eaeb077b1461079f578063f35dda47146107b2578063f851a440146107ba575f80fd5b8063d7bc90ff14610759578063e46761c414610764578063e7a7ed021461078b575f80fd5b8063c89e42df116100c3578063c89e42df146106ff578063cfa8ed4714610712578063d02103ca14610732575f80fd5b8063c754c7ed146106cf578063c7fffd4b146106f7575f80fd5b80639f26f8401161013d578063ada8f91911610118578063ada8f9191461069d578063b0afe154146106b0578063b910e0f9146106bc575f80fd5b80639f26f84014610650578063a3c573eb14610663578063a652f26c1461068a575f80fd5b80638c3d73011161016d5780638c3d73011461061a57806391cafe32146106225780639e00187714610635575f80fd5b806371257022146105cb5780637a5460c5146105de575f80fd5b806342308fab1161023c578063542028d5116101f25780636b8616ce116101cd5780636b8616ce146105905780636e05d2cd146105af5780636ff512cc146105b8575f80fd5b8063542028d51461056d578063669adece14610575578063676870d214610588575f80fd5b806349b7b8021161022257806349b7b802146104f75780634e4877061461051e57806352bdeb6d14610531575f80fd5b806342308fab146104b657806345605267146104be575f80fd5b8063267822471161029c5780633c351e10116102775780633c351e10146104015780633cbc795b1461042157806340b5de6c1461045e575f80fd5b806326782247146103875780632c111c06146103cc57806332c2d153146103ec575f80fd5b806305835f37116102cc57806305835f371461031c578063107bf28c1461036557806311e892d41461036d575f80fd5b8062d0295d146102e65780630350896314610301575b5f80fd5b6102ee6107df565b6040519081526020015b60405180910390f35b610309602081565b60405161ffff90911681526020016102f8565b6103586040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b6040516102f8919061356f565b6103586108e5565b61037560f981565b60405160ff90911681526020016102f8565b6001546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f8565b6008546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b6103ff6103fa3660046135c1565b610971565b005b6009546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b6009546104499074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f8565b6104857fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff0000000000000000000000000000000000000000000000000000000000000090911681526020016102f8565b6102ee602481565b6007546104de9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102f8565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6103ff61052c366004613600565b610a40565b6103586040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b610358610c4f565b6103ff61058336600461361b565b610c5c565b610309601f81565b6102ee61059e366004613600565b60066020525f908152604090205481565b6102ee60055481565b6103ff6105c6366004613645565b610d13565b6103ff6105d9366004613784565b610ddc565b6103586040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b6103ff611395565b6103ff610630366004613645565b611467565b6103a773a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b6103ff61065e366004613873565b61157f565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6103586106983660046138b2565b611c0b565b6103ff6106ab366004613645565b611fe9565b6102ee6405ca1ab1e081565b6103ff6106ca366004613923565b6120b2565b6007546104de90700100000000000000000000000000000000900467ffffffffffffffff1681565b61037560e481565b6103ff61070d3660046139a3565b612996565b6002546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6102ee635ca1ab1e81565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6007546104de9067ffffffffffffffff1681565b6103ff6107ad3660046139d5565b612a28565b610375601b81565b5f546103a79062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561086b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061088f9190613a46565b6007549091505f906108b99067ffffffffffffffff68010000000000000000820481169116613a8a565b67ffffffffffffffff169050805f036108d4575f9250505090565b6108de8183613ab2565b9250505090565b600480546108f290613aea565b80601f016020809104026020016040519081016040528092919081815260200182805461091e90613aea565b80156109695780601f1061094057610100808354040283529160200191610969565b820191905f5260205f20905b81548152906001019060200180831161094c57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146109e0576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596684604051610a3391815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610a96576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610add576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b6a9190613b3b565b610bcb5760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610610bcb576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546108f290613aea565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610ccb576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581905560405181815267ffffffffffffffff8316907f1125aaf62d132d8e2d02005114f8fc360ff204c3105e4f1a700a1340dc55d5b19060200160405180910390a25050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610d69576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c44565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610e4b576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff1615808015610e6957505f54600160ff909116105b80610e825750303b158015610e8257505f5460ff166001145b610f13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610f6f575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f610f7985612eef565b6009549091505f90610fc390889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff1685611c0b565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561103e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110629190613a46565b90505f808483858f611075600143613b5a565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af11580156111bb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111df9190613b73565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886003908161126f9190613bd3565b50600461127c8982613bd3565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e60405161131c93929190613ceb565b60405180910390a1505050505050801561138c575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146113e6576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146114bd576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff1661150c576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb90602001610c44565b60085473ffffffffffffffffffffffffffffffffffffffff1680158015906115bd575073ffffffffffffffffffffffffffffffffffffffff81163314155b156115f4576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611662573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116869190613b73565b6116909190613d29565b67ffffffffffffffff1611156116d2576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81900361170d576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611749576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff8082169161177191849168010000000000000000900416613d4a565b11156117a9576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b83811015611a44575f8787838181106117e4576117e4613d5d565b90506020028101906117f69190613d8a565b6117ff90613dc6565b90508361180b81613e4c565b825180516020918201208185015160408087015160608801519151959a509295505f94611877948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f908152600690935291205490915081146118ff576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f90815260066020526040812055611923600188613b5a565b84036119925742600760109054906101000a900467ffffffffffffffff1684604001516119509190613d29565b67ffffffffffffffff161115611992576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc016040516020818303038152906040528051906020012094505050508080611a3c90613e72565b9150506117c9565b50611aba7f000000000000000000000000000000000000000000000000000000000000000084611a726107df565b611a7c9190613ea9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190613151565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e7390611b8b908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015611ba7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bcb9190613b73565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f87604051602401611c3d96959493929190613ec0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f03611d8d5760f9601f8351611cd19190613f22565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e487604051602001611d779796959493929190613f3d565b6040516020818303038152906040529050611e91565b815161ffff1015611dca576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f9611dd9602083613f22565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b90000000000000000000000000000000000000000000000000000000000008152508588604051602001611e7e979695949392919061401f565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa158015611eef573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611f67576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f90611fac9084906405ca1ab1e090635ca1ab1e90601b907fff0000000000000000000000000000000000000000000000000000000000000090602001614101565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff16331461203f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c44565b60025473ffffffffffffffffffffffffffffffffffffffff163314612103576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f81900361213e576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e881111561217a576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612185602442613d4a565b8467ffffffffffffffff1611156121c8576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561222d575f80fd5b505af115801561223f573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff881660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa1580156122d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122f79190613a46565b905080612330576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b8581101561264c575f8c8c8381811061236c5761236c613d5d565b905060200281019061237e9190613d8a565b61238790613dc6565b8051805160209091012060408201519192509067ffffffffffffffff161561256757856123b381613e4c565b9650505f818360200151846040015185606001516040516020016124159493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f9081526006909352912054909150811461249d576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550612637565b8151516201d4c010156125a6576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b5050808061264490613e72565b915050612351565b5060075467ffffffffffffffff9081169084161115612697576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff8481169083161461274c575f6126bc8386613a8a565b90506126d267ffffffffffffffff821683613b5a565b915061270b7f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff16611a726107df565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b612848337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127ff9190613a46565b6128099190613ea9565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692919061322a565b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af11580156128e4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129089190613b73565b9050888414612943576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e7668760405161297f91815260200190565b60405180910390a250505050505050505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146129ec576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036129f88282613bd3565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c44919061356f565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590612a66575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612a9d576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b06573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b2a9190613b3b565b15612b61576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bcb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bef9190613a46565b905082811115612c2b576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115612c67576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612ca973ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633308461322a565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d379190613a46565b6007805491925067ffffffffffffffff909116905f612d5583613e4c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508585604051612d8c92919061415c565b6040519081900390208142612da2600143613b5a565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303612e98576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2612ee7565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93190612ede90849033908b908b9061416b565b60405180910390a25b505050505050565b606073ffffffffffffffffffffffffffffffffffffffff82161561314c576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015612f96573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612fdb91908101906141db565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa15801561306d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613091919061424d565b915091508163ffffffff165f14613108576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff841617179055613149565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526132259084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261328e565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526132889085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016131a3565b50505050565b5f6132ef826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166133999092919063ffffffff16565b805190915015613225578080602001905181019061330d9190613b3b565b613225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610f0a565b6060611fe184845f85855f808673ffffffffffffffffffffffffffffffffffffffff1685876040516133cb9190614285565b5f6040518083038185875af1925050503d805f8114613405576040519150601f19603f3d011682016040523d82523d5f602084013e61340a565b606091505b509150915061341b87838387613426565b979650505050505050565b606083156134bb5782515f036134b45773ffffffffffffffffffffffffffffffffffffffff85163b6134b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610f0a565b5081611fe1565b611fe183838151156134d05781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0a919061356f565b5f5b8381101561351e578181015183820152602001613506565b50505f910152565b5f815180845261353d816020860160208601613504565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f6135816020830184613526565b9392505050565b67ffffffffffffffff8116811461359d575f80fd5b50565b73ffffffffffffffffffffffffffffffffffffffff8116811461359d575f80fd5b5f805f606084860312156135d3575f80fd5b83356135de81613588565b92506020840135915060408401356135f5816135a0565b809150509250925092565b5f60208284031215613610575f80fd5b813561358181613588565b5f806040838503121561362c575f80fd5b823561363781613588565b946020939093013593505050565b5f60208284031215613655575f80fd5b8135613581816135a0565b63ffffffff8116811461359d575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156136e5576136e5613671565b604052919050565b5f67ffffffffffffffff82111561370657613706613671565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112613741575f80fd5b813561375461374f826136ed565b61369e565b818152846020838601011115613768575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060c08789031215613799575f80fd5b86356137a4816135a0565b955060208701356137b4816135a0565b945060408701356137c481613660565b935060608701356137d4816135a0565b9250608087013567ffffffffffffffff808211156137f0575f80fd5b6137fc8a838b01613732565b935060a0890135915080821115613811575f80fd5b5061381e89828a01613732565b9150509295509295509295565b5f8083601f84011261383b575f80fd5b50813567ffffffffffffffff811115613852575f80fd5b6020830191508360208260051b850101111561386c575f80fd5b9250929050565b5f8060208385031215613884575f80fd5b823567ffffffffffffffff81111561389a575f80fd5b6138a68582860161382b565b90969095509350505050565b5f805f80608085870312156138c5575f80fd5b84356138d081613660565b935060208501356138e0816135a0565b925060408501356138f081613660565b9150606085013567ffffffffffffffff81111561390b575f80fd5b61391787828801613732565b91505092959194509250565b5f805f805f8060a08789031215613938575f80fd5b863567ffffffffffffffff81111561394e575f80fd5b61395a89828a0161382b565b909750955050602087013561396e81613660565b9350604087013561397e81613588565b9250606087013591506080870135613995816135a0565b809150509295509295509295565b5f602082840312156139b3575f80fd5b813567ffffffffffffffff8111156139c9575f80fd5b611fe184828501613732565b5f805f604084860312156139e7575f80fd5b833567ffffffffffffffff808211156139fe575f80fd5b818601915086601f830112613a11575f80fd5b813581811115613a1f575f80fd5b876020828501011115613a30575f80fd5b6020928301989097509590910135949350505050565b5f60208284031215613a56575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff828116828216039080821115613aab57613aab613a5d565b5092915050565b5f82613ae5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c90821680613afe57607f821691505b602082108103613b35577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f60208284031215613b4b575f80fd5b81518015158114613581575f80fd5b81810381811115613b6d57613b6d613a5d565b92915050565b5f60208284031215613b83575f80fd5b815161358181613588565b601f821115613225575f81815260208120601f850160051c81016020861015613bb45750805b601f850160051c820191505b81811015612ee757828155600101613bc0565b815167ffffffffffffffff811115613bed57613bed613671565b613c0181613bfb8454613aea565b84613b8e565b602080601f831160018114613c53575f8415613c1d5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612ee7565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613c9f57888601518255948401946001909101908401613c80565b5085821015613cdb57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f613cfd6060830186613526565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff818116838216019080821115613aab57613aab613a5d565b80820180821115613b6d57613b6d613a5d565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112613dbc575f80fd5b9190910192915050565b5f60808236031215613dd6575f80fd5b6040516080810167ffffffffffffffff8282108183111715613dfa57613dfa613671565b816040528435915080821115613e0e575f80fd5b50613e1b36828601613732565b825250602083013560208201526040830135613e3681613588565b6040820152606092830135928101929092525090565b5f67ffffffffffffffff808316818103613e6857613e68613a5d565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613ea257613ea2613a5d565b5060010190565b8082028115828204841417613b6d57613b6d613a5d565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a0830152613f1660c0830184613526565b98975050505050505050565b61ffff818116838216019080821115613aab57613aab613a5d565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751613fa5816003860160208c01613504565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651613fe8816017840160208b01613504565b808201915050818660f81b1660178201528451915061400e826018830160208801613504565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b1660018401528751614087816003860160208c01613504565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b16600382015286516140ca816017840160208b01613504565b808201915050818660f01b166017820152845191506140f0826019830160208801613504565b016019019998505050505050505050565b5f8651614112818460208b01613504565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff8416602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b5f602082840312156141eb575f80fd5b815167ffffffffffffffff811115614201575f80fd5b8201601f81018413614211575f80fd5b805161421f61374f826136ed565b818152856020838501011115614233575f80fd5b614244826020830160208601613504565b95945050505050565b5f806040838503121561425e575f80fd5b825161426981613660565b602084015190925061427a816135a0565b809150509250929050565b5f8251613dbc81846020870161350456fea26469706673582212205ddecaf86c46faffb47796695a1c8d3aa7161a8585c78896c188600c5892570464736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102e2575f3560e01c80637125702211610187578063c754c7ed116100dd578063d7bc90ff11610093578063eaeb077b1161006e578063eaeb077b1461079f578063f35dda47146107b2578063f851a440146107ba575f80fd5b8063d7bc90ff14610759578063e46761c414610764578063e7a7ed021461078b575f80fd5b8063c89e42df116100c3578063c89e42df146106ff578063cfa8ed4714610712578063d02103ca14610732575f80fd5b8063c754c7ed146106cf578063c7fffd4b146106f7575f80fd5b80639f26f8401161013d578063ada8f91911610118578063ada8f9191461069d578063b0afe154146106b0578063b910e0f9146106bc575f80fd5b80639f26f84014610650578063a3c573eb14610663578063a652f26c1461068a575f80fd5b80638c3d73011161016d5780638c3d73011461061a57806391cafe32146106225780639e00187714610635575f80fd5b806371257022146105cb5780637a5460c5146105de575f80fd5b806342308fab1161023c578063542028d5116101f25780636b8616ce116101cd5780636b8616ce146105905780636e05d2cd146105af5780636ff512cc146105b8575f80fd5b8063542028d51461056d578063669adece14610575578063676870d214610588575f80fd5b806349b7b8021161022257806349b7b802146104f75780634e4877061461051e57806352bdeb6d14610531575f80fd5b806342308fab146104b657806345605267146104be575f80fd5b8063267822471161029c5780633c351e10116102775780633c351e10146104015780633cbc795b1461042157806340b5de6c1461045e575f80fd5b806326782247146103875780632c111c06146103cc57806332c2d153146103ec575f80fd5b806305835f37116102cc57806305835f371461031c578063107bf28c1461036557806311e892d41461036d575f80fd5b8062d0295d146102e65780630350896314610301575b5f80fd5b6102ee6107df565b6040519081526020015b60405180910390f35b610309602081565b60405161ffff90911681526020016102f8565b6103586040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b6040516102f8919061356f565b6103586108e5565b61037560f981565b60405160ff90911681526020016102f8565b6001546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f8565b6008546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b6103ff6103fa3660046135c1565b610971565b005b6009546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b6009546104499074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f8565b6104857fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff0000000000000000000000000000000000000000000000000000000000000090911681526020016102f8565b6102ee602481565b6007546104de9068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102f8565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6103ff61052c366004613600565b610a40565b6103586040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b610358610c4f565b6103ff61058336600461361b565b610c5c565b610309601f81565b6102ee61059e366004613600565b60066020525f908152604090205481565b6102ee60055481565b6103ff6105c6366004613645565b610d13565b6103ff6105d9366004613784565b610ddc565b6103586040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b6103ff611395565b6103ff610630366004613645565b611467565b6103a773a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b6103ff61065e366004613873565b61157f565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6103586106983660046138b2565b611c0b565b6103ff6106ab366004613645565b611fe9565b6102ee6405ca1ab1e081565b6103ff6106ca366004613923565b6120b2565b6007546104de90700100000000000000000000000000000000900467ffffffffffffffff1681565b61037560e481565b6103ff61070d3660046139a3565b612996565b6002546103a79073ffffffffffffffffffffffffffffffffffffffff1681565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6102ee635ca1ab1e81565b6103a77f000000000000000000000000000000000000000000000000000000000000000081565b6007546104de9067ffffffffffffffff1681565b6103ff6107ad3660046139d5565b612a28565b610375601b81565b5f546103a79062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561086b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061088f9190613a46565b6007549091505f906108b99067ffffffffffffffff68010000000000000000820481169116613a8a565b67ffffffffffffffff169050805f036108d4575f9250505090565b6108de8183613ab2565b9250505090565b600480546108f290613aea565b80601f016020809104026020016040519081016040528092919081815260200182805461091e90613aea565b80156109695780601f1061094057610100808354040283529160200191610969565b820191905f5260205f20905b81548152906001019060200180831161094c57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146109e0576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596684604051610a3391815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610a96576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610add576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b6a9190613b3b565b610bcb5760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610610bcb576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546108f290613aea565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610ccb576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581905560405181815267ffffffffffffffff8316907f1125aaf62d132d8e2d02005114f8fc360ff204c3105e4f1a700a1340dc55d5b19060200160405180910390a25050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610d69576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c44565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610e4b576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff1615808015610e6957505f54600160ff909116105b80610e825750303b158015610e8257505f5460ff166001145b610f13576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610f6f575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f610f7985612eef565b6009549091505f90610fc390889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff1685611c0b565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561103e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110629190613a46565b90505f808483858f611075600143613b5a565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af11580156111bb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111df9190613b73565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886003908161126f9190613bd3565b50600461127c8982613bd3565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e60405161131c93929190613ceb565b60405180910390a1505050505050801561138c575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146113e6576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146114bd576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff1661150c576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb90602001610c44565b60085473ffffffffffffffffffffffffffffffffffffffff1680158015906115bd575073ffffffffffffffffffffffffffffffffffffffff81163314155b156115f4576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611662573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116869190613b73565b6116909190613d29565b67ffffffffffffffff1611156116d2576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81900361170d576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611749576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff8082169161177191849168010000000000000000900416613d4a565b11156117a9576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b83811015611a44575f8787838181106117e4576117e4613d5d565b90506020028101906117f69190613d8a565b6117ff90613dc6565b90508361180b81613e4c565b825180516020918201208185015160408087015160608801519151959a509295505f94611877948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f908152600690935291205490915081146118ff576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f90815260066020526040812055611923600188613b5a565b84036119925742600760109054906101000a900467ffffffffffffffff1684604001516119509190613d29565b67ffffffffffffffff161115611992576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc016040516020818303038152906040528051906020012094505050508080611a3c90613e72565b9150506117c9565b50611aba7f000000000000000000000000000000000000000000000000000000000000000084611a726107df565b611a7c9190613ea9565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190613151565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e7390611b8b908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015611ba7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bcb9190613b73565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f87604051602401611c3d96959493929190613ec0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f03611d8d5760f9601f8351611cd19190613f22565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e487604051602001611d779796959493929190613f3d565b6040516020818303038152906040529050611e91565b815161ffff1015611dca576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f9611dd9602083613f22565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b90000000000000000000000000000000000000000000000000000000000008152508588604051602001611e7e979695949392919061401f565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa158015611eef573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611f67576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f90611fac9084906405ca1ab1e090635ca1ab1e90601b907fff0000000000000000000000000000000000000000000000000000000000000090602001614101565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff16331461203f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c44565b60025473ffffffffffffffffffffffffffffffffffffffff163314612103576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f81900361213e576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e881111561217a576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612185602442613d4a565b8467ffffffffffffffff1611156121c8576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561222d575f80fd5b505af115801561223f573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff881660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa1580156122d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122f79190613a46565b905080612330576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b8581101561264c575f8c8c8381811061236c5761236c613d5d565b905060200281019061237e9190613d8a565b61238790613dc6565b8051805160209091012060408201519192509067ffffffffffffffff161561256757856123b381613e4c565b9650505f818360200151846040015185606001516040516020016124159493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f9081526006909352912054909150811461249d576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550612637565b8151516201d4c010156125a6576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b5050808061264490613e72565b915050612351565b5060075467ffffffffffffffff9081169084161115612697576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff8481169083161461274c575f6126bc8386613a8a565b90506126d267ffffffffffffffff821683613b5a565b915061270b7f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff16611a726107df565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b612848337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa1580156127db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127ff9190613a46565b6128099190613ea9565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001692919061322a565b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af11580156128e4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129089190613b73565b9050888414612943576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e7668760405161297f91815260200190565b60405180910390a250505050505050505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146129ec576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60036129f88282613bd3565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c44919061356f565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590612a66575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612a9d576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b06573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b2a9190613b3b565b15612b61576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bcb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bef9190613a46565b905082811115612c2b576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115612c67576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612ca973ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633308461322a565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d379190613a46565b6007805491925067ffffffffffffffff909116905f612d5583613e4c565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508585604051612d8c92919061415c565b6040519081900390208142612da2600143613b5a565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303612e98576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2612ee7565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93190612ede90849033908b908b9061416b565b60405180910390a25b505050505050565b606073ffffffffffffffffffffffffffffffffffffffff82161561314c576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015612f96573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612fdb91908101906141db565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa15801561306d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613091919061424d565b915091508163ffffffff165f14613108576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff841617179055613149565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526132259084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261328e565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526132889085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016131a3565b50505050565b5f6132ef826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166133999092919063ffffffff16565b805190915015613225578080602001905181019061330d9190613b3b565b613225576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610f0a565b6060611fe184845f85855f808673ffffffffffffffffffffffffffffffffffffffff1685876040516133cb9190614285565b5f6040518083038185875af1925050503d805f8114613405576040519150601f19603f3d011682016040523d82523d5f602084013e61340a565b606091505b509150915061341b87838387613426565b979650505050505050565b606083156134bb5782515f036134b45773ffffffffffffffffffffffffffffffffffffffff85163b6134b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610f0a565b5081611fe1565b611fe183838151156134d05781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0a919061356f565b5f5b8381101561351e578181015183820152602001613506565b50505f910152565b5f815180845261353d816020860160208601613504565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f6135816020830184613526565b9392505050565b67ffffffffffffffff8116811461359d575f80fd5b50565b73ffffffffffffffffffffffffffffffffffffffff8116811461359d575f80fd5b5f805f606084860312156135d3575f80fd5b83356135de81613588565b92506020840135915060408401356135f5816135a0565b809150509250925092565b5f60208284031215613610575f80fd5b813561358181613588565b5f806040838503121561362c575f80fd5b823561363781613588565b946020939093013593505050565b5f60208284031215613655575f80fd5b8135613581816135a0565b63ffffffff8116811461359d575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156136e5576136e5613671565b604052919050565b5f67ffffffffffffffff82111561370657613706613671565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112613741575f80fd5b813561375461374f826136ed565b61369e565b818152846020838601011115613768575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060c08789031215613799575f80fd5b86356137a4816135a0565b955060208701356137b4816135a0565b945060408701356137c481613660565b935060608701356137d4816135a0565b9250608087013567ffffffffffffffff808211156137f0575f80fd5b6137fc8a838b01613732565b935060a0890135915080821115613811575f80fd5b5061381e89828a01613732565b9150509295509295509295565b5f8083601f84011261383b575f80fd5b50813567ffffffffffffffff811115613852575f80fd5b6020830191508360208260051b850101111561386c575f80fd5b9250929050565b5f8060208385031215613884575f80fd5b823567ffffffffffffffff81111561389a575f80fd5b6138a68582860161382b565b90969095509350505050565b5f805f80608085870312156138c5575f80fd5b84356138d081613660565b935060208501356138e0816135a0565b925060408501356138f081613660565b9150606085013567ffffffffffffffff81111561390b575f80fd5b61391787828801613732565b91505092959194509250565b5f805f805f8060a08789031215613938575f80fd5b863567ffffffffffffffff81111561394e575f80fd5b61395a89828a0161382b565b909750955050602087013561396e81613660565b9350604087013561397e81613588565b9250606087013591506080870135613995816135a0565b809150509295509295509295565b5f602082840312156139b3575f80fd5b813567ffffffffffffffff8111156139c9575f80fd5b611fe184828501613732565b5f805f604084860312156139e7575f80fd5b833567ffffffffffffffff808211156139fe575f80fd5b818601915086601f830112613a11575f80fd5b813581811115613a1f575f80fd5b876020828501011115613a30575f80fd5b6020928301989097509590910135949350505050565b5f60208284031215613a56575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff828116828216039080821115613aab57613aab613a5d565b5092915050565b5f82613ae5577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c90821680613afe57607f821691505b602082108103613b35577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f60208284031215613b4b575f80fd5b81518015158114613581575f80fd5b81810381811115613b6d57613b6d613a5d565b92915050565b5f60208284031215613b83575f80fd5b815161358181613588565b601f821115613225575f81815260208120601f850160051c81016020861015613bb45750805b601f850160051c820191505b81811015612ee757828155600101613bc0565b815167ffffffffffffffff811115613bed57613bed613671565b613c0181613bfb8454613aea565b84613b8e565b602080601f831160018114613c53575f8415613c1d5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612ee7565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613c9f57888601518255948401946001909101908401613c80565b5085821015613cdb57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f613cfd6060830186613526565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff818116838216019080821115613aab57613aab613a5d565b80820180821115613b6d57613b6d613a5d565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112613dbc575f80fd5b9190910192915050565b5f60808236031215613dd6575f80fd5b6040516080810167ffffffffffffffff8282108183111715613dfa57613dfa613671565b816040528435915080821115613e0e575f80fd5b50613e1b36828601613732565b825250602083013560208201526040830135613e3681613588565b6040820152606092830135928101929092525090565b5f67ffffffffffffffff808316818103613e6857613e68613a5d565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613ea257613ea2613a5d565b5060010190565b8082028115828204841417613b6d57613b6d613a5d565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a0830152613f1660c0830184613526565b98975050505050505050565b61ffff818116838216019080821115613aab57613aab613a5d565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751613fa5816003860160208c01613504565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651613fe8816017840160208b01613504565b808201915050818660f81b1660178201528451915061400e826018830160208801613504565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b1660018401528751614087816003860160208c01613504565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b16600382015286516140ca816017840160208b01613504565b808201915050818660f01b166017820152845191506140f0826019830160208801613504565b016019019998505050505050505050565b5f8651614112818460208b01613504565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff8416602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b5f602082840312156141eb575f80fd5b815167ffffffffffffffff811115614201575f80fd5b8201601f81018413614211575f80fd5b805161421f61374f826136ed565b818152856020838501011115614233575f80fd5b614244826020830160208601613504565b95945050505050565b5f806040838503121561425e575f80fd5b825161426981613660565b602084015190925061427a816135a0565b809150509250929050565b5f8251613dbc81846020870161350456fea26469706673582212205ddecaf86c46faffb47796695a1c8d3aa7161a8585c78896c188600c5892570464736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMEtrogPrevious.json b/compiled-contracts/PolygonZkEVMEtrogPrevious.json index b1466f20c..3109847e8 100644 --- a/compiled-contracts/PolygonZkEVMEtrogPrevious.json +++ b/compiled-contracts/PolygonZkEVMEtrogPrevious.json @@ -1178,8 +1178,8 @@ "type": "function" } ], - "bytecode": "0x61010060405234801562000011575f80fd5b506040516200433b3803806200433b83398101604081905262000034916200006f565b6001600160a01b0393841660a052918316608052821660c0521660e052620000d4565b6001600160a01b03811681146200006c575f80fd5b50565b5f805f806080858703121562000083575f80fd5b8451620000908162000057565b6020860151909450620000a38162000057565b6040860151909350620000b68162000057565b6060860151909250620000c98162000057565b939692955090935050565b60805160a05160c05160e051614184620001b75f395f81816104f10152818161095501528181610ac101528181610d090152818161108b015281816115260152818161197501528181611a6a01528181612639015281816126b2015281816126d4015281816127e9015281816129890152612a4e01525f818161064a01528181611c3401528181611d3c0152818161218701528181612e3c0152612f1101525f818161070601528181610f02015281816122030152612b9601525f818161074b01528181610808015281816119be015281816127800152612b6b01526141845ff3fe608060405234801561000f575f80fd5b50600436106102d7575f3560e01c80637125702211610187578063c7fffd4b116100dd578063def57e5411610093578063eaeb077b1161006e578063eaeb077b14610781578063f35dda4714610794578063f851a4401461079c575f80fd5b8063def57e5414610733578063e46761c414610746578063e7a7ed021461076d575f80fd5b8063cfa8ed47116100c3578063cfa8ed47146106e1578063d02103ca14610701578063d7bc90ff14610728575f80fd5b8063c7fffd4b146106c6578063c89e42df146106ce575f80fd5b80639f26f8401161013d578063ada8f91911610118578063ada8f9191461067f578063b0afe15414610692578063c754c7ed1461069e575f80fd5b80639f26f84014610632578063a3c573eb14610645578063a652f26c1461066c575f80fd5b80638c3d73011161016d5780638c3d7301146105fc57806391cafe32146106045780639e00187714610617575f80fd5b806371257022146105ad5780637a5460c5146105c0575f80fd5b806340b5de6c1161023c57806352bdeb6d116101f25780636b8616ce116101cd5780636b8616ce146105725780636e05d2cd146105915780636ff512cc1461059a575f80fd5b806352bdeb6d14610526578063542028d514610562578063676870d21461056a575f80fd5b8063456052671161022257806345605267146104b357806349b7b802146104ec5780634e48770614610513575f80fd5b806340b5de6c1461045357806342308fab146104ab575f80fd5b8063267822471161029157806332c2d1531161027757806332c2d153146103e15780633c351e10146103f65780633cbc795b14610416575f80fd5b8063267822471461037c5780632c111c06146103c1575f80fd5b806305835f37116102c157806305835f3714610311578063107bf28c1461035a57806311e892d414610362575f80fd5b8062d0295d146102db57806303508963146102f6575b5f80fd5b6102e36107c1565b6040519081526020015b60405180910390f35b6102fe602081565b60405161ffff90911681526020016102ed565b61034d6040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b6040516102ed9190613459565b61034d6108c7565b61036a60f981565b60405160ff90911681526020016102ed565b60015461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102ed565b60085461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b6103f46103ef3660046134ab565b610953565b005b60095461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b60095461043e9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102ed565b61047a7fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff0000000000000000000000000000000000000000000000000000000000000090911681526020016102ed565b6102e3602481565b6007546104d39068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102ed565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b6103f46105213660046134ea565b610a22565b61034d6040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b61034d610c31565b6102fe601f81565b6102e36105803660046134ea565b60066020525f908152604090205481565b6102e360055481565b6103f46105a8366004613505565b610c3e565b6103f46105bb366004613644565b610d07565b61034d6040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b6103f46112c0565b6103f4610612366004613505565b611392565b61039c73a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b6103f4610640366004613733565b6114aa565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b61034d61067a366004613772565b611b36565b6103f461068d366004613505565b611f14565b6102e36405ca1ab1e081565b6007546104d390700100000000000000000000000000000000900467ffffffffffffffff1681565b61036a60e481565b6103f46106dc3660046137e3565b611fdd565b60025461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b6102e3635ca1ab1e81565b6103f4610741366004613815565b61206f565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b6007546104d39067ffffffffffffffff1681565b6103f461078f36600461388d565b612912565b61036a601b81565b5f5461039c9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561084d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087191906138fe565b6007549091505f9061089b9067ffffffffffffffff68010000000000000000820481169116613942565b67ffffffffffffffff169050805f036108b6575f9250505090565b6108c0818361396a565b9250505090565b600480546108d4906139a2565b80601f0160208091040260200160405190810160405280929190818152602001828054610900906139a2565b801561094b5780601f106109225761010080835404028352916020019161094b565b820191905f5260205f20905b81548152906001019060200180831161092e57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146109c2576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596684604051610a1591815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610a78576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610abf576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b28573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b4c91906139f3565b610bad5760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610610bad576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546108d4906139a2565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610c94576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c26565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610d76576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff1615808015610d9457505f54600160ff909116105b80610dad5750303b158015610dad57505f5460ff166001145b610e3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610e9a575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f610ea485612dd9565b6009549091505f90610eee90889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff1685611b36565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f69573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8d91906138fe565b90505f808483858f610fa0600143613a12565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af11580156110e6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061110a9190613a2b565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886003908161119a9190613a8b565b5060046111a78982613a8b565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e60405161124793929190613ba3565b60405180910390a150505050505080156112b7575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611311576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146113e8576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff16611437576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb90602001610c26565b60085473ffffffffffffffffffffffffffffffffffffffff1680158015906114e8575073ffffffffffffffffffffffffffffffffffffffff81163314155b1561151f576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561158d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115b19190613a2b565b6115bb9190613be1565b67ffffffffffffffff1611156115fd576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f819003611638576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611674576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff8082169161169c91849168010000000000000000900416613c02565b11156116d4576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b8381101561196f575f87878381811061170f5761170f613c15565b90506020028101906117219190613c42565b61172a90613c7e565b90508361173681613d04565b825180516020918201208185015160408087015160608801519151959a509295505f946117a2948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f9081526006909352912054909150811461182a576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f9081526006602052604081205561184e600188613a12565b84036118bd5742600760109054906101000a900467ffffffffffffffff16846040015161187b9190613be1565b67ffffffffffffffff1611156118bd576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc01604051602081830303815290604052805190602001209450505050808061196790613d2a565b9150506116f4565b506119e57f00000000000000000000000000000000000000000000000000000000000000008461199d6107c1565b6119a79190613d61565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919061303b565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e7390611ab6908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015611ad2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611af69190613a2b565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f87604051602401611b6896959493929190613d78565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f03611cb85760f9601f8351611bfc9190613dda565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e487604051602001611ca29796959493929190613df5565b6040516020818303038152906040529050611dbc565b815161ffff1015611cf5576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f9611d04602083613dda565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b90000000000000000000000000000000000000000000000000000000000008152508588604051602001611da99796959493929190613ed7565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa158015611e1a573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611e92576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f90611ed79084906405ca1ab1e090635ca1ab1e90601b907fff0000000000000000000000000000000000000000000000000000000000000090602001613fb9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611f6a576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c26565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612033576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600361203f8282613a8b565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c269190613459565b60025473ffffffffffffffffffffffffffffffffffffffff1633146120c0576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835f8190036120fb576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115612137576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612142602442613c02565b8467ffffffffffffffff161115612185576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156121ea575f80fd5b505af11580156121fc573d5f803e3d5ffd5b505050505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635ca1e1656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561226a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061228e91906138fe565b60075460055491925068010000000000000000900467ffffffffffffffff1690815f5b858110156125ac575f8b8b838181106122cc576122cc613c15565b90506020028101906122de9190613c42565b6122e790613c7e565b8051805160209091012060408201519192509067ffffffffffffffff16156124c7578561231381613d04565b9650505f818360200151846040015185606001516040516020016123759493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f908152600690935291205490915081146123fd576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550612597565b8151516201d4c01015612506576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b505080806125a490613d2a565b9150506122b1565b5060075467ffffffffffffffff90811690841611156125f7576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff848116908316146126ac575f61261c8386613942565b905061263267ffffffffffffffff821683613a12565b915061266b7f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff1661199d6107c1565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b6127a8337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa15801561273b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061275f91906138fe565b6127699190613d61565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190613114565b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015612844573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128689190613a2b565b90506128748782613942565b67ffffffffffffffff168967ffffffffffffffff16146128c0576040517f1a070d9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e766876040516128fc91815260200190565b60405180910390a2505050505050505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590612950575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612987576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129f0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a1491906139f3565b15612a4b576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ab5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ad991906138fe565b905082811115612b15576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115612b51576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b9373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084613114565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bfd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c2191906138fe565b6007805491925067ffffffffffffffff909116905f612c3f83613d04565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508585604051612c76929190614014565b6040519081900390208142612c8c600143613a12565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303612d82576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2612dd1565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93190612dc890849033908b908b90614023565b60405180910390a25b505050505050565b606073ffffffffffffffffffffffffffffffffffffffff821615613036576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015612e80573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612ec59190810190614093565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa158015612f57573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f7b9190614105565b915091508163ffffffff165f14612ff2576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff841617179055613033565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261310f9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613178565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526131729085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161308d565b50505050565b5f6131d9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166132839092919063ffffffff16565b80519091501561310f57808060200190518101906131f791906139f3565b61310f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610e35565b6060611f0c84845f85855f808673ffffffffffffffffffffffffffffffffffffffff1685876040516132b5919061413d565b5f6040518083038185875af1925050503d805f81146132ef576040519150601f19603f3d011682016040523d82523d5f602084013e6132f4565b606091505b509150915061330587838387613310565b979650505050505050565b606083156133a55782515f0361339e5773ffffffffffffffffffffffffffffffffffffffff85163b61339e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e35565b5081611f0c565b611f0c83838151156133ba5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e359190613459565b5f5b838110156134085781810151838201526020016133f0565b50505f910152565b5f81518084526134278160208601602086016133ee565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61346b6020830184613410565b9392505050565b67ffffffffffffffff81168114613487575f80fd5b50565b73ffffffffffffffffffffffffffffffffffffffff81168114613487575f80fd5b5f805f606084860312156134bd575f80fd5b83356134c881613472565b92506020840135915060408401356134df8161348a565b809150509250925092565b5f602082840312156134fa575f80fd5b813561346b81613472565b5f60208284031215613515575f80fd5b813561346b8161348a565b63ffffffff81168114613487575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156135a5576135a5613531565b604052919050565b5f67ffffffffffffffff8211156135c6576135c6613531565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112613601575f80fd5b813561361461360f826135ad565b61355e565b818152846020838601011115613628575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060c08789031215613659575f80fd5b86356136648161348a565b955060208701356136748161348a565b9450604087013561368481613520565b935060608701356136948161348a565b9250608087013567ffffffffffffffff808211156136b0575f80fd5b6136bc8a838b016135f2565b935060a08901359150808211156136d1575f80fd5b506136de89828a016135f2565b9150509295509295509295565b5f8083601f8401126136fb575f80fd5b50813567ffffffffffffffff811115613712575f80fd5b6020830191508360208260051b850101111561372c575f80fd5b9250929050565b5f8060208385031215613744575f80fd5b823567ffffffffffffffff81111561375a575f80fd5b613766858286016136eb565b90969095509350505050565b5f805f8060808587031215613785575f80fd5b843561379081613520565b935060208501356137a08161348a565b925060408501356137b081613520565b9150606085013567ffffffffffffffff8111156137cb575f80fd5b6137d7878288016135f2565b91505092959194509250565b5f602082840312156137f3575f80fd5b813567ffffffffffffffff811115613809575f80fd5b611f0c848285016135f2565b5f805f805f60808688031215613829575f80fd5b853567ffffffffffffffff81111561383f575f80fd5b61384b888289016136eb565b909650945050602086013561385f81613472565b9250604086013561386f81613472565b9150606086013561387f8161348a565b809150509295509295909350565b5f805f6040848603121561389f575f80fd5b833567ffffffffffffffff808211156138b6575f80fd5b818601915086601f8301126138c9575f80fd5b8135818111156138d7575f80fd5b8760208285010111156138e8575f80fd5b6020928301989097509590910135949350505050565b5f6020828403121561390e575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff82811682821603908082111561396357613963613915565b5092915050565b5f8261399d577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c908216806139b657607f821691505b6020821081036139ed577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f60208284031215613a03575f80fd5b8151801515811461346b575f80fd5b81810381811115613a2557613a25613915565b92915050565b5f60208284031215613a3b575f80fd5b815161346b81613472565b601f82111561310f575f81815260208120601f850160051c81016020861015613a6c5750805b601f850160051c820191505b81811015612dd157828155600101613a78565b815167ffffffffffffffff811115613aa557613aa5613531565b613ab981613ab384546139a2565b84613a46565b602080601f831160018114613b0b575f8415613ad55750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612dd1565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613b5757888601518255948401946001909101908401613b38565b5085821015613b9357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f613bb56060830186613410565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff81811683821601908082111561396357613963613915565b80820180821115613a2557613a25613915565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112613c74575f80fd5b9190910192915050565b5f60808236031215613c8e575f80fd5b6040516080810167ffffffffffffffff8282108183111715613cb257613cb2613531565b816040528435915080821115613cc6575f80fd5b50613cd3368286016135f2565b825250602083013560208201526040830135613cee81613472565b6040820152606092830135928101929092525090565b5f67ffffffffffffffff808316818103613d2057613d20613915565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d5a57613d5a613915565b5060010190565b8082028115828204841417613a2557613a25613915565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a0830152613dce60c0830184613410565b98975050505050505050565b61ffff81811683821601908082111561396357613963613915565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751613e5d816003860160208c016133ee565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651613ea0816017840160208b016133ee565b808201915050818660f81b16601782015284519150613ec68260188301602088016133ee565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b1660018401528751613f3f816003860160208c016133ee565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651613f82816017840160208b016133ee565b808201915050818660f01b16601782015284519150613fa88260198301602088016133ee565b016019019998505050505050505050565b5f8651613fca818460208b016133ee565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff8416602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b5f602082840312156140a3575f80fd5b815167ffffffffffffffff8111156140b9575f80fd5b8201601f810184136140c9575f80fd5b80516140d761360f826135ad565b8181528560208385010111156140eb575f80fd5b6140fc8260208301602086016133ee565b95945050505050565b5f8060408385031215614116575f80fd5b825161412181613520565b60208401519092506141328161348a565b809150509250929050565b5f8251613c748184602087016133ee56fea2646970667358221220118ed38126a03255376c8ac6fec5a8f623db3501b90222fbe3cde4f3a07ec1b164736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102d7575f3560e01c80637125702211610187578063c7fffd4b116100dd578063def57e5411610093578063eaeb077b1161006e578063eaeb077b14610781578063f35dda4714610794578063f851a4401461079c575f80fd5b8063def57e5414610733578063e46761c414610746578063e7a7ed021461076d575f80fd5b8063cfa8ed47116100c3578063cfa8ed47146106e1578063d02103ca14610701578063d7bc90ff14610728575f80fd5b8063c7fffd4b146106c6578063c89e42df146106ce575f80fd5b80639f26f8401161013d578063ada8f91911610118578063ada8f9191461067f578063b0afe15414610692578063c754c7ed1461069e575f80fd5b80639f26f84014610632578063a3c573eb14610645578063a652f26c1461066c575f80fd5b80638c3d73011161016d5780638c3d7301146105fc57806391cafe32146106045780639e00187714610617575f80fd5b806371257022146105ad5780637a5460c5146105c0575f80fd5b806340b5de6c1161023c57806352bdeb6d116101f25780636b8616ce116101cd5780636b8616ce146105725780636e05d2cd146105915780636ff512cc1461059a575f80fd5b806352bdeb6d14610526578063542028d514610562578063676870d21461056a575f80fd5b8063456052671161022257806345605267146104b357806349b7b802146104ec5780634e48770614610513575f80fd5b806340b5de6c1461045357806342308fab146104ab575f80fd5b8063267822471161029157806332c2d1531161027757806332c2d153146103e15780633c351e10146103f65780633cbc795b14610416575f80fd5b8063267822471461037c5780632c111c06146103c1575f80fd5b806305835f37116102c157806305835f3714610311578063107bf28c1461035a57806311e892d414610362575f80fd5b8062d0295d146102db57806303508963146102f6575b5f80fd5b6102e36107c1565b6040519081526020015b60405180910390f35b6102fe602081565b60405161ffff90911681526020016102ed565b61034d6040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b6040516102ed9190613459565b61034d6108c7565b61036a60f981565b60405160ff90911681526020016102ed565b60015461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102ed565b60085461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b6103f46103ef3660046134ab565b610953565b005b60095461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b60095461043e9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102ed565b61047a7fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff0000000000000000000000000000000000000000000000000000000000000090911681526020016102ed565b6102e3602481565b6007546104d39068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102ed565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b6103f46105213660046134ea565b610a22565b61034d6040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b61034d610c31565b6102fe601f81565b6102e36105803660046134ea565b60066020525f908152604090205481565b6102e360055481565b6103f46105a8366004613505565b610c3e565b6103f46105bb366004613644565b610d07565b61034d6040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b6103f46112c0565b6103f4610612366004613505565b611392565b61039c73a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b6103f4610640366004613733565b6114aa565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b61034d61067a366004613772565b611b36565b6103f461068d366004613505565b611f14565b6102e36405ca1ab1e081565b6007546104d390700100000000000000000000000000000000900467ffffffffffffffff1681565b61036a60e481565b6103f46106dc3660046137e3565b611fdd565b60025461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b6102e3635ca1ab1e81565b6103f4610741366004613815565b61206f565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b6007546104d39067ffffffffffffffff1681565b6103f461078f36600461388d565b612912565b61036a601b81565b5f5461039c9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561084d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087191906138fe565b6007549091505f9061089b9067ffffffffffffffff68010000000000000000820481169116613942565b67ffffffffffffffff169050805f036108b6575f9250505090565b6108c0818361396a565b9250505090565b600480546108d4906139a2565b80601f0160208091040260200160405190810160405280929190818152602001828054610900906139a2565b801561094b5780601f106109225761010080835404028352916020019161094b565b820191905f5260205f20905b81548152906001019060200180831161092e57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146109c2576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596684604051610a1591815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610a78576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610abf576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b28573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b4c91906139f3565b610bad5760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610610bad576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546108d4906139a2565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610c94576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c26565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610d76576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff1615808015610d9457505f54600160ff909116105b80610dad5750303b158015610dad57505f5460ff166001145b610e3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610e9a575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f610ea485612dd9565b6009549091505f90610eee90889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff1685611b36565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f69573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8d91906138fe565b90505f808483858f610fa0600143613a12565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af11580156110e6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061110a9190613a2b565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886003908161119a9190613a8b565b5060046111a78982613a8b565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e60405161124793929190613ba3565b60405180910390a150505050505080156112b7575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611311576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146113e8576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff16611437576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb90602001610c26565b60085473ffffffffffffffffffffffffffffffffffffffff1680158015906114e8575073ffffffffffffffffffffffffffffffffffffffff81163314155b1561151f576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561158d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115b19190613a2b565b6115bb9190613be1565b67ffffffffffffffff1611156115fd576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f819003611638576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611674576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff8082169161169c91849168010000000000000000900416613c02565b11156116d4576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b8381101561196f575f87878381811061170f5761170f613c15565b90506020028101906117219190613c42565b61172a90613c7e565b90508361173681613d04565b825180516020918201208185015160408087015160608801519151959a509295505f946117a2948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f9081526006909352912054909150811461182a576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f9081526006602052604081205561184e600188613a12565b84036118bd5742600760109054906101000a900467ffffffffffffffff16846040015161187b9190613be1565b67ffffffffffffffff1611156118bd576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc01604051602081830303815290604052805190602001209450505050808061196790613d2a565b9150506116f4565b506119e57f00000000000000000000000000000000000000000000000000000000000000008461199d6107c1565b6119a79190613d61565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919061303b565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e7390611ab6908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015611ad2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611af69190613a2b565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f87604051602401611b6896959493929190613d78565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f03611cb85760f9601f8351611bfc9190613dda565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e487604051602001611ca29796959493929190613df5565b6040516020818303038152906040529050611dbc565b815161ffff1015611cf5576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f9611d04602083613dda565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b90000000000000000000000000000000000000000000000000000000000008152508588604051602001611da99796959493929190613ed7565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa158015611e1a573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611e92576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f90611ed79084906405ca1ab1e090635ca1ab1e90601b907fff0000000000000000000000000000000000000000000000000000000000000090602001613fb9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611f6a576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c26565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612033576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600361203f8282613a8b565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c269190613459565b60025473ffffffffffffffffffffffffffffffffffffffff1633146120c0576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835f8190036120fb576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115612137576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612142602442613c02565b8467ffffffffffffffff161115612185576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156121ea575f80fd5b505af11580156121fc573d5f803e3d5ffd5b505050505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635ca1e1656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561226a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061228e91906138fe565b60075460055491925068010000000000000000900467ffffffffffffffff1690815f5b858110156125ac575f8b8b838181106122cc576122cc613c15565b90506020028101906122de9190613c42565b6122e790613c7e565b8051805160209091012060408201519192509067ffffffffffffffff16156124c7578561231381613d04565b9650505f818360200151846040015185606001516040516020016123759493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f908152600690935291205490915081146123fd576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550612597565b8151516201d4c01015612506576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b505080806125a490613d2a565b9150506122b1565b5060075467ffffffffffffffff90811690841611156125f7576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff848116908316146126ac575f61261c8386613942565b905061263267ffffffffffffffff821683613a12565b915061266b7f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff1661199d6107c1565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b6127a8337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa15801561273b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061275f91906138fe565b6127699190613d61565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190613114565b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015612844573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128689190613a2b565b90506128748782613942565b67ffffffffffffffff168967ffffffffffffffff16146128c0576040517f1a070d9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e766876040516128fc91815260200190565b60405180910390a2505050505050505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590612950575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612987576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129f0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a1491906139f3565b15612a4b576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ab5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ad991906138fe565b905082811115612b15576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115612b51576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b9373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084613114565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bfd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c2191906138fe565b6007805491925067ffffffffffffffff909116905f612c3f83613d04565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508585604051612c76929190614014565b6040519081900390208142612c8c600143613a12565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303612d82576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2612dd1565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93190612dc890849033908b908b90614023565b60405180910390a25b505050505050565b606073ffffffffffffffffffffffffffffffffffffffff821615613036576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015612e80573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612ec59190810190614093565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa158015612f57573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f7b9190614105565b915091508163ffffffff165f14612ff2576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff841617179055613033565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261310f9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613178565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526131729085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161308d565b50505050565b5f6131d9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166132839092919063ffffffff16565b80519091501561310f57808060200190518101906131f791906139f3565b61310f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610e35565b6060611f0c84845f85855f808673ffffffffffffffffffffffffffffffffffffffff1685876040516132b5919061413d565b5f6040518083038185875af1925050503d805f81146132ef576040519150601f19603f3d011682016040523d82523d5f602084013e6132f4565b606091505b509150915061330587838387613310565b979650505050505050565b606083156133a55782515f0361339e5773ffffffffffffffffffffffffffffffffffffffff85163b61339e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e35565b5081611f0c565b611f0c83838151156133ba5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e359190613459565b5f5b838110156134085781810151838201526020016133f0565b50505f910152565b5f81518084526134278160208601602086016133ee565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61346b6020830184613410565b9392505050565b67ffffffffffffffff81168114613487575f80fd5b50565b73ffffffffffffffffffffffffffffffffffffffff81168114613487575f80fd5b5f805f606084860312156134bd575f80fd5b83356134c881613472565b92506020840135915060408401356134df8161348a565b809150509250925092565b5f602082840312156134fa575f80fd5b813561346b81613472565b5f60208284031215613515575f80fd5b813561346b8161348a565b63ffffffff81168114613487575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156135a5576135a5613531565b604052919050565b5f67ffffffffffffffff8211156135c6576135c6613531565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112613601575f80fd5b813561361461360f826135ad565b61355e565b818152846020838601011115613628575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060c08789031215613659575f80fd5b86356136648161348a565b955060208701356136748161348a565b9450604087013561368481613520565b935060608701356136948161348a565b9250608087013567ffffffffffffffff808211156136b0575f80fd5b6136bc8a838b016135f2565b935060a08901359150808211156136d1575f80fd5b506136de89828a016135f2565b9150509295509295509295565b5f8083601f8401126136fb575f80fd5b50813567ffffffffffffffff811115613712575f80fd5b6020830191508360208260051b850101111561372c575f80fd5b9250929050565b5f8060208385031215613744575f80fd5b823567ffffffffffffffff81111561375a575f80fd5b613766858286016136eb565b90969095509350505050565b5f805f8060808587031215613785575f80fd5b843561379081613520565b935060208501356137a08161348a565b925060408501356137b081613520565b9150606085013567ffffffffffffffff8111156137cb575f80fd5b6137d7878288016135f2565b91505092959194509250565b5f602082840312156137f3575f80fd5b813567ffffffffffffffff811115613809575f80fd5b611f0c848285016135f2565b5f805f805f60808688031215613829575f80fd5b853567ffffffffffffffff81111561383f575f80fd5b61384b888289016136eb565b909650945050602086013561385f81613472565b9250604086013561386f81613472565b9150606086013561387f8161348a565b809150509295509295909350565b5f805f6040848603121561389f575f80fd5b833567ffffffffffffffff808211156138b6575f80fd5b818601915086601f8301126138c9575f80fd5b8135818111156138d7575f80fd5b8760208285010111156138e8575f80fd5b6020928301989097509590910135949350505050565b5f6020828403121561390e575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff82811682821603908082111561396357613963613915565b5092915050565b5f8261399d577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c908216806139b657607f821691505b6020821081036139ed577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f60208284031215613a03575f80fd5b8151801515811461346b575f80fd5b81810381811115613a2557613a25613915565b92915050565b5f60208284031215613a3b575f80fd5b815161346b81613472565b601f82111561310f575f81815260208120601f850160051c81016020861015613a6c5750805b601f850160051c820191505b81811015612dd157828155600101613a78565b815167ffffffffffffffff811115613aa557613aa5613531565b613ab981613ab384546139a2565b84613a46565b602080601f831160018114613b0b575f8415613ad55750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612dd1565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613b5757888601518255948401946001909101908401613b38565b5085821015613b9357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f613bb56060830186613410565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff81811683821601908082111561396357613963613915565b80820180821115613a2557613a25613915565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112613c74575f80fd5b9190910192915050565b5f60808236031215613c8e575f80fd5b6040516080810167ffffffffffffffff8282108183111715613cb257613cb2613531565b816040528435915080821115613cc6575f80fd5b50613cd3368286016135f2565b825250602083013560208201526040830135613cee81613472565b6040820152606092830135928101929092525090565b5f67ffffffffffffffff808316818103613d2057613d20613915565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d5a57613d5a613915565b5060010190565b8082028115828204841417613a2557613a25613915565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a0830152613dce60c0830184613410565b98975050505050505050565b61ffff81811683821601908082111561396357613963613915565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751613e5d816003860160208c016133ee565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651613ea0816017840160208b016133ee565b808201915050818660f81b16601782015284519150613ec68260188301602088016133ee565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b1660018401528751613f3f816003860160208c016133ee565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651613f82816017840160208b016133ee565b808201915050818660f01b16601782015284519150613fa88260198301602088016133ee565b016019019998505050505050505050565b5f8651613fca818460208b016133ee565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff8416602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b5f602082840312156140a3575f80fd5b815167ffffffffffffffff8111156140b9575f80fd5b8201601f810184136140c9575f80fd5b80516140d761360f826135ad565b8181528560208385010111156140eb575f80fd5b6140fc8260208301602086016133ee565b95945050505050565b5f8060408385031215614116575f80fd5b825161412181613520565b60208401519092506141328161348a565b809150509250929050565b5f8251613c748184602087016133ee56fea2646970667358221220118ed38126a03255376c8ac6fec5a8f623db3501b90222fbe3cde4f3a07ec1b164736f6c63430008140033", + "bytecode": "0x61010060405234801562000011575f80fd5b506040516200441238038062004412833981016040819052620000349162000146565b6001600160a01b0380851660a05280841660805280831660c052811660e05283838383620000616200006f565b5050505050505050620001ab565b5f54610100900460ff1615620000db5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811610156200012c575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b038116811462000143575f80fd5b50565b5f805f80608085870312156200015a575f80fd5b845162000167816200012e565b60208601519094506200017a816200012e565b60408601519093506200018d816200012e565b6060860151909250620001a0816200012e565b939692955090935050565b60805160a05160c05160e0516141846200028e5f395f81816104f10152818161095501528181610ac101528181610d090152818161108b015281816115260152818161197501528181611a6a01528181612639015281816126b2015281816126d4015281816127e9015281816129890152612a4e01525f818161064a01528181611c3401528181611d3c0152818161218701528181612e3c0152612f1101525f818161070601528181610f02015281816122030152612b9601525f818161074b01528181610808015281816119be015281816127800152612b6b01526141845ff3fe608060405234801561000f575f80fd5b50600436106102d7575f3560e01c80637125702211610187578063c7fffd4b116100dd578063def57e5411610093578063eaeb077b1161006e578063eaeb077b14610781578063f35dda4714610794578063f851a4401461079c575f80fd5b8063def57e5414610733578063e46761c414610746578063e7a7ed021461076d575f80fd5b8063cfa8ed47116100c3578063cfa8ed47146106e1578063d02103ca14610701578063d7bc90ff14610728575f80fd5b8063c7fffd4b146106c6578063c89e42df146106ce575f80fd5b80639f26f8401161013d578063ada8f91911610118578063ada8f9191461067f578063b0afe15414610692578063c754c7ed1461069e575f80fd5b80639f26f84014610632578063a3c573eb14610645578063a652f26c1461066c575f80fd5b80638c3d73011161016d5780638c3d7301146105fc57806391cafe32146106045780639e00187714610617575f80fd5b806371257022146105ad5780637a5460c5146105c0575f80fd5b806340b5de6c1161023c57806352bdeb6d116101f25780636b8616ce116101cd5780636b8616ce146105725780636e05d2cd146105915780636ff512cc1461059a575f80fd5b806352bdeb6d14610526578063542028d514610562578063676870d21461056a575f80fd5b8063456052671161022257806345605267146104b357806349b7b802146104ec5780634e48770614610513575f80fd5b806340b5de6c1461045357806342308fab146104ab575f80fd5b8063267822471161029157806332c2d1531161027757806332c2d153146103e15780633c351e10146103f65780633cbc795b14610416575f80fd5b8063267822471461037c5780632c111c06146103c1575f80fd5b806305835f37116102c157806305835f3714610311578063107bf28c1461035a57806311e892d414610362575f80fd5b8062d0295d146102db57806303508963146102f6575b5f80fd5b6102e36107c1565b6040519081526020015b60405180910390f35b6102fe602081565b60405161ffff90911681526020016102ed565b61034d6040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b6040516102ed9190613459565b61034d6108c7565b61036a60f981565b60405160ff90911681526020016102ed565b60015461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102ed565b60085461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b6103f46103ef3660046134ab565b610953565b005b60095461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b60095461043e9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102ed565b61047a7fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff0000000000000000000000000000000000000000000000000000000000000090911681526020016102ed565b6102e3602481565b6007546104d39068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102ed565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b6103f46105213660046134ea565b610a22565b61034d6040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b61034d610c31565b6102fe601f81565b6102e36105803660046134ea565b60066020525f908152604090205481565b6102e360055481565b6103f46105a8366004613505565b610c3e565b6103f46105bb366004613644565b610d07565b61034d6040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b6103f46112c0565b6103f4610612366004613505565b611392565b61039c73a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b6103f4610640366004613733565b6114aa565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b61034d61067a366004613772565b611b36565b6103f461068d366004613505565b611f14565b6102e36405ca1ab1e081565b6007546104d390700100000000000000000000000000000000900467ffffffffffffffff1681565b61036a60e481565b6103f46106dc3660046137e3565b611fdd565b60025461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b6102e3635ca1ab1e81565b6103f4610741366004613815565b61206f565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b6007546104d39067ffffffffffffffff1681565b6103f461078f36600461388d565b612912565b61036a601b81565b5f5461039c9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561084d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087191906138fe565b6007549091505f9061089b9067ffffffffffffffff68010000000000000000820481169116613942565b67ffffffffffffffff169050805f036108b6575f9250505090565b6108c0818361396a565b9250505090565b600480546108d4906139a2565b80601f0160208091040260200160405190810160405280929190818152602001828054610900906139a2565b801561094b5780601f106109225761010080835404028352916020019161094b565b820191905f5260205f20905b81548152906001019060200180831161092e57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146109c2576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596684604051610a1591815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610a78576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610abf576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b28573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b4c91906139f3565b610bad5760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610610bad576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546108d4906139a2565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610c94576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c26565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610d76576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff1615808015610d9457505f54600160ff909116105b80610dad5750303b158015610dad57505f5460ff166001145b610e3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610e9a575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f610ea485612dd9565b6009549091505f90610eee90889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff1685611b36565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f69573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8d91906138fe565b90505f808483858f610fa0600143613a12565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af11580156110e6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061110a9190613a2b565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886003908161119a9190613a8b565b5060046111a78982613a8b565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e60405161124793929190613ba3565b60405180910390a150505050505080156112b7575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611311576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146113e8576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff16611437576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb90602001610c26565b60085473ffffffffffffffffffffffffffffffffffffffff1680158015906114e8575073ffffffffffffffffffffffffffffffffffffffff81163314155b1561151f576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561158d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115b19190613a2b565b6115bb9190613be1565b67ffffffffffffffff1611156115fd576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f819003611638576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611674576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff8082169161169c91849168010000000000000000900416613c02565b11156116d4576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b8381101561196f575f87878381811061170f5761170f613c15565b90506020028101906117219190613c42565b61172a90613c7e565b90508361173681613d04565b825180516020918201208185015160408087015160608801519151959a509295505f946117a2948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f9081526006909352912054909150811461182a576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f9081526006602052604081205561184e600188613a12565b84036118bd5742600760109054906101000a900467ffffffffffffffff16846040015161187b9190613be1565b67ffffffffffffffff1611156118bd576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc01604051602081830303815290604052805190602001209450505050808061196790613d2a565b9150506116f4565b506119e57f00000000000000000000000000000000000000000000000000000000000000008461199d6107c1565b6119a79190613d61565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919061303b565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e7390611ab6908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015611ad2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611af69190613a2b565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f87604051602401611b6896959493929190613d78565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f03611cb85760f9601f8351611bfc9190613dda565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e487604051602001611ca29796959493929190613df5565b6040516020818303038152906040529050611dbc565b815161ffff1015611cf5576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f9611d04602083613dda565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b90000000000000000000000000000000000000000000000000000000000008152508588604051602001611da99796959493929190613ed7565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa158015611e1a573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611e92576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f90611ed79084906405ca1ab1e090635ca1ab1e90601b907fff0000000000000000000000000000000000000000000000000000000000000090602001613fb9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611f6a576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c26565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612033576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600361203f8282613a8b565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c269190613459565b60025473ffffffffffffffffffffffffffffffffffffffff1633146120c0576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835f8190036120fb576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115612137576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612142602442613c02565b8467ffffffffffffffff161115612185576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156121ea575f80fd5b505af11580156121fc573d5f803e3d5ffd5b505050505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635ca1e1656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561226a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061228e91906138fe565b60075460055491925068010000000000000000900467ffffffffffffffff1690815f5b858110156125ac575f8b8b838181106122cc576122cc613c15565b90506020028101906122de9190613c42565b6122e790613c7e565b8051805160209091012060408201519192509067ffffffffffffffff16156124c7578561231381613d04565b9650505f818360200151846040015185606001516040516020016123759493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f908152600690935291205490915081146123fd576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550612597565b8151516201d4c01015612506576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b505080806125a490613d2a565b9150506122b1565b5060075467ffffffffffffffff90811690841611156125f7576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff848116908316146126ac575f61261c8386613942565b905061263267ffffffffffffffff821683613a12565b915061266b7f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff1661199d6107c1565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b6127a8337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa15801561273b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061275f91906138fe565b6127699190613d61565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190613114565b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015612844573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128689190613a2b565b90506128748782613942565b67ffffffffffffffff168967ffffffffffffffff16146128c0576040517f1a070d9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e766876040516128fc91815260200190565b60405180910390a2505050505050505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590612950575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612987576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129f0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a1491906139f3565b15612a4b576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ab5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ad991906138fe565b905082811115612b15576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115612b51576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b9373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084613114565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bfd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c2191906138fe565b6007805491925067ffffffffffffffff909116905f612c3f83613d04565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508585604051612c76929190614014565b6040519081900390208142612c8c600143613a12565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303612d82576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2612dd1565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93190612dc890849033908b908b90614023565b60405180910390a25b505050505050565b606073ffffffffffffffffffffffffffffffffffffffff821615613036576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015612e80573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612ec59190810190614093565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa158015612f57573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f7b9190614105565b915091508163ffffffff165f14612ff2576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff841617179055613033565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261310f9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613178565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526131729085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161308d565b50505050565b5f6131d9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166132839092919063ffffffff16565b80519091501561310f57808060200190518101906131f791906139f3565b61310f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610e35565b6060611f0c84845f85855f808673ffffffffffffffffffffffffffffffffffffffff1685876040516132b5919061413d565b5f6040518083038185875af1925050503d805f81146132ef576040519150601f19603f3d011682016040523d82523d5f602084013e6132f4565b606091505b509150915061330587838387613310565b979650505050505050565b606083156133a55782515f0361339e5773ffffffffffffffffffffffffffffffffffffffff85163b61339e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e35565b5081611f0c565b611f0c83838151156133ba5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e359190613459565b5f5b838110156134085781810151838201526020016133f0565b50505f910152565b5f81518084526134278160208601602086016133ee565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61346b6020830184613410565b9392505050565b67ffffffffffffffff81168114613487575f80fd5b50565b73ffffffffffffffffffffffffffffffffffffffff81168114613487575f80fd5b5f805f606084860312156134bd575f80fd5b83356134c881613472565b92506020840135915060408401356134df8161348a565b809150509250925092565b5f602082840312156134fa575f80fd5b813561346b81613472565b5f60208284031215613515575f80fd5b813561346b8161348a565b63ffffffff81168114613487575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156135a5576135a5613531565b604052919050565b5f67ffffffffffffffff8211156135c6576135c6613531565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112613601575f80fd5b813561361461360f826135ad565b61355e565b818152846020838601011115613628575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060c08789031215613659575f80fd5b86356136648161348a565b955060208701356136748161348a565b9450604087013561368481613520565b935060608701356136948161348a565b9250608087013567ffffffffffffffff808211156136b0575f80fd5b6136bc8a838b016135f2565b935060a08901359150808211156136d1575f80fd5b506136de89828a016135f2565b9150509295509295509295565b5f8083601f8401126136fb575f80fd5b50813567ffffffffffffffff811115613712575f80fd5b6020830191508360208260051b850101111561372c575f80fd5b9250929050565b5f8060208385031215613744575f80fd5b823567ffffffffffffffff81111561375a575f80fd5b613766858286016136eb565b90969095509350505050565b5f805f8060808587031215613785575f80fd5b843561379081613520565b935060208501356137a08161348a565b925060408501356137b081613520565b9150606085013567ffffffffffffffff8111156137cb575f80fd5b6137d7878288016135f2565b91505092959194509250565b5f602082840312156137f3575f80fd5b813567ffffffffffffffff811115613809575f80fd5b611f0c848285016135f2565b5f805f805f60808688031215613829575f80fd5b853567ffffffffffffffff81111561383f575f80fd5b61384b888289016136eb565b909650945050602086013561385f81613472565b9250604086013561386f81613472565b9150606086013561387f8161348a565b809150509295509295909350565b5f805f6040848603121561389f575f80fd5b833567ffffffffffffffff808211156138b6575f80fd5b818601915086601f8301126138c9575f80fd5b8135818111156138d7575f80fd5b8760208285010111156138e8575f80fd5b6020928301989097509590910135949350505050565b5f6020828403121561390e575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff82811682821603908082111561396357613963613915565b5092915050565b5f8261399d577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c908216806139b657607f821691505b6020821081036139ed577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f60208284031215613a03575f80fd5b8151801515811461346b575f80fd5b81810381811115613a2557613a25613915565b92915050565b5f60208284031215613a3b575f80fd5b815161346b81613472565b601f82111561310f575f81815260208120601f850160051c81016020861015613a6c5750805b601f850160051c820191505b81811015612dd157828155600101613a78565b815167ffffffffffffffff811115613aa557613aa5613531565b613ab981613ab384546139a2565b84613a46565b602080601f831160018114613b0b575f8415613ad55750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612dd1565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613b5757888601518255948401946001909101908401613b38565b5085821015613b9357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f613bb56060830186613410565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff81811683821601908082111561396357613963613915565b80820180821115613a2557613a25613915565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112613c74575f80fd5b9190910192915050565b5f60808236031215613c8e575f80fd5b6040516080810167ffffffffffffffff8282108183111715613cb257613cb2613531565b816040528435915080821115613cc6575f80fd5b50613cd3368286016135f2565b825250602083013560208201526040830135613cee81613472565b6040820152606092830135928101929092525090565b5f67ffffffffffffffff808316818103613d2057613d20613915565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d5a57613d5a613915565b5060010190565b8082028115828204841417613a2557613a25613915565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a0830152613dce60c0830184613410565b98975050505050505050565b61ffff81811683821601908082111561396357613963613915565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751613e5d816003860160208c016133ee565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651613ea0816017840160208b016133ee565b808201915050818660f81b16601782015284519150613ec68260188301602088016133ee565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b1660018401528751613f3f816003860160208c016133ee565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651613f82816017840160208b016133ee565b808201915050818660f01b16601782015284519150613fa88260198301602088016133ee565b016019019998505050505050505050565b5f8651613fca818460208b016133ee565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff8416602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b5f602082840312156140a3575f80fd5b815167ffffffffffffffff8111156140b9575f80fd5b8201601f810184136140c9575f80fd5b80516140d761360f826135ad565b8181528560208385010111156140eb575f80fd5b6140fc8260208301602086016133ee565b95945050505050565b5f8060408385031215614116575f80fd5b825161412181613520565b60208401519092506141328161348a565b809150509250929050565b5f8251613c748184602087016133ee56fea264697066735822122085db40c10ef8cab16b910c3133018cca1a119653290a680ee22bc3bb3a64056464736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102d7575f3560e01c80637125702211610187578063c7fffd4b116100dd578063def57e5411610093578063eaeb077b1161006e578063eaeb077b14610781578063f35dda4714610794578063f851a4401461079c575f80fd5b8063def57e5414610733578063e46761c414610746578063e7a7ed021461076d575f80fd5b8063cfa8ed47116100c3578063cfa8ed47146106e1578063d02103ca14610701578063d7bc90ff14610728575f80fd5b8063c7fffd4b146106c6578063c89e42df146106ce575f80fd5b80639f26f8401161013d578063ada8f91911610118578063ada8f9191461067f578063b0afe15414610692578063c754c7ed1461069e575f80fd5b80639f26f84014610632578063a3c573eb14610645578063a652f26c1461066c575f80fd5b80638c3d73011161016d5780638c3d7301146105fc57806391cafe32146106045780639e00187714610617575f80fd5b806371257022146105ad5780637a5460c5146105c0575f80fd5b806340b5de6c1161023c57806352bdeb6d116101f25780636b8616ce116101cd5780636b8616ce146105725780636e05d2cd146105915780636ff512cc1461059a575f80fd5b806352bdeb6d14610526578063542028d514610562578063676870d21461056a575f80fd5b8063456052671161022257806345605267146104b357806349b7b802146104ec5780634e48770614610513575f80fd5b806340b5de6c1461045357806342308fab146104ab575f80fd5b8063267822471161029157806332c2d1531161027757806332c2d153146103e15780633c351e10146103f65780633cbc795b14610416575f80fd5b8063267822471461037c5780632c111c06146103c1575f80fd5b806305835f37116102c157806305835f3714610311578063107bf28c1461035a57806311e892d414610362575f80fd5b8062d0295d146102db57806303508963146102f6575b5f80fd5b6102e36107c1565b6040519081526020015b60405180910390f35b6102fe602081565b60405161ffff90911681526020016102ed565b61034d6040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b6040516102ed9190613459565b61034d6108c7565b61036a60f981565b60405160ff90911681526020016102ed565b60015461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102ed565b60085461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b6103f46103ef3660046134ab565b610953565b005b60095461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b60095461043e9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102ed565b61047a7fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff0000000000000000000000000000000000000000000000000000000000000090911681526020016102ed565b6102e3602481565b6007546104d39068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020016102ed565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b6103f46105213660046134ea565b610a22565b61034d6040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b61034d610c31565b6102fe601f81565b6102e36105803660046134ea565b60066020525f908152604090205481565b6102e360055481565b6103f46105a8366004613505565b610c3e565b6103f46105bb366004613644565b610d07565b61034d6040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b6103f46112c0565b6103f4610612366004613505565b611392565b61039c73a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b6103f4610640366004613733565b6114aa565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b61034d61067a366004613772565b611b36565b6103f461068d366004613505565b611f14565b6102e36405ca1ab1e081565b6007546104d390700100000000000000000000000000000000900467ffffffffffffffff1681565b61036a60e481565b6103f46106dc3660046137e3565b611fdd565b60025461039c9073ffffffffffffffffffffffffffffffffffffffff1681565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b6102e3635ca1ab1e81565b6103f4610741366004613815565b61206f565b61039c7f000000000000000000000000000000000000000000000000000000000000000081565b6007546104d39067ffffffffffffffff1681565b6103f461078f36600461388d565b612912565b61036a601b81565b5f5461039c9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561084d573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061087191906138fe565b6007549091505f9061089b9067ffffffffffffffff68010000000000000000820481169116613942565b67ffffffffffffffff169050805f036108b6575f9250505090565b6108c0818361396a565b9250505090565b600480546108d4906139a2565b80601f0160208091040260200160405190810160405280929190818152602001828054610900906139a2565b801561094b5780601f106109225761010080835404028352916020019161094b565b820191905f5260205f20905b81548152906001019060200180831161092e57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146109c2576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596684604051610a1591815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610a78576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610abf576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b28573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b4c91906139f3565b610bad5760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610610bad576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546108d4906139a2565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610c94576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c26565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610d76576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff1615808015610d9457505f54600160ff909116105b80610dad5750303b158015610dad57505f5460ff166001145b610e3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610e9a575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f610ea485612dd9565b6009549091505f90610eee90889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff1685611b36565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f69573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f8d91906138fe565b90505f808483858f610fa0600143613a12565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af11580156110e6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061110a9190613a2b565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886003908161119a9190613a8b565b5060046111a78982613a8b565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e60405161124793929190613ba3565b60405180910390a150505050505080156112b7575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611311576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146113e8576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff16611437576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb90602001610c26565b60085473ffffffffffffffffffffffffffffffffffffffff1680158015906114e8575073ffffffffffffffffffffffffffffffffffffffff81163314155b1561151f576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561158d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115b19190613a2b565b6115bb9190613be1565b67ffffffffffffffff1611156115fd576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f819003611638576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611674576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff8082169161169c91849168010000000000000000900416613c02565b11156116d4576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b8381101561196f575f87878381811061170f5761170f613c15565b90506020028101906117219190613c42565b61172a90613c7e565b90508361173681613d04565b825180516020918201208185015160408087015160608801519151959a509295505f946117a2948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f9081526006909352912054909150811461182a576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f9081526006602052604081205561184e600188613a12565b84036118bd5742600760109054906101000a900467ffffffffffffffff16846040015161187b9190613be1565b67ffffffffffffffff1611156118bd576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc01604051602081830303815290604052805190602001209450505050808061196790613d2a565b9150506116f4565b506119e57f00000000000000000000000000000000000000000000000000000000000000008461199d6107c1565b6119a79190613d61565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919061303b565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e7390611ab6908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015611ad2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611af69190613a2b565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f87604051602401611b6896959493929190613d78565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f03611cb85760f9601f8351611bfc9190613dda565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e487604051602001611ca29796959493929190613df5565b6040516020818303038152906040529050611dbc565b815161ffff1015611cf5576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f9611d04602083613dda565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b90000000000000000000000000000000000000000000000000000000000008152508588604051602001611da99796959493929190613ed7565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa158015611e1a573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116611e92576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f90611ed79084906405ca1ab1e090635ca1ab1e90601b907fff0000000000000000000000000000000000000000000000000000000000000090602001613fb9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611f6a576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c26565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612033576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600361203f8282613a8b565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c269190613459565b60025473ffffffffffffffffffffffffffffffffffffffff1633146120c0576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835f8190036120fb576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115612137576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612142602442613c02565b8467ffffffffffffffff161115612185576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156121ea575f80fd5b505af11580156121fc573d5f803e3d5ffd5b505050505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635ca1e1656040518163ffffffff1660e01b8152600401602060405180830381865afa15801561226a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061228e91906138fe565b60075460055491925068010000000000000000900467ffffffffffffffff1690815f5b858110156125ac575f8b8b838181106122cc576122cc613c15565b90506020028101906122de9190613c42565b6122e790613c7e565b8051805160209091012060408201519192509067ffffffffffffffff16156124c7578561231381613d04565b9650505f818360200151846040015185606001516040516020016123759493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f908152600690935291205490915081146123fd576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550612597565b8151516201d4c01015612506576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b505080806125a490613d2a565b9150506122b1565b5060075467ffffffffffffffff90811690841611156125f7576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff848116908316146126ac575f61261c8386613942565b905061263267ffffffffffffffff821683613a12565b915061266b7f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff1661199d6107c1565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b6127a8337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa15801561273b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061275f91906138fe565b6127699190613d61565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190613114565b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015612844573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128689190613a2b565b90506128748782613942565b67ffffffffffffffff168967ffffffffffffffff16146128c0576040517f1a070d9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e766876040516128fc91815260200190565b60405180910390a2505050505050505050505050565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590612950575073ffffffffffffffffffffffffffffffffffffffff81163314155b15612987576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156129f0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a1491906139f3565b15612a4b576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ab5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ad991906138fe565b905082811115612b15576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115612b51576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612b9373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084613114565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bfd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c2191906138fe565b6007805491925067ffffffffffffffff909116905f612c3f83613d04565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508585604051612c76929190614014565b6040519081900390208142612c8c600143613a12565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303612d82576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2612dd1565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc93190612dc890849033908b908b90614023565b60405180910390a25b505050505050565b606073ffffffffffffffffffffffffffffffffffffffff821615613036576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015612e80573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612ec59190810190614093565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa158015612f57573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f7b9190614105565b915091508163ffffffff165f14612ff2576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff841617179055613033565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60405173ffffffffffffffffffffffffffffffffffffffff831660248201526044810182905261310f9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613178565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526131729085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161308d565b50505050565b5f6131d9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166132839092919063ffffffff16565b80519091501561310f57808060200190518101906131f791906139f3565b61310f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610e35565b6060611f0c84845f85855f808673ffffffffffffffffffffffffffffffffffffffff1685876040516132b5919061413d565b5f6040518083038185875af1925050503d805f81146132ef576040519150601f19603f3d011682016040523d82523d5f602084013e6132f4565b606091505b509150915061330587838387613310565b979650505050505050565b606083156133a55782515f0361339e5773ffffffffffffffffffffffffffffffffffffffff85163b61339e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e35565b5081611f0c565b611f0c83838151156133ba5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e359190613459565b5f5b838110156134085781810151838201526020016133f0565b50505f910152565b5f81518084526134278160208601602086016133ee565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61346b6020830184613410565b9392505050565b67ffffffffffffffff81168114613487575f80fd5b50565b73ffffffffffffffffffffffffffffffffffffffff81168114613487575f80fd5b5f805f606084860312156134bd575f80fd5b83356134c881613472565b92506020840135915060408401356134df8161348a565b809150509250925092565b5f602082840312156134fa575f80fd5b813561346b81613472565b5f60208284031215613515575f80fd5b813561346b8161348a565b63ffffffff81168114613487575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156135a5576135a5613531565b604052919050565b5f67ffffffffffffffff8211156135c6576135c6613531565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112613601575f80fd5b813561361461360f826135ad565b61355e565b818152846020838601011115613628575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f8060c08789031215613659575f80fd5b86356136648161348a565b955060208701356136748161348a565b9450604087013561368481613520565b935060608701356136948161348a565b9250608087013567ffffffffffffffff808211156136b0575f80fd5b6136bc8a838b016135f2565b935060a08901359150808211156136d1575f80fd5b506136de89828a016135f2565b9150509295509295509295565b5f8083601f8401126136fb575f80fd5b50813567ffffffffffffffff811115613712575f80fd5b6020830191508360208260051b850101111561372c575f80fd5b9250929050565b5f8060208385031215613744575f80fd5b823567ffffffffffffffff81111561375a575f80fd5b613766858286016136eb565b90969095509350505050565b5f805f8060808587031215613785575f80fd5b843561379081613520565b935060208501356137a08161348a565b925060408501356137b081613520565b9150606085013567ffffffffffffffff8111156137cb575f80fd5b6137d7878288016135f2565b91505092959194509250565b5f602082840312156137f3575f80fd5b813567ffffffffffffffff811115613809575f80fd5b611f0c848285016135f2565b5f805f805f60808688031215613829575f80fd5b853567ffffffffffffffff81111561383f575f80fd5b61384b888289016136eb565b909650945050602086013561385f81613472565b9250604086013561386f81613472565b9150606086013561387f8161348a565b809150509295509295909350565b5f805f6040848603121561389f575f80fd5b833567ffffffffffffffff808211156138b6575f80fd5b818601915086601f8301126138c9575f80fd5b8135818111156138d7575f80fd5b8760208285010111156138e8575f80fd5b6020928301989097509590910135949350505050565b5f6020828403121561390e575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff82811682821603908082111561396357613963613915565b5092915050565b5f8261399d577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c908216806139b657607f821691505b6020821081036139ed577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f60208284031215613a03575f80fd5b8151801515811461346b575f80fd5b81810381811115613a2557613a25613915565b92915050565b5f60208284031215613a3b575f80fd5b815161346b81613472565b601f82111561310f575f81815260208120601f850160051c81016020861015613a6c5750805b601f850160051c820191505b81811015612dd157828155600101613a78565b815167ffffffffffffffff811115613aa557613aa5613531565b613ab981613ab384546139a2565b84613a46565b602080601f831160018114613b0b575f8415613ad55750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612dd1565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613b5757888601518255948401946001909101908401613b38565b5085821015613b9357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b606081525f613bb56060830186613410565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff81811683821601908082111561396357613963613915565b80820180821115613a2557613a25613915565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112613c74575f80fd5b9190910192915050565b5f60808236031215613c8e575f80fd5b6040516080810167ffffffffffffffff8282108183111715613cb257613cb2613531565b816040528435915080821115613cc6575f80fd5b50613cd3368286016135f2565b825250602083013560208201526040830135613cee81613472565b6040820152606092830135928101929092525090565b5f67ffffffffffffffff808316818103613d2057613d20613915565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d5a57613d5a613915565b5060010190565b8082028115828204841417613a2557613a25613915565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a0830152613dce60c0830184613410565b98975050505050505050565b61ffff81811683821601908082111561396357613963613915565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751613e5d816003860160208c016133ee565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651613ea0816017840160208b016133ee565b808201915050818660f81b16601782015284519150613ec68260188301602088016133ee565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b1660018401528751613f3f816003860160208c016133ee565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b1660038201528651613f82816017840160208b016133ee565b808201915050818660f01b16601782015284519150613fa88260198301602088016133ee565b016019019998505050505050505050565b5f8651613fca818460208b016133ee565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff8416602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b5f602082840312156140a3575f80fd5b815167ffffffffffffffff8111156140b9575f80fd5b8201601f810184136140c9575f80fd5b80516140d761360f826135ad565b8181528560208385010111156140eb575f80fd5b6140fc8260208301602086016133ee565b95945050505050565b5f8060408385031215614116575f80fd5b825161412181613520565b60208401519092506141328161348a565b809150509250929050565b5f8251613c748184602087016133ee56fea264697066735822122085db40c10ef8cab16b910c3133018cca1a119653290a680ee22bc3bb3a64056464736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMExistentEtrog.json b/compiled-contracts/PolygonZkEVMExistentEtrog.json index 771b5d4d4..9b7df33f1 100644 --- a/compiled-contracts/PolygonZkEVMExistentEtrog.json +++ b/compiled-contracts/PolygonZkEVMExistentEtrog.json @@ -1297,8 +1297,8 @@ "type": "function" } ], - "bytecode": "0x61010060405234801562000011575f80fd5b5060405162004ba538038062004ba583398101604081905262000034916200006f565b6001600160a01b0393841660a052918316608052821660c0521660e052620000d4565b6001600160a01b03811681146200006c575f80fd5b50565b5f805f806080858703121562000083575f80fd5b8451620000908162000057565b6020860151909450620000a38162000057565b6040860151909350620000b68162000057565b6060860151909250620000c98162000057565b939692955090935050565b60805160a05160c05160e0516149d2620001d35f395f8181610512015281816109a401528181610b1001528181610c8f01528181610fd901528181611212015281816113920152818161170f01528181611baa01528181611ff9015281816120ee01528181612ca401528181612d1d01528181612d3f01528181612e540152818161306a015261312f01525f8181610691015281816122b8015281816123c0015281816127950152818161351c01526135f101525f818161076801528181610e4e0152818161158601528181612843015261327701525f818161079a015281816108570152818161204201528181612deb015261324c01526149d25ff3fe608060405234801561000f575f80fd5b50600436106102f8575f3560e01c80637125702211610192578063b910e0f9116100e8578063d7bc90ff11610093578063eaeb077b1161006e578063eaeb077b146107d0578063f35dda47146107e3578063f851a440146107eb575f80fd5b8063d7bc90ff1461078a578063e46761c414610795578063e7a7ed02146107bc575f80fd5b8063c89e42df116100c3578063c89e42df14610730578063cfa8ed4714610743578063d02103ca14610763575f80fd5b8063b910e0f9146106ed578063c754c7ed14610700578063c7fffd4b14610728575f80fd5b80639f26f84011610148578063ada8f91911610123578063ada8f919146106c6578063af7f3e02146106d9578063b0afe154146106e1575f80fd5b80639f26f84014610679578063a3c573eb1461068c578063a652f26c146106b3575f80fd5b80638c3d7301116101785780638c3d73011461064357806391cafe321461064b5780639e0018771461065e575f80fd5b806371257022146105f45780637a5460c514610607575f80fd5b806342308fab116102525780635d6717a5116101fd5780636b8616ce116101d85780636b8616ce146105b95780636e05d2cd146105d85780636ff512cc146105e1575f80fd5b80635d6717a51461058b578063669adece1461059e578063676870d2146105b1575f80fd5b80634e4877061161022d5780634e4877061461053457806352bdeb6d14610547578063542028d514610583575f80fd5b806342308fab146104cc57806345605267146104d457806349b7b8021461050d575f80fd5b806326782247116102b25780633c351e101161028d5780633c351e10146104175780633cbc795b1461043757806340b5de6c14610474575f80fd5b8063267822471461039d5780632c111c06146103e257806332c2d15314610402575f80fd5b806305835f37116102e257806305835f3714610332578063107bf28c1461037b57806311e892d414610383575f80fd5b8062d0295d146102fc5780630350896314610317575b5f80fd5b610304610810565b6040519081526020015b60405180910390f35b61031f602081565b60405161ffff909116815260200161030e565b61036e6040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b60405161030e9190613b39565b61036e610916565b61038b60f981565b60405160ff909116815260200161030e565b6001546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161030e565b6008546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b610415610410366004613b8b565b6109a2565b005b6009546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60095461045f9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff909116815260200161030e565b61049b7fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff00000000000000000000000000000000000000000000000000000000000000909116815260200161030e565b610304602481565b6007546104f49068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161030e565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b610415610542366004613bca565b610a71565b61036e6040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b61036e610c80565b610415610599366004613cf8565b610c8d565b6104156105ac366004613d83565b611210565b61031f601f81565b6103046105c7366004613bca565b60066020525f908152604090205481565b61030460055481565b6104156105ef366004613dad565b6112c7565b610415610602366004613dd9565b611390565b61036e6040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b610415611944565b610415610659366004613dad565b611a16565b6103bd73a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b610415610687366004613ec8565b611b2e565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b61036e6106c1366004613f07565b6121ba565b6104156106d4366004613dad565b612598565b61036e612661565b6103046405ca1ab1e081565b6104156106fb366004613f78565b61267d565b6007546104f490700100000000000000000000000000000000900467ffffffffffffffff1681565b61038b60e481565b61041561073e366004613ff8565b612f61565b6002546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b610304635ca1ab1e81565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b6007546104f49067ffffffffffffffff1681565b6104156107de36600461402a565b612ff3565b61038b601b81565b5f546103bd9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561089c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c0919061409b565b6007549091505f906108ea9067ffffffffffffffff680100000000000000008204811691166140df565b67ffffffffffffffff169050805f03610905575f9250505090565b61090f8183614107565b9250505090565b600480546109239061413f565b80601f016020809104026020016040519081016040528092919081815260200182805461094f9061413f565b801561099a5780601f106109715761010080835404028352916020019161099a565b820191905f5260205f20905b81548152906001019060200180831161097d57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610a11576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596684604051610a6491815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610ac7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610b0e576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b77573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9b9190614190565b610bfc5760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610610bfc576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546109239061413f565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610cfc576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff1615808015610d1a57505f54600160ff909116105b80610d335750303b158015610d3357505f5460ff166001145b610dc4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610e20575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f6040518060a001604052806062815260200161493b6062913990505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eb5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ed9919061409b565b90505f868483858d610eec6001436141af565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291505f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015611034573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061105891906141c8565b90508b5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508a60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555089600390816110e99190614228565b5060046110f68a82614228565b508b60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507fd2c80353fc15ef62c6affc7cd6b7ab5b42c43290c50be3372e55ae552cecd19c8187858e6040516111989493929190614340565b60405180910390a15050505050508015611208575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16331461127f576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581905560405181815267ffffffffffffffff8316907f1125aaf62d132d8e2d02005114f8fc360ff204c3105e4f1a700a1340dc55d5b19060200160405180910390a25050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff16331461131d576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c75565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146113ff576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff161580801561141d57505f54600160ff909116105b806114365750303b15801561143657505f5460ff166001145b6114c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610dbb565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561151e575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f611528856134b9565b6009549091505f9061157290889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff16856121ba565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115ed573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611611919061409b565b90505f808483858f6116246001436141af565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af115801561176a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178e91906141c8565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886003908161181e9190614228565b50600461182b8982614228565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e6040516118cb9392919061438f565b60405180910390a1505050505050801561193b575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611995576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611a6c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff16611abb576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb90602001610c75565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590611b6c575073ffffffffffffffffffffffffffffffffffffffff81163314155b15611ba3576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c11573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c3591906141c8565b611c3f91906143cd565b67ffffffffffffffff161115611c81576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f819003611cbc576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611cf8576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff80821691611d20918491680100000000000000009004166143ee565b1115611d58576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b83811015611ff3575f878783818110611d9357611d93614401565b9050602002810190611da5919061442e565b611dae9061446a565b905083611dba816144f0565b825180516020918201208185015160408087015160608801519151959a509295505f94611e26948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f90815260069093529120549091508114611eae576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f90815260066020526040812055611ed26001886141af565b8403611f415742600760109054906101000a900467ffffffffffffffff168460400151611eff91906143cd565b67ffffffffffffffff161115611f41576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc016040516020818303038152906040528051906020012094505050508080611feb90614516565b915050611d78565b506120697f000000000000000000000000000000000000000000000000000000000000000084612021610810565b61202b919061454d565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919061371b565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e739061213a908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015612156573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061217a91906141c8565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f876040516024016121ec96959493929190614564565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f0361233c5760f9601f835161228091906145c6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e48760405160200161232697969594939291906145e1565b6040516020818303038152906040529050612440565b815161ffff1015612379576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f96123886020836145c6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b9000000000000000000000000000000000000000000000000000000000000815250858860405160200161242d97969594939291906146c3565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa15801561249e573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612516576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f9061255b9084906405ca1ab1e090635ca1ab1e90601b907fff00000000000000000000000000000000000000000000000000000000000000906020016147a5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146125ee576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c75565b6040518060a001604052806062815260200161493b6062913981565b60025473ffffffffffffffffffffffffffffffffffffffff1633146126ce576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f819003612709576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115612745576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6127506024426143ee565b8467ffffffffffffffff161115612793576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156127f8575f80fd5b505af115801561280a573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff881660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa15801561289e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128c2919061409b565b9050806128fb576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b85811015612c17575f8c8c8381811061293757612937614401565b9050602002810190612949919061442e565b6129529061446a565b8051805160209091012060408201519192509067ffffffffffffffff1615612b32578561297e816144f0565b9650505f818360200151846040015185606001516040516020016129e09493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f90815260069093529120549091508114612a68576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550612c02565b8151516201d4c01015612b71576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b50508080612c0f90614516565b91505061291c565b5060075467ffffffffffffffff9081169084161115612c62576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff84811690831614612d17575f612c8783866140df565b9050612c9d67ffffffffffffffff8216836141af565b9150612cd67f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff16612021610810565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b612e13337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa158015612da6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612dca919061409b565b612dd4919061454d565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169291906137f4565b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015612eaf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ed391906141c8565b9050888414612f0e576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e76687604051612f4a91815260200190565b60405180910390a250505050505050505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612fb7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003612fc38282614228565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c759190613b39565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590613031575073ffffffffffffffffffffffffffffffffffffffff81163314155b15613068576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130f59190614190565b1561312c576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015613196573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131ba919061409b565b9050828111156131f6576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115613232576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61327473ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163330846137f4565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132de573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613302919061409b565b6007805491925067ffffffffffffffff909116905f613320836144f0565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508585604051613357929190614800565b604051908190039020814261336d6001436141af565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303613463576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2611208565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931906134a990849033908b908b9061480f565b60405180910390a2505050505050565b606073ffffffffffffffffffffffffffffffffffffffff821615613716576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015613560573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526135a5919081019061487f565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa158015613637573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061365b91906148f1565b915091508163ffffffff165f146136d2576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff841617179055613713565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526137ef9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613858565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526138529085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161376d565b50505050565b5f6138b9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166139639092919063ffffffff16565b8051909150156137ef57808060200190518101906138d79190614190565b6137ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610dbb565b606061259084845f85855f808673ffffffffffffffffffffffffffffffffffffffff1685876040516139959190614929565b5f6040518083038185875af1925050503d805f81146139cf576040519150601f19603f3d011682016040523d82523d5f602084013e6139d4565b606091505b50915091506139e5878383876139f0565b979650505050505050565b60608315613a855782515f03613a7e5773ffffffffffffffffffffffffffffffffffffffff85163b613a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610dbb565b5081612590565b6125908383815115613a9a5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dbb9190613b39565b5f5b83811015613ae8578181015183820152602001613ad0565b50505f910152565b5f8151808452613b07816020860160208601613ace565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f613b4b6020830184613af0565b9392505050565b67ffffffffffffffff81168114613b67575f80fd5b50565b73ffffffffffffffffffffffffffffffffffffffff81168114613b67575f80fd5b5f805f60608486031215613b9d575f80fd5b8335613ba881613b52565b9250602084013591506040840135613bbf81613b6a565b809150509250925092565b5f60208284031215613bda575f80fd5b8135613b4b81613b52565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613c5957613c59613be5565b604052919050565b5f67ffffffffffffffff821115613c7a57613c7a613be5565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112613cb5575f80fd5b8135613cc8613cc382613c61565b613c12565b818152846020838601011115613cdc575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a08688031215613d0c575f80fd5b8535613d1781613b6a565b94506020860135613d2781613b6a565b9350604086013567ffffffffffffffff80821115613d43575f80fd5b613d4f89838a01613ca6565b94506060880135915080821115613d64575f80fd5b50613d7188828901613ca6565b95989497509295608001359392505050565b5f8060408385031215613d94575f80fd5b8235613d9f81613b52565b946020939093013593505050565b5f60208284031215613dbd575f80fd5b8135613b4b81613b6a565b63ffffffff81168114613b67575f80fd5b5f805f805f8060c08789031215613dee575f80fd5b8635613df981613b6a565b95506020870135613e0981613b6a565b94506040870135613e1981613dc8565b93506060870135613e2981613b6a565b9250608087013567ffffffffffffffff80821115613e45575f80fd5b613e518a838b01613ca6565b935060a0890135915080821115613e66575f80fd5b50613e7389828a01613ca6565b9150509295509295509295565b5f8083601f840112613e90575f80fd5b50813567ffffffffffffffff811115613ea7575f80fd5b6020830191508360208260051b8501011115613ec1575f80fd5b9250929050565b5f8060208385031215613ed9575f80fd5b823567ffffffffffffffff811115613eef575f80fd5b613efb85828601613e80565b90969095509350505050565b5f805f8060808587031215613f1a575f80fd5b8435613f2581613dc8565b93506020850135613f3581613b6a565b92506040850135613f4581613dc8565b9150606085013567ffffffffffffffff811115613f60575f80fd5b613f6c87828801613ca6565b91505092959194509250565b5f805f805f8060a08789031215613f8d575f80fd5b863567ffffffffffffffff811115613fa3575f80fd5b613faf89828a01613e80565b9097509550506020870135613fc381613dc8565b93506040870135613fd381613b52565b9250606087013591506080870135613fea81613b6a565b809150509295509295509295565b5f60208284031215614008575f80fd5b813567ffffffffffffffff81111561401e575f80fd5b61259084828501613ca6565b5f805f6040848603121561403c575f80fd5b833567ffffffffffffffff80821115614053575f80fd5b818601915086601f830112614066575f80fd5b813581811115614074575f80fd5b876020828501011115614085575f80fd5b6020928301989097509590910135949350505050565b5f602082840312156140ab575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff828116828216039080821115614100576141006140b2565b5092915050565b5f8261413a577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c9082168061415357607f821691505b60208210810361418a577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f602082840312156141a0575f80fd5b81518015158114613b4b575f80fd5b818103818111156141c2576141c26140b2565b92915050565b5f602082840312156141d8575f80fd5b8151613b4b81613b52565b601f8211156137ef575f81815260208120601f850160051c810160208610156142095750805b601f850160051c820191505b8181101561120857828155600101614215565b815167ffffffffffffffff81111561424257614242613be5565b61425681614250845461413f565b846141e3565b602080601f8311600181146142a8575f84156142725750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611208565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156142f4578886015182559484019460019091019084016142d5565b508582101561433057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff85168152608060208201525f6143626080830186613af0565b905083604083015273ffffffffffffffffffffffffffffffffffffffff8316606083015295945050505050565b606081525f6143a16060830186613af0565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff818116838216019080821115614100576141006140b2565b808201808211156141c2576141c26140b2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614460575f80fd5b9190910192915050565b5f6080823603121561447a575f80fd5b6040516080810167ffffffffffffffff828210818311171561449e5761449e613be5565b8160405284359150808211156144b2575f80fd5b506144bf36828601613ca6565b8252506020830135602082015260408301356144da81613b52565b6040820152606092830135928101929092525090565b5f67ffffffffffffffff80831681810361450c5761450c6140b2565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614546576145466140b2565b5060010190565b80820281158282048414176141c2576141c26140b2565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a08301526145ba60c0830184613af0565b98975050505050505050565b61ffff818116838216019080821115614100576141006140b2565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751614649816003860160208c01613ace565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b166003820152865161468c816017840160208b01613ace565b808201915050818660f81b166017820152845191506146b2826018830160208801613ace565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b166001840152875161472b816003860160208c01613ace565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b166003820152865161476e816017840160208b01613ace565b808201915050818660f01b16601782015284519150614794826019830160208801613ace565b016019019998505050505050505050565b5f86516147b6818460208b01613ace565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff8416602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b5f6020828403121561488f575f80fd5b815167ffffffffffffffff8111156148a5575f80fd5b8201601f810184136148b5575f80fd5b80516148c3613cc382613c61565b8181528560208385010111156148d7575f80fd5b6148e8826020830160208601613ace565b95945050505050565b5f8060408385031215614902575f80fd5b825161490d81613dc8565b602084015190925061491e81613b6a565b809150509250929050565b5f8251614460818460208701613ace56fedf2a8080944d5cf5032b2a844602278b01199ed191a86c93ff8080821092808000000000000000000000000000000000000000000000000000000005ca1ab1e000000000000000000000000000000000000000000000000000000005ca1ab1e01bffa2646970667358221220979431b424408003d816db191eabc1b13183c62a3b89f5a269d7d09e30f3613364736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102f8575f3560e01c80637125702211610192578063b910e0f9116100e8578063d7bc90ff11610093578063eaeb077b1161006e578063eaeb077b146107d0578063f35dda47146107e3578063f851a440146107eb575f80fd5b8063d7bc90ff1461078a578063e46761c414610795578063e7a7ed02146107bc575f80fd5b8063c89e42df116100c3578063c89e42df14610730578063cfa8ed4714610743578063d02103ca14610763575f80fd5b8063b910e0f9146106ed578063c754c7ed14610700578063c7fffd4b14610728575f80fd5b80639f26f84011610148578063ada8f91911610123578063ada8f919146106c6578063af7f3e02146106d9578063b0afe154146106e1575f80fd5b80639f26f84014610679578063a3c573eb1461068c578063a652f26c146106b3575f80fd5b80638c3d7301116101785780638c3d73011461064357806391cafe321461064b5780639e0018771461065e575f80fd5b806371257022146105f45780637a5460c514610607575f80fd5b806342308fab116102525780635d6717a5116101fd5780636b8616ce116101d85780636b8616ce146105b95780636e05d2cd146105d85780636ff512cc146105e1575f80fd5b80635d6717a51461058b578063669adece1461059e578063676870d2146105b1575f80fd5b80634e4877061161022d5780634e4877061461053457806352bdeb6d14610547578063542028d514610583575f80fd5b806342308fab146104cc57806345605267146104d457806349b7b8021461050d575f80fd5b806326782247116102b25780633c351e101161028d5780633c351e10146104175780633cbc795b1461043757806340b5de6c14610474575f80fd5b8063267822471461039d5780632c111c06146103e257806332c2d15314610402575f80fd5b806305835f37116102e257806305835f3714610332578063107bf28c1461037b57806311e892d414610383575f80fd5b8062d0295d146102fc5780630350896314610317575b5f80fd5b610304610810565b6040519081526020015b60405180910390f35b61031f602081565b60405161ffff909116815260200161030e565b61036e6040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b60405161030e9190613b39565b61036e610916565b61038b60f981565b60405160ff909116815260200161030e565b6001546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161030e565b6008546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b610415610410366004613b8b565b6109a2565b005b6009546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60095461045f9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff909116815260200161030e565b61049b7fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff00000000000000000000000000000000000000000000000000000000000000909116815260200161030e565b610304602481565b6007546104f49068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161030e565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b610415610542366004613bca565b610a71565b61036e6040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b61036e610c80565b610415610599366004613cf8565b610c8d565b6104156105ac366004613d83565b611210565b61031f601f81565b6103046105c7366004613bca565b60066020525f908152604090205481565b61030460055481565b6104156105ef366004613dad565b6112c7565b610415610602366004613dd9565b611390565b61036e6040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b610415611944565b610415610659366004613dad565b611a16565b6103bd73a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b610415610687366004613ec8565b611b2e565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b61036e6106c1366004613f07565b6121ba565b6104156106d4366004613dad565b612598565b61036e612661565b6103046405ca1ab1e081565b6104156106fb366004613f78565b61267d565b6007546104f490700100000000000000000000000000000000900467ffffffffffffffff1681565b61038b60e481565b61041561073e366004613ff8565b612f61565b6002546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b610304635ca1ab1e81565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b6007546104f49067ffffffffffffffff1681565b6104156107de36600461402a565b612ff3565b61038b601b81565b5f546103bd9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561089c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c0919061409b565b6007549091505f906108ea9067ffffffffffffffff680100000000000000008204811691166140df565b67ffffffffffffffff169050805f03610905575f9250505090565b61090f8183614107565b9250505090565b600480546109239061413f565b80601f016020809104026020016040519081016040528092919081815260200182805461094f9061413f565b801561099a5780601f106109715761010080835404028352916020019161099a565b820191905f5260205f20905b81548152906001019060200180831161097d57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610a11576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596684604051610a6491815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610ac7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610b0e576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b77573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9b9190614190565b610bfc5760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610610bfc576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546109239061413f565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610cfc576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff1615808015610d1a57505f54600160ff909116105b80610d335750303b158015610d3357505f5460ff166001145b610dc4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610e20575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f6040518060a001604052806062815260200161493b6062913990505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eb5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ed9919061409b565b90505f868483858d610eec6001436141af565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291505f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015611034573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061105891906141c8565b90508b5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508a60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555089600390816110e99190614228565b5060046110f68a82614228565b508b60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507fd2c80353fc15ef62c6affc7cd6b7ab5b42c43290c50be3372e55ae552cecd19c8187858e6040516111989493929190614340565b60405180910390a15050505050508015611208575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16331461127f576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581905560405181815267ffffffffffffffff8316907f1125aaf62d132d8e2d02005114f8fc360ff204c3105e4f1a700a1340dc55d5b19060200160405180910390a25050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff16331461131d576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c75565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146113ff576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff161580801561141d57505f54600160ff909116105b806114365750303b15801561143657505f5460ff166001145b6114c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610dbb565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561151e575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f611528856134b9565b6009549091505f9061157290889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff16856121ba565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115ed573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611611919061409b565b90505f808483858f6116246001436141af565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af115801561176a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178e91906141c8565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886003908161181e9190614228565b50600461182b8982614228565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e6040516118cb9392919061438f565b60405180910390a1505050505050801561193b575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611995576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611a6c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff16611abb576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb90602001610c75565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590611b6c575073ffffffffffffffffffffffffffffffffffffffff81163314155b15611ba3576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c11573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c3591906141c8565b611c3f91906143cd565b67ffffffffffffffff161115611c81576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f819003611cbc576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611cf8576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff80821691611d20918491680100000000000000009004166143ee565b1115611d58576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b83811015611ff3575f878783818110611d9357611d93614401565b9050602002810190611da5919061442e565b611dae9061446a565b905083611dba816144f0565b825180516020918201208185015160408087015160608801519151959a509295505f94611e26948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f90815260069093529120549091508114611eae576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f90815260066020526040812055611ed26001886141af565b8403611f415742600760109054906101000a900467ffffffffffffffff168460400151611eff91906143cd565b67ffffffffffffffff161115611f41576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc016040516020818303038152906040528051906020012094505050508080611feb90614516565b915050611d78565b506120697f000000000000000000000000000000000000000000000000000000000000000084612021610810565b61202b919061454d565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919061371b565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e739061213a908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015612156573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061217a91906141c8565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f876040516024016121ec96959493929190614564565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f0361233c5760f9601f835161228091906145c6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e48760405160200161232697969594939291906145e1565b6040516020818303038152906040529050612440565b815161ffff1015612379576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f96123886020836145c6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b9000000000000000000000000000000000000000000000000000000000000815250858860405160200161242d97969594939291906146c3565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa15801561249e573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612516576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f9061255b9084906405ca1ab1e090635ca1ab1e90601b907fff00000000000000000000000000000000000000000000000000000000000000906020016147a5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146125ee576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c75565b6040518060a001604052806062815260200161493b6062913981565b60025473ffffffffffffffffffffffffffffffffffffffff1633146126ce576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f819003612709576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115612745576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6127506024426143ee565b8467ffffffffffffffff161115612793576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156127f8575f80fd5b505af115801561280a573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff881660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa15801561289e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128c2919061409b565b9050806128fb576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b85811015612c17575f8c8c8381811061293757612937614401565b9050602002810190612949919061442e565b6129529061446a565b8051805160209091012060408201519192509067ffffffffffffffff1615612b32578561297e816144f0565b9650505f818360200151846040015185606001516040516020016129e09493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f90815260069093529120549091508114612a68576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550612c02565b8151516201d4c01015612b71576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b50508080612c0f90614516565b91505061291c565b5060075467ffffffffffffffff9081169084161115612c62576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff84811690831614612d17575f612c8783866140df565b9050612c9d67ffffffffffffffff8216836141af565b9150612cd67f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff16612021610810565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b612e13337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa158015612da6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612dca919061409b565b612dd4919061454d565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169291906137f4565b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015612eaf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ed391906141c8565b9050888414612f0e576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e76687604051612f4a91815260200190565b60405180910390a250505050505050505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612fb7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003612fc38282614228565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c759190613b39565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590613031575073ffffffffffffffffffffffffffffffffffffffff81163314155b15613068576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130f59190614190565b1561312c576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015613196573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131ba919061409b565b9050828111156131f6576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115613232576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61327473ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163330846137f4565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132de573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613302919061409b565b6007805491925067ffffffffffffffff909116905f613320836144f0565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508585604051613357929190614800565b604051908190039020814261336d6001436141af565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303613463576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2611208565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931906134a990849033908b908b9061480f565b60405180910390a2505050505050565b606073ffffffffffffffffffffffffffffffffffffffff821615613716576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015613560573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526135a5919081019061487f565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa158015613637573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061365b91906148f1565b915091508163ffffffff165f146136d2576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff841617179055613713565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526137ef9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613858565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526138529085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161376d565b50505050565b5f6138b9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166139639092919063ffffffff16565b8051909150156137ef57808060200190518101906138d79190614190565b6137ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610dbb565b606061259084845f85855f808673ffffffffffffffffffffffffffffffffffffffff1685876040516139959190614929565b5f6040518083038185875af1925050503d805f81146139cf576040519150601f19603f3d011682016040523d82523d5f602084013e6139d4565b606091505b50915091506139e5878383876139f0565b979650505050505050565b60608315613a855782515f03613a7e5773ffffffffffffffffffffffffffffffffffffffff85163b613a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610dbb565b5081612590565b6125908383815115613a9a5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dbb9190613b39565b5f5b83811015613ae8578181015183820152602001613ad0565b50505f910152565b5f8151808452613b07816020860160208601613ace565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f613b4b6020830184613af0565b9392505050565b67ffffffffffffffff81168114613b67575f80fd5b50565b73ffffffffffffffffffffffffffffffffffffffff81168114613b67575f80fd5b5f805f60608486031215613b9d575f80fd5b8335613ba881613b52565b9250602084013591506040840135613bbf81613b6a565b809150509250925092565b5f60208284031215613bda575f80fd5b8135613b4b81613b52565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613c5957613c59613be5565b604052919050565b5f67ffffffffffffffff821115613c7a57613c7a613be5565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112613cb5575f80fd5b8135613cc8613cc382613c61565b613c12565b818152846020838601011115613cdc575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a08688031215613d0c575f80fd5b8535613d1781613b6a565b94506020860135613d2781613b6a565b9350604086013567ffffffffffffffff80821115613d43575f80fd5b613d4f89838a01613ca6565b94506060880135915080821115613d64575f80fd5b50613d7188828901613ca6565b95989497509295608001359392505050565b5f8060408385031215613d94575f80fd5b8235613d9f81613b52565b946020939093013593505050565b5f60208284031215613dbd575f80fd5b8135613b4b81613b6a565b63ffffffff81168114613b67575f80fd5b5f805f805f8060c08789031215613dee575f80fd5b8635613df981613b6a565b95506020870135613e0981613b6a565b94506040870135613e1981613dc8565b93506060870135613e2981613b6a565b9250608087013567ffffffffffffffff80821115613e45575f80fd5b613e518a838b01613ca6565b935060a0890135915080821115613e66575f80fd5b50613e7389828a01613ca6565b9150509295509295509295565b5f8083601f840112613e90575f80fd5b50813567ffffffffffffffff811115613ea7575f80fd5b6020830191508360208260051b8501011115613ec1575f80fd5b9250929050565b5f8060208385031215613ed9575f80fd5b823567ffffffffffffffff811115613eef575f80fd5b613efb85828601613e80565b90969095509350505050565b5f805f8060808587031215613f1a575f80fd5b8435613f2581613dc8565b93506020850135613f3581613b6a565b92506040850135613f4581613dc8565b9150606085013567ffffffffffffffff811115613f60575f80fd5b613f6c87828801613ca6565b91505092959194509250565b5f805f805f8060a08789031215613f8d575f80fd5b863567ffffffffffffffff811115613fa3575f80fd5b613faf89828a01613e80565b9097509550506020870135613fc381613dc8565b93506040870135613fd381613b52565b9250606087013591506080870135613fea81613b6a565b809150509295509295509295565b5f60208284031215614008575f80fd5b813567ffffffffffffffff81111561401e575f80fd5b61259084828501613ca6565b5f805f6040848603121561403c575f80fd5b833567ffffffffffffffff80821115614053575f80fd5b818601915086601f830112614066575f80fd5b813581811115614074575f80fd5b876020828501011115614085575f80fd5b6020928301989097509590910135949350505050565b5f602082840312156140ab575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff828116828216039080821115614100576141006140b2565b5092915050565b5f8261413a577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c9082168061415357607f821691505b60208210810361418a577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f602082840312156141a0575f80fd5b81518015158114613b4b575f80fd5b818103818111156141c2576141c26140b2565b92915050565b5f602082840312156141d8575f80fd5b8151613b4b81613b52565b601f8211156137ef575f81815260208120601f850160051c810160208610156142095750805b601f850160051c820191505b8181101561120857828155600101614215565b815167ffffffffffffffff81111561424257614242613be5565b61425681614250845461413f565b846141e3565b602080601f8311600181146142a8575f84156142725750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611208565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156142f4578886015182559484019460019091019084016142d5565b508582101561433057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff85168152608060208201525f6143626080830186613af0565b905083604083015273ffffffffffffffffffffffffffffffffffffffff8316606083015295945050505050565b606081525f6143a16060830186613af0565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff818116838216019080821115614100576141006140b2565b808201808211156141c2576141c26140b2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614460575f80fd5b9190910192915050565b5f6080823603121561447a575f80fd5b6040516080810167ffffffffffffffff828210818311171561449e5761449e613be5565b8160405284359150808211156144b2575f80fd5b506144bf36828601613ca6565b8252506020830135602082015260408301356144da81613b52565b6040820152606092830135928101929092525090565b5f67ffffffffffffffff80831681810361450c5761450c6140b2565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614546576145466140b2565b5060010190565b80820281158282048414176141c2576141c26140b2565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a08301526145ba60c0830184613af0565b98975050505050505050565b61ffff818116838216019080821115614100576141006140b2565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751614649816003860160208c01613ace565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b166003820152865161468c816017840160208b01613ace565b808201915050818660f81b166017820152845191506146b2826018830160208801613ace565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b166001840152875161472b816003860160208c01613ace565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b166003820152865161476e816017840160208b01613ace565b808201915050818660f01b16601782015284519150614794826019830160208801613ace565b016019019998505050505050505050565b5f86516147b6818460208b01613ace565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff8416602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b5f6020828403121561488f575f80fd5b815167ffffffffffffffff8111156148a5575f80fd5b8201601f810184136148b5575f80fd5b80516148c3613cc382613c61565b8181528560208385010111156148d7575f80fd5b6148e8826020830160208601613ace565b95945050505050565b5f8060408385031215614902575f80fd5b825161490d81613dc8565b602084015190925061491e81613b6a565b809150509250929050565b5f8251614460818460208701613ace56fedf2a8080944d5cf5032b2a844602278b01199ed191a86c93ff8080821092808000000000000000000000000000000000000000000000000000000005ca1ab1e000000000000000000000000000000000000000000000000000000005ca1ab1e01bffa2646970667358221220979431b424408003d816db191eabc1b13183c62a3b89f5a269d7d09e30f3613364736f6c63430008140033", + "bytecode": "0x61010060405234801562000011575f80fd5b5060405162004c8438038062004c8483398101604081905262000034916200014e565b6001600160a01b0380851660a05280841660805280831660c052811660e05283838383838383836200006562000077565b505050505050505050505050620001b3565b5f54610100900460ff1615620000e35760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff908116101562000134575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b03811681146200014b575f80fd5b50565b5f805f806080858703121562000162575f80fd5b84516200016f8162000136565b6020860151909450620001828162000136565b6040860151909350620001958162000136565b6060860151909250620001a88162000136565b939692955090935050565b60805160a05160c05160e0516149d2620002b25f395f8181610512015281816109a401528181610b1001528181610c8f01528181610fd901528181611212015281816113920152818161170f01528181611baa01528181611ff9015281816120ee01528181612ca401528181612d1d01528181612d3f01528181612e540152818161306a015261312f01525f8181610691015281816122b8015281816123c0015281816127950152818161351c01526135f101525f818161076801528181610e4e0152818161158601528181612843015261327701525f818161079a015281816108570152818161204201528181612deb015261324c01526149d25ff3fe608060405234801561000f575f80fd5b50600436106102f8575f3560e01c80637125702211610192578063b910e0f9116100e8578063d7bc90ff11610093578063eaeb077b1161006e578063eaeb077b146107d0578063f35dda47146107e3578063f851a440146107eb575f80fd5b8063d7bc90ff1461078a578063e46761c414610795578063e7a7ed02146107bc575f80fd5b8063c89e42df116100c3578063c89e42df14610730578063cfa8ed4714610743578063d02103ca14610763575f80fd5b8063b910e0f9146106ed578063c754c7ed14610700578063c7fffd4b14610728575f80fd5b80639f26f84011610148578063ada8f91911610123578063ada8f919146106c6578063af7f3e02146106d9578063b0afe154146106e1575f80fd5b80639f26f84014610679578063a3c573eb1461068c578063a652f26c146106b3575f80fd5b80638c3d7301116101785780638c3d73011461064357806391cafe321461064b5780639e0018771461065e575f80fd5b806371257022146105f45780637a5460c514610607575f80fd5b806342308fab116102525780635d6717a5116101fd5780636b8616ce116101d85780636b8616ce146105b95780636e05d2cd146105d85780636ff512cc146105e1575f80fd5b80635d6717a51461058b578063669adece1461059e578063676870d2146105b1575f80fd5b80634e4877061161022d5780634e4877061461053457806352bdeb6d14610547578063542028d514610583575f80fd5b806342308fab146104cc57806345605267146104d457806349b7b8021461050d575f80fd5b806326782247116102b25780633c351e101161028d5780633c351e10146104175780633cbc795b1461043757806340b5de6c14610474575f80fd5b8063267822471461039d5780632c111c06146103e257806332c2d15314610402575f80fd5b806305835f37116102e257806305835f3714610332578063107bf28c1461037b57806311e892d414610383575f80fd5b8062d0295d146102fc5780630350896314610317575b5f80fd5b610304610810565b6040519081526020015b60405180910390f35b61031f602081565b60405161ffff909116815260200161030e565b61036e6040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b60405161030e9190613b39565b61036e610916565b61038b60f981565b60405160ff909116815260200161030e565b6001546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161030e565b6008546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b610415610410366004613b8b565b6109a2565b005b6009546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60095461045f9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff909116815260200161030e565b61049b7fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff00000000000000000000000000000000000000000000000000000000000000909116815260200161030e565b610304602481565b6007546104f49068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161030e565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b610415610542366004613bca565b610a71565b61036e6040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b61036e610c80565b610415610599366004613cf8565b610c8d565b6104156105ac366004613d83565b611210565b61031f601f81565b6103046105c7366004613bca565b60066020525f908152604090205481565b61030460055481565b6104156105ef366004613dad565b6112c7565b610415610602366004613dd9565b611390565b61036e6040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b610415611944565b610415610659366004613dad565b611a16565b6103bd73a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b610415610687366004613ec8565b611b2e565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b61036e6106c1366004613f07565b6121ba565b6104156106d4366004613dad565b612598565b61036e612661565b6103046405ca1ab1e081565b6104156106fb366004613f78565b61267d565b6007546104f490700100000000000000000000000000000000900467ffffffffffffffff1681565b61038b60e481565b61041561073e366004613ff8565b612f61565b6002546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b610304635ca1ab1e81565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b6007546104f49067ffffffffffffffff1681565b6104156107de36600461402a565b612ff3565b61038b601b81565b5f546103bd9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561089c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c0919061409b565b6007549091505f906108ea9067ffffffffffffffff680100000000000000008204811691166140df565b67ffffffffffffffff169050805f03610905575f9250505090565b61090f8183614107565b9250505090565b600480546109239061413f565b80601f016020809104026020016040519081016040528092919081815260200182805461094f9061413f565b801561099a5780601f106109715761010080835404028352916020019161099a565b820191905f5260205f20905b81548152906001019060200180831161097d57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610a11576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596684604051610a6491815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610ac7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610b0e576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b77573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9b9190614190565b610bfc5760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610610bfc576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546109239061413f565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610cfc576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff1615808015610d1a57505f54600160ff909116105b80610d335750303b158015610d3357505f5460ff166001145b610dc4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610e20575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f6040518060a001604052806062815260200161493b6062913990505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eb5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ed9919061409b565b90505f868483858d610eec6001436141af565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291505f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015611034573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061105891906141c8565b90508b5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508a60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555089600390816110e99190614228565b5060046110f68a82614228565b508b60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507fd2c80353fc15ef62c6affc7cd6b7ab5b42c43290c50be3372e55ae552cecd19c8187858e6040516111989493929190614340565b60405180910390a15050505050508015611208575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16331461127f576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581905560405181815267ffffffffffffffff8316907f1125aaf62d132d8e2d02005114f8fc360ff204c3105e4f1a700a1340dc55d5b19060200160405180910390a25050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff16331461131d576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c75565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146113ff576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff161580801561141d57505f54600160ff909116105b806114365750303b15801561143657505f5460ff166001145b6114c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610dbb565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561151e575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f611528856134b9565b6009549091505f9061157290889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff16856121ba565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115ed573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611611919061409b565b90505f808483858f6116246001436141af565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af115801561176a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178e91906141c8565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886003908161181e9190614228565b50600461182b8982614228565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e6040516118cb9392919061438f565b60405180910390a1505050505050801561193b575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611995576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611a6c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff16611abb576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb90602001610c75565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590611b6c575073ffffffffffffffffffffffffffffffffffffffff81163314155b15611ba3576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c11573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c3591906141c8565b611c3f91906143cd565b67ffffffffffffffff161115611c81576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f819003611cbc576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611cf8576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff80821691611d20918491680100000000000000009004166143ee565b1115611d58576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b83811015611ff3575f878783818110611d9357611d93614401565b9050602002810190611da5919061442e565b611dae9061446a565b905083611dba816144f0565b825180516020918201208185015160408087015160608801519151959a509295505f94611e26948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f90815260069093529120549091508114611eae576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f90815260066020526040812055611ed26001886141af565b8403611f415742600760109054906101000a900467ffffffffffffffff168460400151611eff91906143cd565b67ffffffffffffffff161115611f41576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc016040516020818303038152906040528051906020012094505050508080611feb90614516565b915050611d78565b506120697f000000000000000000000000000000000000000000000000000000000000000084612021610810565b61202b919061454d565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919061371b565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e739061213a908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015612156573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061217a91906141c8565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f876040516024016121ec96959493929190614564565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f0361233c5760f9601f835161228091906145c6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e48760405160200161232697969594939291906145e1565b6040516020818303038152906040529050612440565b815161ffff1015612379576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f96123886020836145c6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b9000000000000000000000000000000000000000000000000000000000000815250858860405160200161242d97969594939291906146c3565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa15801561249e573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612516576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f9061255b9084906405ca1ab1e090635ca1ab1e90601b907fff00000000000000000000000000000000000000000000000000000000000000906020016147a5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146125ee576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c75565b6040518060a001604052806062815260200161493b6062913981565b60025473ffffffffffffffffffffffffffffffffffffffff1633146126ce576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f819003612709576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115612745576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6127506024426143ee565b8467ffffffffffffffff161115612793576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156127f8575f80fd5b505af115801561280a573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff881660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa15801561289e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128c2919061409b565b9050806128fb576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b85811015612c17575f8c8c8381811061293757612937614401565b9050602002810190612949919061442e565b6129529061446a565b8051805160209091012060408201519192509067ffffffffffffffff1615612b32578561297e816144f0565b9650505f818360200151846040015185606001516040516020016129e09493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f90815260069093529120549091508114612a68576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550612c02565b8151516201d4c01015612b71576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b50508080612c0f90614516565b91505061291c565b5060075467ffffffffffffffff9081169084161115612c62576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff84811690831614612d17575f612c8783866140df565b9050612c9d67ffffffffffffffff8216836141af565b9150612cd67f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff16612021610810565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b612e13337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa158015612da6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612dca919061409b565b612dd4919061454d565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169291906137f4565b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015612eaf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ed391906141c8565b9050888414612f0e576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e76687604051612f4a91815260200190565b60405180910390a250505050505050505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612fb7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003612fc38282614228565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c759190613b39565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590613031575073ffffffffffffffffffffffffffffffffffffffff81163314155b15613068576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130f59190614190565b1561312c576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015613196573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131ba919061409b565b9050828111156131f6576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115613232576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61327473ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163330846137f4565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132de573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613302919061409b565b6007805491925067ffffffffffffffff909116905f613320836144f0565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508585604051613357929190614800565b604051908190039020814261336d6001436141af565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303613463576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2611208565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931906134a990849033908b908b9061480f565b60405180910390a2505050505050565b606073ffffffffffffffffffffffffffffffffffffffff821615613716576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015613560573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526135a5919081019061487f565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa158015613637573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061365b91906148f1565b915091508163ffffffff165f146136d2576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff841617179055613713565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526137ef9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613858565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526138529085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161376d565b50505050565b5f6138b9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166139639092919063ffffffff16565b8051909150156137ef57808060200190518101906138d79190614190565b6137ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610dbb565b606061259084845f85855f808673ffffffffffffffffffffffffffffffffffffffff1685876040516139959190614929565b5f6040518083038185875af1925050503d805f81146139cf576040519150601f19603f3d011682016040523d82523d5f602084013e6139d4565b606091505b50915091506139e5878383876139f0565b979650505050505050565b60608315613a855782515f03613a7e5773ffffffffffffffffffffffffffffffffffffffff85163b613a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610dbb565b5081612590565b6125908383815115613a9a5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dbb9190613b39565b5f5b83811015613ae8578181015183820152602001613ad0565b50505f910152565b5f8151808452613b07816020860160208601613ace565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f613b4b6020830184613af0565b9392505050565b67ffffffffffffffff81168114613b67575f80fd5b50565b73ffffffffffffffffffffffffffffffffffffffff81168114613b67575f80fd5b5f805f60608486031215613b9d575f80fd5b8335613ba881613b52565b9250602084013591506040840135613bbf81613b6a565b809150509250925092565b5f60208284031215613bda575f80fd5b8135613b4b81613b52565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613c5957613c59613be5565b604052919050565b5f67ffffffffffffffff821115613c7a57613c7a613be5565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112613cb5575f80fd5b8135613cc8613cc382613c61565b613c12565b818152846020838601011115613cdc575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a08688031215613d0c575f80fd5b8535613d1781613b6a565b94506020860135613d2781613b6a565b9350604086013567ffffffffffffffff80821115613d43575f80fd5b613d4f89838a01613ca6565b94506060880135915080821115613d64575f80fd5b50613d7188828901613ca6565b95989497509295608001359392505050565b5f8060408385031215613d94575f80fd5b8235613d9f81613b52565b946020939093013593505050565b5f60208284031215613dbd575f80fd5b8135613b4b81613b6a565b63ffffffff81168114613b67575f80fd5b5f805f805f8060c08789031215613dee575f80fd5b8635613df981613b6a565b95506020870135613e0981613b6a565b94506040870135613e1981613dc8565b93506060870135613e2981613b6a565b9250608087013567ffffffffffffffff80821115613e45575f80fd5b613e518a838b01613ca6565b935060a0890135915080821115613e66575f80fd5b50613e7389828a01613ca6565b9150509295509295509295565b5f8083601f840112613e90575f80fd5b50813567ffffffffffffffff811115613ea7575f80fd5b6020830191508360208260051b8501011115613ec1575f80fd5b9250929050565b5f8060208385031215613ed9575f80fd5b823567ffffffffffffffff811115613eef575f80fd5b613efb85828601613e80565b90969095509350505050565b5f805f8060808587031215613f1a575f80fd5b8435613f2581613dc8565b93506020850135613f3581613b6a565b92506040850135613f4581613dc8565b9150606085013567ffffffffffffffff811115613f60575f80fd5b613f6c87828801613ca6565b91505092959194509250565b5f805f805f8060a08789031215613f8d575f80fd5b863567ffffffffffffffff811115613fa3575f80fd5b613faf89828a01613e80565b9097509550506020870135613fc381613dc8565b93506040870135613fd381613b52565b9250606087013591506080870135613fea81613b6a565b809150509295509295509295565b5f60208284031215614008575f80fd5b813567ffffffffffffffff81111561401e575f80fd5b61259084828501613ca6565b5f805f6040848603121561403c575f80fd5b833567ffffffffffffffff80821115614053575f80fd5b818601915086601f830112614066575f80fd5b813581811115614074575f80fd5b876020828501011115614085575f80fd5b6020928301989097509590910135949350505050565b5f602082840312156140ab575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff828116828216039080821115614100576141006140b2565b5092915050565b5f8261413a577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c9082168061415357607f821691505b60208210810361418a577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f602082840312156141a0575f80fd5b81518015158114613b4b575f80fd5b818103818111156141c2576141c26140b2565b92915050565b5f602082840312156141d8575f80fd5b8151613b4b81613b52565b601f8211156137ef575f81815260208120601f850160051c810160208610156142095750805b601f850160051c820191505b8181101561120857828155600101614215565b815167ffffffffffffffff81111561424257614242613be5565b61425681614250845461413f565b846141e3565b602080601f8311600181146142a8575f84156142725750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611208565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156142f4578886015182559484019460019091019084016142d5565b508582101561433057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff85168152608060208201525f6143626080830186613af0565b905083604083015273ffffffffffffffffffffffffffffffffffffffff8316606083015295945050505050565b606081525f6143a16060830186613af0565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff818116838216019080821115614100576141006140b2565b808201808211156141c2576141c26140b2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614460575f80fd5b9190910192915050565b5f6080823603121561447a575f80fd5b6040516080810167ffffffffffffffff828210818311171561449e5761449e613be5565b8160405284359150808211156144b2575f80fd5b506144bf36828601613ca6565b8252506020830135602082015260408301356144da81613b52565b6040820152606092830135928101929092525090565b5f67ffffffffffffffff80831681810361450c5761450c6140b2565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614546576145466140b2565b5060010190565b80820281158282048414176141c2576141c26140b2565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a08301526145ba60c0830184613af0565b98975050505050505050565b61ffff818116838216019080821115614100576141006140b2565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751614649816003860160208c01613ace565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b166003820152865161468c816017840160208b01613ace565b808201915050818660f81b166017820152845191506146b2826018830160208801613ace565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b166001840152875161472b816003860160208c01613ace565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b166003820152865161476e816017840160208b01613ace565b808201915050818660f01b16601782015284519150614794826019830160208801613ace565b016019019998505050505050505050565b5f86516147b6818460208b01613ace565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff8416602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b5f6020828403121561488f575f80fd5b815167ffffffffffffffff8111156148a5575f80fd5b8201601f810184136148b5575f80fd5b80516148c3613cc382613c61565b8181528560208385010111156148d7575f80fd5b6148e8826020830160208601613ace565b95945050505050565b5f8060408385031215614902575f80fd5b825161490d81613dc8565b602084015190925061491e81613b6a565b809150509250929050565b5f8251614460818460208701613ace56fedf2a8080944d5cf5032b2a844602278b01199ed191a86c93ff8080821092808000000000000000000000000000000000000000000000000000000005ca1ab1e000000000000000000000000000000000000000000000000000000005ca1ab1e01bffa26469706673582212207856dfc85aae7e627fea5f616cb0ac92c48b5b310deb4f096e99c1918acf281b64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102f8575f3560e01c80637125702211610192578063b910e0f9116100e8578063d7bc90ff11610093578063eaeb077b1161006e578063eaeb077b146107d0578063f35dda47146107e3578063f851a440146107eb575f80fd5b8063d7bc90ff1461078a578063e46761c414610795578063e7a7ed02146107bc575f80fd5b8063c89e42df116100c3578063c89e42df14610730578063cfa8ed4714610743578063d02103ca14610763575f80fd5b8063b910e0f9146106ed578063c754c7ed14610700578063c7fffd4b14610728575f80fd5b80639f26f84011610148578063ada8f91911610123578063ada8f919146106c6578063af7f3e02146106d9578063b0afe154146106e1575f80fd5b80639f26f84014610679578063a3c573eb1461068c578063a652f26c146106b3575f80fd5b80638c3d7301116101785780638c3d73011461064357806391cafe321461064b5780639e0018771461065e575f80fd5b806371257022146105f45780637a5460c514610607575f80fd5b806342308fab116102525780635d6717a5116101fd5780636b8616ce116101d85780636b8616ce146105b95780636e05d2cd146105d85780636ff512cc146105e1575f80fd5b80635d6717a51461058b578063669adece1461059e578063676870d2146105b1575f80fd5b80634e4877061161022d5780634e4877061461053457806352bdeb6d14610547578063542028d514610583575f80fd5b806342308fab146104cc57806345605267146104d457806349b7b8021461050d575f80fd5b806326782247116102b25780633c351e101161028d5780633c351e10146104175780633cbc795b1461043757806340b5de6c14610474575f80fd5b8063267822471461039d5780632c111c06146103e257806332c2d15314610402575f80fd5b806305835f37116102e257806305835f3714610332578063107bf28c1461037b57806311e892d414610383575f80fd5b8062d0295d146102fc5780630350896314610317575b5f80fd5b610304610810565b6040519081526020015b60405180910390f35b61031f602081565b60405161ffff909116815260200161030e565b61036e6040518060400160405280600881526020017f80808401c9c3809400000000000000000000000000000000000000000000000081525081565b60405161030e9190613b39565b61036e610916565b61038b60f981565b60405160ff909116815260200161030e565b6001546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161030e565b6008546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b610415610410366004613b8b565b6109a2565b005b6009546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b60095461045f9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff909116815260200161030e565b61049b7fff0000000000000000000000000000000000000000000000000000000000000081565b6040517fff00000000000000000000000000000000000000000000000000000000000000909116815260200161030e565b610304602481565b6007546104f49068010000000000000000900467ffffffffffffffff1681565b60405167ffffffffffffffff909116815260200161030e565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b610415610542366004613bca565b610a71565b61036e6040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525081565b61036e610c80565b610415610599366004613cf8565b610c8d565b6104156105ac366004613d83565b611210565b61031f601f81565b6103046105c7366004613bca565b60066020525f908152604090205481565b61030460055481565b6104156105ef366004613dad565b6112c7565b610415610602366004613dd9565b611390565b61036e6040518060400160405280600281526020017f80b900000000000000000000000000000000000000000000000000000000000081525081565b610415611944565b610415610659366004613dad565b611a16565b6103bd73a40d5f56745a118d0906a34e69aec8c0db1cb8fa81565b610415610687366004613ec8565b611b2e565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b61036e6106c1366004613f07565b6121ba565b6104156106d4366004613dad565b612598565b61036e612661565b6103046405ca1ab1e081565b6104156106fb366004613f78565b61267d565b6007546104f490700100000000000000000000000000000000900467ffffffffffffffff1681565b61038b60e481565b61041561073e366004613ff8565b612f61565b6002546103bd9073ffffffffffffffffffffffffffffffffffffffff1681565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b610304635ca1ab1e81565b6103bd7f000000000000000000000000000000000000000000000000000000000000000081565b6007546104f49067ffffffffffffffff1681565b6104156107de36600461402a565b612ff3565b61038b601b81565b5f546103bd9062010000900473ffffffffffffffffffffffffffffffffffffffff1681565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561089c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108c0919061409b565b6007549091505f906108ea9067ffffffffffffffff680100000000000000008204811691166140df565b67ffffffffffffffff169050805f03610905575f9250505090565b61090f8183614107565b9250505090565b600480546109239061413f565b80601f016020809104026020016040519081016040528092919081815260200182805461094f9061413f565b801561099a5780601f106109715761010080835404028352916020019161099a565b820191905f5260205f20905b81548152906001019060200180831161097d57829003601f168201915b505050505081565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610a11576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596684604051610a6491815260200190565b60405180910390a3505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314610ac7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115610b0e576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b77573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9b9190614190565b610bfc5760075467ffffffffffffffff700100000000000000000000000000000000909104811690821610610bfc576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600780547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020015b60405180910390a150565b600380546109239061413f565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163314610cfc576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff1615808015610d1a57505f54600160ff909116105b80610d335750303b158015610d3357505f5460ff166001145b610dc4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015610e20575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f6040518060a001604052806062815260200161493b6062913990505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610eb5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ed9919061409b565b90505f868483858d610eec6001436141af565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291505f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015611034573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061105891906141c8565b90508b5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508a60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555089600390816110e99190614228565b5060046110f68a82614228565b508b60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507fd2c80353fc15ef62c6affc7cd6b7ab5b42c43290c50be3372e55ae552cecd19c8187858e6040516111989493929190614340565b60405180910390a15050505050508015611208575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16331461127f576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600581905560405181815267ffffffffffffffff8316907f1125aaf62d132d8e2d02005114f8fc360ff204c3105e4f1a700a1340dc55d5b19060200160405180910390a25050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff16331461131d576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc090602001610c75565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1633146113ff576040517fb9b3a2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f54610100900460ff161580801561141d57505f54600160ff909116105b806114365750303b15801561143657505f5460ff166001145b6114c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610dbb565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561151e575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f611528856134b9565b6009549091505f9061157290889073ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000900463ffffffff16856121ba565b90505f818051906020012090505f4290505f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115ed573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611611919061409b565b90505f808483858f6116246001436141af565b60408051602081019790975286019490945260608086019390935260c09190911b7fffffffffffffffff000000000000000000000000000000000000000000000000166080850152901b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016608883015240609c82015260bc01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815290829052805160209091012060058190557f9a908e73000000000000000000000000000000000000000000000000000000008252600160048301526024820181905291507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af115801561176a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061178e91906141c8565b508c5f60026101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508b60025f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550886003908161181e9190614228565b50600461182b8982614228565b508c60085f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062069780600760106101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055507f060116213bcbf54ca19fd649dc84b59ab2bbd200ab199770e4d923e222a28e7f85838e6040516118cb9392919061438f565b60405180910390a1505050505050801561193b575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611995576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001545f80547fffffffffffffffffffff0000000000000000000000000000000000000000ffff1673ffffffffffffffffffffffffffffffffffffffff9092166201000081029290921790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314611a6c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60085473ffffffffffffffffffffffffffffffffffffffff16611abb576040517fc89374d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600880547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f5fbd7dd171301c4a1611a84aac4ba86d119478560557755f7927595b082634fb90602001610c75565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590611b6c575073ffffffffffffffffffffffffffffffffffffffff81163314155b15611ba3576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b4262093a807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166330c27dde6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c11573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c3591906141c8565b611c3f91906143cd565b67ffffffffffffffff161115611c81576040517f3d49ed4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f819003611cbc576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115611cf8576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075467ffffffffffffffff80821691611d20918491680100000000000000009004166143ee565b1115611d58576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff16905f5b83811015611ff3575f878783818110611d9357611d93614401565b9050602002810190611da5919061442e565b611dae9061446a565b905083611dba816144f0565b825180516020918201208185015160408087015160608801519151959a509295505f94611e26948794929101938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f90815260069093529120549091508114611eae576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f90815260066020526040812055611ed26001886141af565b8403611f415742600760109054906101000a900467ffffffffffffffff168460400151611eff91906143cd565b67ffffffffffffffff161115611f41576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018b90529285018790528481019390935260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808401523390911b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc016040516020818303038152906040528051906020012094505050508080611feb90614516565b915050611d78565b506120697f000000000000000000000000000000000000000000000000000000000000000084612021610810565b61202b919061454d565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016919061371b565b60058190556007805467ffffffffffffffff841668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161790556040517f9a908e730000000000000000000000000000000000000000000000000000000081525f9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690639a908e739061213a908790869060040167ffffffffffffffff929092168252602082015260400190565b6020604051808303815f875af1158015612156573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061217a91906141c8565b60405190915067ffffffffffffffff8216907f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a4905f90a250505050505050565b60605f85858573a40d5f56745a118d0906a34e69aec8c0db1cb8fa5f876040516024016121ec96959493929190614564565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ff811bff70000000000000000000000000000000000000000000000000000000017905283519091506060905f0361233c5760f9601f835161228091906145c6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b800000000000000000000000000000000000000000000000000000000000081525060e48760405160200161232697969594939291906145e1565b6040516020818303038152906040529050612440565b815161ffff1015612379576040517f248b8f8200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160f96123886020836145c6565b6040518060400160405280600881526020017f80808401c9c380940000000000000000000000000000000000000000000000008152507f00000000000000000000000000000000000000000000000000000000000000006040518060400160405280600281526020017f80b9000000000000000000000000000000000000000000000000000000000000815250858860405160200161242d97969594939291906146c3565b6040516020818303038152906040529150505b8051602080830191909120604080515f80825293810180835292909252601b908201526405ca1ab1e06060820152635ca1ab1e608082015260019060a0016020604051602081039080840390855afa15801561249e573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116612516576040517fcd16196600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040515f9061255b9084906405ca1ab1e090635ca1ab1e90601b907fff00000000000000000000000000000000000000000000000000000000000000906020016147a5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529450505050505b949350505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff1633146125ee576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce690602001610c75565b6040518060a001604052806062815260200161493b6062913981565b60025473ffffffffffffffffffffffffffffffffffffffff1633146126ce576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b845f819003612709576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8811115612745576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6127506024426143ee565b8467ffffffffffffffff161115612793576040517f0a00feb300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156127f8575f80fd5b505af115801561280a573d5f803e3d5ffd5b50506040517fef4eeb3500000000000000000000000000000000000000000000000000000000815263ffffffff881660048201525f92507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16915063ef4eeb3590602401602060405180830381865afa15801561289e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128c2919061409b565b9050806128fb576040517fa60721e100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6007546005546801000000000000000090910467ffffffffffffffff1690815f5b85811015612c17575f8c8c8381811061293757612937614401565b9050602002810190612949919061442e565b6129529061446a565b8051805160209091012060408201519192509067ffffffffffffffff1615612b32578561297e816144f0565b9650505f818360200151846040015185606001516040516020016129e09493929190938452602084019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166040830152604882015260680190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f90815260069093529120549091508114612a68576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208381015160408086015160608088015183519586018c90529285018790528481019390935260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166080840152908c901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088830152609c82015260bc0160405160208183030381529060405280519060200120955060065f8867ffffffffffffffff1667ffffffffffffffff1681526020019081526020015f205f905550612c02565b8151516201d4c01015612b71576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160208101879052908101829052606080820189905260c08d901b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528a901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888201525f609c82015260bc016040516020818303038152906040528051906020012094505b50508080612c0f90614516565b91505061291c565b5060075467ffffffffffffffff9081169084161115612c62576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60058290558467ffffffffffffffff84811690831614612d17575f612c8783866140df565b9050612c9d67ffffffffffffffff8216836141af565b9150612cd67f00000000000000000000000000000000000000000000000000000000000000008267ffffffffffffffff16612021610810565b50600780547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000067ffffffffffffffff8716021790555b612e13337f0000000000000000000000000000000000000000000000000000000000000000837f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663477fa2706040518163ffffffff1660e01b8152600401602060405180830381865afa158015612da6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612dca919061409b565b612dd4919061454d565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169291906137f4565b6040517f9a908e7300000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602481018490525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1690639a908e73906044016020604051808303815f875af1158015612eaf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ed391906141c8565b9050888414612f0e576040517fda5bceb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff167f3e54d0825ed78523037d00a81759237eb436ce774bd546993ee67a1b67b6e76687604051612f4a91815260200190565b60405180910390a250505050505050505050505050565b5f5462010000900473ffffffffffffffffffffffffffffffffffffffff163314612fb7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003612fc38282614228565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b2081604051610c759190613b39565b60085473ffffffffffffffffffffffffffffffffffffffff168015801590613031575073ffffffffffffffffffffffffffffffffffffffff81163314155b15613068576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156130d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906130f59190614190565b1561312c576040517f39258d1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663604691696040518163ffffffff1660e01b8152600401602060405180830381865afa158015613196573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131ba919061409b565b9050828111156131f6576040517f2354600f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388841115613232576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61327473ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163330846137f4565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132de573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613302919061409b565b6007805491925067ffffffffffffffff909116905f613320836144f0565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508585604051613357929190614800565b604051908190039020814261336d6001436141af565b60408051602081019590955284019290925260c01b7fffffffffffffffff000000000000000000000000000000000000000000000000166060830152406068820152608801604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012060075467ffffffffffffffff165f9081526006909352912055323303613463576007546040805183815233602082015260608183018190525f90820152905167ffffffffffffffff909216917ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319181900360800190a2611208565b60075460405167ffffffffffffffff909116907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931906134a990849033908b908b9061480f565b60405180910390a2505050505050565b606073ffffffffffffffffffffffffffffffffffffffff821615613716576040517fc00f14ab00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063c00f14ab906024015f60405180830381865afa158015613560573d5f803e3d5ffd5b505050506040513d5f823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526135a5919081019061487f565b6040517f318aee3d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84811660048301529192505f9182917f00000000000000000000000000000000000000000000000000000000000000009091169063318aee3d906024016040805180830381865afa158015613637573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061365b91906148f1565b915091508163ffffffff165f146136d2576009805463ffffffff841674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090911673ffffffffffffffffffffffffffffffffffffffff841617179055613713565b600980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86161790555b50505b919050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526137ef9084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613858565b505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526138529085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161376d565b50505050565b5f6138b9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166139639092919063ffffffff16565b8051909150156137ef57808060200190518101906138d79190614190565b6137ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610dbb565b606061259084845f85855f808673ffffffffffffffffffffffffffffffffffffffff1685876040516139959190614929565b5f6040518083038185875af1925050503d805f81146139cf576040519150601f19603f3d011682016040523d82523d5f602084013e6139d4565b606091505b50915091506139e5878383876139f0565b979650505050505050565b60608315613a855782515f03613a7e5773ffffffffffffffffffffffffffffffffffffffff85163b613a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610dbb565b5081612590565b6125908383815115613a9a5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dbb9190613b39565b5f5b83811015613ae8578181015183820152602001613ad0565b50505f910152565b5f8151808452613b07816020860160208601613ace565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f613b4b6020830184613af0565b9392505050565b67ffffffffffffffff81168114613b67575f80fd5b50565b73ffffffffffffffffffffffffffffffffffffffff81168114613b67575f80fd5b5f805f60608486031215613b9d575f80fd5b8335613ba881613b52565b9250602084013591506040840135613bbf81613b6a565b809150509250925092565b5f60208284031215613bda575f80fd5b8135613b4b81613b52565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613c5957613c59613be5565b604052919050565b5f67ffffffffffffffff821115613c7a57613c7a613be5565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b5f82601f830112613cb5575f80fd5b8135613cc8613cc382613c61565b613c12565b818152846020838601011115613cdc575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a08688031215613d0c575f80fd5b8535613d1781613b6a565b94506020860135613d2781613b6a565b9350604086013567ffffffffffffffff80821115613d43575f80fd5b613d4f89838a01613ca6565b94506060880135915080821115613d64575f80fd5b50613d7188828901613ca6565b95989497509295608001359392505050565b5f8060408385031215613d94575f80fd5b8235613d9f81613b52565b946020939093013593505050565b5f60208284031215613dbd575f80fd5b8135613b4b81613b6a565b63ffffffff81168114613b67575f80fd5b5f805f805f8060c08789031215613dee575f80fd5b8635613df981613b6a565b95506020870135613e0981613b6a565b94506040870135613e1981613dc8565b93506060870135613e2981613b6a565b9250608087013567ffffffffffffffff80821115613e45575f80fd5b613e518a838b01613ca6565b935060a0890135915080821115613e66575f80fd5b50613e7389828a01613ca6565b9150509295509295509295565b5f8083601f840112613e90575f80fd5b50813567ffffffffffffffff811115613ea7575f80fd5b6020830191508360208260051b8501011115613ec1575f80fd5b9250929050565b5f8060208385031215613ed9575f80fd5b823567ffffffffffffffff811115613eef575f80fd5b613efb85828601613e80565b90969095509350505050565b5f805f8060808587031215613f1a575f80fd5b8435613f2581613dc8565b93506020850135613f3581613b6a565b92506040850135613f4581613dc8565b9150606085013567ffffffffffffffff811115613f60575f80fd5b613f6c87828801613ca6565b91505092959194509250565b5f805f805f8060a08789031215613f8d575f80fd5b863567ffffffffffffffff811115613fa3575f80fd5b613faf89828a01613e80565b9097509550506020870135613fc381613dc8565b93506040870135613fd381613b52565b9250606087013591506080870135613fea81613b6a565b809150509295509295509295565b5f60208284031215614008575f80fd5b813567ffffffffffffffff81111561401e575f80fd5b61259084828501613ca6565b5f805f6040848603121561403c575f80fd5b833567ffffffffffffffff80821115614053575f80fd5b818601915086601f830112614066575f80fd5b813581811115614074575f80fd5b876020828501011115614085575f80fd5b6020928301989097509590910135949350505050565b5f602082840312156140ab575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff828116828216039080821115614100576141006140b2565b5092915050565b5f8261413a577f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b500490565b600181811c9082168061415357607f821691505b60208210810361418a577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b5f602082840312156141a0575f80fd5b81518015158114613b4b575f80fd5b818103818111156141c2576141c26140b2565b92915050565b5f602082840312156141d8575f80fd5b8151613b4b81613b52565b601f8211156137ef575f81815260208120601f850160051c810160208610156142095750805b601f850160051c820191505b8181101561120857828155600101614215565b815167ffffffffffffffff81111561424257614242613be5565b61425681614250845461413f565b846141e3565b602080601f8311600181146142a8575f84156142725750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611208565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156142f4578886015182559484019460019091019084016142d5565b508582101561433057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff85168152608060208201525f6143626080830186613af0565b905083604083015273ffffffffffffffffffffffffffffffffffffffff8316606083015295945050505050565b606081525f6143a16060830186613af0565b905083602083015273ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b67ffffffffffffffff818116838216019080821115614100576141006140b2565b808201808211156141c2576141c26140b2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112614460575f80fd5b9190910192915050565b5f6080823603121561447a575f80fd5b6040516080810167ffffffffffffffff828210818311171561449e5761449e613be5565b8160405284359150808211156144b2575f80fd5b506144bf36828601613ca6565b8252506020830135602082015260408301356144da81613b52565b6040820152606092830135928101929092525090565b5f67ffffffffffffffff80831681810361450c5761450c6140b2565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614546576145466140b2565b5060010190565b80820281158282048414176141c2576141c26140b2565b5f63ffffffff808916835273ffffffffffffffffffffffffffffffffffffffff8089166020850152818816604085015280871660608501528086166080850152505060c060a08301526145ba60c0830184613af0565b98975050505050505050565b61ffff818116838216019080821115614100576141006140b2565b5f7fff00000000000000000000000000000000000000000000000000000000000000808a60f81b1683527fffff0000000000000000000000000000000000000000000000000000000000008960f01b1660018401528751614649816003860160208c01613ace565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b166003820152865161468c816017840160208b01613ace565b808201915050818660f81b166017820152845191506146b2826018830160208801613ace565b016018019998505050505050505050565b7fff000000000000000000000000000000000000000000000000000000000000008860f81b1681525f7fffff000000000000000000000000000000000000000000000000000000000000808960f01b166001840152875161472b816003860160208c01613ace565b80840190507fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b166003820152865161476e816017840160208b01613ace565b808201915050818660f01b16601782015284519150614794826019830160208801613ace565b016019019998505050505050505050565b5f86516147b6818460208b01613ace565b9190910194855250602084019290925260f81b7fff000000000000000000000000000000000000000000000000000000000000009081166040840152166041820152604201919050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff8416602082015260606040820152816060820152818360808301375f818301608090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601019392505050565b5f6020828403121561488f575f80fd5b815167ffffffffffffffff8111156148a5575f80fd5b8201601f810184136148b5575f80fd5b80516148c3613cc382613c61565b8181528560208385010111156148d7575f80fd5b6148e8826020830160208601613ace565b95945050505050565b5f8060408385031215614902575f80fd5b825161490d81613dc8565b602084015190925061491e81613b6a565b809150509250929050565b5f8251614460818460208701613ace56fedf2a8080944d5cf5032b2a844602278b01199ed191a86c93ff8080821092808000000000000000000000000000000000000000000000000000000005ca1ab1e000000000000000000000000000000000000000000000000000000005ca1ab1e01bffa26469706673582212207856dfc85aae7e627fea5f616cb0ac92c48b5b310deb4f096e99c1918acf281b64736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMGlobalExitRoot.json b/compiled-contracts/PolygonZkEVMGlobalExitRoot.json index a2d289423..c0957d5d8 100644 --- a/compiled-contracts/PolygonZkEVMGlobalExitRoot.json +++ b/compiled-contracts/PolygonZkEVMGlobalExitRoot.json @@ -19,11 +19,36 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [], + "name": "GlobalExitRootAlreadySet", + "type": "error" + }, + { + "inputs": [], + "name": "NotEnoughGlobalExitRootsInserted", + "type": "error" + }, + { + "inputs": [], + "name": "NotLastInsertedGlobalExitRoot", + "type": "error" + }, { "inputs": [], "name": "OnlyAllowedContracts", "type": "error" }, + { + "inputs": [], + "name": "OnlyGlobalExitRootRemover", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyGlobalExitRootUpdater", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -141,8 +166,8 @@ "type": "function" } ], - "bytecode": "0x60c060405234801561000f575f80fd5b506040516103e13803806103e183398101604081905261002e91610060565b6001600160a01b0391821660a05216608052610091565b80516001600160a01b038116811461005b575f80fd5b919050565b5f8060408385031215610071575f80fd5b61007a83610045565b915061008860208401610045565b90509250929050565b60805160a0516103226100bf5f395f818160e301526101b601525f818161012f015261016d01526103225ff3fe608060405234801561000f575f80fd5b506004361061007a575f3560e01c806333d6247d1161005857806333d6247d146100c15780633ed691ef146100d65780635ec6a8df146100de578063a3c573eb1461012a575f80fd5b806301fd90441461007e578063257b363214610099578063319cf735146100b8575b5f80fd5b6100865f5481565b6040519081526020015b60405180910390f35b6100866100a73660046102d5565b60026020525f908152604090205481565b61008660015481565b6100d46100cf3660046102d5565b610151565b005b61008661029b565b6101057f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610090565b6101057f000000000000000000000000000000000000000000000000000000000000000081565b5f5460015473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361019f575060018290558161021a565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036101e8575f83905582915061021a565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808201849052818301859052825180830384018152606090920190925280519101205f905f8181526002602052604081205491925003610295575f8181526002602052604080822042905551849184917f61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce39190a35b50505050565b5f6102d06001545f54604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b905090565b5f602082840312156102e5575f80fd5b503591905056fea26469706673582212205b8fae68ff3c2dfc257497be9184a2e772688dbece1343c3dc2e8c1923291be864736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061007a575f3560e01c806333d6247d1161005857806333d6247d146100c15780633ed691ef146100d65780635ec6a8df146100de578063a3c573eb1461012a575f80fd5b806301fd90441461007e578063257b363214610099578063319cf735146100b8575b5f80fd5b6100865f5481565b6040519081526020015b60405180910390f35b6100866100a73660046102d5565b60026020525f908152604090205481565b61008660015481565b6100d46100cf3660046102d5565b610151565b005b61008661029b565b6101057f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610090565b6101057f000000000000000000000000000000000000000000000000000000000000000081565b5f5460015473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361019f575060018290558161021a565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036101e8575f83905582915061021a565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808201849052818301859052825180830384018152606090920190925280519101205f905f8181526002602052604081205491925003610295575f8181526002602052604080822042905551849184917f61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce39190a35b50505050565b5f6102d06001545f54604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b905090565b5f602082840312156102e5575f80fd5b503591905056fea26469706673582212205b8fae68ff3c2dfc257497be9184a2e772688dbece1343c3dc2e8c1923291be864736f6c63430008140033", + "bytecode": "0x60c060405234801561000f575f80fd5b506040516103e13803806103e183398101604081905261002e91610060565b6001600160a01b0391821660a05216608052610091565b80516001600160a01b038116811461005b575f80fd5b919050565b5f8060408385031215610071575f80fd5b61007a83610045565b915061008860208401610045565b90509250929050565b60805160a0516103226100bf5f395f818160e301526101b601525f818161012f015261016d01526103225ff3fe608060405234801561000f575f80fd5b506004361061007a575f3560e01c806333d6247d1161005857806333d6247d146100c15780633ed691ef146100d65780635ec6a8df146100de578063a3c573eb1461012a575f80fd5b806301fd90441461007e578063257b363214610099578063319cf735146100b8575b5f80fd5b6100865f5481565b6040519081526020015b60405180910390f35b6100866100a73660046102d5565b60026020525f908152604090205481565b61008660015481565b6100d46100cf3660046102d5565b610151565b005b61008661029b565b6101057f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610090565b6101057f000000000000000000000000000000000000000000000000000000000000000081565b5f5460015473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361019f575060018290558161021a565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036101e8575f83905582915061021a565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808201849052818301859052825180830384018152606090920190925280519101205f905f8181526002602052604081205491925003610295575f8181526002602052604080822042905551849184917f61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce39190a35b50505050565b5f6102d06001545f54604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b905090565b5f602082840312156102e5575f80fd5b503591905056fea26469706673582212205501a0b5f6528630e98aa39629f5866242070924e93a8290cdc0815e798a54e064736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061007a575f3560e01c806333d6247d1161005857806333d6247d146100c15780633ed691ef146100d65780635ec6a8df146100de578063a3c573eb1461012a575f80fd5b806301fd90441461007e578063257b363214610099578063319cf735146100b8575b5f80fd5b6100865f5481565b6040519081526020015b60405180910390f35b6100866100a73660046102d5565b60026020525f908152604090205481565b61008660015481565b6100d46100cf3660046102d5565b610151565b005b61008661029b565b6101057f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610090565b6101057f000000000000000000000000000000000000000000000000000000000000000081565b5f5460015473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361019f575060018290558161021a565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036101e8575f83905582915061021a565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808201849052818301859052825180830384018152606090920190925280519101205f905f8181526002602052604081205491925003610295575f8181526002602052604080822042905551849184917f61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce39190a35b50505050565b5f6102d06001545f54604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b905090565b5f602082840312156102e5575f80fd5b503591905056fea26469706673582212205501a0b5f6528630e98aa39629f5866242070924e93a8290cdc0815e798a54e064736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMGlobalExitRootL2.json b/compiled-contracts/PolygonZkEVMGlobalExitRootL2.json index f65b728ae..e3730c605 100644 --- a/compiled-contracts/PolygonZkEVMGlobalExitRootL2.json +++ b/compiled-contracts/PolygonZkEVMGlobalExitRootL2.json @@ -14,11 +14,36 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [], + "name": "GlobalExitRootAlreadySet", + "type": "error" + }, + { + "inputs": [], + "name": "NotEnoughGlobalExitRootsInserted", + "type": "error" + }, + { + "inputs": [], + "name": "NotLastInsertedGlobalExitRoot", + "type": "error" + }, { "inputs": [], "name": "OnlyAllowedContracts", "type": "error" }, + { + "inputs": [], + "name": "OnlyGlobalExitRootRemover", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyGlobalExitRootUpdater", + "type": "error" + }, { "inputs": [], "name": "bridgeAddress", @@ -78,8 +103,8 @@ "type": "function" } ], - "bytecode": "0x60a060405234801561000f575f80fd5b5060405161023538038061023583398101604081905261002e9161003f565b6001600160a01b031660805261006c565b5f6020828403121561004f575f80fd5b81516001600160a01b0381168114610065575f80fd5b9392505050565b6080516101ab61008a5f395f818160a3015261010201526101ab5ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c806301fd90441461004e578063257b36321461006a57806333d6247d14610089578063a3c573eb1461009e575b5f80fd5b61005760015481565b6040519081526020015b60405180910390f35b61005761007836600461015e565b5f6020819052908152604090205481565b61009c61009736600461015e565b6100ea565b005b6100c57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610061565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610159576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b5f6020828403121561016e575f80fd5b503591905056fea26469706673582212205108c6c4f924146b736832a1bdf696e20d900450207b7452462368d150f2c71c64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c806301fd90441461004e578063257b36321461006a57806333d6247d14610089578063a3c573eb1461009e575b5f80fd5b61005760015481565b6040519081526020015b60405180910390f35b61005761007836600461015e565b5f6020819052908152604090205481565b61009c61009736600461015e565b6100ea565b005b6100c57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610061565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610159576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b5f6020828403121561016e575f80fd5b503591905056fea26469706673582212205108c6c4f924146b736832a1bdf696e20d900450207b7452462368d150f2c71c64736f6c63430008140033", + "bytecode": "0x60a060405234801561000f575f80fd5b5060405161023538038061023583398101604081905261002e9161003f565b6001600160a01b031660805261006c565b5f6020828403121561004f575f80fd5b81516001600160a01b0381168114610065575f80fd5b9392505050565b6080516101ab61008a5f395f818160a3015261010201526101ab5ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c806301fd90441461004e578063257b36321461006a57806333d6247d14610089578063a3c573eb1461009e575b5f80fd5b61005760015481565b6040519081526020015b60405180910390f35b61005761007836600461015e565b5f6020819052908152604090205481565b61009c61009736600461015e565b6100ea565b005b6100c57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610061565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610159576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b5f6020828403121561016e575f80fd5b503591905056fea2646970667358221220f0dec969a2669fd94b3380929dea675446930b1e14fb6c675a20514321fc81fd64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c806301fd90441461004e578063257b36321461006a57806333d6247d14610089578063a3c573eb1461009e575b5f80fd5b61005760015481565b6040519081526020015b60405180910390f35b61005761007836600461015e565b5f6020819052908152604090205481565b61009c61009736600461015e565b6100ea565b005b6100c57f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610061565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610159576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b5f6020828403121561016e575f80fd5b503591905056fea2646970667358221220f0dec969a2669fd94b3380929dea675446930b1e14fb6c675a20514321fc81fd64736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMGlobalExitRootL2Mock.json b/compiled-contracts/PolygonZkEVMGlobalExitRootL2Mock.json index 793f73c8e..d3360d6b8 100644 --- a/compiled-contracts/PolygonZkEVMGlobalExitRootL2Mock.json +++ b/compiled-contracts/PolygonZkEVMGlobalExitRootL2Mock.json @@ -14,11 +14,36 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [], + "name": "GlobalExitRootAlreadySet", + "type": "error" + }, + { + "inputs": [], + "name": "NotEnoughGlobalExitRootsInserted", + "type": "error" + }, + { + "inputs": [], + "name": "NotLastInsertedGlobalExitRoot", + "type": "error" + }, { "inputs": [], "name": "OnlyAllowedContracts", "type": "error" }, + { + "inputs": [], + "name": "OnlyGlobalExitRootRemover", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyGlobalExitRootUpdater", + "type": "error" + }, { "inputs": [], "name": "bridgeAddress", @@ -109,8 +134,8 @@ "type": "function" } ], - "bytecode": "0x60a060405234801561000f575f80fd5b506040516102a73803806102a783398101604081905261002e9161003f565b6001600160a01b031660805261006c565b5f6020828403121561004f575f80fd5b81516001600160a01b0381168114610065575f80fd5b9392505050565b60805161021d61008a5f395f818160fa0152610159015261021d5ff3fe608060405234801561000f575f80fd5b506004361061006f575f3560e01c806333d6247d1161004d57806333d6247d146100c357806396e07459146100d6578063a3c573eb146100f5575f80fd5b806301fd904414610073578063116c40c31461008f578063257b3632146100a4575b5f80fd5b61007c60015481565b6040519081526020015b60405180910390f35b6100a261009d3660046101b0565b600155565b005b61007c6100b23660046101b0565b5f6020819052908152604090205481565b6100a26100d13660046101b0565b610141565b6100a26100e43660046101c7565b5f9182526020829052604090912055565b61011c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610086565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461009d576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f602082840312156101c0575f80fd5b5035919050565b5f80604083850312156101d8575f80fd5b5050803592602090910135915056fea26469706673582212200429aefffcbf7324bb1dde3a45be34c3a7310774300755b6ec66494ae7db89ec64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061006f575f3560e01c806333d6247d1161004d57806333d6247d146100c357806396e07459146100d6578063a3c573eb146100f5575f80fd5b806301fd904414610073578063116c40c31461008f578063257b3632146100a4575b5f80fd5b61007c60015481565b6040519081526020015b60405180910390f35b6100a261009d3660046101b0565b600155565b005b61007c6100b23660046101b0565b5f6020819052908152604090205481565b6100a26100d13660046101b0565b610141565b6100a26100e43660046101c7565b5f9182526020829052604090912055565b61011c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610086565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461009d576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f602082840312156101c0575f80fd5b5035919050565b5f80604083850312156101d8575f80fd5b5050803592602090910135915056fea26469706673582212200429aefffcbf7324bb1dde3a45be34c3a7310774300755b6ec66494ae7db89ec64736f6c63430008140033", + "bytecode": "0x60a060405234801561000f575f80fd5b506040516102a73803806102a783398101604081905261002e9161003f565b6001600160a01b031660805261006c565b5f6020828403121561004f575f80fd5b81516001600160a01b0381168114610065575f80fd5b9392505050565b60805161021d61008a5f395f818160fa0152610159015261021d5ff3fe608060405234801561000f575f80fd5b506004361061006f575f3560e01c806333d6247d1161004d57806333d6247d146100c357806396e07459146100d6578063a3c573eb146100f5575f80fd5b806301fd904414610073578063116c40c31461008f578063257b3632146100a4575b5f80fd5b61007c60015481565b6040519081526020015b60405180910390f35b6100a261009d3660046101b0565b600155565b005b61007c6100b23660046101b0565b5f6020819052908152604090205481565b6100a26100d13660046101b0565b610141565b6100a26100e43660046101c7565b5f9182526020829052604090912055565b61011c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610086565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461009d576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f602082840312156101c0575f80fd5b5035919050565b5f80604083850312156101d8575f80fd5b5050803592602090910135915056fea264697066735822122029aa25f27176bf7f20e5db9aedfaa38745c80a316af8f28eada5a20cc846bb5364736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061006f575f3560e01c806333d6247d1161004d57806333d6247d146100c357806396e07459146100d6578063a3c573eb146100f5575f80fd5b806301fd904414610073578063116c40c31461008f578063257b3632146100a4575b5f80fd5b61007c60015481565b6040519081526020015b60405180910390f35b6100a261009d3660046101b0565b600155565b005b61007c6100b23660046101b0565b5f6020819052908152604090205481565b6100a26100d13660046101b0565b610141565b6100a26100e43660046101c7565b5f9182526020829052604090912055565b61011c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610086565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461009d576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f602082840312156101c0575f80fd5b5035919050565b5f80604083850312156101d8575f80fd5b5050803592602090910135915056fea264697066735822122029aa25f27176bf7f20e5db9aedfaa38745c80a316af8f28eada5a20cc846bb5364736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMGlobalExitRootMock.json b/compiled-contracts/PolygonZkEVMGlobalExitRootMock.json index 6bde95a70..153975a6a 100644 --- a/compiled-contracts/PolygonZkEVMGlobalExitRootMock.json +++ b/compiled-contracts/PolygonZkEVMGlobalExitRootMock.json @@ -19,11 +19,36 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [], + "name": "GlobalExitRootAlreadySet", + "type": "error" + }, + { + "inputs": [], + "name": "NotEnoughGlobalExitRootsInserted", + "type": "error" + }, + { + "inputs": [], + "name": "NotLastInsertedGlobalExitRoot", + "type": "error" + }, { "inputs": [], "name": "OnlyAllowedContracts", "type": "error" }, + { + "inputs": [], + "name": "OnlyGlobalExitRootRemover", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyGlobalExitRootUpdater", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -172,8 +197,8 @@ "type": "function" } ], - "bytecode": "0x60c060405234801561000f575f80fd5b5060405161047838038061047883398101604081905261002e91610060565b6001600160a01b0391821660a05216608052610091565b80516001600160a01b038116811461005b575f80fd5b919050565b5f8060408385031215610071575f80fd5b61007a83610045565b915061008860208401610045565b90509250929050565b60805160a0516103b86100c05f395f818161013a015261022c01525f818161018601526101e301526103b85ff3fe608060405234801561000f575f80fd5b506004361061009f575f3560e01c806333d6247d116100725780635bcef673116100585780635bcef673146101165780635ec6a8df14610135578063a3c573eb14610181575f80fd5b806333d6247d146100fb5780633ed691ef1461010e575f80fd5b806301fd9044146100a3578063051a9e28146100be578063257b3632146100d3578063319cf735146100f2575b5f80fd5b6100ab5f5481565b6040519081526020015b60405180910390f35b6100d16100cc36600461034b565b6101a8565b005b6100ab6100e136600461034b565b60026020525f908152604090205481565b6100ab60015481565b6100d161010936600461034b565b6101c7565b6100ab610311565b6100d1610124366004610362565b5f9182526002602052604090912055565b61015c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b61015c7f000000000000000000000000000000000000000000000000000000000000000081565b8060025f6101b4610311565b815260208101919091526040015f205550565b5f5460015473ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036102155750600182905581610290565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361025e575f839055829150610290565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808201849052818301859052825180830384018152606090920190925280519101205f905f818152600260205260408120549192500361030b575f8181526002602052604080822042905551849184917f61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce39190a35b50505050565b5f6103466001545f54604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b905090565b5f6020828403121561035b575f80fd5b5035919050565b5f8060408385031215610373575f80fd5b5050803592602090910135915056fea26469706673582212200799b5f60aa8eaf6d49205025cc41bfba78ce4f6ad614164e5da3c0bdc94810464736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061009f575f3560e01c806333d6247d116100725780635bcef673116100585780635bcef673146101165780635ec6a8df14610135578063a3c573eb14610181575f80fd5b806333d6247d146100fb5780633ed691ef1461010e575f80fd5b806301fd9044146100a3578063051a9e28146100be578063257b3632146100d3578063319cf735146100f2575b5f80fd5b6100ab5f5481565b6040519081526020015b60405180910390f35b6100d16100cc36600461034b565b6101a8565b005b6100ab6100e136600461034b565b60026020525f908152604090205481565b6100ab60015481565b6100d161010936600461034b565b6101c7565b6100ab610311565b6100d1610124366004610362565b5f9182526002602052604090912055565b61015c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b61015c7f000000000000000000000000000000000000000000000000000000000000000081565b8060025f6101b4610311565b815260208101919091526040015f205550565b5f5460015473ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036102155750600182905581610290565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361025e575f839055829150610290565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808201849052818301859052825180830384018152606090920190925280519101205f905f818152600260205260408120549192500361030b575f8181526002602052604080822042905551849184917f61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce39190a35b50505050565b5f6103466001545f54604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b905090565b5f6020828403121561035b575f80fd5b5035919050565b5f8060408385031215610373575f80fd5b5050803592602090910135915056fea26469706673582212200799b5f60aa8eaf6d49205025cc41bfba78ce4f6ad614164e5da3c0bdc94810464736f6c63430008140033", + "bytecode": "0x60c060405234801561000f575f80fd5b5060405161047838038061047883398101604081905261002e91610060565b6001600160a01b0391821660a05216608052610091565b80516001600160a01b038116811461005b575f80fd5b919050565b5f8060408385031215610071575f80fd5b61007a83610045565b915061008860208401610045565b90509250929050565b60805160a0516103b86100c05f395f818161013a015261022c01525f818161018601526101e301526103b85ff3fe608060405234801561000f575f80fd5b506004361061009f575f3560e01c806333d6247d116100725780635bcef673116100585780635bcef673146101165780635ec6a8df14610135578063a3c573eb14610181575f80fd5b806333d6247d146100fb5780633ed691ef1461010e575f80fd5b806301fd9044146100a3578063051a9e28146100be578063257b3632146100d3578063319cf735146100f2575b5f80fd5b6100ab5f5481565b6040519081526020015b60405180910390f35b6100d16100cc36600461034b565b6101a8565b005b6100ab6100e136600461034b565b60026020525f908152604090205481565b6100ab60015481565b6100d161010936600461034b565b6101c7565b6100ab610311565b6100d1610124366004610362565b5f9182526002602052604090912055565b61015c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b61015c7f000000000000000000000000000000000000000000000000000000000000000081565b8060025f6101b4610311565b815260208101919091526040015f205550565b5f5460015473ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036102155750600182905581610290565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361025e575f839055829150610290565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808201849052818301859052825180830384018152606090920190925280519101205f905f818152600260205260408120549192500361030b575f8181526002602052604080822042905551849184917f61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce39190a35b50505050565b5f6103466001545f54604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b905090565b5f6020828403121561035b575f80fd5b5035919050565b5f8060408385031215610373575f80fd5b5050803592602090910135915056fea26469706673582212205ab2d2ac2787ab66569e655f4a1bb90f7ac88a867ea1c7b1e4da0073f030121164736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061009f575f3560e01c806333d6247d116100725780635bcef673116100585780635bcef673146101165780635ec6a8df14610135578063a3c573eb14610181575f80fd5b806333d6247d146100fb5780633ed691ef1461010e575f80fd5b806301fd9044146100a3578063051a9e28146100be578063257b3632146100d3578063319cf735146100f2575b5f80fd5b6100ab5f5481565b6040519081526020015b60405180910390f35b6100d16100cc36600461034b565b6101a8565b005b6100ab6100e136600461034b565b60026020525f908152604090205481565b6100ab60015481565b6100d161010936600461034b565b6101c7565b6100ab610311565b6100d1610124366004610362565b5f9182526002602052604090912055565b61015c7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b5565b61015c7f000000000000000000000000000000000000000000000000000000000000000081565b8060025f6101b4610311565b815260208101919091526040015f205550565b5f5460015473ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036102155750600182905581610290565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361025e575f839055829150610290565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516020808201849052818301859052825180830384018152606090920190925280519101205f905f818152600260205260408120549192500361030b575f8181526002602052604080822042905551849184917f61014378f82a0d809aefaf87a8ac9505b89c321808287a6e7810f29304c1fce39190a35b50505050565b5f6103466001545f54604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b905090565b5f6020828403121561035b575f80fd5b5035919050565b5f8060408385031215610373575f80fd5b5050803592602090910135915056fea26469706673582212205ab2d2ac2787ab66569e655f4a1bb90f7ac88a867ea1c7b1e4da0073f030121164736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMGlobalExitRootV2.json b/compiled-contracts/PolygonZkEVMGlobalExitRootV2.json index f8a086672..146245ac2 100644 --- a/compiled-contracts/PolygonZkEVMGlobalExitRootV2.json +++ b/compiled-contracts/PolygonZkEVMGlobalExitRootV2.json @@ -19,16 +19,41 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [], + "name": "GlobalExitRootAlreadySet", + "type": "error" + }, { "inputs": [], "name": "MerkleTreeFull", "type": "error" }, + { + "inputs": [], + "name": "NotEnoughGlobalExitRootsInserted", + "type": "error" + }, + { + "inputs": [], + "name": "NotLastInsertedGlobalExitRoot", + "type": "error" + }, { "inputs": [], "name": "OnlyAllowedContracts", "type": "error" }, + { + "inputs": [], + "name": "OnlyGlobalExitRootRemover", + "type": "error" + }, + { + "inputs": [], + "name": "OnlyGlobalExitRootUpdater", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -353,8 +378,8 @@ "type": "function" } ], - "bytecode": "0x60c060405234801561000f575f80fd5b50604051610e9d380380610e9d83398101604081905261002e9161012b565b6001600160a01b0380831660a0528116608052610049610050565b505061015c565b602e54610100900460ff16156100bc5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b602e5460ff908116101561010e57602e805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b0381168114610126575f80fd5b919050565b5f806040838503121561013c575f80fd5b61014583610110565b915061015360208401610110565b90509250929050565b60805160a051610d1261018b5f395f818161015701526102f701525f818161022e01526102ab0152610d125ff3fe608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80635ca1e1651161008857806383f244031161006357806383f2440314610216578063a3c573eb14610229578063ef4eeb3514610250578063fb5708341461026f575f80fd5b80635ca1e1651461019e5780635d810501146101a65780638129fc1c1461020e575f80fd5b8063319cf735116100c3578063319cf7351461012c57806333d6247d146101355780633ed691ef1461014a57806349b7b80214610152575f80fd5b806301fd9044146100e9578063257b3632146101045780632dfdf0b514610123575b5f80fd5b6100f15f5481565b6040519081526020015b60405180910390f35b6100f16101123660046109bf565b60026020525f908152604090205481565b6100f160235481565b6100f160015481565b6101486101433660046109bf565b610292565b005b6100f16104b8565b6101797f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100fb565b6100f16104cb565b6100f16101b43660046109d6565b604080516020808201959095528082019390935260c09190911b7fffffffffffffffff0000000000000000000000000000000000000000000000001660608301528051604881840301815260689092019052805191012090565b6101486104d4565b6100f1610224366004610a41565b6106c8565b6101797f000000000000000000000000000000000000000000000000000000000000000081565b6100f161025e366004610a7d565b602f6020525f908152604090205481565b61028261027d366004610a9d565b61079d565b60405190151581526020016100fb565b5f8073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036102e057505060018190555f548161035f565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361032d5750505f819055600154819061035f565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61036a82846107b4565b5f81815260026020526040812054919250036104b257425f61038d600143610b0f565b5f8481526002602090815260409182902092409283905581518082018790528083018490527fffffffffffffffff00000000000000000000000000000000000000000000000060c087901b1660608201528251808203604801815260689091019092528151910120909150610401906107e3565b5f61040a6104cb565b60235463ffffffff165f908152602f602052604080822083905551919250879187917fda61aa7823fcd807e37b95aabcbe17f03a6f3efd514176444dae191d27fd66b391a360235463ffffffff167faf6c6cd7790e0180a4d22eb8ed846e55846f54ed10e5946db19972b5a0813a598284866040516104a693929190928352602083019190915267ffffffffffffffff16604082015260600190565b60405180910390a25050505b50505050565b5f6104c66001545f546107b4565b905090565b5f6104c66108e3565b602e54610100900460ff16158080156104f45750602e54600160ff909116105b8061050e5750303b15801561050e5750602e5460ff166001145b61059e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b602e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156105fc57602e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f6106056104cb565b6023805463ffffffff9081165f908152602f602090815260409182902085905592548151921682529181018390529192507f11f50c71891002839c2637ce302087160298255a87f1ea60d40e8db081383fad910160405180910390a15080156106c557602e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b5f83815b602081101561079457600163ffffffff8516821c81169003610737578481602081106106fa576106fa610b22565b60200201358260405160200161071a929190918252602082015260400190565b604051602081830303815290604052805190602001209150610782565b8185826020811061074a5761074a610b22565b6020020135604051602001610769929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8061078c81610b4f565b9150506106cc565b50949350505050565b5f816107aa8686866106c8565b1495945050505050565b604080516020808201859052818301849052825180830384018152606090920190925280519101205b92915050565b8060016107f260206002610ca4565b6107fc9190610b0f565b60235410610836576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60235f815461084590610b4f565b918290555090505f5b60208110156108d5578082901c60011660010361088157826003826020811061087957610879610b22565b015550505050565b6003816020811061089457610894610b22565b0154604080516020810192909252810184905260600160405160208183030381529060405280519060200120925080806108cd90610b4f565b91505061084e565b506108de610caf565b505050565b6023545f90819081805b60208110156109b6578083901c60011660010361094a576003816020811061091757610917610b22565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610977565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806109ae90610b4f565b9150506108ed565b50919392505050565b5f602082840312156109cf575f80fd5b5035919050565b5f805f606084860312156109e8575f80fd5b8335925060208401359150604084013567ffffffffffffffff81168114610a0d575f80fd5b809150509250925092565b8061040081018310156107dd575f80fd5b803563ffffffff81168114610a3c575f80fd5b919050565b5f805f6104408486031215610a54575f80fd5b83359250610a658560208601610a18565b9150610a746104208501610a29565b90509250925092565b5f60208284031215610a8d575f80fd5b610a9682610a29565b9392505050565b5f805f806104608587031215610ab1575f80fd5b84359350610ac28660208701610a18565b9250610ad16104208601610a29565b939692955092936104400135925050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b818103818111156107dd576107dd610ae2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610b7f57610b7f610ae2565b5060010190565b600181815b80851115610bdf57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610bc557610bc5610ae2565b80851615610bd257918102915b93841c9390800290610b8b565b509250929050565b5f82610bf5575060016107dd565b81610c0157505f6107dd565b8160018114610c175760028114610c2157610c3d565b60019150506107dd565b60ff841115610c3257610c32610ae2565b50506001821b6107dd565b5060208310610133831016604e8410600b8410161715610c60575081810a6107dd565b610c6a8383610b86565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610c9c57610c9c610ae2565b029392505050565b5f610a968383610be7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffdfea2646970667358221220266cf00c331b0b224bcd6976734955c98ca9e47455a941626d1788f29cf7b3bd64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80635ca1e1651161008857806383f244031161006357806383f2440314610216578063a3c573eb14610229578063ef4eeb3514610250578063fb5708341461026f575f80fd5b80635ca1e1651461019e5780635d810501146101a65780638129fc1c1461020e575f80fd5b8063319cf735116100c3578063319cf7351461012c57806333d6247d146101355780633ed691ef1461014a57806349b7b80214610152575f80fd5b806301fd9044146100e9578063257b3632146101045780632dfdf0b514610123575b5f80fd5b6100f15f5481565b6040519081526020015b60405180910390f35b6100f16101123660046109bf565b60026020525f908152604090205481565b6100f160235481565b6100f160015481565b6101486101433660046109bf565b610292565b005b6100f16104b8565b6101797f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100fb565b6100f16104cb565b6100f16101b43660046109d6565b604080516020808201959095528082019390935260c09190911b7fffffffffffffffff0000000000000000000000000000000000000000000000001660608301528051604881840301815260689092019052805191012090565b6101486104d4565b6100f1610224366004610a41565b6106c8565b6101797f000000000000000000000000000000000000000000000000000000000000000081565b6100f161025e366004610a7d565b602f6020525f908152604090205481565b61028261027d366004610a9d565b61079d565b60405190151581526020016100fb565b5f8073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036102e057505060018190555f548161035f565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361032d5750505f819055600154819061035f565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61036a82846107b4565b5f81815260026020526040812054919250036104b257425f61038d600143610b0f565b5f8481526002602090815260409182902092409283905581518082018790528083018490527fffffffffffffffff00000000000000000000000000000000000000000000000060c087901b1660608201528251808203604801815260689091019092528151910120909150610401906107e3565b5f61040a6104cb565b60235463ffffffff165f908152602f602052604080822083905551919250879187917fda61aa7823fcd807e37b95aabcbe17f03a6f3efd514176444dae191d27fd66b391a360235463ffffffff167faf6c6cd7790e0180a4d22eb8ed846e55846f54ed10e5946db19972b5a0813a598284866040516104a693929190928352602083019190915267ffffffffffffffff16604082015260600190565b60405180910390a25050505b50505050565b5f6104c66001545f546107b4565b905090565b5f6104c66108e3565b602e54610100900460ff16158080156104f45750602e54600160ff909116105b8061050e5750303b15801561050e5750602e5460ff166001145b61059e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b602e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156105fc57602e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f6106056104cb565b6023805463ffffffff9081165f908152602f602090815260409182902085905592548151921682529181018390529192507f11f50c71891002839c2637ce302087160298255a87f1ea60d40e8db081383fad910160405180910390a15080156106c557602e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b5f83815b602081101561079457600163ffffffff8516821c81169003610737578481602081106106fa576106fa610b22565b60200201358260405160200161071a929190918252602082015260400190565b604051602081830303815290604052805190602001209150610782565b8185826020811061074a5761074a610b22565b6020020135604051602001610769929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8061078c81610b4f565b9150506106cc565b50949350505050565b5f816107aa8686866106c8565b1495945050505050565b604080516020808201859052818301849052825180830384018152606090920190925280519101205b92915050565b8060016107f260206002610ca4565b6107fc9190610b0f565b60235410610836576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60235f815461084590610b4f565b918290555090505f5b60208110156108d5578082901c60011660010361088157826003826020811061087957610879610b22565b015550505050565b6003816020811061089457610894610b22565b0154604080516020810192909252810184905260600160405160208183030381529060405280519060200120925080806108cd90610b4f565b91505061084e565b506108de610caf565b505050565b6023545f90819081805b60208110156109b6578083901c60011660010361094a576003816020811061091757610917610b22565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610977565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806109ae90610b4f565b9150506108ed565b50919392505050565b5f602082840312156109cf575f80fd5b5035919050565b5f805f606084860312156109e8575f80fd5b8335925060208401359150604084013567ffffffffffffffff81168114610a0d575f80fd5b809150509250925092565b8061040081018310156107dd575f80fd5b803563ffffffff81168114610a3c575f80fd5b919050565b5f805f6104408486031215610a54575f80fd5b83359250610a658560208601610a18565b9150610a746104208501610a29565b90509250925092565b5f60208284031215610a8d575f80fd5b610a9682610a29565b9392505050565b5f805f806104608587031215610ab1575f80fd5b84359350610ac28660208701610a18565b9250610ad16104208601610a29565b939692955092936104400135925050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b818103818111156107dd576107dd610ae2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610b7f57610b7f610ae2565b5060010190565b600181815b80851115610bdf57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610bc557610bc5610ae2565b80851615610bd257918102915b93841c9390800290610b8b565b509250929050565b5f82610bf5575060016107dd565b81610c0157505f6107dd565b8160018114610c175760028114610c2157610c3d565b60019150506107dd565b60ff841115610c3257610c32610ae2565b50506001821b6107dd565b5060208310610133831016604e8410600b8410161715610c60575081810a6107dd565b610c6a8383610b86565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610c9c57610c9c610ae2565b029392505050565b5f610a968383610be7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffdfea2646970667358221220266cf00c331b0b224bcd6976734955c98ca9e47455a941626d1788f29cf7b3bd64736f6c63430008140033", + "bytecode": "0x60c060405234801561000f575f80fd5b50604051610e9d380380610e9d83398101604081905261002e9161012b565b6001600160a01b0380831660a0528116608052610049610050565b505061015c565b602e54610100900460ff16156100bc5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b602e5460ff908116101561010e57602e805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b0381168114610126575f80fd5b919050565b5f806040838503121561013c575f80fd5b61014583610110565b915061015360208401610110565b90509250929050565b60805160a051610d1261018b5f395f818161015701526102f701525f818161022e01526102ab0152610d125ff3fe608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80635ca1e1651161008857806383f244031161006357806383f2440314610216578063a3c573eb14610229578063ef4eeb3514610250578063fb5708341461026f575f80fd5b80635ca1e1651461019e5780635d810501146101a65780638129fc1c1461020e575f80fd5b8063319cf735116100c3578063319cf7351461012c57806333d6247d146101355780633ed691ef1461014a57806349b7b80214610152575f80fd5b806301fd9044146100e9578063257b3632146101045780632dfdf0b514610123575b5f80fd5b6100f15f5481565b6040519081526020015b60405180910390f35b6100f16101123660046109bf565b60026020525f908152604090205481565b6100f160235481565b6100f160015481565b6101486101433660046109bf565b610292565b005b6100f16104b8565b6101797f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100fb565b6100f16104cb565b6100f16101b43660046109d6565b604080516020808201959095528082019390935260c09190911b7fffffffffffffffff0000000000000000000000000000000000000000000000001660608301528051604881840301815260689092019052805191012090565b6101486104d4565b6100f1610224366004610a41565b6106c8565b6101797f000000000000000000000000000000000000000000000000000000000000000081565b6100f161025e366004610a7d565b602f6020525f908152604090205481565b61028261027d366004610a9d565b61079d565b60405190151581526020016100fb565b5f8073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036102e057505060018190555f548161035f565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361032d5750505f819055600154819061035f565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61036a82846107b4565b5f81815260026020526040812054919250036104b257425f61038d600143610b0f565b5f8481526002602090815260409182902092409283905581518082018790528083018490527fffffffffffffffff00000000000000000000000000000000000000000000000060c087901b1660608201528251808203604801815260689091019092528151910120909150610401906107e3565b5f61040a6104cb565b60235463ffffffff165f908152602f602052604080822083905551919250879187917fda61aa7823fcd807e37b95aabcbe17f03a6f3efd514176444dae191d27fd66b391a360235463ffffffff167faf6c6cd7790e0180a4d22eb8ed846e55846f54ed10e5946db19972b5a0813a598284866040516104a693929190928352602083019190915267ffffffffffffffff16604082015260600190565b60405180910390a25050505b50505050565b5f6104c66001545f546107b4565b905090565b5f6104c66108e3565b602e54610100900460ff16158080156104f45750602e54600160ff909116105b8061050e5750303b15801561050e5750602e5460ff166001145b61059e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b602e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156105fc57602e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f6106056104cb565b6023805463ffffffff9081165f908152602f602090815260409182902085905592548151921682529181018390529192507f11f50c71891002839c2637ce302087160298255a87f1ea60d40e8db081383fad910160405180910390a15080156106c557602e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b5f83815b602081101561079457600163ffffffff8516821c81169003610737578481602081106106fa576106fa610b22565b60200201358260405160200161071a929190918252602082015260400190565b604051602081830303815290604052805190602001209150610782565b8185826020811061074a5761074a610b22565b6020020135604051602001610769929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8061078c81610b4f565b9150506106cc565b50949350505050565b5f816107aa8686866106c8565b1495945050505050565b604080516020808201859052818301849052825180830384018152606090920190925280519101205b92915050565b8060016107f260206002610ca4565b6107fc9190610b0f565b60235410610836576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60235f815461084590610b4f565b918290555090505f5b60208110156108d5578082901c60011660010361088157826003826020811061087957610879610b22565b015550505050565b6003816020811061089457610894610b22565b0154604080516020810192909252810184905260600160405160208183030381529060405280519060200120925080806108cd90610b4f565b91505061084e565b506108de610caf565b505050565b6023545f90819081805b60208110156109b6578083901c60011660010361094a576003816020811061091757610917610b22565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610977565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806109ae90610b4f565b9150506108ed565b50919392505050565b5f602082840312156109cf575f80fd5b5035919050565b5f805f606084860312156109e8575f80fd5b8335925060208401359150604084013567ffffffffffffffff81168114610a0d575f80fd5b809150509250925092565b8061040081018310156107dd575f80fd5b803563ffffffff81168114610a3c575f80fd5b919050565b5f805f6104408486031215610a54575f80fd5b83359250610a658560208601610a18565b9150610a746104208501610a29565b90509250925092565b5f60208284031215610a8d575f80fd5b610a9682610a29565b9392505050565b5f805f806104608587031215610ab1575f80fd5b84359350610ac28660208701610a18565b9250610ad16104208601610a29565b939692955092936104400135925050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b818103818111156107dd576107dd610ae2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610b7f57610b7f610ae2565b5060010190565b600181815b80851115610bdf57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610bc557610bc5610ae2565b80851615610bd257918102915b93841c9390800290610b8b565b509250929050565b5f82610bf5575060016107dd565b81610c0157505f6107dd565b8160018114610c175760028114610c2157610c3d565b60019150506107dd565b60ff841115610c3257610c32610ae2565b50506001821b6107dd565b5060208310610133831016604e8410600b8410161715610c60575081810a6107dd565b610c6a8383610b86565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610c9c57610c9c610ae2565b029392505050565b5f610a968383610be7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffdfea2646970667358221220821207c3abfc2db239c8ffa5eaee95e754357c5f54ffdd19460aa5f36674c7c664736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80635ca1e1651161008857806383f244031161006357806383f2440314610216578063a3c573eb14610229578063ef4eeb3514610250578063fb5708341461026f575f80fd5b80635ca1e1651461019e5780635d810501146101a65780638129fc1c1461020e575f80fd5b8063319cf735116100c3578063319cf7351461012c57806333d6247d146101355780633ed691ef1461014a57806349b7b80214610152575f80fd5b806301fd9044146100e9578063257b3632146101045780632dfdf0b514610123575b5f80fd5b6100f15f5481565b6040519081526020015b60405180910390f35b6100f16101123660046109bf565b60026020525f908152604090205481565b6100f160235481565b6100f160015481565b6101486101433660046109bf565b610292565b005b6100f16104b8565b6101797f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100fb565b6100f16104cb565b6100f16101b43660046109d6565b604080516020808201959095528082019390935260c09190911b7fffffffffffffffff0000000000000000000000000000000000000000000000001660608301528051604881840301815260689092019052805191012090565b6101486104d4565b6100f1610224366004610a41565b6106c8565b6101797f000000000000000000000000000000000000000000000000000000000000000081565b6100f161025e366004610a7d565b602f6020525f908152604090205481565b61028261027d366004610a9d565b61079d565b60405190151581526020016100fb565b5f8073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036102e057505060018190555f548161035f565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361032d5750505f819055600154819061035f565b6040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61036a82846107b4565b5f81815260026020526040812054919250036104b257425f61038d600143610b0f565b5f8481526002602090815260409182902092409283905581518082018790528083018490527fffffffffffffffff00000000000000000000000000000000000000000000000060c087901b1660608201528251808203604801815260689091019092528151910120909150610401906107e3565b5f61040a6104cb565b60235463ffffffff165f908152602f602052604080822083905551919250879187917fda61aa7823fcd807e37b95aabcbe17f03a6f3efd514176444dae191d27fd66b391a360235463ffffffff167faf6c6cd7790e0180a4d22eb8ed846e55846f54ed10e5946db19972b5a0813a598284866040516104a693929190928352602083019190915267ffffffffffffffff16604082015260600190565b60405180910390a25050505b50505050565b5f6104c66001545f546107b4565b905090565b5f6104c66108e3565b602e54610100900460ff16158080156104f45750602e54600160ff909116105b8061050e5750303b15801561050e5750602e5460ff166001145b61059e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a6564000000000000000000000000000000000000606482015260840160405180910390fd5b602e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905580156105fc57602e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b5f6106056104cb565b6023805463ffffffff9081165f908152602f602090815260409182902085905592548151921682529181018390529192507f11f50c71891002839c2637ce302087160298255a87f1ea60d40e8db081383fad910160405180910390a15080156106c557602e80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b50565b5f83815b602081101561079457600163ffffffff8516821c81169003610737578481602081106106fa576106fa610b22565b60200201358260405160200161071a929190918252602082015260400190565b604051602081830303815290604052805190602001209150610782565b8185826020811061074a5761074a610b22565b6020020135604051602001610769929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8061078c81610b4f565b9150506106cc565b50949350505050565b5f816107aa8686866106c8565b1495945050505050565b604080516020808201859052818301849052825180830384018152606090920190925280519101205b92915050565b8060016107f260206002610ca4565b6107fc9190610b0f565b60235410610836576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60235f815461084590610b4f565b918290555090505f5b60208110156108d5578082901c60011660010361088157826003826020811061087957610879610b22565b015550505050565b6003816020811061089457610894610b22565b0154604080516020810192909252810184905260600160405160208183030381529060405280519060200120925080806108cd90610b4f565b91505061084e565b506108de610caf565b505050565b6023545f90819081805b60208110156109b6578083901c60011660010361094a576003816020811061091757610917610b22565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610977565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806109ae90610b4f565b9150506108ed565b50919392505050565b5f602082840312156109cf575f80fd5b5035919050565b5f805f606084860312156109e8575f80fd5b8335925060208401359150604084013567ffffffffffffffff81168114610a0d575f80fd5b809150509250925092565b8061040081018310156107dd575f80fd5b803563ffffffff81168114610a3c575f80fd5b919050565b5f805f6104408486031215610a54575f80fd5b83359250610a658560208601610a18565b9150610a746104208501610a29565b90509250925092565b5f60208284031215610a8d575f80fd5b610a9682610a29565b9392505050565b5f805f806104608587031215610ab1575f80fd5b84359350610ac28660208701610a18565b9250610ad16104208601610a29565b939692955092936104400135925050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b818103818111156107dd576107dd610ae2565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610b7f57610b7f610ae2565b5060010190565b600181815b80851115610bdf57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610bc557610bc5610ae2565b80851615610bd257918102915b93841c9390800290610b8b565b509250929050565b5f82610bf5575060016107dd565b81610c0157505f6107dd565b8160018114610c175760028114610c2157610c3d565b60019150506107dd565b60ff841115610c3257610c32610ae2565b50506001821b6107dd565b5060208310610133831016604e8410600b8410161715610c60575081810a6107dd565b610c6a8383610b86565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115610c9c57610c9c610ae2565b029392505050565b5f610a968383610be7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52600160045260245ffdfea2646970667358221220821207c3abfc2db239c8ffa5eaee95e754357c5f54ffdd19460aa5f36674c7c664736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMMock.json b/compiled-contracts/PolygonZkEVMMock.json index e64320ada..922ee6291 100644 --- a/compiled-contracts/PolygonZkEVMMock.json +++ b/compiled-contracts/PolygonZkEVMMock.json @@ -1935,8 +1935,8 @@ "type": "function" } ], - "bytecode": "0x61014060405234801562000011575f80fd5b5060405162006f2038038062006f208339810160408190526200003491620000a2565b6001600160a01b0395861660c05293851660805291841660a05290921660e0526001600160401b039182166101005216610120526200012a565b6001600160a01b038116811462000083575f80fd5b50565b80516001600160401b03811681146200009d575f80fd5b919050565b5f805f805f8060c08789031215620000b8575f80fd5b8651620000c5816200006e565b6020880151909650620000d8816200006e565b6040880151909550620000eb816200006e565b6060880151909450620000fe816200006e565b92506200010e6080880162000086565b91506200011e60a0880162000086565b90509295509295509295565b60805160a05160c05160e0516101005161012051616d29620001f75f395f818161081501528181611a560152613e5601525f81816109a70152611a2c01525f818161096d015281816129e3015281816144e701526159e601525f8181610b380152818161170c01528181611bc801528181611d93015281816125f001528181612db101528181614757015261554301525f8181610bf801528181614eac01526152fa01525f8181610a75015281816129b1015281816132d90152818161472c0152614f980152616d295ff3fe608060405234801561000f575f80fd5b5060043610610475575f3560e01c80638c3d73011161025d578063c754c7ed11610148578063e7a7ed02116100c3578063f14916d611610093578063f851a44011610079578063f851a44014610c80578063f8b823e414610ca0578063fe16564f14610ca9575f80fd5b8063f14916d614610c5a578063f2fde38b14610c6d575f80fd5b8063e7a7ed0214610bc3578063e8bf92ed14610bf3578063eaeb077b14610c1a578063ed6b010414610c2d575f80fd5b8063d2e129f911610118578063d939b315116100fe578063d939b31514610b80578063dbc1697614610ba8578063e0d1744114610bb0575f80fd5b8063d2e129f914610b5a578063d8d1091b14610b6d575f80fd5b8063c754c7ed14610ac5578063c89e42df14610af1578063cfa8ed4714610b04578063d02103ca14610b33575f80fd5b8063ada8f919116101d8578063b4f77ea9116101a8578063ba58ae391161018e578063ba58ae3914610a97578063c0cad30214610aaa578063c0ed84e014610abd575f80fd5b8063b4f77ea914610a5d578063b6b0b09714610a70575f80fd5b8063ada8f9191461098f578063adc879e9146109a2578063afd23cbe146109c9578063b4d63f58146109f7575f80fd5b80639aa972a31161022d5780639c9f3dfe116102135780639c9f3dfe14610942578063a066215c14610955578063a3c573eb14610968575f80fd5b80639aa972a31461091c5780639b7967601461092f575f80fd5b80638c3d7301146108db5780638da5cb5b146108e357806396dc3d391461090157806399f5634e14610914575f80fd5b80634a1a89a71161037d578063621dd411116102f85780637215541a116102c8578063831c7ead116102ae578063831c7ead14610810578063837a473814610837578063841b24d7146108ab575f80fd5b80637215541a146107e95780637fcb3653146107fc575f80fd5b8063621dd4111461079c5780636b8616ce146107af5780636ff512cc146107ce578063715018a6146107e1575f80fd5b8063542028d51161034d5780635e9145c9116103335780635e9145c9146107795780635ec919581461078c5780636046916914610794575f80fd5b8063542028d5146106d0578063574f649e146106d8575f80fd5b80634a1a89a71461066b5780634a910e6a1461068b5780634e4877061461069e5780635392c5e0146106b1575f80fd5b8063267822471161040d578063383b3be8116103dd578063423fa856116103c3578063423fa8561461060f578063456052671461062f578063458c047714610657575f80fd5b8063383b3be8146105e9578063394218e9146105fc575f80fd5b8063267822471461055257806329878983146105975780632b0006fa146105c35780632c1f816a146105d6575f80fd5b806315064c961161044857806315064c96146104fb5780631816b7e51461051857806319d8ac611461052b578063220d78991461053f575f80fd5b80630a0d9fbe146104795780630eaa86ea146104b0578063107bf28c146104d157806310a01a72146104e6575b5f80fd5b606f5461049290610100900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6104c36104be366004615fac565b610cbc565b6040519081526020016104a7565b6104d961118c565b6040516104a79190616068565b6104f96104f4366004616097565b611218565b005b606f546105089060ff1681565b60405190151581526020016104a7565b6104f9610526366004616124565b6117c6565b6073546104929067ffffffffffffffff1681565b6104d961054d366004616145565b6118de565b607b546105729073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016104a7565b6074546105729068010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104f96105d136600461619f565b611ab4565b6104f96105e4366004616203565b611c7e565b6105086105f7366004616278565b611e86565b6104f961060a366004616278565b611edb565b6073546104929068010000000000000000900467ffffffffffffffff1681565b60735461049290700100000000000000000000000000000000900467ffffffffffffffff1681565b6079546104929067ffffffffffffffff1681565b6079546104929068010000000000000000900467ffffffffffffffff1681565b6104f9610699366004616278565b61205f565b6104f96106ac366004616278565b612112565b6104c36106bf366004616278565b60756020525f908152604090205481565b6104d9612296565b6104c36106e6366004616388565b835160209485012060408051808701979097528681019190915260608087019490945260c09290921b7fffffffffffffffff00000000000000000000000000000000000000000000000016608086015290911b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888401528051808403607c018152609c9093019052815191012090565b6104f961078736600461643d565b6122a3565b6104f9612a9c565b6104c3612b9b565b6104f96107aa36600461619f565b612bb0565b6104c36107bd366004616278565b60716020525f908152604090205481565b6104f96107dc36600461648d565b612f2e565b6104f9613003565b6104f96107f7366004616278565b613016565b6074546104929067ffffffffffffffff1681565b6104927f000000000000000000000000000000000000000000000000000000000000000081565b61087f6108453660046164a6565b60786020525f908152604090208054600182015460029092015467ffffffffffffffff808316936801000000000000000090930416919084565b6040805167ffffffffffffffff95861681529490931660208501529183015260608201526080016104a7565b607954610492907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104f9613183565b60335473ffffffffffffffffffffffffffffffffffffffff16610572565b6104f961090f366004616278565b61324f565b6104c3613292565b6104f961092a366004616203565b6133e5565b6104f961093d366004616278565b613495565b6104f9610950366004616278565b6134e4565b6104f9610963366004616278565b613660565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b6104f961099d36600461648d565b613766565b6104927f000000000000000000000000000000000000000000000000000000000000000081565b606f546109e4906901000000000000000000900461ffff1681565b60405161ffff90911681526020016104a7565b610a37610a05366004616278565b60726020525f90815260409020805460019091015467ffffffffffffffff808216916801000000000000000090041683565b6040805193845267ffffffffffffffff92831660208501529116908201526060016104a7565b6104f9610a6b366004616278565b61382a565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b610508610aa53660046164a6565b61383b565b6104f9610ab83660046164bd565b6138c3565b6104926138db565b607b546104929074010000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104f9610aff3660046164bd565b61392e565b606f54610572906b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b6104f9610b6836600461652d565b6139bb565b6104f9610b7b3660046165d8565b613ef9565b60795461049290700100000000000000000000000000000000900467ffffffffffffffff1681565b6104f9614494565b6104f9610bbe366004616617565b614568565b607354610492907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b6104f9610c28366004616661565b6145f7565b607b54610508907c0100000000000000000000000000000000000000000000000000000000900460ff1681565b6104f9610c6836600461648d565b6149e7565b6104f9610c7b36600461648d565b614ab9565b607a546105729073ffffffffffffffffffffffffffffffffffffffff1681565b6104c360705481565b6104f9610cb73660046166a9565b614b6d565b5f805f610cc76138db565b905067ffffffffffffffff881615610e935760795467ffffffffffffffff9081169089161115610da4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605860248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2070656e60448201527f64696e6753746174654e756d206d757374206265206c657373206f722065717560648201527f616c207468616e206c61737450656e64696e6753746174650000000000000000608482015260a4015b60405180910390fd5b67ffffffffffffffff8089165f908152607860205260409020600281015481549094509091898116680100000000000000009092041614610e8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206d61746368207468652070656e64696e6760648201527f2073746174652062617463680000000000000000000000000000000000000000608482015260a401610d9b565b5061102b565b67ffffffffffffffff87165f90815260756020526040902054915081610f61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d426174636820737461746520726f6f7420646f6573206e6f7420657860648201527f6973740000000000000000000000000000000000000000000000000000000000608482015260a401610d9b565b8067ffffffffffffffff168767ffffffffffffffff16111561102b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605d60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206265206c657373206f7220657175616c2060648201527f7468616e2063757272656e744c61737456657269666965644261746368000000608482015260a401610d9b565b8067ffffffffffffffff168667ffffffffffffffff16116110f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605760248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2066696e60448201527f616c4e65774261746368206d75737420626520626967676572207468616e206360648201527f757272656e744c61737456657269666965644261746368000000000000000000608482015260a401610d9b565b5f61110288888886896118de565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028360405161113691906166d3565b602060405180830381855afa158015611151573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061117491906166ee565b61117e9190616732565b9a9950505050505050505050565b6077805461119990616745565b80601f01602080910402602001604051908101604052809291908181526020018280546111c590616745565b80156112105780601f106111e757610100808354040283529160200191611210565b820191905f5260205f20905b8154815290600101906020018083116111f357829003601f168201915b505050505081565b611220614b8f565b5f8061122a6138db565b905067ffffffffffffffff8a16156113f15760795467ffffffffffffffff908116908b161115611302576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605860248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2070656e60448201527f64696e6753746174654e756d206d757374206265206c657373206f722065717560648201527f616c207468616e206c61737450656e64696e6753746174650000000000000000608482015260a401610d9b565b67ffffffffffffffff808b165f9081526078602052604090206002810154815490945090918b81166801000000000000000090920416146113eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206d61746368207468652070656e64696e6760648201527f2073746174652062617463680000000000000000000000000000000000000000608482015260a401610d9b565b50611589565b67ffffffffffffffff89165f908152607560205260409020549150816114bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d426174636820737461746520726f6f7420646f6573206e6f7420657860648201527f6973740000000000000000000000000000000000000000000000000000000000608482015260a401610d9b565b8067ffffffffffffffff168967ffffffffffffffff161115611589576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605d60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206265206c657373206f7220657175616c2060648201527f7468616e2063757272656e744c61737456657269666965644261746368000000608482015260a401610d9b565b8067ffffffffffffffff168867ffffffffffffffff1611611652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605760248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2066696e60448201527f616c4e65774261746368206d75737420626520626967676572207468616e206360648201527f757272656e744c61737456657269666965644261746368000000000000000000608482015260a401610d9b565b5f6116608a8a8a868b6118de565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8c81169182179092555f90815260756020526040902089905560795491925016156116dd57607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018990527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611762575f80fd5b505af1158015611774573d5f803e3d5ffd5b505060405189815233925067ffffffffffffffff8c1691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe9060200160405180910390a35050505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611817576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88161ffff16108061183057506103ff8161ffff16115b15611867576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffff16690100000000000000000061ffff8416908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a150565b67ffffffffffffffff8086165f818152607260205260408082205493881682529020546060929115801590611911575081155b15611948576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8061197f576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119888461383b565b6119be576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b166020820152603481019690965260548601929092527fffffffffffffffff00000000000000000000000000000000000000000000000060c098891b811660748701527f0000000000000000000000000000000000000000000000000000000000000000891b8116607c8701527f0000000000000000000000000000000000000000000000000000000000000000891b81166084870152608c86019490945260ac85015260cc840194909452509290931b90911660ec830152805180830360d401815260f4909201905290565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611b11576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b1f868686868686614c10565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615611b9957607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611c1e575f80fd5b505af1158015611c30573d5f803e3d5ffd5b505060405184815233925067ffffffffffffffff871691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe906020015b60405180910390a3505050505050565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611cdb576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cea87878787878787614fcb565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615611d6457607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611de9575f80fd5b505af1158015611dfb573d5f803e3d5ffd5b50506079805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a800000000000000000000000000000000000000000000000001790555050604051828152339067ffffffffffffffff8616907fcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf729060200160405180910390a350505050505050565b60795467ffffffffffffffff8281165f9081526078602052604081205490924292611ec992700100000000000000000000000000000000909204811691166167c3565b67ffffffffffffffff16111592915050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611f2c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611f73576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff16611fe25760795467ffffffffffffffff7801000000000000000000000000000000000000000000000000909104811690821610611fe2576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a1906020016118d3565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461210657606f5460ff16156120c7576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120d081611e86565b612106576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61210f816153fa565b50565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612163576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff821611156121aa576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661221557607b5467ffffffffffffffff74010000000000000000000000000000000000000000909104811690821610612215576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020016118d3565b6076805461119990616745565b606f5460ff16156122e0576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314612340576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81900361237b576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156123b7576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f81815260726020526040812054838516949293700100000000000000000000000000000000909304909216919082905b868110156127ff575f8a8a8381811061241d5761241d6167eb565b905060200281019061242f9190616818565b6124389061684a565b8051805160209091012060608201519192509067ffffffffffffffff16156125ad5785612464816168d4565b9650505f81836020015184606001516040516020016124bb93929190928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f90815260719093529120549091508114612543576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8088165f9081526071602052604080822091909155606085015190850151908216911610156125a7576040517f7f7ab87200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506126e7565b602082015115801590612671575060208201516040517f257b363200000000000000000000000000000000000000000000000000000000815260048101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063257b3632906024016020604051808303815f875af115801561264b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061266f91906166ee565b155b156126a8576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516201d4c010156126e7576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8767ffffffffffffffff16826040015167ffffffffffffffff16108061271a575042826040015167ffffffffffffffff16115b15612751576040517fea82791600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602082810151604080850151815193840189905290830184905260608084019290925260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c0160405160208183030381529060405280519060200120945081604001519750505080806127f7906168fa565b915050612402565b5061280a86856167c3565b60735490945067ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169084161115612873576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61287e8285616931565b6128929067ffffffffffffffff1688616952565b604080516060810182528581524267ffffffffffffffff908116602080840191825260738054680100000000000000009081900485168688019081528d86165f8181526072909552979093209551865592516001909501805492519585167fffffffffffffffffffffffffffffffff000000000000000000000000000000009384161795851684029590951790945583548c841691161793029290921790559091508281169085161461298757607380547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8716021790555b6129d933308360705461299a9190616965565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190615607565b6129e16156e9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612a46575f80fd5b505af1158015612a58573d5f803e3d5ffd5b505060405167ffffffffffffffff881692507f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce91505f90a250505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612aed576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b547c0100000000000000000000000000000000000000000000000000000000900460ff16612b49576040517ff6ba91a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690556040517f854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f905f90a1565b5f6070546064612bab9190616965565b905090565b606f5460ff1615612bed576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff8581165f908152607260205260409020600101544292612c39927801000000000000000000000000000000000000000000000000909104811691166167c3565b67ffffffffffffffff161115612c7b576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8612c888686616931565b67ffffffffffffffff161115612cca576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612cd8868686868686614c10565b612ce184615794565b607954700100000000000000000000000000000000900467ffffffffffffffff165f03612e2257607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615612d8257607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015612e07575f80fd5b505af1158015612e19573d5f803e3d5ffd5b50505050612ef0565b612e2a6156e9565b6079805467ffffffffffffffff16905f612e43836168d4565b825467ffffffffffffffff9182166101009390930a92830292820219169190911790915560408051608081018252428316815287831660208083019182528284018981526060840189815260795487165f908152607890935294909120925183549251861668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169516949094171781559151600183015551600290910155505b604051828152339067ffffffffffffffff8616907f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596690602001611c6e565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612f7f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fff0000000000000000000000000000000000000000ffffffffffffffffffffff166b01000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0906020016118d3565b61300b614b8f565b6130145f61596e565b565b60335473ffffffffffffffffffffffffffffffffffffffff16331461317b575f61303e6138db565b90508067ffffffffffffffff168267ffffffffffffffff161161308d576040517f812a372d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000909104811690831611806130d2575067ffffffffffffffff8083165f9081526072602052604090206001015416155b15613109576040517f98c5c01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8083165f9081526072602052604090206001015442916131379162093a8091166167c3565b67ffffffffffffffff161115613179576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b61210f6159e4565b607b5473ffffffffffffffffffffffffffffffffffffffff1633146131d4576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b54607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691821790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b613257614b8f565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561331e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061334291906166ee565b90505f61334d6138db565b60735467ffffffffffffffff6801000000000000000082048116916133a59170010000000000000000000000000000000082048116917801000000000000000000000000000000000000000000000000900416616931565b6133af91906167c3565b6133b99190616931565b67ffffffffffffffff169050805f036133d4575f9250505090565b6133de818361697c565b9250505090565b606f5460ff1615613422576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61343187878787878787614fcb565b67ffffffffffffffff84165f908152607560209081526040918290205482519081529081018490527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a161348c6159e4565b50505050505050565b61349d614b8f565b6073805467ffffffffffffffff90921668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff909216919091179055565b607a5473ffffffffffffffffffffffffffffffffffffffff163314613535576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff8216111561357c576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff166135e35760795467ffffffffffffffff7001000000000000000000000000000000009091048116908216106135e3576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607980547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c75906020016118d3565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146136b1576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620151808167ffffffffffffffff1611156136f8576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1661010067ffffffffffffffff8416908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c28906020016118d3565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146137b7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce6906020016118d3565b613832614b8f565b61210f81615794565b5f67ffffffff0000000167ffffffffffffffff8316108015613872575067ffffffff00000001604083901c67ffffffffffffffff16105b8015613893575067ffffffff00000001608083901c67ffffffffffffffff16105b80156138aa575067ffffffff0000000160c083901c105b156138b757506001919050565b505f919050565b919050565b6138cb614b8f565b60776138d782826169dc565b5050565b6079545f9067ffffffffffffffff161561391d575060795467ffffffffffffffff9081165f908152607860205260409020546801000000000000000090041690565b5060745467ffffffffffffffff1690565b607a5473ffffffffffffffffffffffffffffffffffffffff16331461397f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607661398b82826169dc565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20816040516118d39190616068565b5f54610100900460ff16158080156139d957505f54600160ff909116105b806139f25750303b1580156139f257505f5460ff166001145b613a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d9b565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015613ada575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b613ae7602088018861648d565b607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055613b3c604088016020890161648d565b606f805473ffffffffffffffffffffffffffffffffffffffff929092166b010000000000000000000000027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055613ba1608088016060890161648d565b6074805473ffffffffffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9092169190911790555f805260756020527ff9e3fbf150b7a0077118526f473c53cb4734f166167e2c6213e3567dd390b4ad8690556076613c2b86826169dc565b506077613c3885826169dc565b5062093a80613c4d6060890160408a01616278565b67ffffffffffffffff161115613c8f576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613c9f6060880160408901616278565b6079805467ffffffffffffffff92909216700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905562093a80613d0160a0890160808a01616278565b67ffffffffffffffff161115613d43576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d5360a0880160808901616278565b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff939093169290920291909117905567016345785d8a0000607055606f80547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff166a03ea000000000000070800179055607b80547fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff167c0100000000000697800000000000000000000000000000000000000000179055613e32615a67565b7fed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd65f7f00000000000000000000000000000000000000000000000000000000000000008585604051613e879493929190616b3b565b60405180910390a1801561348c575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff1615613f56576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1615613f93576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f819003613fce576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e881111561400a576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff78010000000000000000000000000000000000000000000000008204811691614055918491700100000000000000000000000000000000900416616b72565b111561408d576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f8181526072602052604081205491937001000000000000000000000000000000009004909216915b84811015614332575f8787838181106140eb576140eb6167eb565b90506020028101906140fd9190616b85565b61410690616bb7565b905083614112816168d4565b825180516020918201208185015160408087015190519499509194505f936141739386939101928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f908152607190935291205490915081146141fb576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f9081526071602052604081205561421f600189616952565b840361428e5742607b60149054906101000a900467ffffffffffffffff16846040015161424c91906167c3565b67ffffffffffffffff16111561428e576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020838101516040805192830188905282018490526060808301919091524260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016608083015233901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c01604051602081830303815290604052805190602001209450505050808061432a906168fa565b9150506140d0565b5061433d84846167c3565b6073805467ffffffffffffffff4281167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217808455604080516060810182528781526020808201958652680100000000000000009384900485168284019081528589165f818152607290935284832093518455965160019390930180549151871686027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921693871693909317179091558554938916700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff938602939093167fffffffffffffffff00000000000000000000000000000000ffffffffffffffff90941693909317919091179093559151929550917f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a49190a2505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146144e5576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dbc169766040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561454a575f80fd5b505af115801561455c573d5f803e3d5ffd5b50505050613014615b06565b614570614b8f565b6040805160608101825293845267ffffffffffffffff92831660208086019182529284168583019081529584165f908152607290935291209251835551600190920180549351821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169290911691909117919091179055565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff1615614654576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1615614691576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61469a612b9b565b9050818111156146d6576040517f4732fdb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388831115614712576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61475473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084615607565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156147be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906147e291906166ee565b60738054919250780100000000000000000000000000000000000000000000000090910467ffffffffffffffff1690601861481c836168d4565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508484604051614853929190616c30565b60408051918290038220602083015281018290527fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b166060820152606801604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206073547801000000000000000000000000000000000000000000000000900467ffffffffffffffff165f9081526071909352912055323303614981576073546040805183815233602082015260609181018290525f91810191909152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319060800160405180910390a26149e0565b607360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931823388886040516149d79493929190616c3f565b60405180910390a25b5050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314614a38576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607480547fffffffff0000000000000000000000000000000000000000ffffffffffffffff166801000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527f61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca906020016118d3565b614ac1614b8f565b73ffffffffffffffffffffffffffffffffffffffff8116614b64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610d9b565b61210f8161596e565b614b75614b8f565b67ffffffffffffffff165f90815260756020526040902055565b60335473ffffffffffffffffffffffffffffffffffffffff163314613014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d9b565b5f80614c1a6138db565b905067ffffffffffffffff881615614ce95760795467ffffffffffffffff9081169089161115614c76576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8089165f908152607860205260409020600281015481549094509091898116680100000000000000009092041614614ce3576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50614d89565b67ffffffffffffffff87165f90815260756020526040902054915081614d3b576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff161115614d89576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168667ffffffffffffffff1611614dd6576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f614de488888886896118de565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051614e1891906166d3565b602060405180830381855afa158015614e33573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190614e5691906166ee565b614e609190616732565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a91614ee291899190600401616c74565b602060405180830381865afa158015614efd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614f219190616cae565b614f57576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fbf33614f65858b616931565b67ffffffffffffffff16614f77613292565b614f819190616965565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190615b94565b50505050505050505050565b5f67ffffffffffffffff8816156150975760795467ffffffffffffffff9081169089161115615026576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5067ffffffffffffffff8088165f908152607860205260409020600281015481549092888116680100000000000000009092041614615091576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50615132565b5067ffffffffffffffff85165f90815260756020526040902054806150e8576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60745467ffffffffffffffff9081169087161115615132576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff908116908816118061516457508767ffffffffffffffff168767ffffffffffffffff1611155b8061518b575060795467ffffffffffffffff68010000000000000000909104811690881611155b156151c2576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8781165f90815260786020526040902054680100000000000000009004811690861614615224576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61523287878785886118de565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028360405161526691906166d3565b602060405180830381855afa158015615281573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906152a491906166ee565b6152ae9190616732565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a9161533091889190600401616c74565b602060405180830381865afa15801561534b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061536f9190616cae565b6153a5576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff89165f90815260786020526040902060020154859003614fbf576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff680100000000000000009091048116908216111580615434575060795467ffffffffffffffff908116908216115b1561546b576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8181165f81815260786020908152604080832080546074805468010000000000000000928390049098167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090981688179055600282015487865260759094529382902092909255607980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff169390940292909217909255600182015490517f33d6247d00000000000000000000000000000000000000000000000000000000815260048101919091529091907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015615599575f80fd5b505af11580156155ab573d5f803e3d5ffd5b505050508267ffffffffffffffff168167ffffffffffffffff167f328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e84600201546040516155fa91815260200190565b60405180910390a3505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526156e39085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152615bef565b50505050565b60795467ffffffffffffffff680100000000000000008204811691161115613014576079545f906157319068010000000000000000900467ffffffffffffffff1660016167c3565b905061573c81611e86565b1561210f576079545f9060029061575e90849067ffffffffffffffff16616931565b6157689190616ccd565b61577290836167c3565b905061577d81611e86565b1561578b576138d7816153fa565b6138d7826153fa565b5f61579d6138db565b9050815f806157ac8484616931565b606f5467ffffffffffffffff91821692505f916157cf9161010090041642616952565b90505b8467ffffffffffffffff168467ffffffffffffffff16146158595767ffffffffffffffff8085165f908152607260205260409020600181015490911682101561583757600181015468010000000000000000900467ffffffffffffffff169450615853565b6158418686616931565b67ffffffffffffffff16935050615859565b506157d2565b5f6158648484616952565b9050838110156158bb57808403600c811161587f5780615882565b600c5b9050806103e80a81606f60099054906101000a900461ffff1661ffff160a60705402816158b1576158b1616705565b046070555061592a565b838103600c81116158cc57806158cf565b600c5b90505f816103e80a82606f60099054906101000a900461ffff1661ffff160a670de0b6b3a7640000028161590557615905616705565b04905080607054670de0b6b3a7640000028161592357615923616705565b0460705550505b683635c9adc5dea00000607054111561594f57683635c9adc5dea0000060705561348c565b633b9aca00607054101561348c57633b9aca0060705550505050505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b158015615a49575f80fd5b505af1158015615a5b573d5f803e3d5ffd5b50505050613014615cfa565b5f54610100900460ff16615afd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d9b565b6130143361596e565b606f5460ff16615b42576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052615bea9084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401615661565b505050565b5f615c50826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16615d8c9092919063ffffffff16565b805190915015615bea5780806020019051810190615c6e9190616cae565b615bea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d9b565b606f5460ff1615615d37576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b6060615d9a84845f85615da2565b949350505050565b606082471015615e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d9b565b5f808673ffffffffffffffffffffffffffffffffffffffff168587604051615e5c91906166d3565b5f6040518083038185875af1925050503d805f8114615e96576040519150601f19603f3d011682016040523d82523d5f602084013e615e9b565b606091505b5091509150615eac87838387615eb7565b979650505050505050565b60608315615f4c5782515f03615f455773ffffffffffffffffffffffffffffffffffffffff85163b615f45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d9b565b5081615d9a565b615d9a8383815115615f615781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d9b9190616068565b803567ffffffffffffffff811681146138be575f80fd5b5f805f805f60a08688031215615fc0575f80fd5b615fc986615f95565b9450615fd760208701615f95565b9350615fe560408701615f95565b94979396509394606081013594506080013592915050565b5f5b83811015616017578181015183820152602001615fff565b50505f910152565b5f8151808452616036816020860160208601615ffd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61607a602083018461601f565b9392505050565b8060408101831015616091575f80fd5b92915050565b5f805f805f805f806101a0898b0312156160af575f80fd5b6160b889615f95565b97506160c660208a01615f95565b96506160d460408a01615f95565b955060608901359450608089013593506160f18a60a08b01616081565b925061016089018a811115616104575f80fd5b60e08a0192506161148b82616081565b9150509295985092959890939650565b5f60208284031215616134575f80fd5b813561ffff8116811461607a575f80fd5b5f805f805f60a08688031215616159575f80fd5b61616286615f95565b945061617060208701615f95565b94979496505050506040830135926060810135926080909101359150565b806103008101831015616091575f80fd5b5f805f805f806103a087890312156161b5575f80fd5b6161be87615f95565b95506161cc60208801615f95565b94506161da60408801615f95565b935060608701359250608087013591506161f78860a0890161618e565b90509295509295509295565b5f805f805f805f6103c0888a03121561621a575f80fd5b61622388615f95565b965061623160208901615f95565b955061623f60408901615f95565b945061624d60608901615f95565b93506080880135925060a0880135915061626a8960c08a0161618e565b905092959891949750929550565b5f60208284031215616288575f80fd5b61607a82615f95565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f8301126162cd575f80fd5b813567ffffffffffffffff808211156162e8576162e8616291565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561632e5761632e616291565b81604052838152866020858801011115616346575f80fd5b836020870160208301375f602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146138be575f80fd5b5f805f805f60a0868803121561639c575f80fd5b85359450602086013567ffffffffffffffff8111156163b9575f80fd5b6163c5888289016162be565b945050604086013592506163db60608701615f95565b91506163e960808701616365565b90509295509295909350565b5f8083601f840112616405575f80fd5b50813567ffffffffffffffff81111561641c575f80fd5b6020830191508360208260051b8501011115616436575f80fd5b9250929050565b5f805f6040848603121561644f575f80fd5b833567ffffffffffffffff811115616465575f80fd5b616471868287016163f5565b9094509250616484905060208501616365565b90509250925092565b5f6020828403121561649d575f80fd5b61607a82616365565b5f602082840312156164b6575f80fd5b5035919050565b5f602082840312156164cd575f80fd5b813567ffffffffffffffff8111156164e3575f80fd5b615d9a848285016162be565b5f8083601f8401126164ff575f80fd5b50813567ffffffffffffffff811115616516575f80fd5b602083019150836020828501011115616436575f80fd5b5f805f805f80868803610120811215616544575f80fd5b60a0811215616551575f80fd5b5086955060a0870135945060c087013567ffffffffffffffff80821115616576575f80fd5b6165828a838b016162be565b955060e0890135915080821115616597575f80fd5b6165a38a838b016162be565b94506101008901359150808211156165b9575f80fd5b506165c689828a016164ef565b979a9699509497509295939492505050565b5f80602083850312156165e9575f80fd5b823567ffffffffffffffff8111156165ff575f80fd5b61660b858286016163f5565b90969095509350505050565b5f805f806080858703121561662a575f80fd5b61663385615f95565b93506020850135925061664860408601615f95565b915061665660608601615f95565b905092959194509250565b5f805f60408486031215616673575f80fd5b833567ffffffffffffffff811115616689575f80fd5b616695868287016164ef565b909790965060209590950135949350505050565b5f80604083850312156166ba575f80fd5b823591506166ca60208401615f95565b90509250929050565b5f82516166e4818460208701615ffd565b9190910192915050565b5f602082840312156166fe575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f8261674057616740616705565b500690565b600181811c9082168061675957607f821691505b602082108103616790577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff8181168382160190808211156167e4576167e4616796565b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818336030181126166e4575f80fd5b5f6080823603121561685a575f80fd5b6040516080810167ffffffffffffffff828210818311171561687e5761687e616291565b816040528435915080821115616892575f80fd5b5061689f368286016162be565b825250602083013560208201526168b860408401615f95565b60408201526168c960608401615f95565b606082015292915050565b5f67ffffffffffffffff8083168181036168f0576168f0616796565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361692a5761692a616796565b5060010190565b67ffffffffffffffff8281168282160390808211156167e4576167e4616796565b8181038181111561609157616091616796565b808202811582820484141761609157616091616796565b5f8261698a5761698a616705565b500490565b601f821115615bea575f81815260208120601f850160051c810160208610156169b55750805b601f850160051c820191505b818110156169d4578281556001016169c1565b505050505050565b815167ffffffffffffffff8111156169f6576169f6616291565b616a0a81616a048454616745565b8461698f565b602080601f831160018114616a5c575f8415616a265750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556169d4565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015616aa857888601518255948401946001909101908401616a89565b5085821015616ae457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f67ffffffffffffffff808716835280861660208401525060606040830152616b68606083018486616af4565b9695505050505050565b8082018082111561609157616091616796565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126166e4575f80fd5b5f60608236031215616bc7575f80fd5b6040516060810167ffffffffffffffff8282108183111715616beb57616beb616291565b816040528435915080821115616bff575f80fd5b50616c0c368286016162be565b82525060208301356020820152616c2560408401615f95565b604082015292915050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201525f616b68606083018486616af4565b6103208101610300808584378201835f5b6001811015616ca4578151835260209283019290910190600101616c85565b5050509392505050565b5f60208284031215616cbe575f80fd5b8151801515811461607a575f80fd5b5f67ffffffffffffffff80841680616ce757616ce7616705565b9216919091049291505056fea2646970667358221220038c52f3bb0c2a50a3bf05e72805503f2e253770ce557d1b39af4a50601925ef64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610475575f3560e01c80638c3d73011161025d578063c754c7ed11610148578063e7a7ed02116100c3578063f14916d611610093578063f851a44011610079578063f851a44014610c80578063f8b823e414610ca0578063fe16564f14610ca9575f80fd5b8063f14916d614610c5a578063f2fde38b14610c6d575f80fd5b8063e7a7ed0214610bc3578063e8bf92ed14610bf3578063eaeb077b14610c1a578063ed6b010414610c2d575f80fd5b8063d2e129f911610118578063d939b315116100fe578063d939b31514610b80578063dbc1697614610ba8578063e0d1744114610bb0575f80fd5b8063d2e129f914610b5a578063d8d1091b14610b6d575f80fd5b8063c754c7ed14610ac5578063c89e42df14610af1578063cfa8ed4714610b04578063d02103ca14610b33575f80fd5b8063ada8f919116101d8578063b4f77ea9116101a8578063ba58ae391161018e578063ba58ae3914610a97578063c0cad30214610aaa578063c0ed84e014610abd575f80fd5b8063b4f77ea914610a5d578063b6b0b09714610a70575f80fd5b8063ada8f9191461098f578063adc879e9146109a2578063afd23cbe146109c9578063b4d63f58146109f7575f80fd5b80639aa972a31161022d5780639c9f3dfe116102135780639c9f3dfe14610942578063a066215c14610955578063a3c573eb14610968575f80fd5b80639aa972a31461091c5780639b7967601461092f575f80fd5b80638c3d7301146108db5780638da5cb5b146108e357806396dc3d391461090157806399f5634e14610914575f80fd5b80634a1a89a71161037d578063621dd411116102f85780637215541a116102c8578063831c7ead116102ae578063831c7ead14610810578063837a473814610837578063841b24d7146108ab575f80fd5b80637215541a146107e95780637fcb3653146107fc575f80fd5b8063621dd4111461079c5780636b8616ce146107af5780636ff512cc146107ce578063715018a6146107e1575f80fd5b8063542028d51161034d5780635e9145c9116103335780635e9145c9146107795780635ec919581461078c5780636046916914610794575f80fd5b8063542028d5146106d0578063574f649e146106d8575f80fd5b80634a1a89a71461066b5780634a910e6a1461068b5780634e4877061461069e5780635392c5e0146106b1575f80fd5b8063267822471161040d578063383b3be8116103dd578063423fa856116103c3578063423fa8561461060f578063456052671461062f578063458c047714610657575f80fd5b8063383b3be8146105e9578063394218e9146105fc575f80fd5b8063267822471461055257806329878983146105975780632b0006fa146105c35780632c1f816a146105d6575f80fd5b806315064c961161044857806315064c96146104fb5780631816b7e51461051857806319d8ac611461052b578063220d78991461053f575f80fd5b80630a0d9fbe146104795780630eaa86ea146104b0578063107bf28c146104d157806310a01a72146104e6575b5f80fd5b606f5461049290610100900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6104c36104be366004615fac565b610cbc565b6040519081526020016104a7565b6104d961118c565b6040516104a79190616068565b6104f96104f4366004616097565b611218565b005b606f546105089060ff1681565b60405190151581526020016104a7565b6104f9610526366004616124565b6117c6565b6073546104929067ffffffffffffffff1681565b6104d961054d366004616145565b6118de565b607b546105729073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016104a7565b6074546105729068010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104f96105d136600461619f565b611ab4565b6104f96105e4366004616203565b611c7e565b6105086105f7366004616278565b611e86565b6104f961060a366004616278565b611edb565b6073546104929068010000000000000000900467ffffffffffffffff1681565b60735461049290700100000000000000000000000000000000900467ffffffffffffffff1681565b6079546104929067ffffffffffffffff1681565b6079546104929068010000000000000000900467ffffffffffffffff1681565b6104f9610699366004616278565b61205f565b6104f96106ac366004616278565b612112565b6104c36106bf366004616278565b60756020525f908152604090205481565b6104d9612296565b6104c36106e6366004616388565b835160209485012060408051808701979097528681019190915260608087019490945260c09290921b7fffffffffffffffff00000000000000000000000000000000000000000000000016608086015290911b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888401528051808403607c018152609c9093019052815191012090565b6104f961078736600461643d565b6122a3565b6104f9612a9c565b6104c3612b9b565b6104f96107aa36600461619f565b612bb0565b6104c36107bd366004616278565b60716020525f908152604090205481565b6104f96107dc36600461648d565b612f2e565b6104f9613003565b6104f96107f7366004616278565b613016565b6074546104929067ffffffffffffffff1681565b6104927f000000000000000000000000000000000000000000000000000000000000000081565b61087f6108453660046164a6565b60786020525f908152604090208054600182015460029092015467ffffffffffffffff808316936801000000000000000090930416919084565b6040805167ffffffffffffffff95861681529490931660208501529183015260608201526080016104a7565b607954610492907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104f9613183565b60335473ffffffffffffffffffffffffffffffffffffffff16610572565b6104f961090f366004616278565b61324f565b6104c3613292565b6104f961092a366004616203565b6133e5565b6104f961093d366004616278565b613495565b6104f9610950366004616278565b6134e4565b6104f9610963366004616278565b613660565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b6104f961099d36600461648d565b613766565b6104927f000000000000000000000000000000000000000000000000000000000000000081565b606f546109e4906901000000000000000000900461ffff1681565b60405161ffff90911681526020016104a7565b610a37610a05366004616278565b60726020525f90815260409020805460019091015467ffffffffffffffff808216916801000000000000000090041683565b6040805193845267ffffffffffffffff92831660208501529116908201526060016104a7565b6104f9610a6b366004616278565b61382a565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b610508610aa53660046164a6565b61383b565b6104f9610ab83660046164bd565b6138c3565b6104926138db565b607b546104929074010000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104f9610aff3660046164bd565b61392e565b606f54610572906b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b6104f9610b6836600461652d565b6139bb565b6104f9610b7b3660046165d8565b613ef9565b60795461049290700100000000000000000000000000000000900467ffffffffffffffff1681565b6104f9614494565b6104f9610bbe366004616617565b614568565b607354610492907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b6104f9610c28366004616661565b6145f7565b607b54610508907c0100000000000000000000000000000000000000000000000000000000900460ff1681565b6104f9610c6836600461648d565b6149e7565b6104f9610c7b36600461648d565b614ab9565b607a546105729073ffffffffffffffffffffffffffffffffffffffff1681565b6104c360705481565b6104f9610cb73660046166a9565b614b6d565b5f805f610cc76138db565b905067ffffffffffffffff881615610e935760795467ffffffffffffffff9081169089161115610da4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605860248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2070656e60448201527f64696e6753746174654e756d206d757374206265206c657373206f722065717560648201527f616c207468616e206c61737450656e64696e6753746174650000000000000000608482015260a4015b60405180910390fd5b67ffffffffffffffff8089165f908152607860205260409020600281015481549094509091898116680100000000000000009092041614610e8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206d61746368207468652070656e64696e6760648201527f2073746174652062617463680000000000000000000000000000000000000000608482015260a401610d9b565b5061102b565b67ffffffffffffffff87165f90815260756020526040902054915081610f61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d426174636820737461746520726f6f7420646f6573206e6f7420657860648201527f6973740000000000000000000000000000000000000000000000000000000000608482015260a401610d9b565b8067ffffffffffffffff168767ffffffffffffffff16111561102b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605d60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206265206c657373206f7220657175616c2060648201527f7468616e2063757272656e744c61737456657269666965644261746368000000608482015260a401610d9b565b8067ffffffffffffffff168667ffffffffffffffff16116110f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605760248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2066696e60448201527f616c4e65774261746368206d75737420626520626967676572207468616e206360648201527f757272656e744c61737456657269666965644261746368000000000000000000608482015260a401610d9b565b5f61110288888886896118de565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028360405161113691906166d3565b602060405180830381855afa158015611151573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061117491906166ee565b61117e9190616732565b9a9950505050505050505050565b6077805461119990616745565b80601f01602080910402602001604051908101604052809291908181526020018280546111c590616745565b80156112105780601f106111e757610100808354040283529160200191611210565b820191905f5260205f20905b8154815290600101906020018083116111f357829003601f168201915b505050505081565b611220614b8f565b5f8061122a6138db565b905067ffffffffffffffff8a16156113f15760795467ffffffffffffffff908116908b161115611302576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605860248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2070656e60448201527f64696e6753746174654e756d206d757374206265206c657373206f722065717560648201527f616c207468616e206c61737450656e64696e6753746174650000000000000000608482015260a401610d9b565b67ffffffffffffffff808b165f9081526078602052604090206002810154815490945090918b81166801000000000000000090920416146113eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206d61746368207468652070656e64696e6760648201527f2073746174652062617463680000000000000000000000000000000000000000608482015260a401610d9b565b50611589565b67ffffffffffffffff89165f908152607560205260409020549150816114bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d426174636820737461746520726f6f7420646f6573206e6f7420657860648201527f6973740000000000000000000000000000000000000000000000000000000000608482015260a401610d9b565b8067ffffffffffffffff168967ffffffffffffffff161115611589576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605d60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206265206c657373206f7220657175616c2060648201527f7468616e2063757272656e744c61737456657269666965644261746368000000608482015260a401610d9b565b8067ffffffffffffffff168867ffffffffffffffff1611611652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605760248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2066696e60448201527f616c4e65774261746368206d75737420626520626967676572207468616e206360648201527f757272656e744c61737456657269666965644261746368000000000000000000608482015260a401610d9b565b5f6116608a8a8a868b6118de565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8c81169182179092555f90815260756020526040902089905560795491925016156116dd57607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018990527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611762575f80fd5b505af1158015611774573d5f803e3d5ffd5b505060405189815233925067ffffffffffffffff8c1691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe9060200160405180910390a35050505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611817576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88161ffff16108061183057506103ff8161ffff16115b15611867576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffff16690100000000000000000061ffff8416908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a150565b67ffffffffffffffff8086165f818152607260205260408082205493881682529020546060929115801590611911575081155b15611948576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8061197f576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119888461383b565b6119be576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b166020820152603481019690965260548601929092527fffffffffffffffff00000000000000000000000000000000000000000000000060c098891b811660748701527f0000000000000000000000000000000000000000000000000000000000000000891b8116607c8701527f0000000000000000000000000000000000000000000000000000000000000000891b81166084870152608c86019490945260ac85015260cc840194909452509290931b90911660ec830152805180830360d401815260f4909201905290565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611b11576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b1f868686868686614c10565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615611b9957607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611c1e575f80fd5b505af1158015611c30573d5f803e3d5ffd5b505060405184815233925067ffffffffffffffff871691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe906020015b60405180910390a3505050505050565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611cdb576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cea87878787878787614fcb565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615611d6457607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611de9575f80fd5b505af1158015611dfb573d5f803e3d5ffd5b50506079805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a800000000000000000000000000000000000000000000000001790555050604051828152339067ffffffffffffffff8616907fcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf729060200160405180910390a350505050505050565b60795467ffffffffffffffff8281165f9081526078602052604081205490924292611ec992700100000000000000000000000000000000909204811691166167c3565b67ffffffffffffffff16111592915050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611f2c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611f73576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff16611fe25760795467ffffffffffffffff7801000000000000000000000000000000000000000000000000909104811690821610611fe2576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a1906020016118d3565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461210657606f5460ff16156120c7576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120d081611e86565b612106576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61210f816153fa565b50565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612163576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff821611156121aa576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661221557607b5467ffffffffffffffff74010000000000000000000000000000000000000000909104811690821610612215576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020016118d3565b6076805461119990616745565b606f5460ff16156122e0576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314612340576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81900361237b576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156123b7576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f81815260726020526040812054838516949293700100000000000000000000000000000000909304909216919082905b868110156127ff575f8a8a8381811061241d5761241d6167eb565b905060200281019061242f9190616818565b6124389061684a565b8051805160209091012060608201519192509067ffffffffffffffff16156125ad5785612464816168d4565b9650505f81836020015184606001516040516020016124bb93929190928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f90815260719093529120549091508114612543576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8088165f9081526071602052604080822091909155606085015190850151908216911610156125a7576040517f7f7ab87200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506126e7565b602082015115801590612671575060208201516040517f257b363200000000000000000000000000000000000000000000000000000000815260048101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063257b3632906024016020604051808303815f875af115801561264b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061266f91906166ee565b155b156126a8576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516201d4c010156126e7576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8767ffffffffffffffff16826040015167ffffffffffffffff16108061271a575042826040015167ffffffffffffffff16115b15612751576040517fea82791600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602082810151604080850151815193840189905290830184905260608084019290925260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c0160405160208183030381529060405280519060200120945081604001519750505080806127f7906168fa565b915050612402565b5061280a86856167c3565b60735490945067ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169084161115612873576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61287e8285616931565b6128929067ffffffffffffffff1688616952565b604080516060810182528581524267ffffffffffffffff908116602080840191825260738054680100000000000000009081900485168688019081528d86165f8181526072909552979093209551865592516001909501805492519585167fffffffffffffffffffffffffffffffff000000000000000000000000000000009384161795851684029590951790945583548c841691161793029290921790559091508281169085161461298757607380547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8716021790555b6129d933308360705461299a9190616965565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190615607565b6129e16156e9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612a46575f80fd5b505af1158015612a58573d5f803e3d5ffd5b505060405167ffffffffffffffff881692507f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce91505f90a250505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612aed576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b547c0100000000000000000000000000000000000000000000000000000000900460ff16612b49576040517ff6ba91a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690556040517f854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f905f90a1565b5f6070546064612bab9190616965565b905090565b606f5460ff1615612bed576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff8581165f908152607260205260409020600101544292612c39927801000000000000000000000000000000000000000000000000909104811691166167c3565b67ffffffffffffffff161115612c7b576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8612c888686616931565b67ffffffffffffffff161115612cca576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612cd8868686868686614c10565b612ce184615794565b607954700100000000000000000000000000000000900467ffffffffffffffff165f03612e2257607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615612d8257607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015612e07575f80fd5b505af1158015612e19573d5f803e3d5ffd5b50505050612ef0565b612e2a6156e9565b6079805467ffffffffffffffff16905f612e43836168d4565b825467ffffffffffffffff9182166101009390930a92830292820219169190911790915560408051608081018252428316815287831660208083019182528284018981526060840189815260795487165f908152607890935294909120925183549251861668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169516949094171781559151600183015551600290910155505b604051828152339067ffffffffffffffff8616907f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596690602001611c6e565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612f7f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fff0000000000000000000000000000000000000000ffffffffffffffffffffff166b01000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0906020016118d3565b61300b614b8f565b6130145f61596e565b565b60335473ffffffffffffffffffffffffffffffffffffffff16331461317b575f61303e6138db565b90508067ffffffffffffffff168267ffffffffffffffff161161308d576040517f812a372d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000909104811690831611806130d2575067ffffffffffffffff8083165f9081526072602052604090206001015416155b15613109576040517f98c5c01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8083165f9081526072602052604090206001015442916131379162093a8091166167c3565b67ffffffffffffffff161115613179576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b61210f6159e4565b607b5473ffffffffffffffffffffffffffffffffffffffff1633146131d4576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b54607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691821790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b613257614b8f565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561331e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061334291906166ee565b90505f61334d6138db565b60735467ffffffffffffffff6801000000000000000082048116916133a59170010000000000000000000000000000000082048116917801000000000000000000000000000000000000000000000000900416616931565b6133af91906167c3565b6133b99190616931565b67ffffffffffffffff169050805f036133d4575f9250505090565b6133de818361697c565b9250505090565b606f5460ff1615613422576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61343187878787878787614fcb565b67ffffffffffffffff84165f908152607560209081526040918290205482519081529081018490527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a161348c6159e4565b50505050505050565b61349d614b8f565b6073805467ffffffffffffffff90921668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff909216919091179055565b607a5473ffffffffffffffffffffffffffffffffffffffff163314613535576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff8216111561357c576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff166135e35760795467ffffffffffffffff7001000000000000000000000000000000009091048116908216106135e3576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607980547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c75906020016118d3565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146136b1576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620151808167ffffffffffffffff1611156136f8576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1661010067ffffffffffffffff8416908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c28906020016118d3565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146137b7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce6906020016118d3565b613832614b8f565b61210f81615794565b5f67ffffffff0000000167ffffffffffffffff8316108015613872575067ffffffff00000001604083901c67ffffffffffffffff16105b8015613893575067ffffffff00000001608083901c67ffffffffffffffff16105b80156138aa575067ffffffff0000000160c083901c105b156138b757506001919050565b505f919050565b919050565b6138cb614b8f565b60776138d782826169dc565b5050565b6079545f9067ffffffffffffffff161561391d575060795467ffffffffffffffff9081165f908152607860205260409020546801000000000000000090041690565b5060745467ffffffffffffffff1690565b607a5473ffffffffffffffffffffffffffffffffffffffff16331461397f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607661398b82826169dc565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20816040516118d39190616068565b5f54610100900460ff16158080156139d957505f54600160ff909116105b806139f25750303b1580156139f257505f5460ff166001145b613a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d9b565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015613ada575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b613ae7602088018861648d565b607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055613b3c604088016020890161648d565b606f805473ffffffffffffffffffffffffffffffffffffffff929092166b010000000000000000000000027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055613ba1608088016060890161648d565b6074805473ffffffffffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9092169190911790555f805260756020527ff9e3fbf150b7a0077118526f473c53cb4734f166167e2c6213e3567dd390b4ad8690556076613c2b86826169dc565b506077613c3885826169dc565b5062093a80613c4d6060890160408a01616278565b67ffffffffffffffff161115613c8f576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613c9f6060880160408901616278565b6079805467ffffffffffffffff92909216700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905562093a80613d0160a0890160808a01616278565b67ffffffffffffffff161115613d43576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d5360a0880160808901616278565b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff939093169290920291909117905567016345785d8a0000607055606f80547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff166a03ea000000000000070800179055607b80547fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff167c0100000000000697800000000000000000000000000000000000000000179055613e32615a67565b7fed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd65f7f00000000000000000000000000000000000000000000000000000000000000008585604051613e879493929190616b3b565b60405180910390a1801561348c575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff1615613f56576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1615613f93576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f819003613fce576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e881111561400a576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff78010000000000000000000000000000000000000000000000008204811691614055918491700100000000000000000000000000000000900416616b72565b111561408d576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f8181526072602052604081205491937001000000000000000000000000000000009004909216915b84811015614332575f8787838181106140eb576140eb6167eb565b90506020028101906140fd9190616b85565b61410690616bb7565b905083614112816168d4565b825180516020918201208185015160408087015190519499509194505f936141739386939101928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f908152607190935291205490915081146141fb576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f9081526071602052604081205561421f600189616952565b840361428e5742607b60149054906101000a900467ffffffffffffffff16846040015161424c91906167c3565b67ffffffffffffffff16111561428e576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020838101516040805192830188905282018490526060808301919091524260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016608083015233901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c01604051602081830303815290604052805190602001209450505050808061432a906168fa565b9150506140d0565b5061433d84846167c3565b6073805467ffffffffffffffff4281167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217808455604080516060810182528781526020808201958652680100000000000000009384900485168284019081528589165f818152607290935284832093518455965160019390930180549151871686027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921693871693909317179091558554938916700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff938602939093167fffffffffffffffff00000000000000000000000000000000ffffffffffffffff90941693909317919091179093559151929550917f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a49190a2505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146144e5576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dbc169766040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561454a575f80fd5b505af115801561455c573d5f803e3d5ffd5b50505050613014615b06565b614570614b8f565b6040805160608101825293845267ffffffffffffffff92831660208086019182529284168583019081529584165f908152607290935291209251835551600190920180549351821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169290911691909117919091179055565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff1615614654576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1615614691576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61469a612b9b565b9050818111156146d6576040517f4732fdb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388831115614712576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61475473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084615607565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156147be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906147e291906166ee565b60738054919250780100000000000000000000000000000000000000000000000090910467ffffffffffffffff1690601861481c836168d4565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508484604051614853929190616c30565b60408051918290038220602083015281018290527fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b166060820152606801604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206073547801000000000000000000000000000000000000000000000000900467ffffffffffffffff165f9081526071909352912055323303614981576073546040805183815233602082015260609181018290525f91810191909152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319060800160405180910390a26149e0565b607360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931823388886040516149d79493929190616c3f565b60405180910390a25b5050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314614a38576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607480547fffffffff0000000000000000000000000000000000000000ffffffffffffffff166801000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527f61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca906020016118d3565b614ac1614b8f565b73ffffffffffffffffffffffffffffffffffffffff8116614b64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610d9b565b61210f8161596e565b614b75614b8f565b67ffffffffffffffff165f90815260756020526040902055565b60335473ffffffffffffffffffffffffffffffffffffffff163314613014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d9b565b5f80614c1a6138db565b905067ffffffffffffffff881615614ce95760795467ffffffffffffffff9081169089161115614c76576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8089165f908152607860205260409020600281015481549094509091898116680100000000000000009092041614614ce3576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50614d89565b67ffffffffffffffff87165f90815260756020526040902054915081614d3b576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff161115614d89576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168667ffffffffffffffff1611614dd6576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f614de488888886896118de565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051614e1891906166d3565b602060405180830381855afa158015614e33573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190614e5691906166ee565b614e609190616732565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a91614ee291899190600401616c74565b602060405180830381865afa158015614efd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614f219190616cae565b614f57576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fbf33614f65858b616931565b67ffffffffffffffff16614f77613292565b614f819190616965565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190615b94565b50505050505050505050565b5f67ffffffffffffffff8816156150975760795467ffffffffffffffff9081169089161115615026576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5067ffffffffffffffff8088165f908152607860205260409020600281015481549092888116680100000000000000009092041614615091576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50615132565b5067ffffffffffffffff85165f90815260756020526040902054806150e8576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60745467ffffffffffffffff9081169087161115615132576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff908116908816118061516457508767ffffffffffffffff168767ffffffffffffffff1611155b8061518b575060795467ffffffffffffffff68010000000000000000909104811690881611155b156151c2576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8781165f90815260786020526040902054680100000000000000009004811690861614615224576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61523287878785886118de565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028360405161526691906166d3565b602060405180830381855afa158015615281573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906152a491906166ee565b6152ae9190616732565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a9161533091889190600401616c74565b602060405180830381865afa15801561534b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061536f9190616cae565b6153a5576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff89165f90815260786020526040902060020154859003614fbf576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff680100000000000000009091048116908216111580615434575060795467ffffffffffffffff908116908216115b1561546b576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8181165f81815260786020908152604080832080546074805468010000000000000000928390049098167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090981688179055600282015487865260759094529382902092909255607980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff169390940292909217909255600182015490517f33d6247d00000000000000000000000000000000000000000000000000000000815260048101919091529091907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015615599575f80fd5b505af11580156155ab573d5f803e3d5ffd5b505050508267ffffffffffffffff168167ffffffffffffffff167f328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e84600201546040516155fa91815260200190565b60405180910390a3505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526156e39085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152615bef565b50505050565b60795467ffffffffffffffff680100000000000000008204811691161115613014576079545f906157319068010000000000000000900467ffffffffffffffff1660016167c3565b905061573c81611e86565b1561210f576079545f9060029061575e90849067ffffffffffffffff16616931565b6157689190616ccd565b61577290836167c3565b905061577d81611e86565b1561578b576138d7816153fa565b6138d7826153fa565b5f61579d6138db565b9050815f806157ac8484616931565b606f5467ffffffffffffffff91821692505f916157cf9161010090041642616952565b90505b8467ffffffffffffffff168467ffffffffffffffff16146158595767ffffffffffffffff8085165f908152607260205260409020600181015490911682101561583757600181015468010000000000000000900467ffffffffffffffff169450615853565b6158418686616931565b67ffffffffffffffff16935050615859565b506157d2565b5f6158648484616952565b9050838110156158bb57808403600c811161587f5780615882565b600c5b9050806103e80a81606f60099054906101000a900461ffff1661ffff160a60705402816158b1576158b1616705565b046070555061592a565b838103600c81116158cc57806158cf565b600c5b90505f816103e80a82606f60099054906101000a900461ffff1661ffff160a670de0b6b3a7640000028161590557615905616705565b04905080607054670de0b6b3a7640000028161592357615923616705565b0460705550505b683635c9adc5dea00000607054111561594f57683635c9adc5dea0000060705561348c565b633b9aca00607054101561348c57633b9aca0060705550505050505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b158015615a49575f80fd5b505af1158015615a5b573d5f803e3d5ffd5b50505050613014615cfa565b5f54610100900460ff16615afd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d9b565b6130143361596e565b606f5460ff16615b42576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052615bea9084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401615661565b505050565b5f615c50826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16615d8c9092919063ffffffff16565b805190915015615bea5780806020019051810190615c6e9190616cae565b615bea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d9b565b606f5460ff1615615d37576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b6060615d9a84845f85615da2565b949350505050565b606082471015615e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d9b565b5f808673ffffffffffffffffffffffffffffffffffffffff168587604051615e5c91906166d3565b5f6040518083038185875af1925050503d805f8114615e96576040519150601f19603f3d011682016040523d82523d5f602084013e615e9b565b606091505b5091509150615eac87838387615eb7565b979650505050505050565b60608315615f4c5782515f03615f455773ffffffffffffffffffffffffffffffffffffffff85163b615f45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d9b565b5081615d9a565b615d9a8383815115615f615781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d9b9190616068565b803567ffffffffffffffff811681146138be575f80fd5b5f805f805f60a08688031215615fc0575f80fd5b615fc986615f95565b9450615fd760208701615f95565b9350615fe560408701615f95565b94979396509394606081013594506080013592915050565b5f5b83811015616017578181015183820152602001615fff565b50505f910152565b5f8151808452616036816020860160208601615ffd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61607a602083018461601f565b9392505050565b8060408101831015616091575f80fd5b92915050565b5f805f805f805f806101a0898b0312156160af575f80fd5b6160b889615f95565b97506160c660208a01615f95565b96506160d460408a01615f95565b955060608901359450608089013593506160f18a60a08b01616081565b925061016089018a811115616104575f80fd5b60e08a0192506161148b82616081565b9150509295985092959890939650565b5f60208284031215616134575f80fd5b813561ffff8116811461607a575f80fd5b5f805f805f60a08688031215616159575f80fd5b61616286615f95565b945061617060208701615f95565b94979496505050506040830135926060810135926080909101359150565b806103008101831015616091575f80fd5b5f805f805f806103a087890312156161b5575f80fd5b6161be87615f95565b95506161cc60208801615f95565b94506161da60408801615f95565b935060608701359250608087013591506161f78860a0890161618e565b90509295509295509295565b5f805f805f805f6103c0888a03121561621a575f80fd5b61622388615f95565b965061623160208901615f95565b955061623f60408901615f95565b945061624d60608901615f95565b93506080880135925060a0880135915061626a8960c08a0161618e565b905092959891949750929550565b5f60208284031215616288575f80fd5b61607a82615f95565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f8301126162cd575f80fd5b813567ffffffffffffffff808211156162e8576162e8616291565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561632e5761632e616291565b81604052838152866020858801011115616346575f80fd5b836020870160208301375f602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146138be575f80fd5b5f805f805f60a0868803121561639c575f80fd5b85359450602086013567ffffffffffffffff8111156163b9575f80fd5b6163c5888289016162be565b945050604086013592506163db60608701615f95565b91506163e960808701616365565b90509295509295909350565b5f8083601f840112616405575f80fd5b50813567ffffffffffffffff81111561641c575f80fd5b6020830191508360208260051b8501011115616436575f80fd5b9250929050565b5f805f6040848603121561644f575f80fd5b833567ffffffffffffffff811115616465575f80fd5b616471868287016163f5565b9094509250616484905060208501616365565b90509250925092565b5f6020828403121561649d575f80fd5b61607a82616365565b5f602082840312156164b6575f80fd5b5035919050565b5f602082840312156164cd575f80fd5b813567ffffffffffffffff8111156164e3575f80fd5b615d9a848285016162be565b5f8083601f8401126164ff575f80fd5b50813567ffffffffffffffff811115616516575f80fd5b602083019150836020828501011115616436575f80fd5b5f805f805f80868803610120811215616544575f80fd5b60a0811215616551575f80fd5b5086955060a0870135945060c087013567ffffffffffffffff80821115616576575f80fd5b6165828a838b016162be565b955060e0890135915080821115616597575f80fd5b6165a38a838b016162be565b94506101008901359150808211156165b9575f80fd5b506165c689828a016164ef565b979a9699509497509295939492505050565b5f80602083850312156165e9575f80fd5b823567ffffffffffffffff8111156165ff575f80fd5b61660b858286016163f5565b90969095509350505050565b5f805f806080858703121561662a575f80fd5b61663385615f95565b93506020850135925061664860408601615f95565b915061665660608601615f95565b905092959194509250565b5f805f60408486031215616673575f80fd5b833567ffffffffffffffff811115616689575f80fd5b616695868287016164ef565b909790965060209590950135949350505050565b5f80604083850312156166ba575f80fd5b823591506166ca60208401615f95565b90509250929050565b5f82516166e4818460208701615ffd565b9190910192915050565b5f602082840312156166fe575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f8261674057616740616705565b500690565b600181811c9082168061675957607f821691505b602082108103616790577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff8181168382160190808211156167e4576167e4616796565b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818336030181126166e4575f80fd5b5f6080823603121561685a575f80fd5b6040516080810167ffffffffffffffff828210818311171561687e5761687e616291565b816040528435915080821115616892575f80fd5b5061689f368286016162be565b825250602083013560208201526168b860408401615f95565b60408201526168c960608401615f95565b606082015292915050565b5f67ffffffffffffffff8083168181036168f0576168f0616796565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361692a5761692a616796565b5060010190565b67ffffffffffffffff8281168282160390808211156167e4576167e4616796565b8181038181111561609157616091616796565b808202811582820484141761609157616091616796565b5f8261698a5761698a616705565b500490565b601f821115615bea575f81815260208120601f850160051c810160208610156169b55750805b601f850160051c820191505b818110156169d4578281556001016169c1565b505050505050565b815167ffffffffffffffff8111156169f6576169f6616291565b616a0a81616a048454616745565b8461698f565b602080601f831160018114616a5c575f8415616a265750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556169d4565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015616aa857888601518255948401946001909101908401616a89565b5085821015616ae457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f67ffffffffffffffff808716835280861660208401525060606040830152616b68606083018486616af4565b9695505050505050565b8082018082111561609157616091616796565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126166e4575f80fd5b5f60608236031215616bc7575f80fd5b6040516060810167ffffffffffffffff8282108183111715616beb57616beb616291565b816040528435915080821115616bff575f80fd5b50616c0c368286016162be565b82525060208301356020820152616c2560408401615f95565b604082015292915050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201525f616b68606083018486616af4565b6103208101610300808584378201835f5b6001811015616ca4578151835260209283019290910190600101616c85565b5050509392505050565b5f60208284031215616cbe575f80fd5b8151801515811461607a575f80fd5b5f67ffffffffffffffff80841680616ce757616ce7616705565b9216919091049291505056fea2646970667358221220038c52f3bb0c2a50a3bf05e72805503f2e253770ce557d1b39af4a50601925ef64736f6c63430008140033", + "bytecode": "0x61014060405234801562000011575f80fd5b5060405162006f2038038062006f208339810160408190526200003491620000a2565b6001600160a01b0395861660c05293851660805291841660a05290921660e0526001600160401b039182166101005216610120526200012a565b6001600160a01b038116811462000083575f80fd5b50565b80516001600160401b03811681146200009d575f80fd5b919050565b5f805f805f8060c08789031215620000b8575f80fd5b8651620000c5816200006e565b6020880151909650620000d8816200006e565b6040880151909550620000eb816200006e565b6060880151909450620000fe816200006e565b92506200010e6080880162000086565b91506200011e60a0880162000086565b90509295509295509295565b60805160a05160c05160e0516101005161012051616d29620001f75f395f818161081501528181611a560152613e5601525f81816109a70152611a2c01525f818161096d015281816129e3015281816144e701526159e601525f8181610b380152818161170c01528181611bc801528181611d93015281816125f001528181612db101528181614757015261554301525f8181610bf801528181614eac01526152fa01525f8181610a75015281816129b1015281816132d90152818161472c0152614f980152616d295ff3fe608060405234801561000f575f80fd5b5060043610610475575f3560e01c80638c3d73011161025d578063c754c7ed11610148578063e7a7ed02116100c3578063f14916d611610093578063f851a44011610079578063f851a44014610c80578063f8b823e414610ca0578063fe16564f14610ca9575f80fd5b8063f14916d614610c5a578063f2fde38b14610c6d575f80fd5b8063e7a7ed0214610bc3578063e8bf92ed14610bf3578063eaeb077b14610c1a578063ed6b010414610c2d575f80fd5b8063d2e129f911610118578063d939b315116100fe578063d939b31514610b80578063dbc1697614610ba8578063e0d1744114610bb0575f80fd5b8063d2e129f914610b5a578063d8d1091b14610b6d575f80fd5b8063c754c7ed14610ac5578063c89e42df14610af1578063cfa8ed4714610b04578063d02103ca14610b33575f80fd5b8063ada8f919116101d8578063b4f77ea9116101a8578063ba58ae391161018e578063ba58ae3914610a97578063c0cad30214610aaa578063c0ed84e014610abd575f80fd5b8063b4f77ea914610a5d578063b6b0b09714610a70575f80fd5b8063ada8f9191461098f578063adc879e9146109a2578063afd23cbe146109c9578063b4d63f58146109f7575f80fd5b80639aa972a31161022d5780639c9f3dfe116102135780639c9f3dfe14610942578063a066215c14610955578063a3c573eb14610968575f80fd5b80639aa972a31461091c5780639b7967601461092f575f80fd5b80638c3d7301146108db5780638da5cb5b146108e357806396dc3d391461090157806399f5634e14610914575f80fd5b80634a1a89a71161037d578063621dd411116102f85780637215541a116102c8578063831c7ead116102ae578063831c7ead14610810578063837a473814610837578063841b24d7146108ab575f80fd5b80637215541a146107e95780637fcb3653146107fc575f80fd5b8063621dd4111461079c5780636b8616ce146107af5780636ff512cc146107ce578063715018a6146107e1575f80fd5b8063542028d51161034d5780635e9145c9116103335780635e9145c9146107795780635ec919581461078c5780636046916914610794575f80fd5b8063542028d5146106d0578063574f649e146106d8575f80fd5b80634a1a89a71461066b5780634a910e6a1461068b5780634e4877061461069e5780635392c5e0146106b1575f80fd5b8063267822471161040d578063383b3be8116103dd578063423fa856116103c3578063423fa8561461060f578063456052671461062f578063458c047714610657575f80fd5b8063383b3be8146105e9578063394218e9146105fc575f80fd5b8063267822471461055257806329878983146105975780632b0006fa146105c35780632c1f816a146105d6575f80fd5b806315064c961161044857806315064c96146104fb5780631816b7e51461051857806319d8ac611461052b578063220d78991461053f575f80fd5b80630a0d9fbe146104795780630eaa86ea146104b0578063107bf28c146104d157806310a01a72146104e6575b5f80fd5b606f5461049290610100900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6104c36104be366004615fac565b610cbc565b6040519081526020016104a7565b6104d961118c565b6040516104a79190616068565b6104f96104f4366004616097565b611218565b005b606f546105089060ff1681565b60405190151581526020016104a7565b6104f9610526366004616124565b6117c6565b6073546104929067ffffffffffffffff1681565b6104d961054d366004616145565b6118de565b607b546105729073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016104a7565b6074546105729068010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104f96105d136600461619f565b611ab4565b6104f96105e4366004616203565b611c7e565b6105086105f7366004616278565b611e86565b6104f961060a366004616278565b611edb565b6073546104929068010000000000000000900467ffffffffffffffff1681565b60735461049290700100000000000000000000000000000000900467ffffffffffffffff1681565b6079546104929067ffffffffffffffff1681565b6079546104929068010000000000000000900467ffffffffffffffff1681565b6104f9610699366004616278565b61205f565b6104f96106ac366004616278565b612112565b6104c36106bf366004616278565b60756020525f908152604090205481565b6104d9612296565b6104c36106e6366004616388565b835160209485012060408051808701979097528681019190915260608087019490945260c09290921b7fffffffffffffffff00000000000000000000000000000000000000000000000016608086015290911b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888401528051808403607c018152609c9093019052815191012090565b6104f961078736600461643d565b6122a3565b6104f9612a9c565b6104c3612b9b565b6104f96107aa36600461619f565b612bb0565b6104c36107bd366004616278565b60716020525f908152604090205481565b6104f96107dc36600461648d565b612f2e565b6104f9613003565b6104f96107f7366004616278565b613016565b6074546104929067ffffffffffffffff1681565b6104927f000000000000000000000000000000000000000000000000000000000000000081565b61087f6108453660046164a6565b60786020525f908152604090208054600182015460029092015467ffffffffffffffff808316936801000000000000000090930416919084565b6040805167ffffffffffffffff95861681529490931660208501529183015260608201526080016104a7565b607954610492907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104f9613183565b60335473ffffffffffffffffffffffffffffffffffffffff16610572565b6104f961090f366004616278565b61324f565b6104c3613292565b6104f961092a366004616203565b6133e5565b6104f961093d366004616278565b613495565b6104f9610950366004616278565b6134e4565b6104f9610963366004616278565b613660565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b6104f961099d36600461648d565b613766565b6104927f000000000000000000000000000000000000000000000000000000000000000081565b606f546109e4906901000000000000000000900461ffff1681565b60405161ffff90911681526020016104a7565b610a37610a05366004616278565b60726020525f90815260409020805460019091015467ffffffffffffffff808216916801000000000000000090041683565b6040805193845267ffffffffffffffff92831660208501529116908201526060016104a7565b6104f9610a6b366004616278565b61382a565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b610508610aa53660046164a6565b61383b565b6104f9610ab83660046164bd565b6138c3565b6104926138db565b607b546104929074010000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104f9610aff3660046164bd565b61392e565b606f54610572906b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b6104f9610b6836600461652d565b6139bb565b6104f9610b7b3660046165d8565b613ef9565b60795461049290700100000000000000000000000000000000900467ffffffffffffffff1681565b6104f9614494565b6104f9610bbe366004616617565b614568565b607354610492907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b6104f9610c28366004616661565b6145f7565b607b54610508907c0100000000000000000000000000000000000000000000000000000000900460ff1681565b6104f9610c6836600461648d565b6149e7565b6104f9610c7b36600461648d565b614ab9565b607a546105729073ffffffffffffffffffffffffffffffffffffffff1681565b6104c360705481565b6104f9610cb73660046166a9565b614b6d565b5f805f610cc76138db565b905067ffffffffffffffff881615610e935760795467ffffffffffffffff9081169089161115610da4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605860248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2070656e60448201527f64696e6753746174654e756d206d757374206265206c657373206f722065717560648201527f616c207468616e206c61737450656e64696e6753746174650000000000000000608482015260a4015b60405180910390fd5b67ffffffffffffffff8089165f908152607860205260409020600281015481549094509091898116680100000000000000009092041614610e8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206d61746368207468652070656e64696e6760648201527f2073746174652062617463680000000000000000000000000000000000000000608482015260a401610d9b565b5061102b565b67ffffffffffffffff87165f90815260756020526040902054915081610f61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d426174636820737461746520726f6f7420646f6573206e6f7420657860648201527f6973740000000000000000000000000000000000000000000000000000000000608482015260a401610d9b565b8067ffffffffffffffff168767ffffffffffffffff16111561102b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605d60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206265206c657373206f7220657175616c2060648201527f7468616e2063757272656e744c61737456657269666965644261746368000000608482015260a401610d9b565b8067ffffffffffffffff168667ffffffffffffffff16116110f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605760248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2066696e60448201527f616c4e65774261746368206d75737420626520626967676572207468616e206360648201527f757272656e744c61737456657269666965644261746368000000000000000000608482015260a401610d9b565b5f61110288888886896118de565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028360405161113691906166d3565b602060405180830381855afa158015611151573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061117491906166ee565b61117e9190616732565b9a9950505050505050505050565b6077805461119990616745565b80601f01602080910402602001604051908101604052809291908181526020018280546111c590616745565b80156112105780601f106111e757610100808354040283529160200191611210565b820191905f5260205f20905b8154815290600101906020018083116111f357829003601f168201915b505050505081565b611220614b8f565b5f8061122a6138db565b905067ffffffffffffffff8a16156113f15760795467ffffffffffffffff908116908b161115611302576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605860248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2070656e60448201527f64696e6753746174654e756d206d757374206265206c657373206f722065717560648201527f616c207468616e206c61737450656e64696e6753746174650000000000000000608482015260a401610d9b565b67ffffffffffffffff808b165f9081526078602052604090206002810154815490945090918b81166801000000000000000090920416146113eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206d61746368207468652070656e64696e6760648201527f2073746174652062617463680000000000000000000000000000000000000000608482015260a401610d9b565b50611589565b67ffffffffffffffff89165f908152607560205260409020549150816114bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d426174636820737461746520726f6f7420646f6573206e6f7420657860648201527f6973740000000000000000000000000000000000000000000000000000000000608482015260a401610d9b565b8067ffffffffffffffff168967ffffffffffffffff161115611589576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605d60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206265206c657373206f7220657175616c2060648201527f7468616e2063757272656e744c61737456657269666965644261746368000000608482015260a401610d9b565b8067ffffffffffffffff168867ffffffffffffffff1611611652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605760248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2066696e60448201527f616c4e65774261746368206d75737420626520626967676572207468616e206360648201527f757272656e744c61737456657269666965644261746368000000000000000000608482015260a401610d9b565b5f6116608a8a8a868b6118de565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8c81169182179092555f90815260756020526040902089905560795491925016156116dd57607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018990527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611762575f80fd5b505af1158015611774573d5f803e3d5ffd5b505060405189815233925067ffffffffffffffff8c1691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe9060200160405180910390a35050505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611817576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88161ffff16108061183057506103ff8161ffff16115b15611867576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffff16690100000000000000000061ffff8416908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a150565b67ffffffffffffffff8086165f818152607260205260408082205493881682529020546060929115801590611911575081155b15611948576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8061197f576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119888461383b565b6119be576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b166020820152603481019690965260548601929092527fffffffffffffffff00000000000000000000000000000000000000000000000060c098891b811660748701527f0000000000000000000000000000000000000000000000000000000000000000891b8116607c8701527f0000000000000000000000000000000000000000000000000000000000000000891b81166084870152608c86019490945260ac85015260cc840194909452509290931b90911660ec830152805180830360d401815260f4909201905290565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611b11576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b1f868686868686614c10565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615611b9957607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611c1e575f80fd5b505af1158015611c30573d5f803e3d5ffd5b505060405184815233925067ffffffffffffffff871691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe906020015b60405180910390a3505050505050565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611cdb576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cea87878787878787614fcb565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615611d6457607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611de9575f80fd5b505af1158015611dfb573d5f803e3d5ffd5b50506079805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a800000000000000000000000000000000000000000000000001790555050604051828152339067ffffffffffffffff8616907fcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf729060200160405180910390a350505050505050565b60795467ffffffffffffffff8281165f9081526078602052604081205490924292611ec992700100000000000000000000000000000000909204811691166167c3565b67ffffffffffffffff16111592915050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611f2c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611f73576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff16611fe25760795467ffffffffffffffff7801000000000000000000000000000000000000000000000000909104811690821610611fe2576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a1906020016118d3565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461210657606f5460ff16156120c7576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120d081611e86565b612106576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61210f816153fa565b50565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612163576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff821611156121aa576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661221557607b5467ffffffffffffffff74010000000000000000000000000000000000000000909104811690821610612215576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020016118d3565b6076805461119990616745565b606f5460ff16156122e0576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314612340576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81900361237b576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156123b7576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f81815260726020526040812054838516949293700100000000000000000000000000000000909304909216919082905b868110156127ff575f8a8a8381811061241d5761241d6167eb565b905060200281019061242f9190616818565b6124389061684a565b8051805160209091012060608201519192509067ffffffffffffffff16156125ad5785612464816168d4565b9650505f81836020015184606001516040516020016124bb93929190928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f90815260719093529120549091508114612543576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8088165f9081526071602052604080822091909155606085015190850151908216911610156125a7576040517f7f7ab87200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506126e7565b602082015115801590612671575060208201516040517f257b363200000000000000000000000000000000000000000000000000000000815260048101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063257b3632906024016020604051808303815f875af115801561264b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061266f91906166ee565b155b156126a8576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516201d4c010156126e7576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8767ffffffffffffffff16826040015167ffffffffffffffff16108061271a575042826040015167ffffffffffffffff16115b15612751576040517fea82791600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602082810151604080850151815193840189905290830184905260608084019290925260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c0160405160208183030381529060405280519060200120945081604001519750505080806127f7906168fa565b915050612402565b5061280a86856167c3565b60735490945067ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169084161115612873576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61287e8285616931565b6128929067ffffffffffffffff1688616952565b604080516060810182528581524267ffffffffffffffff908116602080840191825260738054680100000000000000009081900485168688019081528d86165f8181526072909552979093209551865592516001909501805492519585167fffffffffffffffffffffffffffffffff000000000000000000000000000000009384161795851684029590951790945583548c841691161793029290921790559091508281169085161461298757607380547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8716021790555b6129d933308360705461299a9190616965565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190615607565b6129e16156e9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612a46575f80fd5b505af1158015612a58573d5f803e3d5ffd5b505060405167ffffffffffffffff881692507f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce91505f90a250505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612aed576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b547c0100000000000000000000000000000000000000000000000000000000900460ff16612b49576040517ff6ba91a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690556040517f854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f905f90a1565b5f6070546064612bab9190616965565b905090565b606f5460ff1615612bed576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff8581165f908152607260205260409020600101544292612c39927801000000000000000000000000000000000000000000000000909104811691166167c3565b67ffffffffffffffff161115612c7b576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8612c888686616931565b67ffffffffffffffff161115612cca576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612cd8868686868686614c10565b612ce184615794565b607954700100000000000000000000000000000000900467ffffffffffffffff165f03612e2257607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615612d8257607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015612e07575f80fd5b505af1158015612e19573d5f803e3d5ffd5b50505050612ef0565b612e2a6156e9565b6079805467ffffffffffffffff16905f612e43836168d4565b825467ffffffffffffffff9182166101009390930a92830292820219169190911790915560408051608081018252428316815287831660208083019182528284018981526060840189815260795487165f908152607890935294909120925183549251861668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169516949094171781559151600183015551600290910155505b604051828152339067ffffffffffffffff8616907f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596690602001611c6e565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612f7f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fff0000000000000000000000000000000000000000ffffffffffffffffffffff166b01000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0906020016118d3565b61300b614b8f565b6130145f61596e565b565b60335473ffffffffffffffffffffffffffffffffffffffff16331461317b575f61303e6138db565b90508067ffffffffffffffff168267ffffffffffffffff161161308d576040517f812a372d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000909104811690831611806130d2575067ffffffffffffffff8083165f9081526072602052604090206001015416155b15613109576040517f98c5c01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8083165f9081526072602052604090206001015442916131379162093a8091166167c3565b67ffffffffffffffff161115613179576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b61210f6159e4565b607b5473ffffffffffffffffffffffffffffffffffffffff1633146131d4576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b54607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691821790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b613257614b8f565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561331e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061334291906166ee565b90505f61334d6138db565b60735467ffffffffffffffff6801000000000000000082048116916133a59170010000000000000000000000000000000082048116917801000000000000000000000000000000000000000000000000900416616931565b6133af91906167c3565b6133b99190616931565b67ffffffffffffffff169050805f036133d4575f9250505090565b6133de818361697c565b9250505090565b606f5460ff1615613422576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61343187878787878787614fcb565b67ffffffffffffffff84165f908152607560209081526040918290205482519081529081018490527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a161348c6159e4565b50505050505050565b61349d614b8f565b6073805467ffffffffffffffff90921668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff909216919091179055565b607a5473ffffffffffffffffffffffffffffffffffffffff163314613535576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff8216111561357c576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff166135e35760795467ffffffffffffffff7001000000000000000000000000000000009091048116908216106135e3576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607980547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c75906020016118d3565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146136b1576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620151808167ffffffffffffffff1611156136f8576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1661010067ffffffffffffffff8416908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c28906020016118d3565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146137b7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce6906020016118d3565b613832614b8f565b61210f81615794565b5f67ffffffff0000000167ffffffffffffffff8316108015613872575067ffffffff00000001604083901c67ffffffffffffffff16105b8015613893575067ffffffff00000001608083901c67ffffffffffffffff16105b80156138aa575067ffffffff0000000160c083901c105b156138b757506001919050565b505f919050565b919050565b6138cb614b8f565b60776138d782826169dc565b5050565b6079545f9067ffffffffffffffff161561391d575060795467ffffffffffffffff9081165f908152607860205260409020546801000000000000000090041690565b5060745467ffffffffffffffff1690565b607a5473ffffffffffffffffffffffffffffffffffffffff16331461397f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607661398b82826169dc565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20816040516118d39190616068565b5f54610100900460ff16158080156139d957505f54600160ff909116105b806139f25750303b1580156139f257505f5460ff166001145b613a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d9b565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015613ada575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b613ae7602088018861648d565b607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055613b3c604088016020890161648d565b606f805473ffffffffffffffffffffffffffffffffffffffff929092166b010000000000000000000000027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055613ba1608088016060890161648d565b6074805473ffffffffffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9092169190911790555f805260756020527ff9e3fbf150b7a0077118526f473c53cb4734f166167e2c6213e3567dd390b4ad8690556076613c2b86826169dc565b506077613c3885826169dc565b5062093a80613c4d6060890160408a01616278565b67ffffffffffffffff161115613c8f576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613c9f6060880160408901616278565b6079805467ffffffffffffffff92909216700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905562093a80613d0160a0890160808a01616278565b67ffffffffffffffff161115613d43576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d5360a0880160808901616278565b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff939093169290920291909117905567016345785d8a0000607055606f80547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff166a03ea000000000000070800179055607b80547fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff167c0100000000000697800000000000000000000000000000000000000000179055613e32615a67565b7fed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd65f7f00000000000000000000000000000000000000000000000000000000000000008585604051613e879493929190616b3b565b60405180910390a1801561348c575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff1615613f56576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1615613f93576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f819003613fce576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e881111561400a576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff78010000000000000000000000000000000000000000000000008204811691614055918491700100000000000000000000000000000000900416616b72565b111561408d576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f8181526072602052604081205491937001000000000000000000000000000000009004909216915b84811015614332575f8787838181106140eb576140eb6167eb565b90506020028101906140fd9190616b85565b61410690616bb7565b905083614112816168d4565b825180516020918201208185015160408087015190519499509194505f936141739386939101928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f908152607190935291205490915081146141fb576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f9081526071602052604081205561421f600189616952565b840361428e5742607b60149054906101000a900467ffffffffffffffff16846040015161424c91906167c3565b67ffffffffffffffff16111561428e576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020838101516040805192830188905282018490526060808301919091524260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016608083015233901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c01604051602081830303815290604052805190602001209450505050808061432a906168fa565b9150506140d0565b5061433d84846167c3565b6073805467ffffffffffffffff4281167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217808455604080516060810182528781526020808201958652680100000000000000009384900485168284019081528589165f818152607290935284832093518455965160019390930180549151871686027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921693871693909317179091558554938916700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff938602939093167fffffffffffffffff00000000000000000000000000000000ffffffffffffffff90941693909317919091179093559151929550917f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a49190a2505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146144e5576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dbc169766040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561454a575f80fd5b505af115801561455c573d5f803e3d5ffd5b50505050613014615b06565b614570614b8f565b6040805160608101825293845267ffffffffffffffff92831660208086019182529284168583019081529584165f908152607290935291209251835551600190920180549351821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169290911691909117919091179055565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff1615614654576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1615614691576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61469a612b9b565b9050818111156146d6576040517f4732fdb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388831115614712576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61475473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084615607565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156147be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906147e291906166ee565b60738054919250780100000000000000000000000000000000000000000000000090910467ffffffffffffffff1690601861481c836168d4565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508484604051614853929190616c30565b60408051918290038220602083015281018290527fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b166060820152606801604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206073547801000000000000000000000000000000000000000000000000900467ffffffffffffffff165f9081526071909352912055323303614981576073546040805183815233602082015260609181018290525f91810191909152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319060800160405180910390a26149e0565b607360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931823388886040516149d79493929190616c3f565b60405180910390a25b5050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314614a38576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607480547fffffffff0000000000000000000000000000000000000000ffffffffffffffff166801000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527f61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca906020016118d3565b614ac1614b8f565b73ffffffffffffffffffffffffffffffffffffffff8116614b64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610d9b565b61210f8161596e565b614b75614b8f565b67ffffffffffffffff165f90815260756020526040902055565b60335473ffffffffffffffffffffffffffffffffffffffff163314613014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d9b565b5f80614c1a6138db565b905067ffffffffffffffff881615614ce95760795467ffffffffffffffff9081169089161115614c76576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8089165f908152607860205260409020600281015481549094509091898116680100000000000000009092041614614ce3576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50614d89565b67ffffffffffffffff87165f90815260756020526040902054915081614d3b576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff161115614d89576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168667ffffffffffffffff1611614dd6576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f614de488888886896118de565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051614e1891906166d3565b602060405180830381855afa158015614e33573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190614e5691906166ee565b614e609190616732565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a91614ee291899190600401616c74565b602060405180830381865afa158015614efd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614f219190616cae565b614f57576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fbf33614f65858b616931565b67ffffffffffffffff16614f77613292565b614f819190616965565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190615b94565b50505050505050505050565b5f67ffffffffffffffff8816156150975760795467ffffffffffffffff9081169089161115615026576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5067ffffffffffffffff8088165f908152607860205260409020600281015481549092888116680100000000000000009092041614615091576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50615132565b5067ffffffffffffffff85165f90815260756020526040902054806150e8576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60745467ffffffffffffffff9081169087161115615132576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff908116908816118061516457508767ffffffffffffffff168767ffffffffffffffff1611155b8061518b575060795467ffffffffffffffff68010000000000000000909104811690881611155b156151c2576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8781165f90815260786020526040902054680100000000000000009004811690861614615224576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61523287878785886118de565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028360405161526691906166d3565b602060405180830381855afa158015615281573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906152a491906166ee565b6152ae9190616732565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a9161533091889190600401616c74565b602060405180830381865afa15801561534b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061536f9190616cae565b6153a5576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff89165f90815260786020526040902060020154859003614fbf576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff680100000000000000009091048116908216111580615434575060795467ffffffffffffffff908116908216115b1561546b576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8181165f81815260786020908152604080832080546074805468010000000000000000928390049098167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090981688179055600282015487865260759094529382902092909255607980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff169390940292909217909255600182015490517f33d6247d00000000000000000000000000000000000000000000000000000000815260048101919091529091907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015615599575f80fd5b505af11580156155ab573d5f803e3d5ffd5b505050508267ffffffffffffffff168167ffffffffffffffff167f328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e84600201546040516155fa91815260200190565b60405180910390a3505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526156e39085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152615bef565b50505050565b60795467ffffffffffffffff680100000000000000008204811691161115613014576079545f906157319068010000000000000000900467ffffffffffffffff1660016167c3565b905061573c81611e86565b1561210f576079545f9060029061575e90849067ffffffffffffffff16616931565b6157689190616ccd565b61577290836167c3565b905061577d81611e86565b1561578b576138d7816153fa565b6138d7826153fa565b5f61579d6138db565b9050815f806157ac8484616931565b606f5467ffffffffffffffff91821692505f916157cf9161010090041642616952565b90505b8467ffffffffffffffff168467ffffffffffffffff16146158595767ffffffffffffffff8085165f908152607260205260409020600181015490911682101561583757600181015468010000000000000000900467ffffffffffffffff169450615853565b6158418686616931565b67ffffffffffffffff16935050615859565b506157d2565b5f6158648484616952565b9050838110156158bb57808403600c811161587f5780615882565b600c5b9050806103e80a81606f60099054906101000a900461ffff1661ffff160a60705402816158b1576158b1616705565b046070555061592a565b838103600c81116158cc57806158cf565b600c5b90505f816103e80a82606f60099054906101000a900461ffff1661ffff160a670de0b6b3a7640000028161590557615905616705565b04905080607054670de0b6b3a7640000028161592357615923616705565b0460705550505b683635c9adc5dea00000607054111561594f57683635c9adc5dea0000060705561348c565b633b9aca00607054101561348c57633b9aca0060705550505050505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b158015615a49575f80fd5b505af1158015615a5b573d5f803e3d5ffd5b50505050613014615cfa565b5f54610100900460ff16615afd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d9b565b6130143361596e565b606f5460ff16615b42576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052615bea9084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401615661565b505050565b5f615c50826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16615d8c9092919063ffffffff16565b805190915015615bea5780806020019051810190615c6e9190616cae565b615bea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d9b565b606f5460ff1615615d37576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b6060615d9a84845f85615da2565b949350505050565b606082471015615e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d9b565b5f808673ffffffffffffffffffffffffffffffffffffffff168587604051615e5c91906166d3565b5f6040518083038185875af1925050503d805f8114615e96576040519150601f19603f3d011682016040523d82523d5f602084013e615e9b565b606091505b5091509150615eac87838387615eb7565b979650505050505050565b60608315615f4c5782515f03615f455773ffffffffffffffffffffffffffffffffffffffff85163b615f45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d9b565b5081615d9a565b615d9a8383815115615f615781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d9b9190616068565b803567ffffffffffffffff811681146138be575f80fd5b5f805f805f60a08688031215615fc0575f80fd5b615fc986615f95565b9450615fd760208701615f95565b9350615fe560408701615f95565b94979396509394606081013594506080013592915050565b5f5b83811015616017578181015183820152602001615fff565b50505f910152565b5f8151808452616036816020860160208601615ffd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61607a602083018461601f565b9392505050565b8060408101831015616091575f80fd5b92915050565b5f805f805f805f806101a0898b0312156160af575f80fd5b6160b889615f95565b97506160c660208a01615f95565b96506160d460408a01615f95565b955060608901359450608089013593506160f18a60a08b01616081565b925061016089018a811115616104575f80fd5b60e08a0192506161148b82616081565b9150509295985092959890939650565b5f60208284031215616134575f80fd5b813561ffff8116811461607a575f80fd5b5f805f805f60a08688031215616159575f80fd5b61616286615f95565b945061617060208701615f95565b94979496505050506040830135926060810135926080909101359150565b806103008101831015616091575f80fd5b5f805f805f806103a087890312156161b5575f80fd5b6161be87615f95565b95506161cc60208801615f95565b94506161da60408801615f95565b935060608701359250608087013591506161f78860a0890161618e565b90509295509295509295565b5f805f805f805f6103c0888a03121561621a575f80fd5b61622388615f95565b965061623160208901615f95565b955061623f60408901615f95565b945061624d60608901615f95565b93506080880135925060a0880135915061626a8960c08a0161618e565b905092959891949750929550565b5f60208284031215616288575f80fd5b61607a82615f95565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f8301126162cd575f80fd5b813567ffffffffffffffff808211156162e8576162e8616291565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561632e5761632e616291565b81604052838152866020858801011115616346575f80fd5b836020870160208301375f602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146138be575f80fd5b5f805f805f60a0868803121561639c575f80fd5b85359450602086013567ffffffffffffffff8111156163b9575f80fd5b6163c5888289016162be565b945050604086013592506163db60608701615f95565b91506163e960808701616365565b90509295509295909350565b5f8083601f840112616405575f80fd5b50813567ffffffffffffffff81111561641c575f80fd5b6020830191508360208260051b8501011115616436575f80fd5b9250929050565b5f805f6040848603121561644f575f80fd5b833567ffffffffffffffff811115616465575f80fd5b616471868287016163f5565b9094509250616484905060208501616365565b90509250925092565b5f6020828403121561649d575f80fd5b61607a82616365565b5f602082840312156164b6575f80fd5b5035919050565b5f602082840312156164cd575f80fd5b813567ffffffffffffffff8111156164e3575f80fd5b615d9a848285016162be565b5f8083601f8401126164ff575f80fd5b50813567ffffffffffffffff811115616516575f80fd5b602083019150836020828501011115616436575f80fd5b5f805f805f80868803610120811215616544575f80fd5b60a0811215616551575f80fd5b5086955060a0870135945060c087013567ffffffffffffffff80821115616576575f80fd5b6165828a838b016162be565b955060e0890135915080821115616597575f80fd5b6165a38a838b016162be565b94506101008901359150808211156165b9575f80fd5b506165c689828a016164ef565b979a9699509497509295939492505050565b5f80602083850312156165e9575f80fd5b823567ffffffffffffffff8111156165ff575f80fd5b61660b858286016163f5565b90969095509350505050565b5f805f806080858703121561662a575f80fd5b61663385615f95565b93506020850135925061664860408601615f95565b915061665660608601615f95565b905092959194509250565b5f805f60408486031215616673575f80fd5b833567ffffffffffffffff811115616689575f80fd5b616695868287016164ef565b909790965060209590950135949350505050565b5f80604083850312156166ba575f80fd5b823591506166ca60208401615f95565b90509250929050565b5f82516166e4818460208701615ffd565b9190910192915050565b5f602082840312156166fe575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f8261674057616740616705565b500690565b600181811c9082168061675957607f821691505b602082108103616790577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff8181168382160190808211156167e4576167e4616796565b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818336030181126166e4575f80fd5b5f6080823603121561685a575f80fd5b6040516080810167ffffffffffffffff828210818311171561687e5761687e616291565b816040528435915080821115616892575f80fd5b5061689f368286016162be565b825250602083013560208201526168b860408401615f95565b60408201526168c960608401615f95565b606082015292915050565b5f67ffffffffffffffff8083168181036168f0576168f0616796565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361692a5761692a616796565b5060010190565b67ffffffffffffffff8281168282160390808211156167e4576167e4616796565b8181038181111561609157616091616796565b808202811582820484141761609157616091616796565b5f8261698a5761698a616705565b500490565b601f821115615bea575f81815260208120601f850160051c810160208610156169b55750805b601f850160051c820191505b818110156169d4578281556001016169c1565b505050505050565b815167ffffffffffffffff8111156169f6576169f6616291565b616a0a81616a048454616745565b8461698f565b602080601f831160018114616a5c575f8415616a265750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556169d4565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015616aa857888601518255948401946001909101908401616a89565b5085821015616ae457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f67ffffffffffffffff808716835280861660208401525060606040830152616b68606083018486616af4565b9695505050505050565b8082018082111561609157616091616796565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126166e4575f80fd5b5f60608236031215616bc7575f80fd5b6040516060810167ffffffffffffffff8282108183111715616beb57616beb616291565b816040528435915080821115616bff575f80fd5b50616c0c368286016162be565b82525060208301356020820152616c2560408401615f95565b604082015292915050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201525f616b68606083018486616af4565b6103208101610300808584378201835f5b6001811015616ca4578151835260209283019290910190600101616c85565b5050509392505050565b5f60208284031215616cbe575f80fd5b8151801515811461607a575f80fd5b5f67ffffffffffffffff80841680616ce757616ce7616705565b9216919091049291505056fea264697066735822122009e03fb16d1dca934eb1a5f515609cdcf05c6112fcca4f18507a4541ffa9178b64736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610475575f3560e01c80638c3d73011161025d578063c754c7ed11610148578063e7a7ed02116100c3578063f14916d611610093578063f851a44011610079578063f851a44014610c80578063f8b823e414610ca0578063fe16564f14610ca9575f80fd5b8063f14916d614610c5a578063f2fde38b14610c6d575f80fd5b8063e7a7ed0214610bc3578063e8bf92ed14610bf3578063eaeb077b14610c1a578063ed6b010414610c2d575f80fd5b8063d2e129f911610118578063d939b315116100fe578063d939b31514610b80578063dbc1697614610ba8578063e0d1744114610bb0575f80fd5b8063d2e129f914610b5a578063d8d1091b14610b6d575f80fd5b8063c754c7ed14610ac5578063c89e42df14610af1578063cfa8ed4714610b04578063d02103ca14610b33575f80fd5b8063ada8f919116101d8578063b4f77ea9116101a8578063ba58ae391161018e578063ba58ae3914610a97578063c0cad30214610aaa578063c0ed84e014610abd575f80fd5b8063b4f77ea914610a5d578063b6b0b09714610a70575f80fd5b8063ada8f9191461098f578063adc879e9146109a2578063afd23cbe146109c9578063b4d63f58146109f7575f80fd5b80639aa972a31161022d5780639c9f3dfe116102135780639c9f3dfe14610942578063a066215c14610955578063a3c573eb14610968575f80fd5b80639aa972a31461091c5780639b7967601461092f575f80fd5b80638c3d7301146108db5780638da5cb5b146108e357806396dc3d391461090157806399f5634e14610914575f80fd5b80634a1a89a71161037d578063621dd411116102f85780637215541a116102c8578063831c7ead116102ae578063831c7ead14610810578063837a473814610837578063841b24d7146108ab575f80fd5b80637215541a146107e95780637fcb3653146107fc575f80fd5b8063621dd4111461079c5780636b8616ce146107af5780636ff512cc146107ce578063715018a6146107e1575f80fd5b8063542028d51161034d5780635e9145c9116103335780635e9145c9146107795780635ec919581461078c5780636046916914610794575f80fd5b8063542028d5146106d0578063574f649e146106d8575f80fd5b80634a1a89a71461066b5780634a910e6a1461068b5780634e4877061461069e5780635392c5e0146106b1575f80fd5b8063267822471161040d578063383b3be8116103dd578063423fa856116103c3578063423fa8561461060f578063456052671461062f578063458c047714610657575f80fd5b8063383b3be8146105e9578063394218e9146105fc575f80fd5b8063267822471461055257806329878983146105975780632b0006fa146105c35780632c1f816a146105d6575f80fd5b806315064c961161044857806315064c96146104fb5780631816b7e51461051857806319d8ac611461052b578063220d78991461053f575f80fd5b80630a0d9fbe146104795780630eaa86ea146104b0578063107bf28c146104d157806310a01a72146104e6575b5f80fd5b606f5461049290610100900467ffffffffffffffff1681565b60405167ffffffffffffffff90911681526020015b60405180910390f35b6104c36104be366004615fac565b610cbc565b6040519081526020016104a7565b6104d961118c565b6040516104a79190616068565b6104f96104f4366004616097565b611218565b005b606f546105089060ff1681565b60405190151581526020016104a7565b6104f9610526366004616124565b6117c6565b6073546104929067ffffffffffffffff1681565b6104d961054d366004616145565b6118de565b607b546105729073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016104a7565b6074546105729068010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6104f96105d136600461619f565b611ab4565b6104f96105e4366004616203565b611c7e565b6105086105f7366004616278565b611e86565b6104f961060a366004616278565b611edb565b6073546104929068010000000000000000900467ffffffffffffffff1681565b60735461049290700100000000000000000000000000000000900467ffffffffffffffff1681565b6079546104929067ffffffffffffffff1681565b6079546104929068010000000000000000900467ffffffffffffffff1681565b6104f9610699366004616278565b61205f565b6104f96106ac366004616278565b612112565b6104c36106bf366004616278565b60756020525f908152604090205481565b6104d9612296565b6104c36106e6366004616388565b835160209485012060408051808701979097528681019190915260608087019490945260c09290921b7fffffffffffffffff00000000000000000000000000000000000000000000000016608086015290911b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660888401528051808403607c018152609c9093019052815191012090565b6104f961078736600461643d565b6122a3565b6104f9612a9c565b6104c3612b9b565b6104f96107aa36600461619f565b612bb0565b6104c36107bd366004616278565b60716020525f908152604090205481565b6104f96107dc36600461648d565b612f2e565b6104f9613003565b6104f96107f7366004616278565b613016565b6074546104929067ffffffffffffffff1681565b6104927f000000000000000000000000000000000000000000000000000000000000000081565b61087f6108453660046164a6565b60786020525f908152604090208054600182015460029092015467ffffffffffffffff808316936801000000000000000090930416919084565b6040805167ffffffffffffffff95861681529490931660208501529183015260608201526080016104a7565b607954610492907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104f9613183565b60335473ffffffffffffffffffffffffffffffffffffffff16610572565b6104f961090f366004616278565b61324f565b6104c3613292565b6104f961092a366004616203565b6133e5565b6104f961093d366004616278565b613495565b6104f9610950366004616278565b6134e4565b6104f9610963366004616278565b613660565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b6104f961099d36600461648d565b613766565b6104927f000000000000000000000000000000000000000000000000000000000000000081565b606f546109e4906901000000000000000000900461ffff1681565b60405161ffff90911681526020016104a7565b610a37610a05366004616278565b60726020525f90815260409020805460019091015467ffffffffffffffff808216916801000000000000000090041683565b6040805193845267ffffffffffffffff92831660208501529116908201526060016104a7565b6104f9610a6b366004616278565b61382a565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b610508610aa53660046164a6565b61383b565b6104f9610ab83660046164bd565b6138c3565b6104926138db565b607b546104929074010000000000000000000000000000000000000000900467ffffffffffffffff1681565b6104f9610aff3660046164bd565b61392e565b606f54610572906b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1681565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b6104f9610b6836600461652d565b6139bb565b6104f9610b7b3660046165d8565b613ef9565b60795461049290700100000000000000000000000000000000900467ffffffffffffffff1681565b6104f9614494565b6104f9610bbe366004616617565b614568565b607354610492907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1681565b6105727f000000000000000000000000000000000000000000000000000000000000000081565b6104f9610c28366004616661565b6145f7565b607b54610508907c0100000000000000000000000000000000000000000000000000000000900460ff1681565b6104f9610c6836600461648d565b6149e7565b6104f9610c7b36600461648d565b614ab9565b607a546105729073ffffffffffffffffffffffffffffffffffffffff1681565b6104c360705481565b6104f9610cb73660046166a9565b614b6d565b5f805f610cc76138db565b905067ffffffffffffffff881615610e935760795467ffffffffffffffff9081169089161115610da4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605860248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2070656e60448201527f64696e6753746174654e756d206d757374206265206c657373206f722065717560648201527f616c207468616e206c61737450656e64696e6753746174650000000000000000608482015260a4015b60405180910390fd5b67ffffffffffffffff8089165f908152607860205260409020600281015481549094509091898116680100000000000000009092041614610e8d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206d61746368207468652070656e64696e6760648201527f2073746174652062617463680000000000000000000000000000000000000000608482015260a401610d9b565b5061102b565b67ffffffffffffffff87165f90815260756020526040902054915081610f61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d426174636820737461746520726f6f7420646f6573206e6f7420657860648201527f6973740000000000000000000000000000000000000000000000000000000000608482015260a401610d9b565b8067ffffffffffffffff168767ffffffffffffffff16111561102b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605d60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206265206c657373206f7220657175616c2060648201527f7468616e2063757272656e744c61737456657269666965644261746368000000608482015260a401610d9b565b8067ffffffffffffffff168667ffffffffffffffff16116110f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605760248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2066696e60448201527f616c4e65774261746368206d75737420626520626967676572207468616e206360648201527f757272656e744c61737456657269666965644261746368000000000000000000608482015260a401610d9b565b5f61110288888886896118de565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028360405161113691906166d3565b602060405180830381855afa158015611151573d5f803e3d5ffd5b5050506040513d601f19601f8201168201806040525081019061117491906166ee565b61117e9190616732565b9a9950505050505050505050565b6077805461119990616745565b80601f01602080910402602001604051908101604052809291908181526020018280546111c590616745565b80156112105780601f106111e757610100808354040283529160200191611210565b820191905f5260205f20905b8154815290600101906020018083116111f357829003601f168201915b505050505081565b611220614b8f565b5f8061122a6138db565b905067ffffffffffffffff8a16156113f15760795467ffffffffffffffff908116908b161115611302576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605860248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2070656e60448201527f64696e6753746174654e756d206d757374206265206c657373206f722065717560648201527f616c207468616e206c61737450656e64696e6753746174650000000000000000608482015260a401610d9b565b67ffffffffffffffff808b165f9081526078602052604090206002810154815490945090918b81166801000000000000000090920416146113eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604c60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206d61746368207468652070656e64696e6760648201527f2073746174652062617463680000000000000000000000000000000000000000608482015260a401610d9b565b50611589565b67ffffffffffffffff89165f908152607560205260409020549150816114bf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604360248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d426174636820737461746520726f6f7420646f6573206e6f7420657860648201527f6973740000000000000000000000000000000000000000000000000000000000608482015260a401610d9b565b8067ffffffffffffffff168967ffffffffffffffff161115611589576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605d60248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a20696e6960448201527f744e756d4261746368206d757374206265206c657373206f7220657175616c2060648201527f7468616e2063757272656e744c61737456657269666965644261746368000000608482015260a401610d9b565b8067ffffffffffffffff168867ffffffffffffffff1611611652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152605760248201527f506f6c79676f6e5a6b45564d3a3a766572696679426174636865733a2066696e60448201527f616c4e65774261746368206d75737420626520626967676572207468616e206360648201527f757272656e744c61737456657269666965644261746368000000000000000000608482015260a401610d9b565b5f6116608a8a8a868b6118de565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8c81169182179092555f90815260756020526040902089905560795491925016156116dd57607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018990527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611762575f80fd5b505af1158015611774573d5f803e3d5ffd5b505060405189815233925067ffffffffffffffff8c1691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe9060200160405180910390a35050505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611817576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88161ffff16108061183057506103ff8161ffff16115b15611867576040517f4c2533c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffff0000ffffffffffffffffff16690100000000000000000061ffff8416908102919091179091556040519081527f7019933d795eba185c180209e8ae8bffbaa25bcef293364687702c31f4d302c5906020015b60405180910390a150565b67ffffffffffffffff8086165f818152607260205260408082205493881682529020546060929115801590611911575081155b15611948576040517f6818c29e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8061197f576040517f66385b5100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6119888461383b565b6119be576040517f176b913c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b166020820152603481019690965260548601929092527fffffffffffffffff00000000000000000000000000000000000000000000000060c098891b811660748701527f0000000000000000000000000000000000000000000000000000000000000000891b8116607c8701527f0000000000000000000000000000000000000000000000000000000000000000891b81166084870152608c86019490945260ac85015260cc840194909452509290931b90911660ec830152805180830360d401815260f4909201905290565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611b11576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611b1f868686868686614c10565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615611b9957607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611c1e575f80fd5b505af1158015611c30573d5f803e3d5ffd5b505060405184815233925067ffffffffffffffff871691507fcb339b570a7f0b25afa7333371ff11192092a0aeace12b671f4c212f2815c6fe906020015b60405180910390a3505050505050565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611cdb576040517fbbcbbc0500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611cea87878787878787614fcb565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615611d6457607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015611de9575f80fd5b505af1158015611dfb573d5f803e3d5ffd5b50506079805477ffffffffffffffffffffffffffffffffffffffffffffffff167a093a800000000000000000000000000000000000000000000000001790555050604051828152339067ffffffffffffffff8616907fcc1b5520188bf1dd3e63f98164b577c4d75c11a619ddea692112f0d1aec4cf729060200160405180910390a350505050505050565b60795467ffffffffffffffff8281165f9081526078602052604081205490924292611ec992700100000000000000000000000000000000909204811691166167c3565b67ffffffffffffffff16111592915050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314611f2c576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff82161115611f73576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff16611fe25760795467ffffffffffffffff7801000000000000000000000000000000000000000000000000909104811690821610611fe2576040517f401636df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527f1f4fa24c2e4bad19a7f3ec5c5485f70d46c798461c2e684f55bbd0fc661373a1906020016118d3565b60745468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff16331461210657606f5460ff16156120c7576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120d081611e86565b612106576040517f0ce9e4a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61210f816153fa565b50565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612163576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff821611156121aa576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1661221557607b5467ffffffffffffffff74010000000000000000000000000000000000000000909104811690821610612215576040517ff5e37f2f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fa7eb6cb8a613eb4e8bddc1ac3d61ec6cf10898760f0b187bcca794c6ca6fa40b906020016118d3565b6076805461119990616745565b606f5460ff16156122e0576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546b010000000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314612340576040517f11e7be1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815f81900361237b576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e88111156123b7576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f81815260726020526040812054838516949293700100000000000000000000000000000000909304909216919082905b868110156127ff575f8a8a8381811061241d5761241d6167eb565b905060200281019061242f9190616818565b6124389061684a565b8051805160209091012060608201519192509067ffffffffffffffff16156125ad5785612464816168d4565b9650505f81836020015184606001516040516020016124bb93929190928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff8a165f90815260719093529120549091508114612543576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8088165f9081526071602052604080822091909155606085015190850151908216911610156125a7576040517f7f7ab87200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506126e7565b602082015115801590612671575060208201516040517f257b363200000000000000000000000000000000000000000000000000000000815260048101919091527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063257b3632906024016020604051808303815f875af115801561264b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061266f91906166ee565b155b156126a8576040517f73bd668d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8151516201d4c010156126e7576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8767ffffffffffffffff16826040015167ffffffffffffffff16108061271a575042826040015167ffffffffffffffff16115b15612751576040517fea82791600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602082810151604080850151815193840189905290830184905260608084019290925260c01b7fffffffffffffffff0000000000000000000000000000000000000000000000001660808301528b901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c0160405160208183030381529060405280519060200120945081604001519750505080806127f7906168fa565b915050612402565b5061280a86856167c3565b60735490945067ffffffffffffffff780100000000000000000000000000000000000000000000000090910481169084161115612873576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61287e8285616931565b6128929067ffffffffffffffff1688616952565b604080516060810182528581524267ffffffffffffffff908116602080840191825260738054680100000000000000009081900485168688019081528d86165f8181526072909552979093209551865592516001909501805492519585167fffffffffffffffffffffffffffffffff000000000000000000000000000000009384161795851684029590951790945583548c841691161793029290921790559091508281169085161461298757607380547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8716021790555b6129d933308360705461299a9190616965565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016929190615607565b6129e16156e9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166379e2cf976040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612a46575f80fd5b505af1158015612a58573d5f803e3d5ffd5b505060405167ffffffffffffffff881692507f303446e6a8cb73c83dff421c0b1d5e5ce0719dab1bff13660fc254e58cc17fce91505f90a250505050505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612aed576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b547c0100000000000000000000000000000000000000000000000000000000900460ff16612b49576040517ff6ba91a100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690556040517f854dd6ce5a1445c4c54388b21cffd11cf5bba1b9e763aec48ce3da75d617412f905f90a1565b5f6070546064612bab9190616965565b905090565b606f5460ff1615612bed576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff8581165f908152607260205260409020600101544292612c39927801000000000000000000000000000000000000000000000000909104811691166167c3565b67ffffffffffffffff161115612c7b576040517f8a0704d300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e8612c888686616931565b67ffffffffffffffff161115612cca576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612cd8868686868686614c10565b612ce184615794565b607954700100000000000000000000000000000000900467ffffffffffffffff165f03612e2257607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff8681169182179092555f9081526075602052604090208390556079541615612d8257607980547fffffffffffffffffffffffffffffffff000000000000000000000000000000001690555b6040517f33d6247d000000000000000000000000000000000000000000000000000000008152600481018490527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015612e07575f80fd5b505af1158015612e19573d5f803e3d5ffd5b50505050612ef0565b612e2a6156e9565b6079805467ffffffffffffffff16905f612e43836168d4565b825467ffffffffffffffff9182166101009390930a92830292820219169190911790915560408051608081018252428316815287831660208083019182528284018981526060840189815260795487165f908152607890935294909120925183549251861668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009093169516949094171781559151600183015551600290910155505b604051828152339067ffffffffffffffff8616907f9c72852172521097ba7e1482e6b44b351323df0155f97f4ea18fcec28e1f596690602001611c6e565b607a5473ffffffffffffffffffffffffffffffffffffffff163314612f7f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fff0000000000000000000000000000000000000000ffffffffffffffffffffff166b01000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527ff54144f9611984021529f814a1cb6a41e22c58351510a0d9f7e822618abb9cc0906020016118d3565b61300b614b8f565b6130145f61596e565b565b60335473ffffffffffffffffffffffffffffffffffffffff16331461317b575f61303e6138db565b90508067ffffffffffffffff168267ffffffffffffffff161161308d576040517f812a372d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000909104811690831611806130d2575067ffffffffffffffff8083165f9081526072602052604090206001015416155b15613109576040517f98c5c01400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8083165f9081526072602052604090206001015442916131379162093a8091166167c3565b67ffffffffffffffff161115613179576040517fd257555a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b61210f6159e4565b607b5473ffffffffffffffffffffffffffffffffffffffff1633146131d4576040517fd1ec4b2300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b54607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691821790556040519081527f056dc487bbf0795d0bbb1b4f0af523a855503cff740bfb4d5475f7a90c091e8e9060200160405180910390a1565b613257614b8f565b607480547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff92909216919091179055565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201525f90819073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561331e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061334291906166ee565b90505f61334d6138db565b60735467ffffffffffffffff6801000000000000000082048116916133a59170010000000000000000000000000000000082048116917801000000000000000000000000000000000000000000000000900416616931565b6133af91906167c3565b6133b99190616931565b67ffffffffffffffff169050805f036133d4575f9250505090565b6133de818361697c565b9250505090565b606f5460ff1615613422576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61343187878787878787614fcb565b67ffffffffffffffff84165f908152607560209081526040918290205482519081529081018490527f1f44c21118c4603cfb4e1b621dbcfa2b73efcececee2b99b620b2953d33a7010910160405180910390a161348c6159e4565b50505050505050565b61349d614b8f565b6073805467ffffffffffffffff90921668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff909216919091179055565b607a5473ffffffffffffffffffffffffffffffffffffffff163314613535576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62093a8067ffffffffffffffff8216111561357c576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff166135e35760795467ffffffffffffffff7001000000000000000000000000000000009091048116908216106135e3576040517f48a05a9000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607980547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff1670010000000000000000000000000000000067ffffffffffffffff8416908102919091179091556040519081527fc4121f4e22c69632ebb7cf1f462be0511dc034f999b52013eddfb24aab765c75906020016118d3565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146136b1576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620151808167ffffffffffffffff1611156136f8576040517fe067dfe800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1661010067ffffffffffffffff8416908102919091179091556040519081527f1b023231a1ab6b5d93992f168fb44498e1a7e64cef58daff6f1c216de6a68c28906020016118d3565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146137b7576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fa5b56b7906fd0a20e3f35120dd8343db1e12e037a6c90111c7e42885e82a1ce6906020016118d3565b613832614b8f565b61210f81615794565b5f67ffffffff0000000167ffffffffffffffff8316108015613872575067ffffffff00000001604083901c67ffffffffffffffff16105b8015613893575067ffffffff00000001608083901c67ffffffffffffffff16105b80156138aa575067ffffffff0000000160c083901c105b156138b757506001919050565b505f919050565b919050565b6138cb614b8f565b60776138d782826169dc565b5050565b6079545f9067ffffffffffffffff161561391d575060795467ffffffffffffffff9081165f908152607860205260409020546801000000000000000090041690565b5060745467ffffffffffffffff1690565b607a5473ffffffffffffffffffffffffffffffffffffffff16331461397f576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607661398b82826169dc565b507f6b8f723a4c7a5335cafae8a598a0aa0301be1387c037dccc085b62add6448b20816040516118d39190616068565b5f54610100900460ff16158080156139d957505f54600160ff909116105b806139f25750303b1580156139f257505f5460ff166001145b613a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401610d9b565b5f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790558015613ada575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b613ae7602088018861648d565b607a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055613b3c604088016020890161648d565b606f805473ffffffffffffffffffffffffffffffffffffffff929092166b010000000000000000000000027fff0000000000000000000000000000000000000000ffffffffffffffffffffff909216919091179055613ba1608088016060890161648d565b6074805473ffffffffffffffffffffffffffffffffffffffff9290921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9092169190911790555f805260756020527ff9e3fbf150b7a0077118526f473c53cb4734f166167e2c6213e3567dd390b4ad8690556076613c2b86826169dc565b506077613c3885826169dc565b5062093a80613c4d6060890160408a01616278565b67ffffffffffffffff161115613c8f576040517fcc96507000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613c9f6060880160408901616278565b6079805467ffffffffffffffff92909216700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff90921691909117905562093a80613d0160a0890160808a01616278565b67ffffffffffffffff161115613d43576040517f1d06e87900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b613d5360a0880160808901616278565b6079805477ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000067ffffffffffffffff939093169290920291909117905567016345785d8a0000607055606f80547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000ff166a03ea000000000000070800179055607b80547fffffff000000000000000000ffffffffffffffffffffffffffffffffffffffff167c0100000000000697800000000000000000000000000000000000000000179055613e32615a67565b7fed7be53c9f1a96a481223b15568a5b1a475e01a74b347d6ca187c8bf0c078cd65f7f00000000000000000000000000000000000000000000000000000000000000008585604051613e879493929190616b3b565b60405180910390a1801561348c575f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff1615613f56576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1615613f93576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805f819003613fce576040517fcb591a5f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103e881111561400a576040517fb59f753a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff78010000000000000000000000000000000000000000000000008204811691614055918491700100000000000000000000000000000000900416616b72565b111561408d576040517fc630a00d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60735467ffffffffffffffff68010000000000000000820481165f8181526072602052604081205491937001000000000000000000000000000000009004909216915b84811015614332575f8787838181106140eb576140eb6167eb565b90506020028101906140fd9190616b85565b61410690616bb7565b905083614112816168d4565b825180516020918201208185015160408087015190519499509194505f936141739386939101928352602083019190915260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016604082015260480190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152815160209283012067ffffffffffffffff89165f908152607190935291205490915081146141fb576040517fce3d755e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff86165f9081526071602052604081205561421f600189616952565b840361428e5742607b60149054906101000a900467ffffffffffffffff16846040015161424c91906167c3565b67ffffffffffffffff16111561428e576040517fc44a082100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6020838101516040805192830188905282018490526060808301919091524260c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016608083015233901b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166088820152609c01604051602081830303815290604052805190602001209450505050808061432a906168fa565b9150506140d0565b5061433d84846167c3565b6073805467ffffffffffffffff4281167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217808455604080516060810182528781526020808201958652680100000000000000009384900485168284019081528589165f818152607290935284832093518455965160019390930180549151871686027fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921693871693909317179091558554938916700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff938602939093167fffffffffffffffff00000000000000000000000000000000ffffffffffffffff90941693909317919091179093559151929550917f648a61dd2438f072f5a1960939abd30f37aea80d2e94c9792ad142d3e0a490a49190a2505050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff1633146144e5576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663dbc169766040518163ffffffff1660e01b81526004015f604051808303815f87803b15801561454a575f80fd5b505af115801561455c573d5f803e3d5ffd5b50505050613014615b06565b614570614b8f565b6040805160608101825293845267ffffffffffffffff92831660208086019182529284168583019081529584165f908152607290935291209251835551600190920180549351821668010000000000000000027fffffffffffffffffffffffffffffffff000000000000000000000000000000009094169290911691909117919091179055565b607b547c0100000000000000000000000000000000000000000000000000000000900460ff1615614654576040517f24eff8c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f5460ff1615614691576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61469a612b9b565b9050818111156146d6576040517f4732fdb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611388831115614712576040517fa29a6c7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61475473ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084615607565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16633ed691ef6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156147be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906147e291906166ee565b60738054919250780100000000000000000000000000000000000000000000000090910467ffffffffffffffff1690601861481c836168d4565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550508484604051614853929190616c30565b60408051918290038220602083015281018290527fffffffffffffffff0000000000000000000000000000000000000000000000004260c01b166060820152606801604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301206073547801000000000000000000000000000000000000000000000000900467ffffffffffffffff165f9081526071909352912055323303614981576073546040805183815233602082015260609181018290525f91810191909152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16907ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc9319060800160405180910390a26149e0565b607360189054906101000a900467ffffffffffffffff1667ffffffffffffffff167ff94bb37db835f1ab585ee00041849a09b12cd081d77fa15ca070757619cbc931823388886040516149d79493929190616c3f565b60405180910390a25b5050505050565b607a5473ffffffffffffffffffffffffffffffffffffffff163314614a38576040517f4755657900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b607480547fffffffff0000000000000000000000000000000000000000ffffffffffffffff166801000000000000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527f61f8fec29495a3078e9271456f05fb0707fd4e41f7661865f80fc437d06681ca906020016118d3565b614ac1614b8f565b73ffffffffffffffffffffffffffffffffffffffff8116614b64576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610d9b565b61210f8161596e565b614b75614b8f565b67ffffffffffffffff165f90815260756020526040902055565b60335473ffffffffffffffffffffffffffffffffffffffff163314613014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610d9b565b5f80614c1a6138db565b905067ffffffffffffffff881615614ce95760795467ffffffffffffffff9081169089161115614c76576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8089165f908152607860205260409020600281015481549094509091898116680100000000000000009092041614614ce3576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50614d89565b67ffffffffffffffff87165f90815260756020526040902054915081614d3b576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168767ffffffffffffffff161115614d89576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8067ffffffffffffffff168667ffffffffffffffff1611614dd6576040517fb9b18f5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f614de488888886896118de565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600283604051614e1891906166d3565b602060405180830381855afa158015614e33573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190614e5691906166ee565b614e609190616732565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a91614ee291899190600401616c74565b602060405180830381865afa158015614efd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190614f219190616cae565b614f57576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b614fbf33614f65858b616931565b67ffffffffffffffff16614f77613292565b614f819190616965565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169190615b94565b50505050505050505050565b5f67ffffffffffffffff8816156150975760795467ffffffffffffffff9081169089161115615026576040517fbb14c20500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5067ffffffffffffffff8088165f908152607860205260409020600281015481549092888116680100000000000000009092041614615091576040517f2bd2e3e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50615132565b5067ffffffffffffffff85165f90815260756020526040902054806150e8576040517f4997b98600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60745467ffffffffffffffff9081169087161115615132576040517f1e56e9e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff908116908816118061516457508767ffffffffffffffff168767ffffffffffffffff1611155b8061518b575060795467ffffffffffffffff68010000000000000000909104811690881611155b156151c2576040517fbfa7079f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8781165f90815260786020526040902054680100000000000000009004811690861614615224576040517f32a2a77f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f61523287878785886118de565b90505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160028360405161526691906166d3565b602060405180830381855afa158015615281573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906152a491906166ee565b6152ae9190616732565b6040805160208101825282815290517f9121da8a00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001691639121da8a9161533091889190600401616c74565b602060405180830381865afa15801561534b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061536f9190616cae565b6153a5576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff89165f90815260786020526040902060020154859003614fbf576040517fa47276bd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60795467ffffffffffffffff680100000000000000009091048116908216111580615434575060795467ffffffffffffffff908116908216115b1561546b576040517fd086b70b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8181165f81815260786020908152604080832080546074805468010000000000000000928390049098167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090981688179055600282015487865260759094529382902092909255607980547fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff169390940292909217909255600182015490517f33d6247d00000000000000000000000000000000000000000000000000000000815260048101919091529091907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906333d6247d906024015f604051808303815f87803b158015615599575f80fd5b505af11580156155ab573d5f803e3d5ffd5b505050508267ffffffffffffffff168167ffffffffffffffff167f328d3c6c0fd6f1be0515e422f2d87e59f25922cbc2233568515a0c4bc3f8510e84600201546040516155fa91815260200190565b60405180910390a3505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526156e39085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152615bef565b50505050565b60795467ffffffffffffffff680100000000000000008204811691161115613014576079545f906157319068010000000000000000900467ffffffffffffffff1660016167c3565b905061573c81611e86565b1561210f576079545f9060029061575e90849067ffffffffffffffff16616931565b6157689190616ccd565b61577290836167c3565b905061577d81611e86565b1561578b576138d7816153fa565b6138d7826153fa565b5f61579d6138db565b9050815f806157ac8484616931565b606f5467ffffffffffffffff91821692505f916157cf9161010090041642616952565b90505b8467ffffffffffffffff168467ffffffffffffffff16146158595767ffffffffffffffff8085165f908152607260205260409020600181015490911682101561583757600181015468010000000000000000900467ffffffffffffffff169450615853565b6158418686616931565b67ffffffffffffffff16935050615859565b506157d2565b5f6158648484616952565b9050838110156158bb57808403600c811161587f5780615882565b600c5b9050806103e80a81606f60099054906101000a900461ffff1661ffff160a60705402816158b1576158b1616705565b046070555061592a565b838103600c81116158cc57806158cf565b600c5b90505f816103e80a82606f60099054906101000a900461ffff1661ffff160a670de0b6b3a7640000028161590557615905616705565b04905080607054670de0b6b3a7640000028161592357615923616705565b0460705550505b683635c9adc5dea00000607054111561594f57683635c9adc5dea0000060705561348c565b633b9aca00607054101561348c57633b9aca0060705550505050505050565b6033805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632072f6c56040518163ffffffff1660e01b81526004015f604051808303815f87803b158015615a49575f80fd5b505af1158015615a5b573d5f803e3d5ffd5b50505050613014615cfa565b5f54610100900460ff16615afd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e670000000000000000000000000000000000000000006064820152608401610d9b565b6130143361596e565b606f5460ff16615b42576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052615bea9084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401615661565b505050565b5f615c50826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16615d8c9092919063ffffffff16565b805190915015615bea5780806020019051810190615c6e9190616cae565b615bea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d9b565b606f5460ff1615615d37576040517f2f0047fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b6060615d9a84845f85615da2565b949350505050565b606082471015615e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d9b565b5f808673ffffffffffffffffffffffffffffffffffffffff168587604051615e5c91906166d3565b5f6040518083038185875af1925050503d805f8114615e96576040519150601f19603f3d011682016040523d82523d5f602084013e615e9b565b606091505b5091509150615eac87838387615eb7565b979650505050505050565b60608315615f4c5782515f03615f455773ffffffffffffffffffffffffffffffffffffffff85163b615f45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d9b565b5081615d9a565b615d9a8383815115615f615781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d9b9190616068565b803567ffffffffffffffff811681146138be575f80fd5b5f805f805f60a08688031215615fc0575f80fd5b615fc986615f95565b9450615fd760208701615f95565b9350615fe560408701615f95565b94979396509394606081013594506080013592915050565b5f5b83811015616017578181015183820152602001615fff565b50505f910152565b5f8151808452616036816020860160208601615ffd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081525f61607a602083018461601f565b9392505050565b8060408101831015616091575f80fd5b92915050565b5f805f805f805f806101a0898b0312156160af575f80fd5b6160b889615f95565b97506160c660208a01615f95565b96506160d460408a01615f95565b955060608901359450608089013593506160f18a60a08b01616081565b925061016089018a811115616104575f80fd5b60e08a0192506161148b82616081565b9150509295985092959890939650565b5f60208284031215616134575f80fd5b813561ffff8116811461607a575f80fd5b5f805f805f60a08688031215616159575f80fd5b61616286615f95565b945061617060208701615f95565b94979496505050506040830135926060810135926080909101359150565b806103008101831015616091575f80fd5b5f805f805f806103a087890312156161b5575f80fd5b6161be87615f95565b95506161cc60208801615f95565b94506161da60408801615f95565b935060608701359250608087013591506161f78860a0890161618e565b90509295509295509295565b5f805f805f805f6103c0888a03121561621a575f80fd5b61622388615f95565b965061623160208901615f95565b955061623f60408901615f95565b945061624d60608901615f95565b93506080880135925060a0880135915061626a8960c08a0161618e565b905092959891949750929550565b5f60208284031215616288575f80fd5b61607a82615f95565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f8301126162cd575f80fd5b813567ffffffffffffffff808211156162e8576162e8616291565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561632e5761632e616291565b81604052838152866020858801011115616346575f80fd5b836020870160208301375f602085830101528094505050505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146138be575f80fd5b5f805f805f60a0868803121561639c575f80fd5b85359450602086013567ffffffffffffffff8111156163b9575f80fd5b6163c5888289016162be565b945050604086013592506163db60608701615f95565b91506163e960808701616365565b90509295509295909350565b5f8083601f840112616405575f80fd5b50813567ffffffffffffffff81111561641c575f80fd5b6020830191508360208260051b8501011115616436575f80fd5b9250929050565b5f805f6040848603121561644f575f80fd5b833567ffffffffffffffff811115616465575f80fd5b616471868287016163f5565b9094509250616484905060208501616365565b90509250925092565b5f6020828403121561649d575f80fd5b61607a82616365565b5f602082840312156164b6575f80fd5b5035919050565b5f602082840312156164cd575f80fd5b813567ffffffffffffffff8111156164e3575f80fd5b615d9a848285016162be565b5f8083601f8401126164ff575f80fd5b50813567ffffffffffffffff811115616516575f80fd5b602083019150836020828501011115616436575f80fd5b5f805f805f80868803610120811215616544575f80fd5b60a0811215616551575f80fd5b5086955060a0870135945060c087013567ffffffffffffffff80821115616576575f80fd5b6165828a838b016162be565b955060e0890135915080821115616597575f80fd5b6165a38a838b016162be565b94506101008901359150808211156165b9575f80fd5b506165c689828a016164ef565b979a9699509497509295939492505050565b5f80602083850312156165e9575f80fd5b823567ffffffffffffffff8111156165ff575f80fd5b61660b858286016163f5565b90969095509350505050565b5f805f806080858703121561662a575f80fd5b61663385615f95565b93506020850135925061664860408601615f95565b915061665660608601615f95565b905092959194509250565b5f805f60408486031215616673575f80fd5b833567ffffffffffffffff811115616689575f80fd5b616695868287016164ef565b909790965060209590950135949350505050565b5f80604083850312156166ba575f80fd5b823591506166ca60208401615f95565b90509250929050565b5f82516166e4818460208701615ffd565b9190910192915050565b5f602082840312156166fe575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f8261674057616740616705565b500690565b600181811c9082168061675957607f821691505b602082108103616790577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b67ffffffffffffffff8181168382160190808211156167e4576167e4616796565b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff818336030181126166e4575f80fd5b5f6080823603121561685a575f80fd5b6040516080810167ffffffffffffffff828210818311171561687e5761687e616291565b816040528435915080821115616892575f80fd5b5061689f368286016162be565b825250602083013560208201526168b860408401615f95565b60408201526168c960608401615f95565b606082015292915050565b5f67ffffffffffffffff8083168181036168f0576168f0616796565b6001019392505050565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361692a5761692a616796565b5060010190565b67ffffffffffffffff8281168282160390808211156167e4576167e4616796565b8181038181111561609157616091616796565b808202811582820484141761609157616091616796565b5f8261698a5761698a616705565b500490565b601f821115615bea575f81815260208120601f850160051c810160208610156169b55750805b601f850160051c820191505b818110156169d4578281556001016169c1565b505050505050565b815167ffffffffffffffff8111156169f6576169f6616291565b616a0a81616a048454616745565b8461698f565b602080601f831160018114616a5c575f8415616a265750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556169d4565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015616aa857888601518255948401946001909101908401616a89565b5085821015616ae457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b5f67ffffffffffffffff808716835280861660208401525060606040830152616b68606083018486616af4565b9695505050505050565b8082018082111561609157616091616796565b5f82357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126166e4575f80fd5b5f60608236031215616bc7575f80fd5b6040516060810167ffffffffffffffff8282108183111715616beb57616beb616291565b816040528435915080821115616bff575f80fd5b50616c0c368286016162be565b82525060208301356020820152616c2560408401615f95565b604082015292915050565b818382375f9101908152919050565b84815273ffffffffffffffffffffffffffffffffffffffff84166020820152606060408201525f616b68606083018486616af4565b6103208101610300808584378201835f5b6001811015616ca4578151835260209283019290910190600101616c85565b5050509392505050565b5f60208284031215616cbe575f80fd5b8151801515811461607a575f80fd5b5f67ffffffffffffffff80841680616ce757616ce7616705565b9216919091049291505056fea264697066735822122009e03fb16d1dca934eb1a5f515609cdcf05c6112fcca4f18507a4541ffa9178b64736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/PolygonZkEVMTimelock.json b/compiled-contracts/PolygonZkEVMTimelock.json index 36a06c6db..23a7ef2c2 100644 --- a/compiled-contracts/PolygonZkEVMTimelock.json +++ b/compiled-contracts/PolygonZkEVMTimelock.json @@ -892,8 +892,8 @@ "type": "receive" } ], - "bytecode": "0x60a060405234801562000010575f80fd5b5060405162002c4d38038062002c4d833981016040819052620000339162000412565b84848484620000515f8051602062002bcd8339815191528062000232565b620000795f8051602062002bed8339815191525f8051602062002bcd83398151915262000232565b620000a15f8051602062002c0d8339815191525f8051602062002bcd83398151915262000232565b620000c95f8051602062002c2d8339815191525f8051602062002bcd83398151915262000232565b620000e35f8051602062002bcd833981519152306200027c565b6001600160a01b038116156200010d576200010d5f8051602062002bcd833981519152826200027c565b5f5b83518110156200019057620001555f8051602062002bed833981519152858381518110620001415762000141620004ad565b60200260200101516200027c60201b60201c565b6200017d5f8051602062002c2d833981519152858381518110620001415762000141620004ad565b6200018881620004c1565b90506200010f565b505f5b8251811015620001d857620001c55f8051602062002c0d833981519152848381518110620001415762000141620004ad565b620001d081620004c1565b905062000193565b506002849055604080515f8152602081018690527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1505050506001600160a01b031660805250620004e692505050565b5f82815260208190526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6200028882826200028c565b5050565b5f828152602081815260408083206001600160a01b038516845290915290205460ff1662000288575f828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620002e63390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b634e487b7160e01b5f52604160045260245ffd5b6001600160a01b038116811462000353575f80fd5b50565b805162000363816200033e565b919050565b5f82601f83011262000378575f80fd5b815160206001600160401b03808311156200039757620003976200032a565b8260051b604051601f19603f83011681018181108482111715620003bf57620003bf6200032a565b604052938452858101830193838101925087851115620003dd575f80fd5b83870191505b848210156200040757620003f78262000356565b83529183019190830190620003e3565b979650505050505050565b5f805f805f60a0868803121562000427575f80fd5b855160208701519095506001600160401b038082111562000446575f80fd5b6200045489838a0162000368565b955060408801519150808211156200046a575f80fd5b50620004798882890162000368565b93505060608601516200048c816200033e565b60808701519092506200049f816200033e565b809150509295509295909350565b634e487b7160e01b5f52603260045260245ffd5b5f60018201620004df57634e487b7160e01b5f52601160045260245ffd5b5060010190565b6080516126c06200050d5f395f818161040201528181611124015261116401526126c05ff3fe6080604052600436106101bd575f3560e01c806364d62353116100f2578063b1c5f42711610092578063d547741f11610062578063d547741f1461063a578063e38335e514610659578063f23a6e611461066c578063f27a0c92146106b0575f80fd5b8063b1c5f4271461058d578063bc197c81146105ac578063c4d252f5146105f0578063d45c44351461060f575f80fd5b80638f61f4f5116100cd5780638f61f4f5146104c557806391d14854146104f8578063a217fddf14610547578063b08e51c01461055a575f80fd5b806364d62353146104685780638065657f146104875780638f2a0bb0146104a6575f80fd5b8063248a9ca31161015d57806331d507501161013857806331d50750146103b357806336568abe146103d25780633a6aae72146103f1578063584b153e14610449575f80fd5b8063248a9ca3146103375780632ab0f529146103655780632f2ff15d14610394575f80fd5b80630d3cf6fc116101985780630d3cf6fc1461025e578063134008d31461029157806313bc9f20146102a4578063150b7a02146102c3575f80fd5b806301d5062a146101c857806301ffc9a7146101e957806307bd02651461021d575f80fd5b366101c457005b5f80fd5b3480156101d3575f80fd5b506101e76101e2366004611bf6565b6106c4565b005b3480156101f4575f80fd5b50610208610203366004611c65565b610757565b60405190151581526020015b60405180910390f35b348015610228575f80fd5b506102507fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610214565b348015610269575f80fd5b506102507f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101e761029f366004611ca4565b6107b2565b3480156102af575f80fd5b506102086102be366004611d0b565b6108a7565b3480156102ce575f80fd5b506103066102dd366004611e28565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610214565b348015610342575f80fd5b50610250610351366004611d0b565b5f9081526020819052604090206001015490565b348015610370575f80fd5b5061020861037f366004611d0b565b5f908152600160208190526040909120541490565b34801561039f575f80fd5b506101e76103ae366004611e8c565b6108cc565b3480156103be575f80fd5b506102086103cd366004611d0b565b6108f5565b3480156103dd575f80fd5b506101e76103ec366004611e8c565b61090d565b3480156103fc575f80fd5b506104247f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b348015610454575f80fd5b50610208610463366004611d0b565b6109c5565b348015610473575f80fd5b506101e7610482366004611d0b565b6109da565b348015610492575f80fd5b506102506104a1366004611ca4565b610aaa565b3480156104b1575f80fd5b506101e76104c0366004611ef7565b610ae8565b3480156104d0575f80fd5b506102507fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610503575f80fd5b50610208610512366004611e8c565b5f9182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b348015610552575f80fd5b506102505f81565b348015610565575f80fd5b506102507ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b348015610598575f80fd5b506102506105a7366004611fa0565b610d18565b3480156105b7575f80fd5b506103066105c63660046120be565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b3480156105fb575f80fd5b506101e761060a366004611d0b565b610d5c565b34801561061a575f80fd5b50610250610629366004611d0b565b5f9081526001602052604090205490565b348015610645575f80fd5b506101e7610654366004611e8c565b610e56565b6101e7610667366004611fa0565b610e7a565b348015610677575f80fd5b50610306610686366004612161565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106bb575f80fd5b50610250611121565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16106ee81611200565b5f6106fd898989898989610aaa565b9050610709818461120d565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a60405161074496959493929190612208565b60405180910390a3505050505050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107ac57506107ac82611359565b92915050565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661082e5761082e81336113ef565b5f61083d888888888888610aaa565b905061084981856114a6565b610855888888886115e2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a60405161088c9493929190612252565b60405180910390a361089d816116e2565b5050505050505050565b5f818152600160205260408120546001811180156108c55750428111155b9392505050565b5f828152602081905260409020600101546108e681611200565b6108f0838361178a565b505050565b5f8181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109c18282611878565b5050565b5f818152600160208190526040822054610906565b333014610a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109ae565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b5f868686868686604051602001610ac696959493929190612208565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b1281611200565b888714610ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b888514610c30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f610c418b8b8b8b8b8b8b8b610d18565b9050610c4d818461120d565b5f5b8a811015610d0a5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610c8c57610c8c612291565b9050602002016020810190610ca191906122be565b8d8d86818110610cb357610cb3612291565b905060200201358c8c87818110610ccc57610ccc612291565b9050602002810190610cde91906122d7565b8c8b604051610cf296959493929190612208565b60405180910390a3610d0381612365565b9050610c4f565b505050505050505050505050565b5f8888888888888888604051602001610d38989796959493929190612447565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610d8681611200565b610d8f826109c5565b610e1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109ae565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610e7081611200565b6108f08383611878565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610ef657610ef681336113ef565b878614610f85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b878414611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f6110258a8a8a8a8a8a8a8a610d18565b905061103181856114a6565b5f5b8981101561110b575f8b8b8381811061104e5761104e612291565b905060200201602081019061106391906122be565b90505f8a8a8481811061107857611078612291565b905060200201359050365f8a8a8681811061109557611095612291565b90506020028101906110a791906122d7565b915091506110b7848484846115e2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58868686866040516110ee9493929190612252565b60405180910390a3505050508061110490612365565b9050611033565b50611115816116e2565b50505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16158015906111ef57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ef919061250c565b156111f957505f90565b5060025490565b61120a81336113ef565b50565b611216826108f5565b156112a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109ae565b6112ab611121565b81101561133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109ae565b611344814261252b565b5f928352600160205260409092209190915550565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107ac57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107ac565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c15761142c8161192d565b61143783602061194c565b604051602001611448929190612560565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109ae916004016125e0565b6114af826108a7565b61153b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b80158061155657505f81815260016020819052604090912054145b6109c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f8473ffffffffffffffffffffffffffffffffffffffff1684848460405161160b929190612630565b5f6040518083038185875af1925050503d805f8114611645576040519150601f19603f3d011682016040523d82523d5f602084013e61164a565b606091505b50509050806116db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109ae565b5050505050565b6116eb816108a7565b611777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b5f90815260016020819052604090912055565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561181a3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107ac73ffffffffffffffffffffffffffffffffffffffff831660145b60605f61195a83600261263f565b61196590600261252b565b67ffffffffffffffff81111561197d5761197d611d22565b6040519080825280601f01601f1916602001820160405280156119a7576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106119dd576119dd612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a3f57611a3f612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f611a7984600261263f565b611a8490600161252b565b90505b6001811115611b20577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611ac557611ac5612291565b1a60f81b828281518110611adb57611adb612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535060049490941c93611b1981612656565b9050611a87565b5083156108c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109ae565b803573ffffffffffffffffffffffffffffffffffffffff81168114611bac575f80fd5b919050565b5f8083601f840112611bc1575f80fd5b50813567ffffffffffffffff811115611bd8575f80fd5b602083019150836020828501011115611bef575f80fd5b9250929050565b5f805f805f805f60c0888a031215611c0c575f80fd5b611c1588611b89565b965060208801359550604088013567ffffffffffffffff811115611c37575f80fd5b611c438a828b01611bb1565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f60208284031215611c75575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108c5575f80fd5b5f805f805f8060a08789031215611cb9575f80fd5b611cc287611b89565b955060208701359450604087013567ffffffffffffffff811115611ce4575f80fd5b611cf089828a01611bb1565b979a9699509760608101359660809091013595509350505050565b5f60208284031215611d1b575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d9657611d96611d22565b604052919050565b5f82601f830112611dad575f80fd5b813567ffffffffffffffff811115611dc757611dc7611d22565b611df860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611d4f565b818152846020838601011115611e0c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215611e3b575f80fd5b611e4485611b89565b9350611e5260208601611b89565b925060408501359150606085013567ffffffffffffffff811115611e74575f80fd5b611e8087828801611d9e565b91505092959194509250565b5f8060408385031215611e9d575f80fd5b82359150611ead60208401611b89565b90509250929050565b5f8083601f840112611ec6575f80fd5b50813567ffffffffffffffff811115611edd575f80fd5b6020830191508360208260051b8501011115611bef575f80fd5b5f805f805f805f805f60c08a8c031215611f0f575f80fd5b893567ffffffffffffffff80821115611f26575f80fd5b611f328d838e01611eb6565b909b50995060208c0135915080821115611f4a575f80fd5b611f568d838e01611eb6565b909950975060408c0135915080821115611f6e575f80fd5b50611f7b8c828d01611eb6565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f805f805f805f8060a0898b031215611fb7575f80fd5b883567ffffffffffffffff80821115611fce575f80fd5b611fda8c838d01611eb6565b909a50985060208b0135915080821115611ff2575f80fd5b611ffe8c838d01611eb6565b909850965060408b0135915080821115612016575f80fd5b506120238b828c01611eb6565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112612050575f80fd5b8135602067ffffffffffffffff82111561206c5761206c611d22565b8160051b61207b828201611d4f565b9283528481018201928281019087851115612094575f80fd5b83870192505b848310156120b35782358252918301919083019061209a565b979650505050505050565b5f805f805f60a086880312156120d2575f80fd5b6120db86611b89565b94506120e960208701611b89565b9350604086013567ffffffffffffffff80821115612105575f80fd5b61211189838a01612041565b94506060880135915080821115612126575f80fd5b61213289838a01612041565b93506080880135915080821115612147575f80fd5b5061215488828901611d9e565b9150509295509295909350565b5f805f805f60a08688031215612175575f80fd5b61217e86611b89565b945061218c60208701611b89565b93506040860135925060608601359150608086013567ffffffffffffffff8111156121b5575f80fd5b61215488828901611d9e565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a060408201525f61223d60a0830186886121c1565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201525f6122876060830184866121c1565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156122ce575f80fd5b6108c582611b89565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261230a575f80fd5b83018035915067ffffffffffffffff821115612324575f80fd5b602001915036819003821315611bef575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361239557612395612338565b5060010190565b8183525f6020808501808196508560051b81019150845f5b8781101561243a57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126123f2575f80fd5b8701858101903567ffffffffffffffff81111561240d575f80fd5b80360382131561241b575f80fd5b6124268682846121c1565b9a87019a95505050908401906001016123b4565b5091979650505050505050565b60a080825281018890525f8960c08301825b8b8110156124945773ffffffffffffffffffffffffffffffffffffffff61247f84611b89565b16825260209283019290910190600101612459565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8911156124cc575f80fd5b8860051b9150818a602083013701828103602090810160408501526124f4908201878961239c565b60608401959095525050608001529695505050505050565b5f6020828403121561251c575f80fd5b815180151581146108c5575f80fd5b808201808211156107ac576107ac612338565b5f5b83811015612558578181015183820152602001612540565b50505f910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f835161259781601785016020880161253e565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516125d481602884016020880161253e565b01602801949350505050565b602081525f82518060208401526125fe81604085016020870161253e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b818382375f9101908152919050565b80820281158282048414176107ac576107ac612338565b5f8161266457612664612338565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220e28ae7494480ab1c619fd775dc5ff665588c808a910d66178a982c2e7c76a1e664736f6c634300081400335f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5b09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63fd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783", - "deployedBytecode": "0x6080604052600436106101bd575f3560e01c806364d62353116100f2578063b1c5f42711610092578063d547741f11610062578063d547741f1461063a578063e38335e514610659578063f23a6e611461066c578063f27a0c92146106b0575f80fd5b8063b1c5f4271461058d578063bc197c81146105ac578063c4d252f5146105f0578063d45c44351461060f575f80fd5b80638f61f4f5116100cd5780638f61f4f5146104c557806391d14854146104f8578063a217fddf14610547578063b08e51c01461055a575f80fd5b806364d62353146104685780638065657f146104875780638f2a0bb0146104a6575f80fd5b8063248a9ca31161015d57806331d507501161013857806331d50750146103b357806336568abe146103d25780633a6aae72146103f1578063584b153e14610449575f80fd5b8063248a9ca3146103375780632ab0f529146103655780632f2ff15d14610394575f80fd5b80630d3cf6fc116101985780630d3cf6fc1461025e578063134008d31461029157806313bc9f20146102a4578063150b7a02146102c3575f80fd5b806301d5062a146101c857806301ffc9a7146101e957806307bd02651461021d575f80fd5b366101c457005b5f80fd5b3480156101d3575f80fd5b506101e76101e2366004611bf6565b6106c4565b005b3480156101f4575f80fd5b50610208610203366004611c65565b610757565b60405190151581526020015b60405180910390f35b348015610228575f80fd5b506102507fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610214565b348015610269575f80fd5b506102507f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101e761029f366004611ca4565b6107b2565b3480156102af575f80fd5b506102086102be366004611d0b565b6108a7565b3480156102ce575f80fd5b506103066102dd366004611e28565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610214565b348015610342575f80fd5b50610250610351366004611d0b565b5f9081526020819052604090206001015490565b348015610370575f80fd5b5061020861037f366004611d0b565b5f908152600160208190526040909120541490565b34801561039f575f80fd5b506101e76103ae366004611e8c565b6108cc565b3480156103be575f80fd5b506102086103cd366004611d0b565b6108f5565b3480156103dd575f80fd5b506101e76103ec366004611e8c565b61090d565b3480156103fc575f80fd5b506104247f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b348015610454575f80fd5b50610208610463366004611d0b565b6109c5565b348015610473575f80fd5b506101e7610482366004611d0b565b6109da565b348015610492575f80fd5b506102506104a1366004611ca4565b610aaa565b3480156104b1575f80fd5b506101e76104c0366004611ef7565b610ae8565b3480156104d0575f80fd5b506102507fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610503575f80fd5b50610208610512366004611e8c565b5f9182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b348015610552575f80fd5b506102505f81565b348015610565575f80fd5b506102507ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b348015610598575f80fd5b506102506105a7366004611fa0565b610d18565b3480156105b7575f80fd5b506103066105c63660046120be565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b3480156105fb575f80fd5b506101e761060a366004611d0b565b610d5c565b34801561061a575f80fd5b50610250610629366004611d0b565b5f9081526001602052604090205490565b348015610645575f80fd5b506101e7610654366004611e8c565b610e56565b6101e7610667366004611fa0565b610e7a565b348015610677575f80fd5b50610306610686366004612161565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106bb575f80fd5b50610250611121565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16106ee81611200565b5f6106fd898989898989610aaa565b9050610709818461120d565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a60405161074496959493929190612208565b60405180910390a3505050505050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107ac57506107ac82611359565b92915050565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661082e5761082e81336113ef565b5f61083d888888888888610aaa565b905061084981856114a6565b610855888888886115e2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a60405161088c9493929190612252565b60405180910390a361089d816116e2565b5050505050505050565b5f818152600160205260408120546001811180156108c55750428111155b9392505050565b5f828152602081905260409020600101546108e681611200565b6108f0838361178a565b505050565b5f8181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109c18282611878565b5050565b5f818152600160208190526040822054610906565b333014610a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109ae565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b5f868686868686604051602001610ac696959493929190612208565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b1281611200565b888714610ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b888514610c30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f610c418b8b8b8b8b8b8b8b610d18565b9050610c4d818461120d565b5f5b8a811015610d0a5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610c8c57610c8c612291565b9050602002016020810190610ca191906122be565b8d8d86818110610cb357610cb3612291565b905060200201358c8c87818110610ccc57610ccc612291565b9050602002810190610cde91906122d7565b8c8b604051610cf296959493929190612208565b60405180910390a3610d0381612365565b9050610c4f565b505050505050505050505050565b5f8888888888888888604051602001610d38989796959493929190612447565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610d8681611200565b610d8f826109c5565b610e1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109ae565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610e7081611200565b6108f08383611878565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610ef657610ef681336113ef565b878614610f85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b878414611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f6110258a8a8a8a8a8a8a8a610d18565b905061103181856114a6565b5f5b8981101561110b575f8b8b8381811061104e5761104e612291565b905060200201602081019061106391906122be565b90505f8a8a8481811061107857611078612291565b905060200201359050365f8a8a8681811061109557611095612291565b90506020028101906110a791906122d7565b915091506110b7848484846115e2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58868686866040516110ee9493929190612252565b60405180910390a3505050508061110490612365565b9050611033565b50611115816116e2565b50505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16158015906111ef57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ef919061250c565b156111f957505f90565b5060025490565b61120a81336113ef565b50565b611216826108f5565b156112a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109ae565b6112ab611121565b81101561133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109ae565b611344814261252b565b5f928352600160205260409092209190915550565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107ac57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107ac565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c15761142c8161192d565b61143783602061194c565b604051602001611448929190612560565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109ae916004016125e0565b6114af826108a7565b61153b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b80158061155657505f81815260016020819052604090912054145b6109c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f8473ffffffffffffffffffffffffffffffffffffffff1684848460405161160b929190612630565b5f6040518083038185875af1925050503d805f8114611645576040519150601f19603f3d011682016040523d82523d5f602084013e61164a565b606091505b50509050806116db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109ae565b5050505050565b6116eb816108a7565b611777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b5f90815260016020819052604090912055565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561181a3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107ac73ffffffffffffffffffffffffffffffffffffffff831660145b60605f61195a83600261263f565b61196590600261252b565b67ffffffffffffffff81111561197d5761197d611d22565b6040519080825280601f01601f1916602001820160405280156119a7576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106119dd576119dd612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a3f57611a3f612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f611a7984600261263f565b611a8490600161252b565b90505b6001811115611b20577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611ac557611ac5612291565b1a60f81b828281518110611adb57611adb612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535060049490941c93611b1981612656565b9050611a87565b5083156108c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109ae565b803573ffffffffffffffffffffffffffffffffffffffff81168114611bac575f80fd5b919050565b5f8083601f840112611bc1575f80fd5b50813567ffffffffffffffff811115611bd8575f80fd5b602083019150836020828501011115611bef575f80fd5b9250929050565b5f805f805f805f60c0888a031215611c0c575f80fd5b611c1588611b89565b965060208801359550604088013567ffffffffffffffff811115611c37575f80fd5b611c438a828b01611bb1565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f60208284031215611c75575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108c5575f80fd5b5f805f805f8060a08789031215611cb9575f80fd5b611cc287611b89565b955060208701359450604087013567ffffffffffffffff811115611ce4575f80fd5b611cf089828a01611bb1565b979a9699509760608101359660809091013595509350505050565b5f60208284031215611d1b575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d9657611d96611d22565b604052919050565b5f82601f830112611dad575f80fd5b813567ffffffffffffffff811115611dc757611dc7611d22565b611df860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611d4f565b818152846020838601011115611e0c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215611e3b575f80fd5b611e4485611b89565b9350611e5260208601611b89565b925060408501359150606085013567ffffffffffffffff811115611e74575f80fd5b611e8087828801611d9e565b91505092959194509250565b5f8060408385031215611e9d575f80fd5b82359150611ead60208401611b89565b90509250929050565b5f8083601f840112611ec6575f80fd5b50813567ffffffffffffffff811115611edd575f80fd5b6020830191508360208260051b8501011115611bef575f80fd5b5f805f805f805f805f60c08a8c031215611f0f575f80fd5b893567ffffffffffffffff80821115611f26575f80fd5b611f328d838e01611eb6565b909b50995060208c0135915080821115611f4a575f80fd5b611f568d838e01611eb6565b909950975060408c0135915080821115611f6e575f80fd5b50611f7b8c828d01611eb6565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f805f805f805f8060a0898b031215611fb7575f80fd5b883567ffffffffffffffff80821115611fce575f80fd5b611fda8c838d01611eb6565b909a50985060208b0135915080821115611ff2575f80fd5b611ffe8c838d01611eb6565b909850965060408b0135915080821115612016575f80fd5b506120238b828c01611eb6565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112612050575f80fd5b8135602067ffffffffffffffff82111561206c5761206c611d22565b8160051b61207b828201611d4f565b9283528481018201928281019087851115612094575f80fd5b83870192505b848310156120b35782358252918301919083019061209a565b979650505050505050565b5f805f805f60a086880312156120d2575f80fd5b6120db86611b89565b94506120e960208701611b89565b9350604086013567ffffffffffffffff80821115612105575f80fd5b61211189838a01612041565b94506060880135915080821115612126575f80fd5b61213289838a01612041565b93506080880135915080821115612147575f80fd5b5061215488828901611d9e565b9150509295509295909350565b5f805f805f60a08688031215612175575f80fd5b61217e86611b89565b945061218c60208701611b89565b93506040860135925060608601359150608086013567ffffffffffffffff8111156121b5575f80fd5b61215488828901611d9e565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a060408201525f61223d60a0830186886121c1565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201525f6122876060830184866121c1565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156122ce575f80fd5b6108c582611b89565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261230a575f80fd5b83018035915067ffffffffffffffff821115612324575f80fd5b602001915036819003821315611bef575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361239557612395612338565b5060010190565b8183525f6020808501808196508560051b81019150845f5b8781101561243a57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126123f2575f80fd5b8701858101903567ffffffffffffffff81111561240d575f80fd5b80360382131561241b575f80fd5b6124268682846121c1565b9a87019a95505050908401906001016123b4565b5091979650505050505050565b60a080825281018890525f8960c08301825b8b8110156124945773ffffffffffffffffffffffffffffffffffffffff61247f84611b89565b16825260209283019290910190600101612459565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8911156124cc575f80fd5b8860051b9150818a602083013701828103602090810160408501526124f4908201878961239c565b60608401959095525050608001529695505050505050565b5f6020828403121561251c575f80fd5b815180151581146108c5575f80fd5b808201808211156107ac576107ac612338565b5f5b83811015612558578181015183820152602001612540565b50505f910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f835161259781601785016020880161253e565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516125d481602884016020880161253e565b01602801949350505050565b602081525f82518060208401526125fe81604085016020870161253e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b818382375f9101908152919050565b80820281158282048414176107ac576107ac612338565b5f8161266457612664612338565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220e28ae7494480ab1c619fd775dc5ff665588c808a910d66178a982c2e7c76a1e664736f6c63430008140033", + "bytecode": "0x60a060405234801562000010575f80fd5b5060405162002c4d38038062002c4d833981016040819052620000339162000412565b84848484620000515f8051602062002bcd8339815191528062000232565b620000795f8051602062002bed8339815191525f8051602062002bcd83398151915262000232565b620000a15f8051602062002c0d8339815191525f8051602062002bcd83398151915262000232565b620000c95f8051602062002c2d8339815191525f8051602062002bcd83398151915262000232565b620000e35f8051602062002bcd833981519152306200027c565b6001600160a01b038116156200010d576200010d5f8051602062002bcd833981519152826200027c565b5f5b83518110156200019057620001555f8051602062002bed833981519152858381518110620001415762000141620004ad565b60200260200101516200027c60201b60201c565b6200017d5f8051602062002c2d833981519152858381518110620001415762000141620004ad565b6200018881620004c1565b90506200010f565b505f5b8251811015620001d857620001c55f8051602062002c0d833981519152848381518110620001415762000141620004ad565b620001d081620004c1565b905062000193565b506002849055604080515f8152602081018690527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1505050506001600160a01b031660805250620004e692505050565b5f82815260208190526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b6200028882826200028c565b5050565b5f828152602081815260408083206001600160a01b038516845290915290205460ff1662000288575f828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055620002e63390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b634e487b7160e01b5f52604160045260245ffd5b6001600160a01b038116811462000353575f80fd5b50565b805162000363816200033e565b919050565b5f82601f83011262000378575f80fd5b815160206001600160401b03808311156200039757620003976200032a565b8260051b604051601f19603f83011681018181108482111715620003bf57620003bf6200032a565b604052938452858101830193838101925087851115620003dd575f80fd5b83870191505b848210156200040757620003f78262000356565b83529183019190830190620003e3565b979650505050505050565b5f805f805f60a0868803121562000427575f80fd5b855160208701519095506001600160401b038082111562000446575f80fd5b6200045489838a0162000368565b955060408801519150808211156200046a575f80fd5b50620004798882890162000368565b93505060608601516200048c816200033e565b60808701519092506200049f816200033e565b809150509295509295909350565b634e487b7160e01b5f52603260045260245ffd5b5f60018201620004df57634e487b7160e01b5f52601160045260245ffd5b5060010190565b6080516126c06200050d5f395f818161040201528181611124015261116401526126c05ff3fe6080604052600436106101bd575f3560e01c806364d62353116100f2578063b1c5f42711610092578063d547741f11610062578063d547741f1461063a578063e38335e514610659578063f23a6e611461066c578063f27a0c92146106b0575f80fd5b8063b1c5f4271461058d578063bc197c81146105ac578063c4d252f5146105f0578063d45c44351461060f575f80fd5b80638f61f4f5116100cd5780638f61f4f5146104c557806391d14854146104f8578063a217fddf14610547578063b08e51c01461055a575f80fd5b806364d62353146104685780638065657f146104875780638f2a0bb0146104a6575f80fd5b8063248a9ca31161015d57806331d507501161013857806331d50750146103b357806336568abe146103d25780633a6aae72146103f1578063584b153e14610449575f80fd5b8063248a9ca3146103375780632ab0f529146103655780632f2ff15d14610394575f80fd5b80630d3cf6fc116101985780630d3cf6fc1461025e578063134008d31461029157806313bc9f20146102a4578063150b7a02146102c3575f80fd5b806301d5062a146101c857806301ffc9a7146101e957806307bd02651461021d575f80fd5b366101c457005b5f80fd5b3480156101d3575f80fd5b506101e76101e2366004611bf6565b6106c4565b005b3480156101f4575f80fd5b50610208610203366004611c65565b610757565b60405190151581526020015b60405180910390f35b348015610228575f80fd5b506102507fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610214565b348015610269575f80fd5b506102507f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101e761029f366004611ca4565b6107b2565b3480156102af575f80fd5b506102086102be366004611d0b565b6108a7565b3480156102ce575f80fd5b506103066102dd366004611e28565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610214565b348015610342575f80fd5b50610250610351366004611d0b565b5f9081526020819052604090206001015490565b348015610370575f80fd5b5061020861037f366004611d0b565b5f908152600160208190526040909120541490565b34801561039f575f80fd5b506101e76103ae366004611e8c565b6108cc565b3480156103be575f80fd5b506102086103cd366004611d0b565b6108f5565b3480156103dd575f80fd5b506101e76103ec366004611e8c565b61090d565b3480156103fc575f80fd5b506104247f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b348015610454575f80fd5b50610208610463366004611d0b565b6109c5565b348015610473575f80fd5b506101e7610482366004611d0b565b6109da565b348015610492575f80fd5b506102506104a1366004611ca4565b610aaa565b3480156104b1575f80fd5b506101e76104c0366004611ef7565b610ae8565b3480156104d0575f80fd5b506102507fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610503575f80fd5b50610208610512366004611e8c565b5f9182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b348015610552575f80fd5b506102505f81565b348015610565575f80fd5b506102507ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b348015610598575f80fd5b506102506105a7366004611fa0565b610d18565b3480156105b7575f80fd5b506103066105c63660046120be565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b3480156105fb575f80fd5b506101e761060a366004611d0b565b610d5c565b34801561061a575f80fd5b50610250610629366004611d0b565b5f9081526001602052604090205490565b348015610645575f80fd5b506101e7610654366004611e8c565b610e56565b6101e7610667366004611fa0565b610e7a565b348015610677575f80fd5b50610306610686366004612161565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106bb575f80fd5b50610250611121565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16106ee81611200565b5f6106fd898989898989610aaa565b9050610709818461120d565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a60405161074496959493929190612208565b60405180910390a3505050505050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107ac57506107ac82611359565b92915050565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661082e5761082e81336113ef565b5f61083d888888888888610aaa565b905061084981856114a6565b610855888888886115e2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a60405161088c9493929190612252565b60405180910390a361089d816116e2565b5050505050505050565b5f818152600160205260408120546001811180156108c55750428111155b9392505050565b5f828152602081905260409020600101546108e681611200565b6108f0838361178a565b505050565b5f8181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109c18282611878565b5050565b5f818152600160208190526040822054610906565b333014610a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109ae565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b5f868686868686604051602001610ac696959493929190612208565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b1281611200565b888714610ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b888514610c30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f610c418b8b8b8b8b8b8b8b610d18565b9050610c4d818461120d565b5f5b8a811015610d0a5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610c8c57610c8c612291565b9050602002016020810190610ca191906122be565b8d8d86818110610cb357610cb3612291565b905060200201358c8c87818110610ccc57610ccc612291565b9050602002810190610cde91906122d7565b8c8b604051610cf296959493929190612208565b60405180910390a3610d0381612365565b9050610c4f565b505050505050505050505050565b5f8888888888888888604051602001610d38989796959493929190612447565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610d8681611200565b610d8f826109c5565b610e1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109ae565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610e7081611200565b6108f08383611878565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610ef657610ef681336113ef565b878614610f85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b878414611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f6110258a8a8a8a8a8a8a8a610d18565b905061103181856114a6565b5f5b8981101561110b575f8b8b8381811061104e5761104e612291565b905060200201602081019061106391906122be565b90505f8a8a8481811061107857611078612291565b905060200201359050365f8a8a8681811061109557611095612291565b90506020028101906110a791906122d7565b915091506110b7848484846115e2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58868686866040516110ee9493929190612252565b60405180910390a3505050508061110490612365565b9050611033565b50611115816116e2565b50505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16158015906111ef57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ef919061250c565b156111f957505f90565b5060025490565b61120a81336113ef565b50565b611216826108f5565b156112a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109ae565b6112ab611121565b81101561133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109ae565b611344814261252b565b5f928352600160205260409092209190915550565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107ac57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107ac565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c15761142c8161192d565b61143783602061194c565b604051602001611448929190612560565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109ae916004016125e0565b6114af826108a7565b61153b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b80158061155657505f81815260016020819052604090912054145b6109c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f8473ffffffffffffffffffffffffffffffffffffffff1684848460405161160b929190612630565b5f6040518083038185875af1925050503d805f8114611645576040519150601f19603f3d011682016040523d82523d5f602084013e61164a565b606091505b50509050806116db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109ae565b5050505050565b6116eb816108a7565b611777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b5f90815260016020819052604090912055565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561181a3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107ac73ffffffffffffffffffffffffffffffffffffffff831660145b60605f61195a83600261263f565b61196590600261252b565b67ffffffffffffffff81111561197d5761197d611d22565b6040519080825280601f01601f1916602001820160405280156119a7576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106119dd576119dd612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a3f57611a3f612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f611a7984600261263f565b611a8490600161252b565b90505b6001811115611b20577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611ac557611ac5612291565b1a60f81b828281518110611adb57611adb612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535060049490941c93611b1981612656565b9050611a87565b5083156108c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109ae565b803573ffffffffffffffffffffffffffffffffffffffff81168114611bac575f80fd5b919050565b5f8083601f840112611bc1575f80fd5b50813567ffffffffffffffff811115611bd8575f80fd5b602083019150836020828501011115611bef575f80fd5b9250929050565b5f805f805f805f60c0888a031215611c0c575f80fd5b611c1588611b89565b965060208801359550604088013567ffffffffffffffff811115611c37575f80fd5b611c438a828b01611bb1565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f60208284031215611c75575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108c5575f80fd5b5f805f805f8060a08789031215611cb9575f80fd5b611cc287611b89565b955060208701359450604087013567ffffffffffffffff811115611ce4575f80fd5b611cf089828a01611bb1565b979a9699509760608101359660809091013595509350505050565b5f60208284031215611d1b575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d9657611d96611d22565b604052919050565b5f82601f830112611dad575f80fd5b813567ffffffffffffffff811115611dc757611dc7611d22565b611df860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611d4f565b818152846020838601011115611e0c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215611e3b575f80fd5b611e4485611b89565b9350611e5260208601611b89565b925060408501359150606085013567ffffffffffffffff811115611e74575f80fd5b611e8087828801611d9e565b91505092959194509250565b5f8060408385031215611e9d575f80fd5b82359150611ead60208401611b89565b90509250929050565b5f8083601f840112611ec6575f80fd5b50813567ffffffffffffffff811115611edd575f80fd5b6020830191508360208260051b8501011115611bef575f80fd5b5f805f805f805f805f60c08a8c031215611f0f575f80fd5b893567ffffffffffffffff80821115611f26575f80fd5b611f328d838e01611eb6565b909b50995060208c0135915080821115611f4a575f80fd5b611f568d838e01611eb6565b909950975060408c0135915080821115611f6e575f80fd5b50611f7b8c828d01611eb6565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f805f805f805f8060a0898b031215611fb7575f80fd5b883567ffffffffffffffff80821115611fce575f80fd5b611fda8c838d01611eb6565b909a50985060208b0135915080821115611ff2575f80fd5b611ffe8c838d01611eb6565b909850965060408b0135915080821115612016575f80fd5b506120238b828c01611eb6565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112612050575f80fd5b8135602067ffffffffffffffff82111561206c5761206c611d22565b8160051b61207b828201611d4f565b9283528481018201928281019087851115612094575f80fd5b83870192505b848310156120b35782358252918301919083019061209a565b979650505050505050565b5f805f805f60a086880312156120d2575f80fd5b6120db86611b89565b94506120e960208701611b89565b9350604086013567ffffffffffffffff80821115612105575f80fd5b61211189838a01612041565b94506060880135915080821115612126575f80fd5b61213289838a01612041565b93506080880135915080821115612147575f80fd5b5061215488828901611d9e565b9150509295509295909350565b5f805f805f60a08688031215612175575f80fd5b61217e86611b89565b945061218c60208701611b89565b93506040860135925060608601359150608086013567ffffffffffffffff8111156121b5575f80fd5b61215488828901611d9e565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a060408201525f61223d60a0830186886121c1565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201525f6122876060830184866121c1565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156122ce575f80fd5b6108c582611b89565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261230a575f80fd5b83018035915067ffffffffffffffff821115612324575f80fd5b602001915036819003821315611bef575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361239557612395612338565b5060010190565b8183525f6020808501808196508560051b81019150845f5b8781101561243a57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126123f2575f80fd5b8701858101903567ffffffffffffffff81111561240d575f80fd5b80360382131561241b575f80fd5b6124268682846121c1565b9a87019a95505050908401906001016123b4565b5091979650505050505050565b60a080825281018890525f8960c08301825b8b8110156124945773ffffffffffffffffffffffffffffffffffffffff61247f84611b89565b16825260209283019290910190600101612459565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8911156124cc575f80fd5b8860051b9150818a602083013701828103602090810160408501526124f4908201878961239c565b60608401959095525050608001529695505050505050565b5f6020828403121561251c575f80fd5b815180151581146108c5575f80fd5b808201808211156107ac576107ac612338565b5f5b83811015612558578181015183820152602001612540565b50505f910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f835161259781601785016020880161253e565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516125d481602884016020880161253e565b01602801949350505050565b602081525f82518060208401526125fe81604085016020870161253e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b818382375f9101908152919050565b80820281158282048414176107ac576107ac612338565b5f8161266457612664612338565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea26469706673582212207a0bffd7acf8a1c68466909b51b363a979f9728750c0d1cf39cda1f88c34525d64736f6c634300081400335f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5b09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1d8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e63fd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783", + "deployedBytecode": "0x6080604052600436106101bd575f3560e01c806364d62353116100f2578063b1c5f42711610092578063d547741f11610062578063d547741f1461063a578063e38335e514610659578063f23a6e611461066c578063f27a0c92146106b0575f80fd5b8063b1c5f4271461058d578063bc197c81146105ac578063c4d252f5146105f0578063d45c44351461060f575f80fd5b80638f61f4f5116100cd5780638f61f4f5146104c557806391d14854146104f8578063a217fddf14610547578063b08e51c01461055a575f80fd5b806364d62353146104685780638065657f146104875780638f2a0bb0146104a6575f80fd5b8063248a9ca31161015d57806331d507501161013857806331d50750146103b357806336568abe146103d25780633a6aae72146103f1578063584b153e14610449575f80fd5b8063248a9ca3146103375780632ab0f529146103655780632f2ff15d14610394575f80fd5b80630d3cf6fc116101985780630d3cf6fc1461025e578063134008d31461029157806313bc9f20146102a4578063150b7a02146102c3575f80fd5b806301d5062a146101c857806301ffc9a7146101e957806307bd02651461021d575f80fd5b366101c457005b5f80fd5b3480156101d3575f80fd5b506101e76101e2366004611bf6565b6106c4565b005b3480156101f4575f80fd5b50610208610203366004611c65565b610757565b60405190151581526020015b60405180910390f35b348015610228575f80fd5b506102507fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610214565b348015610269575f80fd5b506102507f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101e761029f366004611ca4565b6107b2565b3480156102af575f80fd5b506102086102be366004611d0b565b6108a7565b3480156102ce575f80fd5b506103066102dd366004611e28565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610214565b348015610342575f80fd5b50610250610351366004611d0b565b5f9081526020819052604090206001015490565b348015610370575f80fd5b5061020861037f366004611d0b565b5f908152600160208190526040909120541490565b34801561039f575f80fd5b506101e76103ae366004611e8c565b6108cc565b3480156103be575f80fd5b506102086103cd366004611d0b565b6108f5565b3480156103dd575f80fd5b506101e76103ec366004611e8c565b61090d565b3480156103fc575f80fd5b506104247f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b348015610454575f80fd5b50610208610463366004611d0b565b6109c5565b348015610473575f80fd5b506101e7610482366004611d0b565b6109da565b348015610492575f80fd5b506102506104a1366004611ca4565b610aaa565b3480156104b1575f80fd5b506101e76104c0366004611ef7565b610ae8565b3480156104d0575f80fd5b506102507fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610503575f80fd5b50610208610512366004611e8c565b5f9182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b348015610552575f80fd5b506102505f81565b348015610565575f80fd5b506102507ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b348015610598575f80fd5b506102506105a7366004611fa0565b610d18565b3480156105b7575f80fd5b506103066105c63660046120be565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b3480156105fb575f80fd5b506101e761060a366004611d0b565b610d5c565b34801561061a575f80fd5b50610250610629366004611d0b565b5f9081526001602052604090205490565b348015610645575f80fd5b506101e7610654366004611e8c565b610e56565b6101e7610667366004611fa0565b610e7a565b348015610677575f80fd5b50610306610686366004612161565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106bb575f80fd5b50610250611121565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16106ee81611200565b5f6106fd898989898989610aaa565b9050610709818461120d565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a60405161074496959493929190612208565b60405180910390a3505050505050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107ac57506107ac82611359565b92915050565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661082e5761082e81336113ef565b5f61083d888888888888610aaa565b905061084981856114a6565b610855888888886115e2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a60405161088c9493929190612252565b60405180910390a361089d816116e2565b5050505050505050565b5f818152600160205260408120546001811180156108c55750428111155b9392505050565b5f828152602081905260409020600101546108e681611200565b6108f0838361178a565b505050565b5f8181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109c18282611878565b5050565b5f818152600160208190526040822054610906565b333014610a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109ae565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b5f868686868686604051602001610ac696959493929190612208565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b1281611200565b888714610ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b888514610c30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f610c418b8b8b8b8b8b8b8b610d18565b9050610c4d818461120d565b5f5b8a811015610d0a5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610c8c57610c8c612291565b9050602002016020810190610ca191906122be565b8d8d86818110610cb357610cb3612291565b905060200201358c8c87818110610ccc57610ccc612291565b9050602002810190610cde91906122d7565b8c8b604051610cf296959493929190612208565b60405180910390a3610d0381612365565b9050610c4f565b505050505050505050505050565b5f8888888888888888604051602001610d38989796959493929190612447565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610d8681611200565b610d8f826109c5565b610e1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109ae565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610e7081611200565b6108f08383611878565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610ef657610ef681336113ef565b878614610f85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b878414611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f6110258a8a8a8a8a8a8a8a610d18565b905061103181856114a6565b5f5b8981101561110b575f8b8b8381811061104e5761104e612291565b905060200201602081019061106391906122be565b90505f8a8a8481811061107857611078612291565b905060200201359050365f8a8a8681811061109557611095612291565b90506020028101906110a791906122d7565b915091506110b7848484846115e2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58868686866040516110ee9493929190612252565b60405180910390a3505050508061110490612365565b9050611033565b50611115816116e2565b50505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16158015906111ef57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ef919061250c565b156111f957505f90565b5060025490565b61120a81336113ef565b50565b611216826108f5565b156112a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109ae565b6112ab611121565b81101561133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109ae565b611344814261252b565b5f928352600160205260409092209190915550565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107ac57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107ac565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c15761142c8161192d565b61143783602061194c565b604051602001611448929190612560565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109ae916004016125e0565b6114af826108a7565b61153b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b80158061155657505f81815260016020819052604090912054145b6109c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f8473ffffffffffffffffffffffffffffffffffffffff1684848460405161160b929190612630565b5f6040518083038185875af1925050503d805f8114611645576040519150601f19603f3d011682016040523d82523d5f602084013e61164a565b606091505b50509050806116db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109ae565b5050505050565b6116eb816108a7565b611777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b5f90815260016020819052604090912055565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561181a3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107ac73ffffffffffffffffffffffffffffffffffffffff831660145b60605f61195a83600261263f565b61196590600261252b565b67ffffffffffffffff81111561197d5761197d611d22565b6040519080825280601f01601f1916602001820160405280156119a7576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106119dd576119dd612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a3f57611a3f612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f611a7984600261263f565b611a8490600161252b565b90505b6001811115611b20577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611ac557611ac5612291565b1a60f81b828281518110611adb57611adb612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535060049490941c93611b1981612656565b9050611a87565b5083156108c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109ae565b803573ffffffffffffffffffffffffffffffffffffffff81168114611bac575f80fd5b919050565b5f8083601f840112611bc1575f80fd5b50813567ffffffffffffffff811115611bd8575f80fd5b602083019150836020828501011115611bef575f80fd5b9250929050565b5f805f805f805f60c0888a031215611c0c575f80fd5b611c1588611b89565b965060208801359550604088013567ffffffffffffffff811115611c37575f80fd5b611c438a828b01611bb1565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f60208284031215611c75575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108c5575f80fd5b5f805f805f8060a08789031215611cb9575f80fd5b611cc287611b89565b955060208701359450604087013567ffffffffffffffff811115611ce4575f80fd5b611cf089828a01611bb1565b979a9699509760608101359660809091013595509350505050565b5f60208284031215611d1b575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d9657611d96611d22565b604052919050565b5f82601f830112611dad575f80fd5b813567ffffffffffffffff811115611dc757611dc7611d22565b611df860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611d4f565b818152846020838601011115611e0c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215611e3b575f80fd5b611e4485611b89565b9350611e5260208601611b89565b925060408501359150606085013567ffffffffffffffff811115611e74575f80fd5b611e8087828801611d9e565b91505092959194509250565b5f8060408385031215611e9d575f80fd5b82359150611ead60208401611b89565b90509250929050565b5f8083601f840112611ec6575f80fd5b50813567ffffffffffffffff811115611edd575f80fd5b6020830191508360208260051b8501011115611bef575f80fd5b5f805f805f805f805f60c08a8c031215611f0f575f80fd5b893567ffffffffffffffff80821115611f26575f80fd5b611f328d838e01611eb6565b909b50995060208c0135915080821115611f4a575f80fd5b611f568d838e01611eb6565b909950975060408c0135915080821115611f6e575f80fd5b50611f7b8c828d01611eb6565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f805f805f805f8060a0898b031215611fb7575f80fd5b883567ffffffffffffffff80821115611fce575f80fd5b611fda8c838d01611eb6565b909a50985060208b0135915080821115611ff2575f80fd5b611ffe8c838d01611eb6565b909850965060408b0135915080821115612016575f80fd5b506120238b828c01611eb6565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112612050575f80fd5b8135602067ffffffffffffffff82111561206c5761206c611d22565b8160051b61207b828201611d4f565b9283528481018201928281019087851115612094575f80fd5b83870192505b848310156120b35782358252918301919083019061209a565b979650505050505050565b5f805f805f60a086880312156120d2575f80fd5b6120db86611b89565b94506120e960208701611b89565b9350604086013567ffffffffffffffff80821115612105575f80fd5b61211189838a01612041565b94506060880135915080821115612126575f80fd5b61213289838a01612041565b93506080880135915080821115612147575f80fd5b5061215488828901611d9e565b9150509295509295909350565b5f805f805f60a08688031215612175575f80fd5b61217e86611b89565b945061218c60208701611b89565b93506040860135925060608601359150608086013567ffffffffffffffff8111156121b5575f80fd5b61215488828901611d9e565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a060408201525f61223d60a0830186886121c1565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201525f6122876060830184866121c1565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156122ce575f80fd5b6108c582611b89565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261230a575f80fd5b83018035915067ffffffffffffffff821115612324575f80fd5b602001915036819003821315611bef575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361239557612395612338565b5060010190565b8183525f6020808501808196508560051b81019150845f5b8781101561243a57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126123f2575f80fd5b8701858101903567ffffffffffffffff81111561240d575f80fd5b80360382131561241b575f80fd5b6124268682846121c1565b9a87019a95505050908401906001016123b4565b5091979650505050505050565b60a080825281018890525f8960c08301825b8b8110156124945773ffffffffffffffffffffffffffffffffffffffff61247f84611b89565b16825260209283019290910190600101612459565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8911156124cc575f80fd5b8860051b9150818a602083013701828103602090810160408501526124f4908201878961239c565b60608401959095525050608001529695505050505050565b5f6020828403121561251c575f80fd5b815180151581146108c5575f80fd5b808201808211156107ac576107ac612338565b5f5b83811015612558578181015183820152602001612540565b50505f910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f835161259781601785016020880161253e565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516125d481602884016020880161253e565b01602801949350505050565b602081525f82518060208401526125fe81604085016020870161253e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b818382375f9101908152919050565b80820281158282048414176107ac576107ac612338565b5f8161266457612664612338565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea26469706673582212207a0bffd7acf8a1c68466909b51b363a979f9728750c0d1cf39cda1f88c34525d64736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/compiled-contracts/SP1VerifierPlonk.json b/compiled-contracts/SP1VerifierPlonk.json new file mode 100644 index 000000000..d0f2186f9 --- /dev/null +++ b/compiled-contracts/SP1VerifierPlonk.json @@ -0,0 +1,124 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "SP1VerifierPlonk", + "sourceName": "contracts/verifiers/v4.0.0-rc.3/SP1VerifierPlonk.sol", + "abi": [ + { + "inputs": [], + "name": "InvalidProof", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "received", + "type": "bytes4" + }, + { + "internalType": "bytes4", + "name": "expected", + "type": "bytes4" + } + ], + "name": "WrongVerifierSelector", + "type": "error" + }, + { + "inputs": [], + "name": "VERIFIER_HASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "VERSION", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "proof", + "type": "bytes" + }, + { + "internalType": "uint256[]", + "name": "public_inputs", + "type": "uint256[]" + } + ], + "name": "Verify", + "outputs": [ + { + "internalType": "bool", + "name": "success", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "publicValues", + "type": "bytes" + } + ], + "name": "hashPublicValues", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "publicValues", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "proofBytes", + "type": "bytes" + } + ], + "name": "verifyProof", + "outputs": [], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x608060405234801561000f575f80fd5b50612f768061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610064575f3560e01c80636b61d8e71161004d5780636b61d8e7146100b25780637e4f7a8a146100c5578063ffa1ad74146100e8575f80fd5b80632a5104361461006857806341493c601461009d575b5f80fd5b7f1b34fe11a637737f0c75c88241669dcf9ca3c03713659265b8241f398a2d286d5b6040519081526020015b60405180910390f35b6100b06100ab366004612c16565b610127565b005b61008a6100c0366004612c8a565b610335565b6100d86100d3366004612cc9565b6103b1565b6040519015158152602001610094565b604080518082018252600b81527f76342e302e302d72632e33000000000000000000000000000000000000000000602082015290516100949190612d5b565b5f6101356004828486612dc4565b61013e91612deb565b90507f1b34fe11a637737f0c75c88241669dcf9ca3c03713659265b8241f398a2d286d7f1b34fe11000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461020c576040517f988066a10000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000080841660048301528216602482015260440160405180910390fd5b5f6102178787610335565b6040805160028082526060820183529293505f929091602083019080368337019050509050885f1c815f8151811061025157610251612e33565b602002602001018181525050815f1c8160018151811061027357610273612e33565b60209081029190910101525f30637e4f7a8a610292886004818c612dc4565b856040518463ffffffff1660e01b81526004016102b193929190612e60565b602060405180830381865afa1580156102cc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102f09190612ef4565b905080610329576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050505050565b5f7f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f1b6002848460405161036b929190612f1a565b602060405180830381855afa158015610386573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906103a99190612f29565b169392505050565b5f60405161024081016103c384610853565b6103cd8585610866565b6103d6866108b5565b6103df876108cb565b5f6103eb86868a610a65565b90506103f681610d9b565b90506104028189610e01565b905061040e8189610e8f565b5060608201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000061046584630100000085612b66565b086101c084015250610478818587610efa565b61048382868a61126f565b91507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183086101a0840152506104ba9050611614565b6104c38661275a565b6104cc866126ab565b6104d5866122d2565b6104de86611dfe565b6104e786611b63565b6104f086611765565b61020001519050612bc9565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f77726f6e67206e756d626572206f66207075626c696320696e707574730000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f72206d6f6420657870000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6572726f72206563206f7065726174696f6e00000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f696e707574732061726520626967676572207468616e207200000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f77726f6e672070726f6f662073697a65000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f6f70656e696e677320626967676572207468616e2072000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f6572726f722070616972696e67000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f722076657269667900000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6572726f722072616e646f6d2067656e206b7a670000000000000000000000006044820152606481fd5b60028114610863576108636104fc565b50565b5f5b818110156108b0577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000833511156108a1576108a1610619565b60209290920191600101610868565b505050565b6103608181146108c7576108c7610678565b5050565b61018081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610901576109016106d7565b506101a081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610938576109386106d7565b506101c081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000008135111561096f5761096f6106d7565b506101e081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109a6576109a66106d7565b5061020081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109dd576109dd6106d7565b5061026081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610a1457610a146106d7565b5061030081015f5b60018110156108b0577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000082351115610a5657610a566106d7565b60209190910190600101610a1c565b5f60405161024081016467616d6d6181527f12a48c83bdc2bd4ee1f40afcc423cc0afc88de1ea9582ba24e270756ec8cce8f60208201527f30435d8f96e055b4a6e430f453f5513c76ea9678640bce0c1e038c0d4722e41960408201527f06639c1513f4b71307b9e27b59ba424e751e278c396e503d983083c829492c0c60608201527f12ac9af6832ed9b17d99d5ddd50ceab75fb36d13181f468fa3efedc1416de3b760808201527f1c81c1fbd342d416ee266b3a399beef9ffe2b51fff92b48d737d758d30d1241f60a08201527f0bc9e4b1e207ed79eb7d6ad861084410020a8d41d7eb6f57ca0868c4777cc34460c08201527f27c295f097038eb58f0f6d66aa345510a9e2ea3b5e9dc75f182376207134042860e08201527f1d5b1420aee936b0d295b5dcb8173a17c8a44b564509db9f95897cb73395a6be6101008201527f241e02c138aeebc8e2fe50b6d55271f1f682e8e368fb2d21c27324ff98f3ebdd6101208201527e31f7998d7bd4be4577b6bd0ccdc99ebaff0e4f82186584da8f600721cb29436101408201527f180091bdef5b48f8c60eaf427d872e6373841cf9920767c6a7af32dbfeaed0326101608201527f1481951fc49629d6c1a6218bc3cd3971d969ed4781de2cd4d3ba18909e187dc76101808201527f19634c7169f97677973fe29c865df785fc3859da2968bd9b21ac0d4f64834f216101a08201527f267532c6f9f01f4cadf688a9fa0a591f9acdc5820428d4fdc1b16733d56306e16101c08201527f0e19ddfd3a5601df62b35b4e93ccba750fd3b16db7c49c2b8ed111d84a0074346101e08201527f1b77a9dcbe482f7c56727522fa37c7c3c4814db3b53ca4b3a3ea488376b97d4f6102008201527f239fd065b19f5fd14ab4226f6453ec6999736e4e4dfde3c66b68ffe2985627e76102208201527f292721d067d5f787ff7f0fd1d6eab321c598d1da89f668035dde31b300d24dff610240820152610260810160208602808883379081019060c0808784375061030501905060208282601b820160025afa905080610d6557610d65610795565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182066040820152509392505050565b5f60405161024060405101636265746181528360208201526020816024601c840160025afa80610dcd57610dcd610795565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018206602082015250919050565b5f60405161024060405101606564616c7068618252602082018681526020810190506103208601600160400280828437928301929190910190506040610220870182375060208282601b850160025afa905080610e6057610e60610795565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181069091529392505050565b60405161024060405101637a657461815283602082015260c0808401604083013760208160e4601c840160025afa80610eca57610eca610795565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006606091909101525050565b5f60405160608101516101c0820151915085610f1881878585610f93565b5f92505f91505b85821015610f89577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001853582510992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018385086020958601959094506001929092019101610f1f565b5050509392505050565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c1183096001855f5b86811015611081577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103860882527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b8409925060209190910190600101610fdc565b5061108d818789611145565b5060019050855f5b8681101561113b577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001868551090982526020820191507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b84099250600101611095565b5050505050505050565b600183525f805b8381101561119a5781850151828401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181830990506020840193508084880152505060018101905061114c565b5060208103820191508084019350506111db6020840160027f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001038551612b66565b5f5b838110156112685760208503945082517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018651840984527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184097fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909401939250506001016111dd565b5050505050565b5f60405160608101516101c0820151915061032084015f80611297896020850135853561141b565b91506112aa8962a59c328a0187876112e0565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018082840987089998505050505050505050565b5f61130c85857f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001817f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103840894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c11820990506113c5867f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff87612b66565b94507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018482099695505050505050565b5f83525f602084015280604084015250806060830152505f6080820153603060818201535f60828201536042608382015360536084820153604260858201536032608682015360326087820153602d608882015360506089820153606c608a820153606f608b820153606e608c820153606b608d820153600b608e8201535f602082608f8460025afa806114b1576114b1610795565b8251600160208501536042602185015360536022850153604260238501536032602485015360326025850153602d602685015360506027850153606c6028850153606f6029850153606e602a850153606b602b850153600b602c850153602084602d8660025afa91508161152757611527610795565b8351186020840152600260408401536042604184015360536042840153604260438401536032604484015360326045840153602d604684015360506047840153606c6048840153606f6049840153606e604a840153606b604b840153600b604c84015360208301602081602d8360025afa915050806115a8576115a8610795565b507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017001000000000000000000000000000000008351099050602082015160801c7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183089392505050565b604051610240604051016101c08201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000010360608501510861169a837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff83612b66565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c11820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282098451935091507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001905082820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282099050806080840152505050565b60405161024081016101608201518152610180820151602082015261028083013560408201526102a08301356060820152610220830135608082015261024083013560a08201526102c083013560c08201526102e083013560e082015260608201516101008201526101e08201516101208201526020816101408360025afa806117f1576117f16107f4565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182510690508160408101925061028085013581526102a0850135602082015261184183836102c0880184612acd565b61016084016118568484610220890184612acd565b610140850161186a84610260890183612b14565b7f1fa4be93b5e7f7e674d5059b63554fab99638b304ed8310e9fa44c281ac9b03b85527f1a01ae7fac6228e39d3cb5a5e71fd31160f3241e79a5f48ffb3737e6c389b7216020860152805160408087019182529095908160608160075afa9150816118d7576118d7610795565b60208101915081517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703825261190f868285866129c4565b50508360408501945061192c8560608801516102808a0184612a5b565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b60608801510995507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186850993506119ac85856102c08a0184612acd565b6119b8858284856129c4565b50602082810180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd470381528251865291810151908501527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260408501527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608501527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808501527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a0850152905160c0840152805160e08401527f22f1acbb03c4508760c2430af35865e7cdf9f3eb1224504fdcc3708ddb954a486101008401527f2a344fad01c2ed0ed73142ae1752429eaea515c6f3f6b941103cc21c2308e1cb6101208401527f159f15b842ba9c8449aa3268f981010d4c7142e5193473d80b464e964845c3f86101408401527f0efd30ac7b6f8d0d3ccbc2207587c2acbad1532dc0293f0d034cf8258cd428b361016084015292506108b090508160405160205f6101808460085afa80611b5557611b55610736565b505f51610200919091015250565b6040516102406040510160208101604082016101e084015180610160860160e08701518152610100870151610180880152610120870151610140880152611bae86835f8b0184612acd565b611bc1826101808a016101408a01612b14565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611bf6868360408b0184612acd565b611c09826101a08a016101408a01612b14565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611c3e868360808b0184612acd565b611c51826101c08a016101408a01612b14565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f12a48c83bdc2bd4ee1f40afcc423cc0afc88de1ea9582ba24e270756ec8cce8f86527f30435d8f96e055b4a6e430f453f5513c76ea9678640bce0c1e038c0d4722e4198552611cc984838884612a86565b611cdc826101e08a016101408a01612b14565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f06639c1513f4b71307b9e27b59ba424e751e278c396e503d983083c829492c0c86527f12ac9af6832ed9b17d99d5ddd50ceab75fb36d13181f468fa3efedc1416de3b78552611d5484838884612a86565b611d67826102008a016101408a01612b14565b61030088017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184840992507f239fd065b19f5fd14ab4226f6453ec6999736e4e4dfde3c66b68ffe2985627e787527f292721d067d5f787ff7f0fd1d6eab321c598d1da89f668035dde31b300d24dff8652611de485848985612a86565b611df383826101408b01612b14565b505050505050505050565b6040516467616d6d616102408201908152606082015161026083015260e08201516102808301526101008201516102a083015260c0836102c08401377f12a48c83bdc2bd4ee1f40afcc423cc0afc88de1ea9582ba24e270756ec8cce8f6101408201527f30435d8f96e055b4a6e430f453f5513c76ea9678640bce0c1e038c0d4722e4196101608201527f06639c1513f4b71307b9e27b59ba424e751e278c396e503d983083c829492c0c610180808301919091527f12ac9af6832ed9b17d99d5ddd50ceab75fb36d13181f468fa3efedc1416de3b76101a0808401919091527f239fd065b19f5fd14ab4226f6453ec6999736e4e4dfde3c66b68ffe2985627e76101c0808501919091527f292721d067d5f787ff7f0fd1d6eab321c598d1da89f668035dde31b300d24dff6101e0808601919091526101208601516102008087019190915293870135610220860152918601356102408501528501356102608401528401356102808301528301356102a08201526102c081016103008401602081833750610260840135602091820152601b906102e5906101e085018285850160025afa9250505080611fb457611fb4610795565b506101e00180517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006905250565b604051610240604051017f27c295f097038eb58f0f6d66aa345510a9e2ea3b5e9dc75f182376207134042881527f1d5b1420aee936b0d295b5dcb8173a17c8a44b564509db9f95897cb73395a6be602082015261204d604082016101808501358360e08601612a30565b7f241e02c138aeebc8e2fe50b6d55271f1f682e8e368fb2d21c27324ff98f3ebdd81527e31f7998d7bd4be4577b6bd0ccdc99ebaff0e4f82186584da8f600721cb294360208201526120ac604082016101a08501358360e08601612a86565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840135610180850135097f180091bdef5b48f8c60eaf427d872e6373841cf9920767c6a7af32dbfeaed03282527f1481951fc49629d6c1a6218bc3cd3971d969ed4781de2cd4d3ba18909e187dc7602083015261213560408301828460e08701612a86565b507f19634c7169f97677973fe29c865df785fc3859da2968bd9b21ac0d4f64834f2181527f267532c6f9f01f4cadf688a9fa0a591f9acdc5820428d4fdc1b16733d56306e16020820152612196604082016101c08501358360e08601612a86565b7f0e19ddfd3a5601df62b35b4e93ccba750fd3b16db7c49c2b8ed111d84a00743481527f1b77a9dcbe482f7c56727522fa37c7c3c4814db3b53ca4b3a3ea488376b97d4f60208201526121f1604082018260e08501806129c4565b610300830161032084015f5b600181101561223d5781358452602082013560208501526122276040850184358660e08901612a86565b60209290920191604091909101906001016121fd565b5050507f1c81c1fbd342d416ee266b3a399beef9ffe2b51fff92b48d737d758d30d1241f81527f0bc9e4b1e207ed79eb7d6ad861084410020a8d41d7eb6f57ca0868c4777cc344602082015261229b60408201858360e08601612a86565b610220830135815261024083013560208201526122c060408201868360e08601612a86565b6112688160a0840160e08501806129c4565b6040516020810151604082015160608301515f8401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184610260880135097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101e088013586097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180890135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161020089013587097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08a0135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600580097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001878a0998507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101808c01358a0894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188860894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160058a0993507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08c0135850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001818a099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101c08b0135830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000187830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183850997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018289097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001908103985085890997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160808a01518908975061032988828c611fe3565b6040516002630100000001610240604051016126cc81836060860151612b66565b91506126e18183610140870160a08701612a5b565b6126f481610100860160a08601806129fa565b612703818360a0860180612a30565b6127158160c0860160a08601806129fa565b61272c816101c085015160a0860160a08701612a30565b505060c00180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703905250565b6040515f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208301516101e08501350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040830151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180840135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208401516102008601350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040840151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0850135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160408501516101c08701350890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182840992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000015f840151830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610260850135830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840151830860808401519092507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000190810391508183087f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001036101209390930192909252505050565b8151845260208201516020850152825160408501526020830151606085015260408160808660065afa80611268576112686105ba565b8151845260208201516020850152823560408501526020830135606085015260408160808660065afa80611268576112686105ba565b815184526020820151602085015282604085015260408160608660075afa80611268576112686105ba565b813584526020820135602085015282604085015260408160608660075afa80611268576112686105ba565b815184526020820151602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa1680611268576112686105ba565b813584526020820135602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa1680611268576112686105ba565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001838335097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181835108825250505050565b602083526020808401526020604084015280606084015250806080830152507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160a08201525f60208260c08460055afa80612bc357612bc361055b565b50505190565b949350505050565b5f8083601f840112612be1575f80fd5b50813567ffffffffffffffff811115612bf8575f80fd5b602083019150836020828501011115612c0f575f80fd5b9250929050565b5f805f805f60608688031215612c2a575f80fd5b85359450602086013567ffffffffffffffff80821115612c48575f80fd5b612c5489838a01612bd1565b90965094506040880135915080821115612c6c575f80fd5b50612c7988828901612bd1565b969995985093965092949392505050565b5f8060208385031215612c9b575f80fd5b823567ffffffffffffffff811115612cb1575f80fd5b612cbd85828601612bd1565b90969095509350505050565b5f805f8060408587031215612cdc575f80fd5b843567ffffffffffffffff80821115612cf3575f80fd5b612cff88838901612bd1565b90965094506020870135915080821115612d17575f80fd5b818701915087601f830112612d2a575f80fd5b813581811115612d38575f80fd5b8860208260051b8501011115612d4c575f80fd5b95989497505060200194505050565b5f6020808352835180828501525f5b81811015612d8657858101830151858201604001528201612d6a565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b5f8085851115612dd2575f80fd5b83861115612dde575f80fd5b5050820193919092039150565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015612e2b5780818660040360031b1b83161692505b505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b60408152826040820152828460608301375f606084830101525f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011682016060810160206060858403018186015281865180845260808501915082880194505f93505b80841015612ee75784518252938201936001939093019290820190612ec7565b5098975050505050505050565b5f60208284031215612f04575f80fd5b81518015158114612f13575f80fd5b9392505050565b818382375f9101908152919050565b5f60208284031215612f39575f80fd5b505191905056fea2646970667358221220ac5a88251da015f24b0f25a0be73e96fb607cc2f726051134c52915549351e2664736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610064575f3560e01c80636b61d8e71161004d5780636b61d8e7146100b25780637e4f7a8a146100c5578063ffa1ad74146100e8575f80fd5b80632a5104361461006857806341493c601461009d575b5f80fd5b7f1b34fe11a637737f0c75c88241669dcf9ca3c03713659265b8241f398a2d286d5b6040519081526020015b60405180910390f35b6100b06100ab366004612c16565b610127565b005b61008a6100c0366004612c8a565b610335565b6100d86100d3366004612cc9565b6103b1565b6040519015158152602001610094565b604080518082018252600b81527f76342e302e302d72632e33000000000000000000000000000000000000000000602082015290516100949190612d5b565b5f6101356004828486612dc4565b61013e91612deb565b90507f1b34fe11a637737f0c75c88241669dcf9ca3c03713659265b8241f398a2d286d7f1b34fe11000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461020c576040517f988066a10000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000080841660048301528216602482015260440160405180910390fd5b5f6102178787610335565b6040805160028082526060820183529293505f929091602083019080368337019050509050885f1c815f8151811061025157610251612e33565b602002602001018181525050815f1c8160018151811061027357610273612e33565b60209081029190910101525f30637e4f7a8a610292886004818c612dc4565b856040518463ffffffff1660e01b81526004016102b193929190612e60565b602060405180830381865afa1580156102cc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102f09190612ef4565b905080610329576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050505050565b5f7f1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5f1b6002848460405161036b929190612f1a565b602060405180830381855afa158015610386573d5f803e3d5ffd5b5050506040513d601f19601f820116820180604052508101906103a99190612f29565b169392505050565b5f60405161024081016103c384610853565b6103cd8585610866565b6103d6866108b5565b6103df876108cb565b5f6103eb86868a610a65565b90506103f681610d9b565b90506104028189610e01565b905061040e8189610e8f565b5060608201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000061046584630100000085612b66565b086101c084015250610478818587610efa565b61048382868a61126f565b91507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183086101a0840152506104ba9050611614565b6104c38661275a565b6104cc866126ab565b6104d5866122d2565b6104de86611dfe565b6104e786611b63565b6104f086611765565b61020001519050612bc9565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f77726f6e67206e756d626572206f66207075626c696320696e707574730000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f72206d6f6420657870000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6572726f72206563206f7065726174696f6e00000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f696e707574732061726520626967676572207468616e207200000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f77726f6e672070726f6f662073697a65000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f6f70656e696e677320626967676572207468616e2072000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f6572726f722070616972696e67000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f6572726f722076657269667900000000000000000000000000000000000000006044820152606481fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f6572726f722072616e646f6d2067656e206b7a670000000000000000000000006044820152606481fd5b60028114610863576108636104fc565b50565b5f5b818110156108b0577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000833511156108a1576108a1610619565b60209290920191600101610868565b505050565b6103608181146108c7576108c7610678565b5050565b61018081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610901576109016106d7565b506101a081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610938576109386106d7565b506101c081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000008135111561096f5761096f6106d7565b506101e081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109a6576109a66106d7565b5061020081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000813511156109dd576109dd6106d7565b5061026081017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000081351115610a1457610a146106d7565b5061030081015f5b60018110156108b0577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000082351115610a5657610a566106d7565b60209190910190600101610a1c565b5f60405161024081016467616d6d6181527f12a48c83bdc2bd4ee1f40afcc423cc0afc88de1ea9582ba24e270756ec8cce8f60208201527f30435d8f96e055b4a6e430f453f5513c76ea9678640bce0c1e038c0d4722e41960408201527f06639c1513f4b71307b9e27b59ba424e751e278c396e503d983083c829492c0c60608201527f12ac9af6832ed9b17d99d5ddd50ceab75fb36d13181f468fa3efedc1416de3b760808201527f1c81c1fbd342d416ee266b3a399beef9ffe2b51fff92b48d737d758d30d1241f60a08201527f0bc9e4b1e207ed79eb7d6ad861084410020a8d41d7eb6f57ca0868c4777cc34460c08201527f27c295f097038eb58f0f6d66aa345510a9e2ea3b5e9dc75f182376207134042860e08201527f1d5b1420aee936b0d295b5dcb8173a17c8a44b564509db9f95897cb73395a6be6101008201527f241e02c138aeebc8e2fe50b6d55271f1f682e8e368fb2d21c27324ff98f3ebdd6101208201527e31f7998d7bd4be4577b6bd0ccdc99ebaff0e4f82186584da8f600721cb29436101408201527f180091bdef5b48f8c60eaf427d872e6373841cf9920767c6a7af32dbfeaed0326101608201527f1481951fc49629d6c1a6218bc3cd3971d969ed4781de2cd4d3ba18909e187dc76101808201527f19634c7169f97677973fe29c865df785fc3859da2968bd9b21ac0d4f64834f216101a08201527f267532c6f9f01f4cadf688a9fa0a591f9acdc5820428d4fdc1b16733d56306e16101c08201527f0e19ddfd3a5601df62b35b4e93ccba750fd3b16db7c49c2b8ed111d84a0074346101e08201527f1b77a9dcbe482f7c56727522fa37c7c3c4814db3b53ca4b3a3ea488376b97d4f6102008201527f239fd065b19f5fd14ab4226f6453ec6999736e4e4dfde3c66b68ffe2985627e76102208201527f292721d067d5f787ff7f0fd1d6eab321c598d1da89f668035dde31b300d24dff610240820152610260810160208602808883379081019060c0808784375061030501905060208282601b820160025afa905080610d6557610d65610795565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182066040820152509392505050565b5f60405161024060405101636265746181528360208201526020816024601c840160025afa80610dcd57610dcd610795565b5080519250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018206602082015250919050565b5f60405161024060405101606564616c7068618252602082018681526020810190506103208601600160400280828437928301929190910190506040610220870182375060208282601b850160025afa905080610e6057610e60610795565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181069091529392505050565b60405161024060405101637a657461815283602082015260c0808401604083013760208160e4601c840160025afa80610eca57610eca610795565b50517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006606091909101525050565b5f60405160608101516101c0820151915085610f1881878585610f93565b5f92505f91505b85821015610f89577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001853582510992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018385086020958601959094506001929092019101610f1f565b5050509392505050565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c1183096001855f5b86811015611081577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103860882527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b8409925060209190910190600101610fdc565b5061108d818789611145565b5060019050855f5b8681101561113b577f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001868551090982526020820191507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b84099250600101611095565b5050505050505050565b600183525f805b8381101561119a5781850151828401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181830990506020840193508084880152505060018101905061114c565b5060208103820191508084019350506111db6020840160027f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001038551612b66565b5f5b838110156112685760208503945082517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018651840984527f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184097fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909401939250506001016111dd565b5050505050565b5f60405160608101516101c0820151915061032084015f80611297896020850135853561141b565b91506112aa8962a59c328a0187876112e0565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018082840987089998505050505050505050565b5f61130c85857f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b612b66565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001817f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000103840894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c11820990506113c5867f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff87612b66565b94507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018482099695505050505050565b5f83525f602084015280604084015250806060830152505f6080820153603060818201535f60828201536042608382015360536084820153604260858201536032608682015360326087820153602d608882015360506089820153606c608a820153606f608b820153606e608c820153606b608d820153600b608e8201535f602082608f8460025afa806114b1576114b1610795565b8251600160208501536042602185015360536022850153604260238501536032602485015360326025850153602d602685015360506027850153606c6028850153606f6029850153606e602a850153606b602b850153600b602c850153602084602d8660025afa91508161152757611527610795565b8351186020840152600260408401536042604184015360536042840153604260438401536032604484015360326045840153602d604684015360506047840153606c6048840153606f6049840153606e604a840153606b604b840153600b604c84015360208301602081602d8360025afa915050806115a8576115a8610795565b507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017001000000000000000000000000000000008351099050602082015160801c7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018183089392505050565b604051610240604051016101c08201517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000010360608501510861169a837f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593efffffff83612b66565b90507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f30644e427ce32d4886b01bfe313ba1dba6db8b2045d128178a7164500e0a6c11820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282098451935091507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001905082820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018282099050806080840152505050565b60405161024081016101608201518152610180820151602082015261028083013560408201526102a08301356060820152610220830135608082015261024083013560a08201526102c083013560c08201526102e083013560e082015260608201516101008201526101e08201516101208201526020816101408360025afa806117f1576117f16107f4565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182510690508160408101925061028085013581526102a0850135602082015261184183836102c0880184612acd565b61016084016118568484610220890184612acd565b610140850161186a84610260890183612b14565b7f1fa4be93b5e7f7e674d5059b63554fab99638b304ed8310e9fa44c281ac9b03b85527f1a01ae7fac6228e39d3cb5a5e71fd31160f3241e79a5f48ffb3737e6c389b7216020860152805160408087019182529095908160608160075afa9150816118d7576118d7610795565b60208101915081517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703825261190f868285866129c4565b50508360408501945061192c8560608801516102808a0184612a5b565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000017f0c9fabc7845d50d2852e2a0371c6441f145e0db82e8326961c25f1e3e32b045b60608801510995507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186850993506119ac85856102c08a0184612acd565b6119b8858284856129c4565b50602082810180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd470381528251865291810151908501527f198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c260408501527f1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed60608501527f090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b60808501527f12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa60a0850152905160c0840152805160e08401527f22f1acbb03c4508760c2430af35865e7cdf9f3eb1224504fdcc3708ddb954a486101008401527f2a344fad01c2ed0ed73142ae1752429eaea515c6f3f6b941103cc21c2308e1cb6101208401527f159f15b842ba9c8449aa3268f981010d4c7142e5193473d80b464e964845c3f86101408401527f0efd30ac7b6f8d0d3ccbc2207587c2acbad1532dc0293f0d034cf8258cd428b361016084015292506108b090508160405160205f6101808460085afa80611b5557611b55610736565b505f51610200919091015250565b6040516102406040510160208101604082016101e084015180610160860160e08701518152610100870151610180880152610120870151610140880152611bae86835f8b0184612acd565b611bc1826101808a016101408a01612b14565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611bf6868360408b0184612acd565b611c09826101a08a016101408a01612b14565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018383099150611c3e868360808b0184612acd565b611c51826101c08a016101408a01612b14565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f12a48c83bdc2bd4ee1f40afcc423cc0afc88de1ea9582ba24e270756ec8cce8f86527f30435d8f96e055b4a6e430f453f5513c76ea9678640bce0c1e038c0d4722e4198552611cc984838884612a86565b611cdc826101e08a016101408a01612b14565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183830991507f06639c1513f4b71307b9e27b59ba424e751e278c396e503d983083c829492c0c86527f12ac9af6832ed9b17d99d5ddd50ceab75fb36d13181f468fa3efedc1416de3b78552611d5484838884612a86565b611d67826102008a016101408a01612b14565b61030088017f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184840992507f239fd065b19f5fd14ab4226f6453ec6999736e4e4dfde3c66b68ffe2985627e787527f292721d067d5f787ff7f0fd1d6eab321c598d1da89f668035dde31b300d24dff8652611de485848985612a86565b611df383826101408b01612b14565b505050505050505050565b6040516467616d6d616102408201908152606082015161026083015260e08201516102808301526101008201516102a083015260c0836102c08401377f12a48c83bdc2bd4ee1f40afcc423cc0afc88de1ea9582ba24e270756ec8cce8f6101408201527f30435d8f96e055b4a6e430f453f5513c76ea9678640bce0c1e038c0d4722e4196101608201527f06639c1513f4b71307b9e27b59ba424e751e278c396e503d983083c829492c0c610180808301919091527f12ac9af6832ed9b17d99d5ddd50ceab75fb36d13181f468fa3efedc1416de3b76101a0808401919091527f239fd065b19f5fd14ab4226f6453ec6999736e4e4dfde3c66b68ffe2985627e76101c0808501919091527f292721d067d5f787ff7f0fd1d6eab321c598d1da89f668035dde31b300d24dff6101e0808601919091526101208601516102008087019190915293870135610220860152918601356102408501528501356102608401528401356102808301528301356102a08201526102c081016103008401602081833750610260840135602091820152601b906102e5906101e085018285850160025afa9250505080611fb457611fb4610795565b506101e00180517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000019006905250565b604051610240604051017f27c295f097038eb58f0f6d66aa345510a9e2ea3b5e9dc75f182376207134042881527f1d5b1420aee936b0d295b5dcb8173a17c8a44b564509db9f95897cb73395a6be602082015261204d604082016101808501358360e08601612a30565b7f241e02c138aeebc8e2fe50b6d55271f1f682e8e368fb2d21c27324ff98f3ebdd81527e31f7998d7bd4be4577b6bd0ccdc99ebaff0e4f82186584da8f600721cb294360208201526120ac604082016101a08501358360e08601612a86565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840135610180850135097f180091bdef5b48f8c60eaf427d872e6373841cf9920767c6a7af32dbfeaed03282527f1481951fc49629d6c1a6218bc3cd3971d969ed4781de2cd4d3ba18909e187dc7602083015261213560408301828460e08701612a86565b507f19634c7169f97677973fe29c865df785fc3859da2968bd9b21ac0d4f64834f2181527f267532c6f9f01f4cadf688a9fa0a591f9acdc5820428d4fdc1b16733d56306e16020820152612196604082016101c08501358360e08601612a86565b7f0e19ddfd3a5601df62b35b4e93ccba750fd3b16db7c49c2b8ed111d84a00743481527f1b77a9dcbe482f7c56727522fa37c7c3c4814db3b53ca4b3a3ea488376b97d4f60208201526121f1604082018260e08501806129c4565b610300830161032084015f5b600181101561223d5781358452602082013560208501526122276040850184358660e08901612a86565b60209290920191604091909101906001016121fd565b5050507f1c81c1fbd342d416ee266b3a399beef9ffe2b51fff92b48d737d758d30d1241f81527f0bc9e4b1e207ed79eb7d6ad861084410020a8d41d7eb6f57ca0868c4777cc344602082015261229b60408201858360e08601612a86565b610220830135815261024083013560208201526122c060408201868360e08601612a86565b6112688160a0840160e08501806129c4565b6040516020810151604082015160608301515f8401517f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000184610260880135097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101e088013586097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180890135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000161020089013587097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08a0135820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000186820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018284097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000185820990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001600580097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001878a0998507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101808c01358a0894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188860894507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160058a0993507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a08c0135850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000188850893507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001818a099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101c08b0135830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000187830891507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000183850997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018289097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001908103985085890997507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160808a01518908975061032988828c611fe3565b6040516002630100000001610240604051016126cc81836060860151612b66565b91506126e18183610140870160a08701612a5b565b6126f481610100860160a08601806129fa565b612703818360a0860180612a30565b6127158160c0860160a08601806129fa565b61272c816101c085015160a0860160a08701612a30565b505060c00180517f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4703905250565b6040515f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208301516101e08501350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040830151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610180840135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160208401516102008601350990507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016040840151820890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0850135820890505f7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160408501516101c08701350890507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000182840992507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000018184099250507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000015f840151830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001610260850135830991507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f00000016101a0840151830860808401519092507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000190810391508183087f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001036101209390930192909252505050565b8151845260208201516020850152825160408501526020830151606085015260408160808660065afa80611268576112686105ba565b8151845260208201516020850152823560408501526020830135606085015260408160808660065afa80611268576112686105ba565b815184526020820151602085015282604085015260408160608660075afa80611268576112686105ba565b813584526020820135602085015282604085015260408160608660075afa80611268576112686105ba565b815184526020820151602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa1680611268576112686105ba565b813584526020820135602085015282604085015260408460608660075afa815160408601526020820151606086015260408260808760065afa1680611268576112686105ba565b7f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001838335097f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000181835108825250505050565b602083526020808401526020604084015280606084015250806080830152507f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f000000160a08201525f60208260c08460055afa80612bc357612bc361055b565b50505190565b949350505050565b5f8083601f840112612be1575f80fd5b50813567ffffffffffffffff811115612bf8575f80fd5b602083019150836020828501011115612c0f575f80fd5b9250929050565b5f805f805f60608688031215612c2a575f80fd5b85359450602086013567ffffffffffffffff80821115612c48575f80fd5b612c5489838a01612bd1565b90965094506040880135915080821115612c6c575f80fd5b50612c7988828901612bd1565b969995985093965092949392505050565b5f8060208385031215612c9b575f80fd5b823567ffffffffffffffff811115612cb1575f80fd5b612cbd85828601612bd1565b90969095509350505050565b5f805f8060408587031215612cdc575f80fd5b843567ffffffffffffffff80821115612cf3575f80fd5b612cff88838901612bd1565b90965094506020870135915080821115612d17575f80fd5b818701915087601f830112612d2a575f80fd5b813581811115612d38575f80fd5b8860208260051b8501011115612d4c575f80fd5b95989497505060200194505050565b5f6020808352835180828501525f5b81811015612d8657858101830151858201604001528201612d6a565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b5f8085851115612dd2575f80fd5b83861115612dde575f80fd5b5050820193919092039150565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015612e2b5780818660040360031b1b83161692505b505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b60408152826040820152828460608301375f606084830101525f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85011682016060810160206060858403018186015281865180845260808501915082880194505f93505b80841015612ee75784518252938201936001939093019290820190612ec7565b5098975050505050505050565b5f60208284031215612f04575f80fd5b81518015158114612f13575f80fd5b9392505050565b818382375f9101908152919050565b5f60208284031215612f39575f80fd5b505191905056fea2646970667358221220ac5a88251da015f24b0f25a0be73e96fb607cc2f726051134c52915549351e2664736f6c63430008140033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/compiled-contracts/VerifierRollupHelperMock.json b/compiled-contracts/VerifierRollupHelperMock.json index 38a3b45b6..6e9659641 100644 --- a/compiled-contracts/VerifierRollupHelperMock.json +++ b/compiled-contracts/VerifierRollupHelperMock.json @@ -3,6 +3,29 @@ "contractName": "VerifierRollupHelperMock", "sourceName": "contracts/mocks/VerifierRollupHelperMock.sol", "abi": [ + { + "inputs": [ + { + "internalType": "bytes32", + "name": "programVKey", + "type": "bytes32" + }, + { + "internalType": "bytes", + "name": "publicValues", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "proofBytes", + "type": "bytes" + } + ], + "name": "verifyProof", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, { "inputs": [ { @@ -28,8 +51,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561000f575f80fd5b5061014e8061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610029575f3560e01c80639121da8a1461002d575b5f80fd5b61004361003b366004610084565b600192915050565b604051901515815260200160405180910390f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f80610320808486031215610097575f80fd5b6103008401858111156100a8575f80fd5b8493508561031f8601126100ba575f80fd5b604051602080820182811067ffffffffffffffff821117156100de576100de610057565b6040529286019281888511156100f2575f80fd5b5b8484101561010a57833581529281019281016100f3565b50949790965094505050505056fea2646970667358221220cd116917bfb356f793a2cef2885c134856a021af9708cf6e35bd8e053205c63b64736f6c63430008140033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610029575f3560e01c80639121da8a1461002d575b5f80fd5b61004361003b366004610084565b600192915050565b604051901515815260200160405180910390f35b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f80610320808486031215610097575f80fd5b6103008401858111156100a8575f80fd5b8493508561031f8601126100ba575f80fd5b604051602080820182811067ffffffffffffffff821117156100de576100de610057565b6040529286019281888511156100f2575f80fd5b5b8484101561010a57833581529281019281016100f3565b50949790965094505050505056fea2646970667358221220cd116917bfb356f793a2cef2885c134856a021af9708cf6e35bd8e053205c63b64736f6c63430008140033", + "bytecode": "0x608060405234801561000f575f80fd5b506102298061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806341493c60146100385780639121da8a1461004f575b5f80fd5b61004d6100463660046100be565b5050505050565b005b61006561005d36600461015f565b600192915050565b604051901515815260200160405180910390f35b5f8083601f840112610089575f80fd5b50813567ffffffffffffffff8111156100a0575f80fd5b6020830191508360208285010111156100b7575f80fd5b9250929050565b5f805f805f606086880312156100d2575f80fd5b85359450602086013567ffffffffffffffff808211156100f0575f80fd5b6100fc89838a01610079565b90965094506040880135915080821115610114575f80fd5b5061012188828901610079565b969995985093965092949392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f80610320808486031215610172575f80fd5b610300840185811115610183575f80fd5b8493508561031f860112610195575f80fd5b604051602080820182811067ffffffffffffffff821117156101b9576101b9610132565b6040529286019281888511156101cd575f80fd5b5b848410156101e557833581529281019281016101ce565b50949790965094505050505056fea264697066735822122038f5c9c95c4978a4f60bda4cf2b4c4a4e47b3482ea70dd8897f22c393d354bd964736f6c63430008140033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610034575f3560e01c806341493c60146100385780639121da8a1461004f575b5f80fd5b61004d6100463660046100be565b5050505050565b005b61006561005d36600461015f565b600192915050565b604051901515815260200160405180910390f35b5f8083601f840112610089575f80fd5b50813567ffffffffffffffff8111156100a0575f80fd5b6020830191508360208285010111156100b7575f80fd5b9250929050565b5f805f805f606086880312156100d2575f80fd5b85359450602086013567ffffffffffffffff808211156100f0575f80fd5b6100fc89838a01610079565b90965094506040880135915080821115610114575f80fd5b5061012188828901610079565b969995985093965092949392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f80610320808486031215610172575f80fd5b610300840185811115610183575f80fd5b8493508561031f860112610195575f80fd5b604051602080820182811067ffffffffffffffff821117156101b9576101b9610132565b6040529286019281888511156101cd575f80fd5b5b848410156101e557833581529281019281016101ce565b50949790965094505050505056fea264697066735822122038f5c9c95c4978a4f60bda4cf2b4c4a4e47b3482ea70dd8897f22c393d354bd964736f6c63430008140033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/contracts/PolygonZkEVMBridge.sol b/contracts/PolygonZkEVMBridge.sol index 1892f6b26..dadf50f12 100644 --- a/contracts/PolygonZkEVMBridge.sol +++ b/contracts/PolygonZkEVMBridge.sol @@ -139,7 +139,7 @@ contract PolygonZkEVMBridge is * @param destinationNetwork Network destination * @param destinationAddress Address destination * @param amount Amount of tokens - * @param token Token address, 0 address is reserved for ether + * @param token Token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token * @param forceUpdateGlobalExitRoot Indicates if the new global exit root is updated or not * @param permitData Raw data of the call `permit` of the token */ @@ -306,7 +306,7 @@ contract PolygonZkEVMBridge is * @param mainnetExitRoot Mainnet exit root * @param rollupExitRoot Rollup exit root * @param originNetwork Origin network - * @param originTokenAddress Origin token address, 0 address is reserved for ether + * @param originTokenAddress Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token * @param destinationNetwork Network destination * @param destinationAddress Address destination * @param amount Amount of tokens @@ -483,7 +483,7 @@ contract PolygonZkEVMBridge is * Since the metadata has relevance in the address deployed, this function will not return a valid * wrapped address if the metadata provided is not the original one. * @param originNetwork Origin network - * @param originTokenAddress Origin token address, 0 address is reserved for ether + * @param originTokenAddress Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token * @param name Name of the token * @param symbol Symbol of the token * @param decimals Decimals of the token @@ -520,7 +520,7 @@ contract PolygonZkEVMBridge is /** * @notice Returns the address of a wrapper using the token information if already exist * @param originNetwork Origin network - * @param originTokenAddress Origin token address, 0 address is reserved for ether + * @param originTokenAddress Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token */ function getTokenWrappedAddress( uint32 originNetwork, diff --git a/contracts/PolygonZkEVMGlobalExitRootL2.sol b/contracts/PolygonZkEVMGlobalExitRootL2.sol index 1a7bbe33c..13d0603d9 100644 --- a/contracts/PolygonZkEVMGlobalExitRootL2.sol +++ b/contracts/PolygonZkEVMGlobalExitRootL2.sol @@ -27,6 +27,12 @@ contract PolygonZkEVMGlobalExitRootL2 is IBasePolygonZkEVMGlobalExitRoot { // PolygonZkEVM Bridge address address public immutable bridgeAddress; + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + */ + uint256[50] private _gap; + /** * @param _bridgeAddress PolygonZkEVMBridge contract address */ diff --git a/contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol b/contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol index 3d558f9b0..8a2920adb 100644 --- a/contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol +++ b/contracts/interfaces/IBasePolygonZkEVMGlobalExitRoot.sol @@ -8,6 +8,31 @@ interface IBasePolygonZkEVMGlobalExitRoot { */ error OnlyAllowedContracts(); + /** + * @dev Thrown when the caller is not the coinbase neither the globalExitRootUpdater + */ + error OnlyGlobalExitRootUpdater(); + + /** + * @dev Thrown when the caller is not the globalExitRootRemover + */ + error OnlyGlobalExitRootRemover(); + + /** + * @dev Thrown when trying to insert a global exit root that is already set + */ + error GlobalExitRootAlreadySet(); + + /** + * @dev Thrown when trying to remove more global exit roots thank inserted + */ + error NotEnoughGlobalExitRootsInserted(); + + /** + * @dev Thrown when trying to remove a ger that is not the last one + */ + error NotLastInsertedGlobalExitRoot(); + function updateExitRoot(bytes32 newRollupExitRoot) external; function globalExitRootMap( diff --git a/contracts/mocks/DepositContractMock.sol b/contracts/mocks/DepositContractMock.sol index ff2ebfad2..404731b04 100644 --- a/contracts/mocks/DepositContractMock.sol +++ b/contracts/mocks/DepositContractMock.sol @@ -18,7 +18,7 @@ contract DepositContractMock is DepositContract { * @notice Given the leaf data returns the leaf value * @param leafType Leaf type * @param originNetwork Origin Network - * @param originTokenAddress Origin token address, 0 address is reserved for ether + * @param originTokenAddress Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token * @param destinationNetwork Destination network * @param destinationAddress Destination address * @param amount Amount of tokens diff --git a/contracts/mocks/ERC20Decimals.sol b/contracts/mocks/ERC20Decimals.sol new file mode 100644 index 000000000..d7c442752 --- /dev/null +++ b/contracts/mocks/ERC20Decimals.sol @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity 0.8.20; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract ERC20Decimals is ERC20 { + uint8 private _decimals; + + constructor( + string memory name, + string memory symbol, + address initialAccount, + uint256 initialBalance, + uint8 decimals_ + ) payable ERC20(name, symbol) { + _mint(initialAccount, initialBalance); + NAME_HASH = keccak256(bytes(name)); + _decimals = decimals_; + } + + function decimals() public view virtual override returns (uint8) { + return _decimals; + } + + function mint(address account, uint256 amount) public { + _mint(account, amount); + } + + function burn(uint256 amount) public { + _burn(msg.sender, amount); + } + + function transferInternal(address from, address to, uint256 value) public { + _transfer(from, to, value); + } + + function approveInternal( + address owner, + address spender, + uint256 value + ) public { + _approve(owner, spender, value); + } + + // erc20 permit + mapping(address => uint256) public nonces; + + bytes32 public constant PERMIT_TYPEHASH = + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ); + + bytes32 public NAME_HASH; + + // bytes32 public constant VERSION_HASH = + // keccak256("1") + bytes32 public constant VERSION_HASH = + 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6; + + // bytes32 public constant EIP712DOMAIN_HASH = + // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") + bytes32 public constant EIP712DOMAIN_HASH = + 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; + + function _validateSignedData( + address signer, + bytes32 encodeData, + uint8 v, + bytes32 r, + bytes32 s + ) internal view { + bytes32 domainSeparator = keccak256( + abi.encode( + EIP712DOMAIN_HASH, + NAME_HASH, + VERSION_HASH, + getChainId(), + address(this) + ) + ); + + bytes32 digest = keccak256( + abi.encodePacked("\x19\x01", domainSeparator, encodeData) + ); + address recoveredAddress = ecrecover(digest, v, r, s); + // Explicitly disallow authorizations for address(0) as ecrecover returns address(0) on malformed messages + require( + recoveredAddress != address(0) && recoveredAddress == signer, + "HEZ::_validateSignedData: INVALID_SIGNATURE" + ); + } + + function getChainId() public view returns (uint256 chainId) { + assembly { + chainId := chainid() + } + } + + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external { + require(deadline >= block.timestamp, "HEZ::permit: AUTH_EXPIRED"); + bytes32 encodeData = keccak256( + abi.encode( + PERMIT_TYPEHASH, + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ); + _validateSignedData(owner, encodeData, v, r, s); + _approve(owner, spender, value); + } + + function DOMAIN_SEPARATOR() external view returns (bytes32) { + return + keccak256( + abi.encode( + EIP712DOMAIN_HASH, + NAME_HASH, + VERSION_HASH, + getChainId(), + address(this) + ) + ); + } +} diff --git a/contracts/mocks/PolygonZkEVMBridgeMock.sol b/contracts/mocks/PolygonZkEVMBridgeMock.sol index 8a59ef889..fcb00505e 100644 --- a/contracts/mocks/PolygonZkEVMBridgeMock.sol +++ b/contracts/mocks/PolygonZkEVMBridgeMock.sol @@ -42,7 +42,7 @@ contract PolygonZkEVMBridgeMock is PolygonZkEVMBridge, OwnableUpgradeable { * @param destinationNetwork Network destination * @param destinationAddress Address destination * @param amount Amount of tokens - * @param token Token address, 0 address is reserved for ether + * @param token Token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token * @param permitData Raw data of the call `permit` of the token */ function bridgeAsset( diff --git a/contracts/mocks/VerifierRollupHelperMock.sol b/contracts/mocks/VerifierRollupHelperMock.sol index 85e6b9192..4544d6efb 100644 --- a/contracts/mocks/VerifierRollupHelperMock.sol +++ b/contracts/mocks/VerifierRollupHelperMock.sol @@ -3,12 +3,20 @@ pragma solidity 0.8.20; import "../interfaces/IVerifierRollup.sol"; +import "../v2/interfaces/ISP1Verifier.sol"; -contract VerifierRollupHelperMock is IVerifierRollup { +contract VerifierRollupHelperMock is IVerifierRollup, ISP1Verifier { function verifyProof( bytes32[24] calldata proof, uint256[1] memory pubSignals ) public pure override returns (bool) { return true; } + + // SP1 interface + function verifyProof( + bytes32 programVKey, + bytes calldata publicValues, + bytes calldata proofBytes + ) public pure {} } diff --git a/contracts/token-wrapped-bridge-compiled/TokenWrappedBridge.sol b/contracts/token-wrapped-bridge-compiled/TokenWrappedBridge.sol new file mode 100644 index 000000000..69a8bd13e --- /dev/null +++ b/contracts/token-wrapped-bridge-compiled/TokenWrappedBridge.sol @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-3.0 +// Implementation of permit based on https://github.com/WETH10/WETH10/blob/main/contracts/WETH10.sol +pragma solidity 0.8.17; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +// This contract contains the solidity code that compiles into the BASE_INIT_BYTECODE_WRAPPED_TOKEN constant on the PolygonZkEVMBridgeV2 +// This contract should remain untouched, even if it's not used directly as dependency. The main use is to verify on block explorers +// and check the implementation. +contract TokenWrappedBridge is ERC20 { + // Domain typehash + bytes32 public constant DOMAIN_TYPEHASH = + keccak256( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ); + // Permit typehash + bytes32 public constant PERMIT_TYPEHASH = + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ); + + // Version + string public constant VERSION = "1"; + + // Chain id on deployment + uint256 public immutable deploymentChainId; + + // Domain separator calculated on deployment + bytes32 private immutable _DEPLOYMENT_DOMAIN_SEPARATOR; + + // PolygonZkEVM Bridge address + address public immutable bridgeAddress; + + // Decimals + uint8 private immutable _decimals; + + // Permit nonces + mapping(address => uint256) public nonces; + + modifier onlyBridge() { + require( + msg.sender == bridgeAddress, + "TokenWrapped::onlyBridge: Not PolygonZkEVMBridge" + ); + _; + } + + constructor( + string memory name, + string memory symbol, + uint8 __decimals + ) ERC20(name, symbol) { + bridgeAddress = msg.sender; + _decimals = __decimals; + deploymentChainId = block.chainid; + _DEPLOYMENT_DOMAIN_SEPARATOR = _calculateDomainSeparator(block.chainid); + } + + function mint(address to, uint256 value) external onlyBridge { + _mint(to, value); + } + + // Notice that is not require to approve wrapped tokens to use the bridge + function burn(address account, uint256 value) external onlyBridge { + _burn(account, value); + } + + function decimals() public view virtual override returns (uint8) { + return _decimals; + } + + // Permit relative functions + function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) external { + require( + block.timestamp <= deadline, + "TokenWrapped::permit: Expired permit" + ); + + bytes32 hashStruct = keccak256( + abi.encode( + PERMIT_TYPEHASH, + owner, + spender, + value, + nonces[owner]++, + deadline + ) + ); + + bytes32 digest = keccak256( + abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), hashStruct) + ); + + address signer = ecrecover(digest, v, r, s); + require( + signer != address(0) && signer == owner, + "TokenWrapped::permit: Invalid signature" + ); + + _approve(owner, spender, value); + } + + /** + * @notice Calculate domain separator, given a chainID. + * @param chainId Current chainID + */ + function _calculateDomainSeparator( + uint256 chainId + ) private view returns (bytes32) { + return + keccak256( + abi.encode( + DOMAIN_TYPEHASH, + keccak256(bytes(name())), + keccak256(bytes(VERSION)), + chainId, + address(this) + ) + ); + } + + /// @dev Return the DOMAIN_SEPARATOR. + function DOMAIN_SEPARATOR() public view returns (bytes32) { + return + block.chainid == deploymentChainId + ? _DEPLOYMENT_DOMAIN_SEPARATOR + : _calculateDomainSeparator(block.chainid); + } +} diff --git a/contracts/v2/PolygonRollupManager.sol b/contracts/v2/PolygonRollupManager.sol index 33b4fe196..d854b593f 100644 --- a/contracts/v2/PolygonRollupManager.sol +++ b/contracts/v2/PolygonRollupManager.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.20; -import "./interfaces/IPolygonRollupManager.sol"; import "./interfaces/IPolygonZkEVMGlobalExitRootV2.sol"; import "../interfaces/IPolygonZkEVMBridge.sol"; import "./interfaces/IPolygonRollupBase.sol"; @@ -14,6 +13,9 @@ import "./lib/PolygonAccessControlUpgradeable.sol"; import "./lib/LegacyZKEVMStateVariables.sol"; import "./consensus/zkEVM/PolygonZkEVMExistentEtrog.sol"; import "./lib/PolygonConstantsBase.sol"; +import "./interfaces/IPolygonPessimisticConsensus.sol"; +import "./interfaces/ISP1Verifier.sol"; +import "./interfaces/IPolygonRollupManager.sol"; /** * Contract responsible for managing rollups and the verification of their batches. @@ -33,19 +35,23 @@ contract PolygonRollupManager is /** * @notice Struct which to store the rollup type data * @param consensusImplementation Consensus implementation ( contains the consensus logic for the transaparent proxy) - * @param verifier verifier + * @param address verifier * @param forkID fork ID - * @param rollupCompatibilityID Rollup compatibility ID, to check upgradability between rollup types + * @param rollupVerifierType Rollup compatibility ID, to check upgradability between rollup types * @param obsolete Indicates if the rollup type is obsolete * @param genesis Genesis block of the rollup, note that will only be used on creating new rollups, not upgrade them + * @param programVKey Hashed program that will be executed in case of using a "general purpose ZK verifier" e.g SP1 */ struct RollupType { address consensusImplementation; - IVerifierRollup verifier; + address verifier; uint64 forkID; - uint8 rollupCompatibilityID; + /// @custom:oz-renamed-from rollupCompatibilityID + /// @custom:oz-retyped-from uint8 + VerifierType rollupVerifierType; bool obsolete; bytes32 genesis; + bytes32 programVKey; } /** @@ -57,41 +63,109 @@ contract PolygonRollupManager is * @param forkID ForkID of the rollup * @param batchNumToStateRoot State root mapping * @param sequencedBatches Queue of batches that defines the virtual state - * @param pendingStateTransitions Pending state mapping + * @param _legacyPendingStateTransitions Pending state mapping (deprecated) * @param lastLocalExitRoot Last exit root verified, used for compute the rollupExitRoot * @param lastBatchSequenced Last batch sent by the consensus contract * @param lastVerifiedBatch Last batch verified - * @param lastPendingState Last pending state - * @param lastPendingStateConsolidated Last pending state consolidated + * @param _legacyLastPendingState Last pending state (deprecated) + * @param _legacyLastPendingStateConsolidated Last pending state consolidated (deprecated) * @param lastVerifiedBatchBeforeUpgrade Last batch verified before the last upgrade * @param rollupTypeID Rollup type ID, can be 0 if it was added as an existing rollup - * @param rollupCompatibilityID Rollup ID used for compatibility checks when upgrading + * @param rollupVerifierType Rollup ID used for compatibility checks when upgrading + * @param lastPessimisticRoot Pessimistic info, currently contains the local balance tree and the local nullifier tree hashed + * @param programVKey Hashed program that will be executed in case of using a "general purpose ZK verifier" e.g SP1 */ struct RollupData { IPolygonRollupBase rollupContract; uint64 chainID; - IVerifierRollup verifier; + address verifier; uint64 forkID; mapping(uint64 batchNum => bytes32) batchNumToStateRoot; mapping(uint64 batchNum => SequencedBatchData) sequencedBatches; - mapping(uint256 pendingStateNum => PendingState) pendingStateTransitions; + /// @custom:oz-renamed-from pendingStateTransitions + mapping(uint256 pendingStateNum => PendingState) _legacyPendingStateTransitions; + bytes32 lastLocalExitRoot; + uint64 lastBatchSequenced; + uint64 lastVerifiedBatch; + /// @custom:oz-renamed-from lastPendingState + uint64 _legacyLastPendingState; + /// @custom:oz-renamed-from lastPendingStateConsolidated + uint64 _legacyLastPendingStateConsolidated; + uint64 lastVerifiedBatchBeforeUpgrade; + uint64 rollupTypeID; + /// @custom:oz-renamed-from rollupCompatibilityID + /// @custom:oz-retyped-from uint8 + VerifierType rollupVerifierType; + bytes32 lastPessimisticRoot; + bytes32 programVKey; + } + + /** + * @notice Struct to return all the necessary rollup info: VerifierType StateTransition + * @param rollupContract Rollup consensus contract, which manages everything + * related to sequencing transactions + * @param chainID Chain ID of the rollup + * @param verifier Verifier contract + * @param forkID ForkID of the rollup + * @param lastLocalExitRoot Last exit root verified, used for compute the rollupExitRoot + * @param lastBatchSequenced Last batch sent by the consensus contract + * @param lastVerifiedBatch Last batch verified + * @param _legacyLastPendingState Last pending state (deprecated) + * @param _legacyLastPendingStateConsolidated Last pending state consolidated (deprecated) + * @param lastVerifiedBatchBeforeUpgrade Last batch verified before the last upgrade + * @param rollupTypeID Rollup type ID, can be 0 if it was added as an existing rollup + * @param rollupVerifierType Rollup ID used for compatibility checks when upgrading + */ + struct RollupDataReturn { + IPolygonRollupBase rollupContract; + uint64 chainID; + address verifier; + uint64 forkID; + bytes32 lastLocalExitRoot; + uint64 lastBatchSequenced; + uint64 lastVerifiedBatch; + uint64 _legacyLastPendingState; + uint64 _legacyLastPendingStateConsolidated; + uint64 lastVerifiedBatchBeforeUpgrade; + uint64 rollupTypeID; + VerifierType rollupVerifierType; + } + + /** + * @notice Struct which to store the rollup data of each chain + * @param rollupContract Rollup consensus contract, which manages everything + * related to sequencing transactions + * @param chainID Chain ID of the rollup + * @param verifier Verifier contract + * @param forkID ForkID of the rollup + * @param lastLocalExitRoot Last exit root verified, used for compute the rollupExitRoot + * @param lastBatchSequenced Last batch sent by the consensus contract + * @param lastVerifiedBatch Last batch verified + * @param lastVerifiedBatchBeforeUpgrade Last batch verified before the last upgrade + * @param rollupTypeID Rollup type ID, can be 0 if it was added as an existing rollup + * @param rollupVerifierType Rollup ID used for compatibility checks when upgrading + * @param lastPessimisticRoot Pessimistic info, currently contains the local balance tree and the local nullifier tree hashed + * @param programVKey Hashed program that will be executed in case of using a "general purpose ZK verifier" e.g SP1 + */ + struct RollupDataReturnV2 { + address rollupContract; + uint64 chainID; + address verifier; + uint64 forkID; bytes32 lastLocalExitRoot; uint64 lastBatchSequenced; uint64 lastVerifiedBatch; - uint64 lastPendingState; - uint64 lastPendingStateConsolidated; uint64 lastVerifiedBatchBeforeUpgrade; uint64 rollupTypeID; - uint8 rollupCompatibilityID; + VerifierType rollupVerifierType; + bytes32 lastPessimisticRoot; + bytes32 programVKey; } // Modulus zkSNARK uint256 internal constant _RFIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617; - // Max batch multiplier per verification - uint256 internal constant _MAX_BATCH_MULTIPLIER = 12; - // Max batch fee value uint256 internal constant _MAX_BATCH_FEE = 1000 ether; @@ -157,6 +231,9 @@ contract PolygonRollupManager is bytes32 internal constant _EMERGENCY_COUNCIL_ADMIN = keccak256("EMERGENCY_COUNCIL_ADMIN"); + // Current rollup manager version + string public constant ROLLUP_MANAGER_VERSION = "pessimistic"; + // Global Exit Root address IPolygonZkEVMGlobalExitRootV2 public immutable globalExitRootManager; @@ -170,13 +247,15 @@ contract PolygonRollupManager is uint32 public rollupTypeCount; // Rollup type mapping + /// @custom:oz-retyped-from PolygonRollupManagerPrevious.RollupType mapping(uint32 rollupTypeID => RollupType) public rollupTypeMap; // Number of rollups added, every new rollup will be assigned sequencially a new ID uint32 public rollupCount; // Rollups ID mapping - mapping(uint32 rollupID => RollupData) public rollupIDToRollupData; + /// @custom:oz-retyped-from PolygonRollupManagerPrevious.RollupData + mapping(uint32 rollupID => RollupData) internal _rollupIDToRollupData; // Rollups address mapping mapping(address rollupAddress => uint32 rollupID) public rollupAddressToID; @@ -196,17 +275,21 @@ contract PolygonRollupManager is // Trusted aggregator timeout, if a sequence is not verified in this time frame, // everyone can verify that sequence - uint64 public trustedAggregatorTimeout; + /// @custom:oz-renamed-from trustedAggregatorTimeout + uint64 internal __legacyTrustedAggregatorTimeout; - // Once a pending state exceeds this timeout it can be consolidated - uint64 public pendingStateTimeout; + // Once a pending state exceeds this timeout it can be consolidated (deprecated) + /// @custom:oz-renamed-from pendingStateTimeout + uint64 internal __legacyPendingStateTimeout; // Time target of the verification of a batch // Adaptively the batchFee will be updated to achieve this target - uint64 public verifyBatchTimeTarget; + /// @custom:oz-renamed-from verifyBatchTimeTarget + uint64 internal __legacyVerifyBatchTimeTarget; // Batch fee multiplier with 3 decimals that goes from 1000 - 1023 - uint16 public multiplierBatchFee; + /// @custom:oz-renamed-from multiplierBatchFee + uint16 internal __legacyMultiplierBatchFee; // Current POL fee per batch sequenced // note This variable is internal, since the view function getBatchFee is likely to be upgraded @@ -223,9 +306,10 @@ contract PolygonRollupManager is address consensusImplementation, address verifier, uint64 forkID, - uint8 rollupCompatibilityID, + VerifierType rollupVerifierType, bytes32 genesis, - string description + string description, + bytes32 programVKey ); /** @@ -252,8 +336,9 @@ contract PolygonRollupManager is uint64 forkID, address rollupAddress, uint64 chainID, - uint8 rollupCompatibilityID, - uint64 lastVerifiedBatchBeforeUpgrade + VerifierType rollupVerifierType, + uint64 lastVerifiedBatchBeforeUpgrade, + bytes32 programVKey ); /** @@ -270,17 +355,6 @@ contract PolygonRollupManager is */ event OnSequenceBatches(uint32 indexed rollupID, uint64 lastBatchSequenced); - /** - * @dev Emitted when an aggregator verifies batches - */ - event VerifyBatches( - uint32 indexed rollupID, - uint64 numBatch, - bytes32 stateRoot, - bytes32 exitRoot, - address indexed aggregator - ); - /** * @dev Emitted when the trusted aggregator verifies batches */ @@ -292,36 +366,6 @@ contract PolygonRollupManager is address indexed aggregator ); - /** - * @dev Emitted when pending state is consolidated - */ - event ConsolidatePendingState( - uint32 indexed rollupID, - uint64 numBatch, - bytes32 stateRoot, - bytes32 exitRoot, - uint64 pendingStateNum - ); - - /** - * @dev Emitted when is proved a different state given the same batches - */ - event ProveNonDeterministicPendingState( - bytes32 storedStateRoot, - bytes32 provedStateRoot - ); - - /** - * @dev Emitted when the trusted aggregator overrides pending state - */ - event OverridePendingState( - uint32 indexed rollupID, - uint64 numBatch, - bytes32 stateRoot, - bytes32 exitRoot, - address aggregator - ); - /** * @dev Emitted when rollback batches */ @@ -331,26 +375,6 @@ contract PolygonRollupManager is bytes32 accInputHashToRollback ); - /** - * @dev Emitted when is updated the trusted aggregator timeout - */ - event SetTrustedAggregatorTimeout(uint64 newTrustedAggregatorTimeout); - - /** - * @dev Emitted when is updated the pending state timeout - */ - event SetPendingStateTimeout(uint64 newPendingStateTimeout); - - /** - * @dev Emitted when is updated the multiplier batch fee - */ - event SetMultiplierBatchFee(uint16 newMultiplierBatchFee); - - /** - * @dev Emitted when is updated the verify batch timeout - */ - event SetVerifyBatchTimeTarget(uint64 newVerifyBatchTimeTarget); - /** * @dev Emitted when is updated the trusted aggregator address */ @@ -361,6 +385,11 @@ contract PolygonRollupManager is */ event SetBatchFee(uint256 newBatchFee); + /** + * @dev Emitted when rollup manager is upgraded + */ + event UpdateRollupManagerVersion(string rollupManagerVersion); + /** * @param _globalExitRootManager Global exit root manager address * @param _pol POL token address @@ -379,6 +408,13 @@ contract PolygonRollupManager is _disableInitializers(); } + /** + * Initializer function to set new rollup manager version + */ + function initialize() external virtual reinitializer(3) { + emit UpdateRollupManagerVersion(ROLLUP_MANAGER_VERSION); + } + /////////////////////////////////////// // Rollups management functions /////////////////////////////////////// @@ -388,36 +424,49 @@ contract PolygonRollupManager is * @param consensusImplementation Consensus implementation * @param verifier Verifier address * @param forkID ForkID of the verifier + * @param rollupVerifierType rollup verifier type * @param genesis Genesis block of the rollup * @param description Description of the rollup type + * @param programVKey Hashed program that will be executed in case of using a "general purpose ZK verifier" e.g SP1 */ function addNewRollupType( address consensusImplementation, - IVerifierRollup verifier, + address verifier, uint64 forkID, - uint8 rollupCompatibilityID, + VerifierType rollupVerifierType, bytes32 genesis, - string memory description + string memory description, + bytes32 programVKey ) external onlyRole(_ADD_ROLLUP_TYPE_ROLE) { uint32 rollupTypeID = ++rollupTypeCount; + if (rollupVerifierType == VerifierType.Pessimistic) { + // No genesis on pessimistic rollups + if (genesis != bytes32(0)) revert InvalidRollupType(); + } else { + // No programVKey on state transition rollups + if (programVKey != bytes32(0)) revert InvalidRollupType(); + } + rollupTypeMap[rollupTypeID] = RollupType({ consensusImplementation: consensusImplementation, verifier: verifier, forkID: forkID, - rollupCompatibilityID: rollupCompatibilityID, + rollupVerifierType: rollupVerifierType, obsolete: false, - genesis: genesis + genesis: genesis, + programVKey: programVKey }); emit AddNewRollupType( rollupTypeID, consensusImplementation, - address(verifier), + verifier, forkID, - rollupCompatibilityID, + rollupVerifierType, genesis, - description + description, + programVKey ); } @@ -435,7 +484,7 @@ contract PolygonRollupManager is // Check rollup type is not obsolete RollupType storage currentRollupType = rollupTypeMap[rollupTypeID]; - if (currentRollupType.obsolete == true) { + if (currentRollupType.obsolete) { revert RollupTypeObsolete(); } @@ -471,7 +520,7 @@ contract PolygonRollupManager is // Check rollup type is not obsolete RollupType storage rollupType = rollupTypeMap[rollupTypeID]; - if (rollupType.obsolete == true) { + if (rollupType.obsolete) { revert RollupTypeObsolete(); } @@ -503,7 +552,7 @@ contract PolygonRollupManager is // Store rollup data rollupAddressToID[rollupAddress] = rollupID; - RollupData storage rollup = rollupIDToRollupData[rollupID]; + RollupData storage rollup = _rollupIDToRollupData[rollupID]; rollup.rollupContract = IPolygonRollupBase(rollupAddress); rollup.forkID = rollupType.forkID; @@ -511,7 +560,8 @@ contract PolygonRollupManager is rollup.chainID = chainID; rollup.batchNumToStateRoot[0] = rollupType.genesis; rollup.rollupTypeID = rollupTypeID; - rollup.rollupCompatibilityID = rollupType.rollupCompatibilityID; + rollup.rollupVerifierType = rollupType.rollupVerifierType; + rollup.programVKey = rollupType.programVKey; emit CreateNewRollup( rollupID, @@ -539,16 +589,18 @@ contract PolygonRollupManager is * @param verifier Verifier address, must be added before * @param forkID Fork id of the added rollup * @param chainID Chain id of the added rollup - * @param genesis Genesis block for this rollup - * @param rollupCompatibilityID Compatibility ID for the added rollup + * @param initRoot Genesis block for StateTransitionChains & localExitRoot for pessimistic chain + * @param rollupVerifierType Compatibility ID for the added rollup + * @param programVKey Hashed program that will be executed in case of using a "general purpose ZK verifier" e.g SP1 */ function addExistingRollup( IPolygonRollupBase rollupAddress, - IVerifierRollup verifier, + address verifier, uint64 forkID, uint64 chainID, - bytes32 genesis, - uint8 rollupCompatibilityID + bytes32 initRoot, + VerifierType rollupVerifierType, + bytes32 programVKey ) external onlyRole(_ADD_EXISTING_ROLLUP_ROLE) { // Check chainID nullifier if (chainIDToRollupID[chainID] != 0) { @@ -560,37 +612,13 @@ contract PolygonRollupManager is if (chainID > type(uint32).max) { revert ChainIDOutOfRange(); } + // Check if rollup address was already added if (rollupAddressToID[address(rollupAddress)] != 0) { revert RollupAddressAlreadyExist(); } - RollupData storage rollup = _addExistingRollup( - rollupAddress, - verifier, - forkID, - chainID, - rollupCompatibilityID - ); - rollup.batchNumToStateRoot[0] = genesis; - } - - /** - * @notice Add an already deployed rollup - * note that this rollup does not follow any rollupType - * @param rollupAddress Rollup address - * @param verifier Verifier address, must be added before - * @param forkID Fork id of the added rollup - * @param chainID Chain id of the added rollup - * @param rollupCompatibilityID Compatibility ID for the added rollup - */ - function _addExistingRollup( - IPolygonRollupBase rollupAddress, - IVerifierRollup verifier, - uint64 forkID, - uint64 chainID, - uint8 rollupCompatibilityID - ) internal returns (RollupData storage rollup) { + // Increment rollup count uint32 rollupID = ++rollupCount; // Set chainID nullifier @@ -599,21 +627,30 @@ contract PolygonRollupManager is // Store rollup data rollupAddressToID[address(rollupAddress)] = rollupID; - rollup = rollupIDToRollupData[rollupID]; + RollupData storage rollup = _rollupIDToRollupData[rollupID]; rollup.rollupContract = rollupAddress; rollup.forkID = forkID; rollup.verifier = verifier; rollup.chainID = chainID; - rollup.rollupCompatibilityID = rollupCompatibilityID; - // rollup type is 0, since it does not follow any rollup type + rollup.rollupVerifierType = rollupVerifierType; + + // Check verifier type + if (rollupVerifierType == VerifierType.Pessimistic) { + rollup.programVKey = programVKey; + rollup.lastLocalExitRoot = initRoot; + } else { + rollup.batchNumToStateRoot[0] = initRoot; + } + // rollup type is 0, since it does not follow any rollup type emit AddExistingRollup( rollupID, forkID, address(rollupAddress), chainID, - rollupCompatibilityID, - 0 + rollupVerifierType, + 0, + programVKey ); } @@ -633,7 +670,7 @@ contract PolygonRollupManager is } // Check all sequences are verified before upgrading - RollupData storage rollup = rollupIDToRollupData[ + RollupData storage rollup = _rollupIDToRollupData[ rollupAddressToID[address(rollupContract)] ]; @@ -686,7 +723,7 @@ contract PolygonRollupManager is revert RollupMustExist(); } - RollupData storage rollup = rollupIDToRollupData[rollupID]; + RollupData storage rollup = _rollupIDToRollupData[rollupID]; // The update must be to a new rollup type if (rollup.rollupTypeID == newRollupTypeID) { @@ -696,27 +733,21 @@ contract PolygonRollupManager is RollupType storage newRollupType = rollupTypeMap[newRollupTypeID]; // Check rollup type is not obsolete - if (newRollupType.obsolete == true) { + if (newRollupType.obsolete) { revert RollupTypeObsolete(); } - // Check compatibility of the rollups - if ( - rollup.rollupCompatibilityID != newRollupType.rollupCompatibilityID - ) { + // Check rollup types + if (rollup.rollupVerifierType != newRollupType.rollupVerifierType) { revert UpdateNotCompatible(); } // Update rollup parameters rollup.verifier = newRollupType.verifier; rollup.forkID = newRollupType.forkID; + rollup.programVKey = newRollupType.programVKey; rollup.rollupTypeID = newRollupTypeID; - // review fix to vulnerability front running attack - if (rollup.lastPendingState != rollup.lastPendingStateConsolidated) { - revert CannotUpdateWithUnconsolidatedPendingState(); - } - uint64 lastVerifiedBatch = getLastVerifiedBatch(rollupID); rollup.lastVerifiedBatchBeforeUpgrade = lastVerifiedBatch; @@ -731,6 +762,7 @@ contract PolygonRollupManager is /** * @notice Rollback batches of the target rollup + * Only applies to state transition rollups * @param rollupContract Rollup consensus proxy address * @param targetBatch Batch to rollback up to but not including this batch */ @@ -753,7 +785,12 @@ contract PolygonRollupManager is } // Load rollup - RollupData storage rollup = rollupIDToRollupData[rollupID]; + RollupData storage rollup = _rollupIDToRollupData[rollupID]; + + if (rollup.rollupVerifierType != VerifierType.StateTransition) { + revert OnlyStateTransitionChains(); + } + uint64 lastBatchSequenced = rollup.lastBatchSequenced; // Batch to rollback should be already sequenced @@ -791,18 +828,6 @@ contract PolygonRollupManager is // Update totalSequencedBatches totalSequencedBatches -= lastBatchSequenced - targetBatch; - // Check pending state - if (rollup.lastPendingState > 0) { - // update total verified batches - uint64 currentLastVerifiedBatch = _getLastVerifiedBatch(rollup); - totalVerifiedBatches -= - currentLastVerifiedBatch - - rollup.lastVerifiedBatch; - - rollup.lastPendingState = 0; - rollup.lastPendingStateConsolidated = 0; - } - // Clean pending state if any rollupContract.rollbackBatches( targetBatch, @@ -840,7 +865,11 @@ contract PolygonRollupManager is revert MustSequenceSomeBatch(); } - RollupData storage rollup = rollupIDToRollupData[rollupID]; + RollupData storage rollup = _rollupIDToRollupData[rollupID]; + + if (rollup.rollupVerifierType != VerifierType.StateTransition) { + revert OnlyStateTransitionChains(); + } // Update total sequence parameters totalSequencedBatches += newSequencedBatches; @@ -857,18 +886,15 @@ contract PolygonRollupManager is previousLastBatchSequenced: previousLastBatchSequenced }); - // Consolidate pending state if possible - _tryConsolidatePendingState(rollup); - emit OnSequenceBatches(rollupID, newLastBatchSequenced); return newLastBatchSequenced; } /** - * @notice Allows an aggregator to verify multiple batches + * @notice Allows a trusted aggregator to verify multiple batches * @param rollupID Rollup identifier - * @param pendingStateNum Init pending state, 0 if consolidated state is used + * @param pendingStateNum Init pending state, 0 if consolidated state is used (deprecated) * @param initNumBatch Batch which the aggregator starts the verification * @param finalNewBatch Last batch aggregator intends to verify * @param newLocalExitRoot New local exit root once the batch is processed @@ -876,7 +902,7 @@ contract PolygonRollupManager is * @param beneficiary Address that will receive the verification reward * @param proof Fflonk proof */ - function verifyBatches( + function verifyBatchesTrustedAggregator( uint32 rollupID, uint64 pendingStateNum, uint64 initNumBatch, @@ -885,102 +911,21 @@ contract PolygonRollupManager is bytes32 newStateRoot, address beneficiary, bytes32[24] calldata proof - ) external ifNotEmergencyState { - RollupData storage rollup = rollupIDToRollupData[rollupID]; - - // Check if the trusted aggregator timeout expired, - // Note that the sequencedBatches struct must exists for this finalNewBatch, if not newAccInputHash will be 0 - if ( - rollup.sequencedBatches[finalNewBatch].sequencedTimestamp + - trustedAggregatorTimeout > - block.timestamp - ) { - revert TrustedAggregatorTimeoutNotExpired(); - } - - if (finalNewBatch - initNumBatch > _MAX_VERIFY_BATCHES) { - revert ExceedMaxVerifyBatches(); + ) external onlyRole(_TRUSTED_AGGREGATOR_ROLE) { + // Pending state became deprecated, + // It's still there just to have backwards compatibility interface + if (pendingStateNum != 0) { + revert PendingStateNumExist(); } - _verifyAndRewardBatches( - rollup, - pendingStateNum, - initNumBatch, - finalNewBatch, - newLocalExitRoot, - newStateRoot, - beneficiary, - proof - ); + RollupData storage rollup = _rollupIDToRollupData[rollupID]; - // Update batch fees - _updateBatchFee(rollup, finalNewBatch); - - if (pendingStateTimeout == 0) { - // Consolidate state - rollup.lastVerifiedBatch = finalNewBatch; - rollup.batchNumToStateRoot[finalNewBatch] = newStateRoot; - rollup.lastLocalExitRoot = newLocalExitRoot; - - // Clean pending state if any - if (rollup.lastPendingState > 0) { - rollup.lastPendingState = 0; - rollup.lastPendingStateConsolidated = 0; - } - - // Interact with globalExitRootManager - globalExitRootManager.updateExitRoot(getRollupExitRoot()); - } else { - // Consolidate pending state if possible - _tryConsolidatePendingState(rollup); - - // Update pending state - rollup.lastPendingState++; - rollup.pendingStateTransitions[ - rollup.lastPendingState - ] = PendingState({ - timestamp: uint64(block.timestamp), - lastVerifiedBatch: finalNewBatch, - exitRoot: newLocalExitRoot, - stateRoot: newStateRoot - }); + if (rollup.rollupVerifierType != VerifierType.StateTransition) { + revert OnlyStateTransitionChains(); } - emit VerifyBatches( - rollupID, - finalNewBatch, - newStateRoot, - newLocalExitRoot, - msg.sender - ); - } - - /** - * @notice Allows a trusted aggregator to verify multiple batches - * @param rollupID Rollup identifier - * @param pendingStateNum Init pending state, 0 if consolidated state is used - * @param initNumBatch Batch which the aggregator starts the verification - * @param finalNewBatch Last batch aggregator intends to verify - * @param newLocalExitRoot New local exit root once the batch is processed - * @param newStateRoot New State root once the batch is processed - * @param beneficiary Address that will receive the verification reward - * @param proof Fflonk proof - */ - function verifyBatchesTrustedAggregator( - uint32 rollupID, - uint64 pendingStateNum, - uint64 initNumBatch, - uint64 finalNewBatch, - bytes32 newLocalExitRoot, - bytes32 newStateRoot, - address beneficiary, - bytes32[24] calldata proof - ) external onlyRole(_TRUSTED_AGGREGATOR_ROLE) { - RollupData storage rollup = rollupIDToRollupData[rollupID]; - _verifyAndRewardBatches( rollup, - pendingStateNum, initNumBatch, finalNewBatch, newLocalExitRoot, @@ -994,12 +939,6 @@ contract PolygonRollupManager is rollup.batchNumToStateRoot[finalNewBatch] = newStateRoot; rollup.lastLocalExitRoot = newLocalExitRoot; - // Clean pending state if any - if (rollup.lastPendingState > 0) { - rollup.lastPendingState = 0; - rollup.lastPendingStateConsolidated = 0; - } - // Interact with globalExitRootManager globalExitRootManager.updateExitRoot(getRollupExitRoot()); @@ -1015,7 +954,6 @@ contract PolygonRollupManager is /** * @notice Verify and reward batches internal function * @param rollup Rollup Data storage pointer that will be used to the verification - * @param pendingStateNum Init pending state, 0 if consolidated state is used * @param initNumBatch Batch which the aggregator starts the verification * @param finalNewBatch Last batch aggregator intends to verify * @param newLocalExitRoot New local exit root once the batch is processed @@ -1025,7 +963,6 @@ contract PolygonRollupManager is */ function _verifyAndRewardBatches( RollupData storage rollup, - uint64 pendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, @@ -1034,43 +971,23 @@ contract PolygonRollupManager is bytes32[24] calldata proof ) internal virtual { bytes32 oldStateRoot; + uint64 currentLastVerifiedBatch = _getLastVerifiedBatch(rollup); if (initNumBatch < rollup.lastVerifiedBatchBeforeUpgrade) { revert InitBatchMustMatchCurrentForkID(); } - // Use pending state if specified, otherwise use consolidated state - if (pendingStateNum != 0) { - // Check that pending state exist - // Already consolidated pending states can be used aswell - if (pendingStateNum > rollup.lastPendingState) { - revert PendingStateDoesNotExist(); - } - - // Check choosen pending state - PendingState storage currentPendingState = rollup - .pendingStateTransitions[pendingStateNum]; - - // Get oldStateRoot from pending batch - oldStateRoot = currentPendingState.stateRoot; + // Use consolidated state + oldStateRoot = rollup.batchNumToStateRoot[initNumBatch]; - // Check initNumBatch matches the pending state - if (initNumBatch != currentPendingState.lastVerifiedBatch) { - revert InitNumBatchDoesNotMatchPendingState(); - } - } else { - // Use consolidated state - oldStateRoot = rollup.batchNumToStateRoot[initNumBatch]; - - if (oldStateRoot == bytes32(0)) { - revert OldStateRootDoesNotExist(); - } + if (oldStateRoot == bytes32(0)) { + revert OldStateRootDoesNotExist(); + } - // Check initNumBatch is inside the range, sanity check - if (initNumBatch > currentLastVerifiedBatch) { - revert InitNumBatchAboveLastVerifiedBatch(); - } + // Check initNumBatch is inside the range, sanity check + if (initNumBatch > currentLastVerifiedBatch) { + revert InitNumBatchAboveLastVerifiedBatch(); } // Check final batch @@ -1092,7 +1009,9 @@ contract PolygonRollupManager is uint256 inputSnark = uint256(sha256(snarkHashBytes)) % _RFIELD; // Verify proof - if (!rollup.verifier.verifyProof(proof, [inputSnark])) { + if ( + !IVerifierRollup(rollup.verifier).verifyProof(proof, [inputSnark]) + ) { revert InvalidProof(); } @@ -1117,408 +1036,74 @@ contract PolygonRollupManager is } /** - * @notice Internal function to consolidate the state automatically once sequence or verify batches are called - * It tries to consolidate the first and the middle pending state in the queue - */ - function _tryConsolidatePendingState(RollupData storage rollup) internal { - // Check if there's any state to consolidate - if (rollup.lastPendingState > rollup.lastPendingStateConsolidated) { - // Check if it's possible to consolidate the next pending state - uint64 nextPendingState = rollup.lastPendingStateConsolidated + 1; - if (_isPendingStateConsolidable(rollup, nextPendingState)) { - // Check middle pending state ( binary search of 1 step) - uint64 middlePendingState = nextPendingState + - (rollup.lastPendingState - nextPendingState) / - 2; - - // Try to consolidate it, and if not, consolidate the nextPendingState - if (_isPendingStateConsolidable(rollup, middlePendingState)) { - _consolidatePendingState(rollup, middlePendingState); - } else { - _consolidatePendingState(rollup, nextPendingState); - } - } - } - } - - /** - * @notice Allows to consolidate any pending state that has already exceed the pendingStateTimeout - * Can be called by the trusted aggregator, which can consolidate any state without the timeout restrictions + * @notice Allows a trusted aggregator to verify pessimistic proof * @param rollupID Rollup identifier - * @param pendingStateNum Pending state to consolidate + * @param l1InfoTreeLeafCount Count of the L1InfoTree leaf that will be used to verify imported bridge exits + * @param newLocalExitRoot New local exit root + * @param newPessimisticRoot New pessimistic information, Hash(localBalanceTreeRoot, nullifierTreeRoot) + * @param proof SP1 proof (Plonk) */ - function consolidatePendingState( + function verifyPessimisticTrustedAggregator( uint32 rollupID, - uint64 pendingStateNum - ) external { - RollupData storage rollup = rollupIDToRollupData[rollupID]; - // Check if pending state can be consolidated - // If trusted aggregator is the sender, do not check the timeout or the emergency state - if (!hasRole(_TRUSTED_AGGREGATOR_ROLE, msg.sender)) { - if (isEmergencyState) { - revert OnlyNotEmergencyState(); - } + uint32 l1InfoTreeLeafCount, + bytes32 newLocalExitRoot, + bytes32 newPessimisticRoot, + bytes calldata proof + ) external onlyRole(_TRUSTED_AGGREGATOR_ROLE) { + RollupData storage rollup = _rollupIDToRollupData[rollupID]; - if (!_isPendingStateConsolidable(rollup, pendingStateNum)) { - revert PendingStateNotConsolidable(); - } + // Only for pessimistic verifiers + if (rollup.rollupVerifierType != VerifierType.Pessimistic) { + revert OnlyChainsWithPessimisticProofs(); } - _consolidatePendingState(rollup, pendingStateNum); - } - /** - * @notice Internal function to consolidate any pending state that has already exceed the pendingStateTimeout - * @param rollup Rollup data storage pointer - * @param pendingStateNum Pending state to consolidate - */ - function _consolidatePendingState( - RollupData storage rollup, - uint64 pendingStateNum - ) internal { - // Check if pendingStateNum is in correct range - // - not consolidated (implicity checks that is not 0) - // - exist ( has been added) - if ( - pendingStateNum <= rollup.lastPendingStateConsolidated || - pendingStateNum > rollup.lastPendingState - ) { - revert PendingStateInvalid(); - } - - PendingState storage currentPendingState = rollup - .pendingStateTransitions[pendingStateNum]; - - // Update state - uint64 newLastVerifiedBatch = currentPendingState.lastVerifiedBatch; - rollup.lastVerifiedBatch = newLastVerifiedBatch; - rollup.batchNumToStateRoot[newLastVerifiedBatch] = currentPendingState - .stateRoot; - rollup.lastLocalExitRoot = currentPendingState.exitRoot; - - // Update pending state - rollup.lastPendingStateConsolidated = pendingStateNum; - - // Interact with globalExitRootManager - globalExitRootManager.updateExitRoot(getRollupExitRoot()); - - emit ConsolidatePendingState( - rollupAddressToID[address(rollup.rollupContract)], - newLastVerifiedBatch, - currentPendingState.stateRoot, - currentPendingState.exitRoot, - pendingStateNum + // Check l1InfoTreeLeafCount has a valid l1InfoTreeRoot + bytes32 l1InfoRoot = globalExitRootManager.l1InfoRootMap( + l1InfoTreeLeafCount ); - } - ///////////////////////////////// - // Soundness protection functions - ///////////////////////////////// - - /** - * @notice Allows the trusted aggregator to override the pending state - * if it's possible to prove a different state root given the same batches - * @param rollupID Rollup identifier - * @param initPendingStateNum Init pending state, 0 if consolidated state is used - * @param finalPendingStateNum Final pending state, that will be used to compare with the newStateRoot - * @param initNumBatch Batch which the aggregator starts the verification - * @param finalNewBatch Last batch aggregator intends to verify - * @param newLocalExitRoot New local exit root once the batch is processed - * @param newStateRoot New State root once the batch is processed - * @param proof Fflonk proof - */ - function overridePendingState( - uint32 rollupID, - uint64 initPendingStateNum, - uint64 finalPendingStateNum, - uint64 initNumBatch, - uint64 finalNewBatch, - bytes32 newLocalExitRoot, - bytes32 newStateRoot, - bytes32[24] calldata proof - ) external onlyRole(_TRUSTED_AGGREGATOR_ROLE) { - RollupData storage rollup = rollupIDToRollupData[rollupID]; + if (l1InfoRoot == bytes32(0)) { + revert L1InfoTreeLeafCountInvalid(); + } - _proveDistinctPendingState( + bytes memory inputPessimisticBytes = _getInputPessimisticBytes( + rollupID, rollup, - initPendingStateNum, - finalPendingStateNum, - initNumBatch, - finalNewBatch, + l1InfoRoot, newLocalExitRoot, - newStateRoot, + newPessimisticRoot + ); + + // Verify proof + ISP1Verifier(rollup.verifier).verifyProof( + rollup.programVKey, + inputPessimisticBytes, proof ); + // TODO: Since there are no batches we could have either: + // A pool of POL for pessimistic, or make the fee system offchain, since there are already a + // dependency with the trusted aggregator ( or pessimistic aggregator) + + // Update aggregation parameters + lastAggregationTimestamp = uint64(block.timestamp); // Consolidate state - rollup.lastVerifiedBatch = finalNewBatch; - rollup.batchNumToStateRoot[finalNewBatch] = newStateRoot; rollup.lastLocalExitRoot = newLocalExitRoot; - - // Clean pending state if any - if (rollup.lastPendingState > 0) { - rollup.lastPendingState = 0; - rollup.lastPendingStateConsolidated = 0; - } + rollup.lastPessimisticRoot = newPessimisticRoot; // Interact with globalExitRootManager globalExitRootManager.updateExitRoot(getRollupExitRoot()); - // Update trusted aggregator timeout to max - trustedAggregatorTimeout = _HALT_AGGREGATION_TIMEOUT; - - emit OverridePendingState( + // Same event as verifyBatches to support current bridge service to synchronize everything + emit VerifyBatchesTrustedAggregator( rollupID, - finalNewBatch, - newStateRoot, + 0, // final batch: does not apply in pessimistic + bytes32(0), // new state root: does not apply in pessimistic newLocalExitRoot, msg.sender ); } - /** - * @notice Allows activate the emergency state if its possible to prove a different state root given the same batches - * @param rollupID Rollup identifier - * @param initPendingStateNum Init pending state, 0 if consolidated state is used - * @param finalPendingStateNum Final pending state, that will be used to compare with the newStateRoot - * @param initNumBatch Batch which the aggregator starts the verification - * @param finalNewBatch Last batch aggregator intends to verify - * @param newLocalExitRoot New local exit root once the batch is processed - * @param newStateRoot New State root once the batch is processed - * @param proof Fflonk proof - */ - function proveNonDeterministicPendingState( - uint32 rollupID, - uint64 initPendingStateNum, - uint64 finalPendingStateNum, - uint64 initNumBatch, - uint64 finalNewBatch, - bytes32 newLocalExitRoot, - bytes32 newStateRoot, - bytes32[24] calldata proof - ) external ifNotEmergencyState { - RollupData storage rollup = rollupIDToRollupData[rollupID]; - - _proveDistinctPendingState( - rollup, - initPendingStateNum, - finalPendingStateNum, - initNumBatch, - finalNewBatch, - newLocalExitRoot, - newStateRoot, - proof - ); - - emit ProveNonDeterministicPendingState( - rollup.pendingStateTransitions[finalPendingStateNum].stateRoot, - newStateRoot - ); - - // Activate emergency state - _activateEmergencyState(); - } - - /** - * @notice Internal function that proves a different state root given the same batches to verify - * @param rollup Rollup Data struct that will be checked - * @param initPendingStateNum Init pending state, 0 if consolidated state is used - * @param finalPendingStateNum Final pending state, that will be used to compare with the newStateRoot - * @param initNumBatch Batch which the aggregator starts the verification - * @param finalNewBatch Last batch aggregator intends to verify - * @param newLocalExitRoot New local exit root once the batch is processed - * @param newStateRoot New State root once the batch is processed - * @param proof Fflonk proof - */ - function _proveDistinctPendingState( - RollupData storage rollup, - uint64 initPendingStateNum, - uint64 finalPendingStateNum, - uint64 initNumBatch, - uint64 finalNewBatch, - bytes32 newLocalExitRoot, - bytes32 newStateRoot, - bytes32[24] calldata proof - ) internal view virtual { - bytes32 oldStateRoot; - - if (initNumBatch < rollup.lastVerifiedBatchBeforeUpgrade) { - revert InitBatchMustMatchCurrentForkID(); - } - - // Use pending state if specified, otherwise use consolidated state - if (initPendingStateNum != 0) { - // Check that pending state exist - // Already consolidated pending states can be used aswell - if (initPendingStateNum > rollup.lastPendingState) { - revert PendingStateDoesNotExist(); - } - - // Check choosen pending state - PendingState storage initPendingState = rollup - .pendingStateTransitions[initPendingStateNum]; - - // Get oldStateRoot from init pending state - oldStateRoot = initPendingState.stateRoot; - - // Check initNumBatch matches the init pending state - if (initNumBatch != initPendingState.lastVerifiedBatch) { - revert InitNumBatchDoesNotMatchPendingState(); - } - } else { - // Use consolidated state - oldStateRoot = rollup.batchNumToStateRoot[initNumBatch]; - if (oldStateRoot == bytes32(0)) { - revert OldStateRootDoesNotExist(); - } - - // Check initNumBatch is inside the range, sanity check - if (initNumBatch > rollup.lastVerifiedBatch) { - revert InitNumBatchAboveLastVerifiedBatch(); - } - } - - // Assert final pending state num is in correct range - // - exist ( has been added) - // - bigger than the initPendingstate - // - not consolidated - if ( - finalPendingStateNum > rollup.lastPendingState || - finalPendingStateNum <= initPendingStateNum || - finalPendingStateNum <= rollup.lastPendingStateConsolidated - ) { - revert FinalPendingStateNumInvalid(); - } - - // Check final num batch - if ( - finalNewBatch != - rollup - .pendingStateTransitions[finalPendingStateNum] - .lastVerifiedBatch - ) { - revert FinalNumBatchDoesNotMatchPendingState(); - } - - // Get snark bytes - bytes memory snarkHashBytes = _getInputSnarkBytes( - rollup, - initNumBatch, - finalNewBatch, - newLocalExitRoot, - oldStateRoot, - newStateRoot - ); - - // Calulate the snark input - uint256 inputSnark = uint256(sha256(snarkHashBytes)) % _RFIELD; - - // Verify proof - if (!rollup.verifier.verifyProof(proof, [inputSnark])) { - revert InvalidProof(); - } - - if ( - rollup.pendingStateTransitions[finalPendingStateNum].stateRoot == - newStateRoot - ) { - revert StoredRootMustBeDifferentThanNewRoot(); - } - } - - /** - * @notice Function to update the batch fee based on the new verified batches - * The batch fee will not be updated when the trusted aggregator verifies batches - * @param newLastVerifiedBatch New last verified batch - */ - function _updateBatchFee( - RollupData storage rollup, - uint64 newLastVerifiedBatch - ) internal { - uint64 currentLastVerifiedBatch = _getLastVerifiedBatch(rollup); - uint64 currentBatch = newLastVerifiedBatch; - - uint256 totalBatchesAboveTarget; - uint256 newBatchesVerified = newLastVerifiedBatch - - currentLastVerifiedBatch; - - uint256 targetTimestamp = block.timestamp - verifyBatchTimeTarget; - - while (currentBatch != currentLastVerifiedBatch) { - // Load sequenced batchdata - SequencedBatchData storage currentSequencedBatchData = rollup - .sequencedBatches[currentBatch]; - - // Check if timestamp is below the verifyBatchTimeTarget - if ( - targetTimestamp < currentSequencedBatchData.sequencedTimestamp - ) { - // update currentBatch - currentBatch = currentSequencedBatchData - .previousLastBatchSequenced; - } else { - // The rest of batches will be above - totalBatchesAboveTarget = - currentBatch - - currentLastVerifiedBatch; - break; - } - } - - uint256 totalBatchesBelowTarget = newBatchesVerified - - totalBatchesAboveTarget; - - // _MAX_BATCH_FEE --> (< 70 bits) - // multiplierBatchFee --> (< 10 bits) - // _MAX_BATCH_MULTIPLIER = 12 - // multiplierBatchFee ** _MAX_BATCH_MULTIPLIER --> (< 128 bits) - // batchFee * (multiplierBatchFee ** _MAX_BATCH_MULTIPLIER)--> - // (< 70 bits) * (< 128 bits) = < 256 bits - - // Since all the following operations cannot overflow, we can optimize this operations with unchecked - unchecked { - if (totalBatchesBelowTarget < totalBatchesAboveTarget) { - // There are more batches above target, fee is multiplied - uint256 diffBatches = totalBatchesAboveTarget - - totalBatchesBelowTarget; - - diffBatches = diffBatches > _MAX_BATCH_MULTIPLIER - ? _MAX_BATCH_MULTIPLIER - : diffBatches; - - // For every multiplierBatchFee multiplication we must shift 3 zeroes since we have 3 decimals - _batchFee = - (_batchFee * (uint256(multiplierBatchFee) ** diffBatches)) / - (uint256(1000) ** diffBatches); - } else { - // There are more batches below target, fee is divided - uint256 diffBatches = totalBatchesBelowTarget - - totalBatchesAboveTarget; - - diffBatches = diffBatches > _MAX_BATCH_MULTIPLIER - ? _MAX_BATCH_MULTIPLIER - : diffBatches; - - // For every multiplierBatchFee multiplication we must shift 3 zeroes since we have 3 decimals - uint256 accDivisor = (uint256(1 ether) * - (uint256(multiplierBatchFee) ** diffBatches)) / - (uint256(1000) ** diffBatches); - - // multiplyFactor = multiplierBatchFee ** diffBatches / 10 ** (diffBatches * 3) - // accDivisor = 1E18 * multiplyFactor - // 1E18 * batchFee / accDivisor = batchFee / multiplyFactor - // < 60 bits * < 70 bits / ~60 bits --> overflow not possible - _batchFee = (uint256(1 ether) * _batchFee) / accDivisor; - } - } - - // Batch fee must remain inside a range - if (_batchFee > _MAX_BATCH_FEE) { - _batchFee = _MAX_BATCH_FEE; - } else if (_batchFee < _MIN_BATCH_FEE) { - _batchFee = _MIN_BATCH_FEE; - } - } - //////////////////////// // Emergency state functions //////////////////////// @@ -1575,73 +1160,6 @@ contract PolygonRollupManager is // Setter functions ////////////////// - /** - * @notice Set a new pending state timeout - * The timeout can only be lowered, except if emergency state is active - * @param newTrustedAggregatorTimeout Trusted aggregator timeout - */ - function setTrustedAggregatorTimeout( - uint64 newTrustedAggregatorTimeout - ) external onlyRole(_TWEAK_PARAMETERS_ROLE) { - if (!isEmergencyState) { - if (newTrustedAggregatorTimeout >= trustedAggregatorTimeout) { - revert NewTrustedAggregatorTimeoutMustBeLower(); - } - } - - trustedAggregatorTimeout = newTrustedAggregatorTimeout; - emit SetTrustedAggregatorTimeout(newTrustedAggregatorTimeout); - } - - /** - * @notice Set a new trusted aggregator timeout - * The timeout can only be lowered, except if emergency state is active - * @param newPendingStateTimeout Trusted aggregator timeout - */ - function setPendingStateTimeout( - uint64 newPendingStateTimeout - ) external onlyRole(_TWEAK_PARAMETERS_ROLE) { - if (!isEmergencyState) { - if (newPendingStateTimeout >= pendingStateTimeout) { - revert NewPendingStateTimeoutMustBeLower(); - } - } - - pendingStateTimeout = newPendingStateTimeout; - emit SetPendingStateTimeout(newPendingStateTimeout); - } - - /** - * @notice Set a new multiplier batch fee - * @param newMultiplierBatchFee multiplier batch fee - */ - function setMultiplierBatchFee( - uint16 newMultiplierBatchFee - ) external onlyRole(_TWEAK_PARAMETERS_ROLE) { - if (newMultiplierBatchFee < 1000 || newMultiplierBatchFee > 1023) { - revert InvalidRangeMultiplierBatchFee(); - } - - multiplierBatchFee = newMultiplierBatchFee; - emit SetMultiplierBatchFee(newMultiplierBatchFee); - } - - /** - * @notice Set a new verify batch time target - * This value will only be relevant once the aggregation is decentralized, so - * the trustedAggregatorTimeout should be zero or very close to zero - * @param newVerifyBatchTimeTarget Verify batch time target - */ - function setVerifyBatchTimeTarget( - uint64 newVerifyBatchTimeTarget - ) external onlyRole(_TWEAK_PARAMETERS_ROLE) { - if (newVerifyBatchTimeTarget > 1 days) { - revert InvalidRangeBatchTimeTarget(); - } - verifyBatchTimeTarget = newVerifyBatchTimeTarget; - emit SetVerifyBatchTimeTarget(newVerifyBatchTimeTarget); - } - /** * @notice Set the current batch fee * @param newBatchFee new batch fee @@ -1680,7 +1198,7 @@ contract PolygonRollupManager is // In the first iteration the nodes will be the leafs which are the local exit roots of each network for (uint256 i = 0; i < currentNodes; i++) { // The first rollup ID starts on 1 - tmpTree[i] = rollupIDToRollupData[uint32(i + 1)].lastLocalExitRoot; + tmpTree[i] = _rollupIDToRollupData[uint32(i + 1)].lastLocalExitRoot; } // This variable will keep track of the zero hashes @@ -1735,7 +1253,7 @@ contract PolygonRollupManager is function getLastVerifiedBatch( uint32 rollupID ) public view returns (uint64) { - return _getLastVerifiedBatch(rollupIDToRollupData[rollupID]); + return _getLastVerifiedBatch(_rollupIDToRollupData[rollupID]); } /** @@ -1744,46 +1262,7 @@ contract PolygonRollupManager is function _getLastVerifiedBatch( RollupData storage rollup ) internal view returns (uint64) { - if (rollup.lastPendingState > 0) { - return - rollup - .pendingStateTransitions[rollup.lastPendingState] - .lastVerifiedBatch; - } else { - return rollup.lastVerifiedBatch; - } - } - - /** - * @notice Returns a boolean that indicates if the pendingStateNum is or not consolidable - * @param rollupID Rollup id - * @param pendingStateNum Pending state number to check - * Note that his function does not check if the pending state currently exists, or if it's consolidated already - */ - function isPendingStateConsolidable( - uint32 rollupID, - uint64 pendingStateNum - ) public view returns (bool) { - return - _isPendingStateConsolidable( - rollupIDToRollupData[rollupID], - pendingStateNum - ); - } - - /** - * @notice Returns a boolean that indicates if the pendingStateNum is or not consolidable - * @param rollup Rollup data storage pointer - * @param pendingStateNum Pending state number to check - * Note that his function does not check if the pending state currently exists, or if it's consolidated already - */ - function _isPendingStateConsolidable( - RollupData storage rollup, - uint64 pendingStateNum - ) internal view returns (bool) { - return (rollup.pendingStateTransitions[pendingStateNum].timestamp + - pendingStateTimeout <= - block.timestamp); + return rollup.lastVerifiedBatch; } /** @@ -1816,6 +1295,61 @@ contract PolygonRollupManager is return _batchFee * 100; } + /** + * @notice Function to calculate the pessimistic input bytes + * @param rollupID Rollup id used to calculate the input snark bytes + * @param l1InfoTreeRoot L1 Info tree root to proof imported bridges + * @param newLocalExitRoot New local exit root + * @param newPessimisticRoot New pessimistic information, Hash(localBalanceTreeRoot, nullifierTreeRoot) + */ + function getInputPessimisticBytes( + uint32 rollupID, + bytes32 l1InfoTreeRoot, + bytes32 newLocalExitRoot, + bytes32 newPessimisticRoot + ) external view returns (bytes memory) { + return + _getInputPessimisticBytes( + rollupID, + _rollupIDToRollupData[rollupID], + l1InfoTreeRoot, + newLocalExitRoot, + newPessimisticRoot + ); + } + + /** + * @notice Function to calculate the input snark bytes + * @param rollupID Rollup identifier + * @param rollup Rollup data storage pointer + * @param l1InfoTreeRoot L1 Info tree root to proof imported bridges + * @param newLocalExitRoot New local exit root + * @param newPessimisticRoot New pessimistic information, Hash(localBalanceTreeRoot, nullifierTreeRoot) + */ + function _getInputPessimisticBytes( + uint32 rollupID, + RollupData storage rollup, + bytes32 l1InfoTreeRoot, + bytes32 newLocalExitRoot, + bytes32 newPessimisticRoot + ) internal view returns (bytes memory) { + // Get consensus information from the consensus contract + bytes32 consensusHash = IPolygonPessimisticConsensus( + address(rollup.rollupContract) + ).getConsensusHash(); + + return + abi.encodePacked( + rollup.lastLocalExitRoot, + rollup.lastPessimisticRoot, + l1InfoTreeRoot, + rollupID, + consensusHash, + newLocalExitRoot, + newPessimisticRoot + ); + } + /** * @notice Function to calculate the input snark bytes * @param rollupID Rollup id used to calculate the input snark bytes @@ -1835,7 +1369,7 @@ contract PolygonRollupManager is ) public view returns (bytes memory) { return _getInputSnarkBytes( - rollupIDToRollupData[rollupID], + _rollupIDToRollupData[rollupID], initNumBatch, finalNewBatch, newLocalExitRoot, @@ -1928,7 +1462,7 @@ contract PolygonRollupManager is uint32 rollupID, uint64 batchNum ) public view returns (bytes32) { - return rollupIDToRollupData[rollupID].batchNumToStateRoot[batchNum]; + return _rollupIDToRollupData[rollupID].batchNumToStateRoot[batchNum]; } /** @@ -1940,18 +1474,55 @@ contract PolygonRollupManager is uint32 rollupID, uint64 batchNum ) public view returns (SequencedBatchData memory) { - return rollupIDToRollupData[rollupID].sequencedBatches[batchNum]; + return _rollupIDToRollupData[rollupID].sequencedBatches[batchNum]; } /** - * @notice Get rollup sequence pending state struct given a batch number + * @notice Get rollup data: VerifierType StateTransition * @param rollupID Rollup identifier - * @param batchNum Batch number */ - function getRollupPendingStateTransitions( - uint32 rollupID, - uint64 batchNum - ) public view returns (PendingState memory) { - return rollupIDToRollupData[rollupID].pendingStateTransitions[batchNum]; + function rollupIDToRollupData( + uint32 rollupID + ) public view returns (RollupDataReturn memory rollupData) { + RollupData storage rollup = _rollupIDToRollupData[rollupID]; + + rollupData.rollupContract = rollup.rollupContract; + rollupData.chainID = rollup.chainID; + rollupData.verifier = rollup.verifier; + rollupData.forkID = rollup.forkID; + rollupData.lastLocalExitRoot = rollup.lastLocalExitRoot; + rollupData.lastBatchSequenced = rollup.lastBatchSequenced; + rollupData.lastVerifiedBatch = rollup.lastVerifiedBatch; + rollupData._legacyLastPendingState = rollup._legacyLastPendingState; + rollupData._legacyLastPendingStateConsolidated = rollup + ._legacyLastPendingStateConsolidated; + rollupData.lastVerifiedBatchBeforeUpgrade = rollup + .lastVerifiedBatchBeforeUpgrade; + rollupData.rollupTypeID = rollup.rollupTypeID; + rollupData.rollupVerifierType = rollup.rollupVerifierType; + } + + /** + * @notice Get rollup data: VerifierType Pessimistic + * @param rollupID Rollup identifier + */ + function rollupIDToRollupDataV2( + uint32 rollupID + ) public view returns (RollupDataReturnV2 memory rollupData) { + RollupData storage rollup = _rollupIDToRollupData[rollupID]; + + rollupData.rollupContract = address(rollup.rollupContract); + rollupData.chainID = rollup.chainID; + rollupData.verifier = rollup.verifier; + rollupData.forkID = rollup.forkID; + rollupData.lastLocalExitRoot = rollup.lastLocalExitRoot; + rollupData.lastBatchSequenced = rollup.lastBatchSequenced; + rollupData.lastVerifiedBatch = rollup.lastVerifiedBatch; + rollupData.lastVerifiedBatchBeforeUpgrade = rollup + .lastVerifiedBatchBeforeUpgrade; + rollupData.rollupTypeID = rollup.rollupTypeID; + rollupData.rollupVerifierType = rollup.rollupVerifierType; + rollupData.lastPessimisticRoot = rollup.lastPessimisticRoot; + rollupData.programVKey = rollup.programVKey; } } diff --git a/contracts/v2/PolygonZkEVMBridgeV2.sol b/contracts/v2/PolygonZkEVMBridgeV2.sol index 8f88fa8e5..3045b642d 100644 --- a/contracts/v2/PolygonZkEVMBridgeV2.sol +++ b/contracts/v2/PolygonZkEVMBridgeV2.sol @@ -30,10 +30,10 @@ contract PolygonZkEVMBridgeV2 is } // bytes4(keccak256(bytes("permit(address,address,uint256,uint256,uint8,bytes32,bytes32)"))); - bytes4 private constant _PERMIT_SIGNATURE = 0xd505accf; + bytes4 internal constant _PERMIT_SIGNATURE = 0xd505accf; // bytes4(keccak256(bytes("permit(address,address,uint256,uint256,bool,uint8,bytes32,bytes32)"))); - bytes4 private constant _PERMIT_SIGNATURE_DAI = 0x8fcbaf0c; + bytes4 internal constant _PERMIT_SIGNATURE_DAI = 0x8fcbaf0c; // Mainnet identifier uint32 private constant _MAINNET_NETWORK_ID = 0; @@ -48,7 +48,7 @@ contract PolygonZkEVMBridgeV2 is uint8 private constant _LEAF_TYPE_MESSAGE = 1; // Nullifier offset - uint256 private constant _MAX_LEAFS_PER_NETWORK = 2 ** 32; + uint256 internal constant _MAX_LEAFS_PER_NETWORK = 2 ** 32; // Indicate where's the mainnet flag bit in the global index uint256 private constant _GLOBAL_INDEX_MAINNET_FLAG = 2 ** 64; @@ -89,8 +89,16 @@ contract PolygonZkEVMBridgeV2 is bytes public gasTokenMetadata; // WETH address + // @note WETH address will only be present when the native token is not ether, but another gasToken. + // This variable is set at the initialization of the contract in case there's a gas token differnet than ether, (gasTokenAddress != address(0) ) so a new wrapped Token will be deployed to handle ether that came from other networks TokenWrapped public WETHToken; + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + */ + uint256[50] private _gap; + /** * @dev Emitted when bridge assets or messages to another network */ @@ -197,7 +205,7 @@ contract PolygonZkEVMBridgeV2 is * @param destinationNetwork Network destination * @param destinationAddress Address destination * @param amount Amount of tokens - * @param token Token address, 0 address is reserved for ether + * @param token Token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token * @param forceUpdateGlobalExitRoot Indicates if the new global exit root is updated or not * @param permitData Raw data of the call `permit` of the token */ @@ -238,7 +246,7 @@ contract PolygonZkEVMBridgeV2 is // In case ether is the native token, WETHToken will be 0, and the address 0 is already checked if (token == address(WETHToken)) { // Burn tokens - TokenWrapped(token).burn(msg.sender, amount); + _bridgeWrappedAsset(TokenWrapped(token), amount); // Both origin network and originTokenAddress will be 0 // Metadata will be empty @@ -250,8 +258,7 @@ contract PolygonZkEVMBridgeV2 is if (tokenInfo.originTokenAddress != address(0)) { // The token is a wrapped token from another network - // Burn tokens - TokenWrapped(token).burn(msg.sender, amount); + _bridgeWrappedAsset(TokenWrapped(token), amount); originTokenAddress = tokenInfo.originTokenAddress; originNetwork = tokenInfo.originNetwork; @@ -364,7 +371,7 @@ contract PolygonZkEVMBridgeV2 is } // Burn wETH tokens - WETHToken.burn(msg.sender, amountWETH); + _bridgeWrappedAsset(WETHToken, amountWETH); _bridgeMessage( destinationNetwork, @@ -437,7 +444,7 @@ contract PolygonZkEVMBridgeV2 is * @param mainnetExitRoot Mainnet exit root * @param rollupExitRoot Rollup exit root * @param originNetwork Origin network - * @param originTokenAddress Origin token address, 0 address is reserved for ether + * @param originTokenAddress Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token * @param destinationNetwork Network destination * @param destinationAddress Address destination * @param amount Amount of tokens @@ -492,7 +499,7 @@ contract PolygonZkEVMBridgeV2 is } } else { // Claim wETH - WETHToken.mint(destinationAddress, amount); + _claimWrappedAsset(WETHToken, destinationAddress, amount); } } else { // Check if it's gas token @@ -536,7 +543,11 @@ contract PolygonZkEVMBridgeV2 is ); // Mint tokens for the destination address - newWrappedToken.mint(destinationAddress, amount); + _claimWrappedAsset( + newWrappedToken, + destinationAddress, + amount + ); // Create mappings tokenInfoToWrappedToken[tokenInfoHash] = address( @@ -555,7 +566,8 @@ contract PolygonZkEVMBridgeV2 is ); } else { // Use the existing wrapped erc20 - TokenWrapped(wrappedToken).mint( + _claimWrappedAsset( + TokenWrapped(wrappedToken), destinationAddress, amount ); @@ -646,7 +658,7 @@ contract PolygonZkEVMBridgeV2 is ); } else { // Mint wETH tokens - WETHToken.mint(destinationAddress, amount); + _claimWrappedAsset(WETHToken, destinationAddress, amount); // Execute message /* solhint-disable avoid-low-level-calls */ @@ -677,7 +689,7 @@ contract PolygonZkEVMBridgeV2 is * Since the metadata has relevance in the address deployed, this function will not return a valid * wrapped address if the metadata provided is not the original one. * @param originNetwork Origin network - * @param originTokenAddress Origin token address, 0 address is reserved for ether + * @param originTokenAddress Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token * @param name Name of the token * @param symbol Symbol of the token * @param decimals Decimals of the token @@ -714,7 +726,7 @@ contract PolygonZkEVMBridgeV2 is /** * @notice Returns the address of a wrapper using the token information if already exist * @param originNetwork Origin network - * @param originTokenAddress Origin token address, 0 address is reserved for ether + * @param originTokenAddress Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token */ function getTokenWrappedAddress( uint32 originNetwork, @@ -730,7 +742,7 @@ contract PolygonZkEVMBridgeV2 is * @notice Function to activate the emergency state " Only can be called by the Polygon ZK-EVM in extreme situations */ - function activateEmergencyState() external onlyRollupManager { + function activateEmergencyState() external virtual onlyRollupManager { _activateEmergencyState(); } @@ -738,7 +750,7 @@ contract PolygonZkEVMBridgeV2 is * @notice Function to deactivate the emergency state " Only can be called by the Polygon ZK-EVM */ - function deactivateEmergencyState() external onlyRollupManager { + function deactivateEmergencyState() external virtual onlyRollupManager { _deactivateEmergencyState(); } @@ -827,7 +839,7 @@ contract PolygonZkEVMBridgeV2 is function isClaimed( uint32 leafIndex, uint32 sourceBridgeNetwork - ) external view returns (bool) { + ) external view virtual returns (bool) { uint256 globalIndex; // For consistency with the previous setted nullifiers @@ -855,7 +867,7 @@ contract PolygonZkEVMBridgeV2 is function _setAndCheckClaimed( uint32 leafIndex, uint32 sourceBridgeNetwork - ) private { + ) internal virtual { uint256 globalIndex; // For consistency with the previous setted nullifiers @@ -895,13 +907,43 @@ contract PolygonZkEVMBridgeV2 is globalExitRootManager.updateExitRoot(getRoot()); } + /** + * @notice Burn tokens from wrapped token to execute the bridge + * note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain + * @param tokenWrapped Wrapped token to burnt + * @param amount Amount of tokens + */ + function _bridgeWrappedAsset( + TokenWrapped tokenWrapped, + uint256 amount + ) internal virtual { + // Burn tokens + tokenWrapped.burn(msg.sender, amount); + } + + /** + * @notice Mints tokens from wrapped token to proceed with the claim + * note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain + * @param tokenWrapped Wrapped token to mint + * @param destinationAddress Minted token receiver + * @param amount Amount of tokens + */ + function _claimWrappedAsset( + TokenWrapped tokenWrapped, + address destinationAddress, + uint256 amount + ) internal virtual { + // Mint tokens + tokenWrapped.mint(destinationAddress, amount); + } + /** * @notice Function decode an index into a wordPos and bitPos * @param index Index */ function _bitmapPositions( uint256 index - ) private pure returns (uint256 wordPos, uint256 bitPos) { + ) internal pure returns (uint256 wordPos, uint256 bitPos) { wordPos = uint248(index >> 8); bitPos = uint8(index); } @@ -916,7 +958,7 @@ contract PolygonZkEVMBridgeV2 is address token, uint256 amount, bytes calldata permitData - ) internal { + ) internal virtual { bytes4 sig = bytes4(permitData[:4]); if (sig == _PERMIT_SIGNATURE) { ( @@ -1140,7 +1182,7 @@ contract PolygonZkEVMBridgeV2 is * Since the metadata has relevance in the address deployed, this function will not return a valid * wrapped address if the metadata provided is not the original one. * @param originNetwork Origin network - * @param originTokenAddress Origin token address, 0 address is reserved for ether + * @param originTokenAddress Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token * @param token Address of the token to calculate the wrapper address */ function calculateTokenWrapperAddress( diff --git a/contracts/v2/PolygonZkEVMGlobalExitRootV2.sol b/contracts/v2/PolygonZkEVMGlobalExitRootV2.sol index c904686b5..5298249a7 100644 --- a/contracts/v2/PolygonZkEVMGlobalExitRootV2.sol +++ b/contracts/v2/PolygonZkEVMGlobalExitRootV2.sol @@ -78,7 +78,7 @@ contract PolygonZkEVMGlobalExitRootV2 is * @param newRoot new exit tree root */ function updateExitRoot(bytes32 newRoot) external { - // Store storage variables into temporal variables since will be used multiple times + // Store storage variables into temporary variables since will be used multiple times bytes32 cacheLastRollupExitRoot; bytes32 cacheLastMainnetExitRoot; @@ -101,14 +101,14 @@ contract PolygonZkEVMGlobalExitRootV2 is // If it already exists, do not modify the blockhash if (globalExitRootMap[newGlobalExitRoot] == 0) { - uint64 currentTimestmap = uint64(block.timestamp); + uint64 currentTimestamp = uint64(block.timestamp); uint256 lastBlockHash = uint256(blockhash(block.number - 1)); globalExitRootMap[newGlobalExitRoot] = lastBlockHash; // save new leaf in L1InfoTree _addLeaf( - getLeafValue(newGlobalExitRoot, lastBlockHash, currentTimestmap) + getLeafValue(newGlobalExitRoot, lastBlockHash, currentTimestamp) ); // Get the current historic root @@ -126,7 +126,7 @@ contract PolygonZkEVMGlobalExitRootV2 is currentL1InfoRoot, uint32(depositCount), lastBlockHash, - currentTimestmap + currentTimestamp ); } } @@ -157,7 +157,7 @@ contract PolygonZkEVMGlobalExitRootV2 is /** * @notice Given the leaf data returns the leaf hash * @param newGlobalExitRoot Last global exit root - * @param lastBlockHash Last accesible block hash + * @param lastBlockHash Last accessible block hash * @param timestamp Ethereum timestamp in seconds */ function getLeafValue( diff --git a/contracts/v2/consensus/pessimistic/PolygonPessimisticConsensus.sol b/contracts/v2/consensus/pessimistic/PolygonPessimisticConsensus.sol new file mode 100644 index 000000000..cc2d59525 --- /dev/null +++ b/contracts/v2/consensus/pessimistic/PolygonPessimisticConsensus.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity 0.8.20; + +import "../../lib/PolygonConsensusBase.sol"; +import "../../interfaces/IPolygonPessimisticConsensus.sol"; + +contract PolygonPessimisticConsensus is + PolygonConsensusBase, + IPolygonPessimisticConsensus +{ + uint32 public constant CONSENSUS_TYPE = 0; + + /** + * @param _globalExitRootManager Global exit root manager address + * @param _pol POL token address + * @param _bridgeAddress Bridge address + * @param _rollupManager Rollup manager address + */ + constructor( + IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, + IERC20Upgradeable _pol, + IPolygonZkEVMBridgeV2 _bridgeAddress, + PolygonRollupManager _rollupManager + ) + PolygonConsensusBase( + _globalExitRootManager, + _pol, + _bridgeAddress, + _rollupManager + ) + {} + + /** + * Note Return the necessary consensus information for the proof hashed + */ + function getConsensusHash() public view returns (bytes32) { + return keccak256(abi.encodePacked(CONSENSUS_TYPE, trustedSequencer)); + } +} diff --git a/contracts/v2/consensus/validium/PolygonValidiumEtrog.sol b/contracts/v2/consensus/validium/PolygonValidiumEtrog.sol index 7a0f72bdb..77b0784e8 100644 --- a/contracts/v2/consensus/validium/PolygonValidiumEtrog.sol +++ b/contracts/v2/consensus/validium/PolygonValidiumEtrog.sol @@ -77,7 +77,7 @@ contract PolygonValidiumEtrog is PolygonRollupBaseEtrog, IPolygonValidium { /** * @notice Allows a sequencer to send multiple batches * @param batches Struct array which holds the necessary data to append new batches to the sequence - * @param l1InfoTreeLeafCount leaf count of the L1InfoRoot that will be used in this sequence + * @param l1InfoTreeLeafCount Count of the L1InfoTree leaf that will be used in this sequence * @param maxSequenceTimestamp Max timestamp of the sequence. This timestamp must be inside a safety range (actual + 36 seconds). * This timestamp should be equal or higher of the last block inside the sequence, otherwise this batch will be invalidated by circuit. * @param expectedFinalAccInputHash This parameter must match the acc input hash after hash all the batch data @@ -247,7 +247,7 @@ contract PolygonValidiumEtrog is PolygonRollupBaseEtrog, IPolygonValidium { /** * @notice Allows a sequencer to send multiple batches * @param batches Struct array which holds the necessary data to append new batches to the sequence - * @param l1InfoTreeLeafCount Index of the L1InfoRoot that will be used in this sequence + * @param l1InfoTreeLeafCount Count of the L1InfoTree leaf that will be used in this sequence * @param maxSequenceTimestamp Max timestamp of the sequence. This timestamp must be inside a safety range (actual + 36 seconds). * This timestamp should be equal or higher of the last block inside the sequence, otherwise this batch will be invalidated by circuit. * @param expectedFinalAccInputHash This parameter must match the acc input hash after hash all the batch data diff --git a/contracts/v2/interfaces/IBridgeL2SovereignChains.sol b/contracts/v2/interfaces/IBridgeL2SovereignChains.sol new file mode 100644 index 000000000..a4b6e9416 --- /dev/null +++ b/contracts/v2/interfaces/IBridgeL2SovereignChains.sol @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity ^0.8.20; +import "../../interfaces/IBasePolygonZkEVMGlobalExitRoot.sol"; +import "./IPolygonZkEVMBridgeV2.sol"; + +interface IBridgeL2SovereignChains is IPolygonZkEVMBridgeV2 { + /** + * @dev Thrown when try to set a zero address to a non valid zero address field + */ + error InvalidZeroAddress(); + + /** + * @dev Thrown when the origin network is invalid + */ + error OriginNetworkInvalid(); + + /** + * @dev Thrown when sender is not the bridge manager + * @notice Bridge manager can set custom mapping for any token + */ + error OnlyBridgeManager(); + + /** + * @dev Thrown when trying to remove a token mapping that has not been updated by a new one + */ + error TokenNotMapped(); + + /** + * @dev Thrown when trying to migrate a legacy token that is already the current token + */ + error TokenAlreadyUpdated(); + + /** + * @dev Thrown when initializing sovereign bridge with invalid sovereign WETH token params + */ + error InvalidSovereignWETHAddressParams(); + + /** + * @dev Thrown when initializing sovereign bridge with invalid sovereign WETH token params + */ + error InvalidInitializeFunction(); + + /** + * @dev Thrown when initializing calling a function with invalid arrays length + */ + error InputArraysLengthMismatch(); + + /** + * @dev Thrown when trying to map a token that is already mapped + */ + error TokenAlreadyMapped(); + + /** + * @dev Thrown when trying to remove a legacy mapped token that has nor previously been remapped + */ + error TokenNotRemapped(); + + /** + * @dev Thrown when trying to set a custom wrapper for weth on a gas token network + */ + error WETHRemappingNotSupportedOnGasTokenNetworks(); + /** + * @dev Thrown when trying to unset a not setted claim + */ + error ClaimNotSet(); + + /** + * @dev Thrown when trying to activate emergency state in a not allowed bridge context (e.g. sovereign chains) + */ + error EmergencyStateNotAllowed(); + + function initialize( + uint32 _networkID, + address _gasTokenAddress, + uint32 _gasTokenNetwork, + IBasePolygonZkEVMGlobalExitRoot _globalExitRootManager, + address _polygonRollupManager, + bytes memory _gasTokenMetadata, + address _bridgeManager, + address sovereignWETHAddress, + bool _sovereignWETHAddressIsNotMintable + ) external; +} diff --git a/contracts/v2/interfaces/IPolygonConsensusBase.sol b/contracts/v2/interfaces/IPolygonConsensusBase.sol new file mode 100644 index 000000000..5ce3a14b2 --- /dev/null +++ b/contracts/v2/interfaces/IPolygonConsensusBase.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity ^0.8.20; + +interface IPolygonConsensusBase { + function initialize( + address _admin, + address sequencer, + uint32 networkID, + address gasTokenAddress, + string memory sequencerURL, + string memory _networkName + ) external; + + function admin() external view returns (address); +} diff --git a/contracts/v2/interfaces/IPolygonPessimisticConsensus.sol b/contracts/v2/interfaces/IPolygonPessimisticConsensus.sol new file mode 100644 index 000000000..9106d9afc --- /dev/null +++ b/contracts/v2/interfaces/IPolygonPessimisticConsensus.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity ^0.8.20; + +interface IPolygonPessimisticConsensus { + function getConsensusHash() external view returns (bytes32); +} diff --git a/contracts/v2/interfaces/IPolygonRollupBase.sol b/contracts/v2/interfaces/IPolygonRollupBase.sol index 023828f52..e840697c7 100644 --- a/contracts/v2/interfaces/IPolygonRollupBase.sol +++ b/contracts/v2/interfaces/IPolygonRollupBase.sol @@ -2,24 +2,15 @@ pragma solidity ^0.8.20; -interface IPolygonRollupBase { - function initialize( - address _admin, - address sequencer, - uint32 networkID, - address gasTokenAddress, - string memory sequencerURL, - string memory _networkName - ) external; +import "./IPolygonConsensusBase.sol"; +interface IPolygonRollupBase is IPolygonConsensusBase { function onVerifyBatches( uint64 lastVerifiedBatch, bytes32 newStateRoot, address aggregator ) external; - function admin() external returns (address); - function rollbackBatches( uint64 targetBatch, bytes32 accInputHashToRollback diff --git a/contracts/v2/interfaces/IPolygonRollupManager.sol b/contracts/v2/interfaces/IPolygonRollupManager.sol index f5ce2003c..e5848c901 100644 --- a/contracts/v2/interfaces/IPolygonRollupManager.sol +++ b/contracts/v2/interfaces/IPolygonRollupManager.sol @@ -2,6 +2,10 @@ pragma solidity ^0.8.20; +import "../../interfaces/IVerifierRollup.sol"; +import "./IPolygonRollupBase.sol"; +import {ITransparentUpgradeableProxy} from "@openzeppelin/contracts5/proxy/transparent/TransparentUpgradeableProxy.sol"; + interface IPolygonRollupManager { /** * @dev Thrown when sender is not the PolygonZkEVM address @@ -262,4 +266,165 @@ interface IPolygonRollupManager { * @dev rollbackBatches is called from a non authorized address */ error NotAllowedAddress(); + + /** + * @dev Invalid Rollup type parameters + */ + error InvalidRollupType(); + + /** + * @dev Invalid Rollup parameters + */ + error InvalidRollup(); + + /** + * @dev Not valid L1 info tree leaf count + */ + error L1InfoTreeLeafCountInvalid(); + + /** + * @dev Only State Transition Chains + */ + error OnlyStateTransitionChains(); + + /** + * @dev Pending state num exist + */ + error PendingStateNumExist(); + + /** + * @dev Only Chains with Pesismistic proofs + */ + error OnlyChainsWithPessimisticProofs(); + + /** + * @dev Invalid Pessimistic proof + */ + error InvalidPessimisticProof(); + + /** + * @dev Invalid Verifier Type when getting rollup data + */ + error InvalidVerifierType(); + + enum VerifierType { + StateTransition, + Pessimistic + } + + function addNewRollupType( + address consensusImplementation, + address verifier, + uint64 forkID, + VerifierType rollupVerifierType, + bytes32 initRoot, + string memory description, + bytes32 programVKey + ) external; + + function obsoleteRollupType(uint32 rollupTypeID) external; + + function createNewRollup( + uint32 rollupTypeID, + uint64 chainID, + address admin, + address sequencer, + address gasTokenAddress, + string memory sequencerURL, + string memory networkName + ) external; + + function addExistingRollup( + IPolygonRollupBase rollupAddress, + address verifier, + uint64 forkID, + uint64 chainID, + bytes32 initRoot, + VerifierType rollupVerifierType, + bytes32 programVKey + ) external; + + function updateRollupByRollupAdmin( + ITransparentUpgradeableProxy rollupContract, + uint32 newRollupTypeID + ) external; + + function updateRollup( + ITransparentUpgradeableProxy rollupContract, + uint32 newRollupTypeID, + bytes memory upgradeData + ) external; + + function rollbackBatches( + IPolygonRollupBase rollupContract, + uint64 targetBatch + ) external; + + function onSequenceBatches( + uint64 newSequencedBatches, + bytes32 newAccInputHash + ) external returns (uint64); + + function verifyBatchesTrustedAggregator( + uint32 rollupID, + uint64 pendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + address beneficiary, + bytes32[24] calldata proof + ) external; + + function verifyPessimisticTrustedAggregator( + uint32 rollupID, + uint32 l1InfoTreeLeafCount, + bytes32 newLocalExitRoot, + bytes32 newPessimisticRoot, + bytes calldata proof + ) external; + + function activateEmergencyState() external; + + function deactivateEmergencyState() external; + + function setBatchFee(uint256 newBatchFee) external; + + function getRollupExitRoot() external view returns (bytes32); + + function getLastVerifiedBatch( + uint32 rollupID + ) external view returns (uint64); + + function calculateRewardPerBatch() external view returns (uint256); + + function getBatchFee() external view returns (uint256); + + function getForcedBatchFee() external view returns (uint256); + + function getInputPessimisticBytes( + uint32 rollupID, + bytes32 selectedGlobalExitRoot, + bytes32 newLocalExitRoot, + bytes32 newPessimisticRoot + ) external view returns (bytes memory); + + function getInputSnarkBytes( + uint32 rollupID, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 oldStateRoot, + bytes32 newStateRoot + ) external view returns (bytes memory); + + function getRollupBatchNumToStateRoot( + uint32 rollupID, + uint64 batchNum + ) external view returns (bytes32); + + function lastDeactivatedEmergencyStateTimestamp() + external + view + returns (uint64); } diff --git a/contracts/v2/interfaces/IPolygonZkEVMVEtrogErrors.sol b/contracts/v2/interfaces/IPolygonZkEVMEtrogErrors.sol similarity index 96% rename from contracts/v2/interfaces/IPolygonZkEVMVEtrogErrors.sol rename to contracts/v2/interfaces/IPolygonZkEVMEtrogErrors.sol index 1d38fd371..ec2161bc7 100644 --- a/contracts/v2/interfaces/IPolygonZkEVMVEtrogErrors.sol +++ b/contracts/v2/interfaces/IPolygonZkEVMEtrogErrors.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.20; import "../../interfaces/IPolygonZkEVMErrors.sol"; -interface IPolygonZkEVMVEtrogErrors is IPolygonZkEVMErrors { +interface IPolygonZkEVMEtrogErrors is IPolygonZkEVMErrors { /** * @dev Thrown when the caller is not the trusted sequencer */ diff --git a/contracts/v2/interfaces/ISP1Verifier.sol b/contracts/v2/interfaces/ISP1Verifier.sol new file mode 100644 index 000000000..154dc7dbb --- /dev/null +++ b/contracts/v2/interfaces/ISP1Verifier.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +// imported from: https://github.com/succinctlabs/sp1-contracts/blob/main/contracts/src/ISP1Verifier.sol + +/// @title SP1 Verifier Interface +/// @author Succinct Labs +/// @notice This contract is the interface for the SP1 Verifier. +interface ISP1Verifier { + /// @notice Verifies a proof with given public values and vkey. + /// @dev It is expected that the first 4 bytes of proofBytes must match the first 4 bytes of + /// target verifier's VERIFIER_HASH. + /// @param programVKey The verification key for the RISC-V program. + /// @param publicValues The public values encoded as bytes. + /// @param proofBytes The proof of the program execution the SP1 zkVM encoded as bytes. + function verifyProof( + bytes32 programVKey, + bytes calldata publicValues, + bytes calldata proofBytes + ) external view; +} + +interface ISP1VerifierWithHash is ISP1Verifier { + /// @notice Returns the hash of the verifier. + function VERIFIER_HASH() external pure returns (bytes32); +} \ No newline at end of file diff --git a/contracts/v2/lib/DepositContractV2.sol b/contracts/v2/lib/DepositContractV2.sol index 2a2313fec..2606578d2 100644 --- a/contracts/v2/lib/DepositContractV2.sol +++ b/contracts/v2/lib/DepositContractV2.sol @@ -13,7 +13,7 @@ contract DepositContractV2 is ReentrancyGuardUpgradeable, DepositContractBase { * @notice Given the leaf data returns the leaf value * @param leafType Leaf type --> [0] transfer Ether / ERC20 tokens, [1] message * @param originNetwork Origin Network - * @param originAddress [0] Origin token address, 0 address is reserved for ether, [1] msg.sender of the message + * @param originAddress [0] Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token, [1] msg.sender of the message * @param destinationNetwork Destination network * @param destinationAddress Destination address * @param amount [0] Amount of tokens/ether, [1] Amount of ether diff --git a/contracts/v2/lib/PolygonConsensusBase.sol b/contracts/v2/lib/PolygonConsensusBase.sol new file mode 100644 index 000000000..72284ac3e --- /dev/null +++ b/contracts/v2/lib/PolygonConsensusBase.sol @@ -0,0 +1,222 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; +import "../interfaces/IPolygonZkEVMGlobalExitRootV2.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "../../interfaces/IPolygonZkEVMErrors.sol"; +import "../interfaces/IPolygonZkEVMEtrogErrors.sol"; +import "../interfaces/IPolygonConsensusBase.sol"; +import "../interfaces/IPolygonRollupBase.sol"; +import "../interfaces/IPolygonZkEVMBridgeV2.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; +import "./PolygonConstantsBase.sol"; +import "../PolygonRollupManager.sol"; + +/** + * Contract responsible for managing the states and the updates of L2 network. + * There will be a trusted sequencer, which is able to send transactions. + * Any user can force some transaction and the sequencer will have a timeout to add them in the queue. + * The sequenced state is deterministic and can be precalculated before it's actually verified by a zkProof. + * The aggregators will be able to verify the sequenced state with zkProofs and therefore make available the withdrawals from L2 network. + * To enter and exit of the L2 network will be used a PolygonZkEVMBridge smart contract that will be deployed in both networks. + */ +abstract contract PolygonConsensusBase is + Initializable, + IPolygonConsensusBase, + IPolygonZkEVMEtrogErrors +{ + // POL token address + IERC20Upgradeable public immutable pol; + + // Global Exit Root interface + IPolygonZkEVMGlobalExitRootV2 public immutable globalExitRootManager; + + // PolygonZkEVM Bridge Address + IPolygonZkEVMBridgeV2 public immutable bridgeAddress; + + // Rollup manager + PolygonRollupManager public immutable rollupManager; + + // Address that will be able to adjust contract parameters + address public admin; + + // This account will be able to accept the admin role + address public pendingAdmin; + + // Trusted sequencer address + address public trustedSequencer; + + // Trusted sequencer URL + string public trustedSequencerURL; + + // L2 network name + string public networkName; + + // Current accumulate input hash + bytes32 public lastAccInputHash; + + // Queue of forced batches with their associated data + // ForceBatchNum --> hashedForcedBatchData + // hashedForcedBatchData: hash containing the necessary information to force a batch: + // keccak256(keccak256(bytes transactions), bytes32 forcedGlobalExitRoot, unint64 forcedTimestamp, bytes32 forcedBlockHashL1) + mapping(uint64 => bytes32) public forcedBatches; + + // Last forced batch + uint64 public lastForceBatch; + + // Last forced batch included in the sequence + uint64 public lastForceBatchSequenced; + + // Force batch timeout + uint64 public forceBatchTimeout; + + // Indicates what address is able to do forced batches + // If the address is set to 0, forced batches are open to everyone + address public forceBatchAddress; + + // Token address that will be used to pay gas fees in this rollup. This variable it's just for read purposes + address public gasTokenAddress; + + // Native network of the token address of the gas tokena address. This variable it's just for read purposes + uint32 public gasTokenNetwork; + + /** + * @dev This empty reserved space is put in place to allow future versions to add new + * variables without shifting down storage in the inheritance chain. + */ + uint256[50] private _gap; + + /** + * @dev Emitted when the admin updates the trusted sequencer address + */ + event SetTrustedSequencer(address newTrustedSequencer); + + /** + * @dev Emitted when the admin updates the sequencer URL + */ + event SetTrustedSequencerURL(string newTrustedSequencerURL); + + /** + * @dev Emitted when the admin starts the two-step transfer role setting a new pending admin + */ + event TransferAdminRole(address newPendingAdmin); + + /** + * @dev Emitted when the pending admin accepts the admin role + */ + event AcceptAdminRole(address newAdmin); + + // General parameters that will have in common all networks that deploys rollup manager + + /** + * @param _globalExitRootManager Global exit root manager address + * @param _pol POL token address + * @param _bridgeAddress Bridge address + * @param _rollupManager Global exit root manager address + */ + constructor( + IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, + IERC20Upgradeable _pol, + IPolygonZkEVMBridgeV2 _bridgeAddress, + PolygonRollupManager _rollupManager + ) { + globalExitRootManager = _globalExitRootManager; + pol = _pol; + bridgeAddress = _bridgeAddress; + rollupManager = _rollupManager; + + // Disable initalizers on the implementation following the best practices + _disableInitializers(); + } + + /** + * @param _admin Admin address + * @param sequencer Trusted sequencer address + * @param _gasTokenAddress Indicates the token address in mainnet that will be used as a gas token + * Note if a wrapped token of the bridge is used, the original network and address of this wrapped are used instead + * @param sequencerURL Trusted sequencer URL + * @param _networkName L2 network name + */ + function initialize( + address _admin, + address sequencer, + uint32, //networkID, + address _gasTokenAddress, + string memory sequencerURL, + string memory _networkName + ) external virtual onlyRollupManager initializer { + // Set initialize variables + admin = _admin; + trustedSequencer = sequencer; + + trustedSequencerURL = sequencerURL; + networkName = _networkName; + + gasTokenAddress = _gasTokenAddress; + } + + modifier onlyAdmin() { + if (admin != msg.sender) { + revert OnlyAdmin(); + } + _; + } + + modifier onlyRollupManager() { + if (address(rollupManager) != msg.sender) { + revert OnlyRollupManager(); + } + _; + } + + ////////////////// + // admin functions + ////////////////// + + /** + * @notice Allow the admin to set a new trusted sequencer + * @param newTrustedSequencer Address of the new trusted sequencer + */ + function setTrustedSequencer( + address newTrustedSequencer + ) external onlyAdmin { + trustedSequencer = newTrustedSequencer; + + emit SetTrustedSequencer(newTrustedSequencer); + } + + /** + * @notice Allow the admin to set the trusted sequencer URL + * @param newTrustedSequencerURL URL of trusted sequencer + */ + function setTrustedSequencerURL( + string memory newTrustedSequencerURL + ) external onlyAdmin { + trustedSequencerURL = newTrustedSequencerURL; + + emit SetTrustedSequencerURL(newTrustedSequencerURL); + } + + /** + * @notice Starts the admin role transfer + * This is a two step process, the pending admin must accepted to finalize the process + * @param newPendingAdmin Address of the new pending admin + */ + function transferAdminRole(address newPendingAdmin) external onlyAdmin { + pendingAdmin = newPendingAdmin; + emit TransferAdminRole(newPendingAdmin); + } + + /** + * @notice Allow the current pending admin to accept the admin role + */ + function acceptAdminRole() external { + if (pendingAdmin != msg.sender) { + revert OnlyPendingAdmin(); + } + + admin = pendingAdmin; + emit AcceptAdminRole(pendingAdmin); + } +} diff --git a/contracts/v2/lib/PolygonRollupBaseEtrog.sol b/contracts/v2/lib/PolygonRollupBaseEtrog.sol index 2004eee5c..5700c94d1 100644 --- a/contracts/v2/lib/PolygonRollupBaseEtrog.sol +++ b/contracts/v2/lib/PolygonRollupBaseEtrog.sol @@ -3,14 +3,14 @@ pragma solidity ^0.8.20; import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; import "../interfaces/IPolygonZkEVMGlobalExitRootV2.sol"; -import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "../../interfaces/IPolygonZkEVMErrors.sol"; -import "../interfaces/IPolygonZkEVMVEtrogErrors.sol"; +import "../interfaces/IPolygonZkEVMEtrogErrors.sol"; import "../PolygonRollupManager.sol"; import "../interfaces/IPolygonRollupBase.sol"; import "../interfaces/IPolygonZkEVMBridgeV2.sol"; import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; import "./PolygonConstantsBase.sol"; +import "./PolygonConsensusBase.sol"; /** * Contract responsible for managing the states and the updates of L2 network. @@ -21,9 +21,8 @@ import "./PolygonConstantsBase.sol"; * To enter and exit of the L2 network will be used a PolygonZkEVMBridge smart contract that will be deployed in both networks. */ abstract contract PolygonRollupBaseEtrog is - Initializable, + PolygonConsensusBase, PolygonConstantsBase, - IPolygonZkEVMVEtrogErrors, IPolygonRollupBase { using SafeERC20Upgradeable for IERC20Upgradeable; @@ -136,67 +135,6 @@ abstract contract PolygonRollupBaseEtrog is // Timestamp range that's given to the sequencer as a safety measure to avoid reverts if the transaction is mined to quickly uint256 public constant TIMESTAMP_RANGE = 36; - // POL token address - IERC20Upgradeable public immutable pol; - - // Global Exit Root interface - IPolygonZkEVMGlobalExitRootV2 public immutable globalExitRootManager; - - // PolygonZkEVM Bridge Address - IPolygonZkEVMBridgeV2 public immutable bridgeAddress; - - // Rollup manager - PolygonRollupManager public immutable rollupManager; - - // Address that will be able to adjust contract parameters - address public admin; - - // This account will be able to accept the admin role - address public pendingAdmin; - - // Trusted sequencer address - address public trustedSequencer; - - // Trusted sequencer URL - string public trustedSequencerURL; - - // L2 network name - string public networkName; - - // Current accumulate input hash - bytes32 public lastAccInputHash; - - // Queue of forced batches with their associated data - // ForceBatchNum --> hashedForcedBatchData - // hashedForcedBatchData: hash containing the necessary information to force a batch: - // keccak256(keccak256(bytes transactions), bytes32 forcedGlobalExitRoot, unint64 forcedTimestamp, bytes32 forcedBlockHashL1) - mapping(uint64 => bytes32) public forcedBatches; - - // Last forced batch - uint64 public lastForceBatch; - - // Last forced batch included in the sequence - uint64 public lastForceBatchSequenced; - - // Force batch timeout - uint64 public forceBatchTimeout; - - // Indicates what address is able to do forced batches - // If the address is set to 0, forced batches are open to everyone - address public forceBatchAddress; - - // Token address that will be used to pay gas fees in this rollup. This variable it's just for read purposes - address public gasTokenAddress; - - // Native network of the token address of the gas tokena address. This variable it's just for read purposes - uint32 public gasTokenNetwork; - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - */ - uint256[50] private _gap; - /** * @dev Emitted when the trusted sequencer sends a new batch of transactions */ @@ -243,16 +181,6 @@ abstract contract PolygonRollupBaseEtrog is bytes32 accInputHashToRollback ); - /** - * @dev Emitted when the admin updates the trusted sequencer address - */ - event SetTrustedSequencer(address newTrustedSequencer); - - /** - * @dev Emitted when the admin updates the sequencer URL - */ - event SetTrustedSequencerURL(string newTrustedSequencerURL); - /** * @dev Emitted when the admin update the force batch timeout */ @@ -263,16 +191,6 @@ abstract contract PolygonRollupBaseEtrog is */ event SetForceBatchAddress(address newForceBatchAddress); - /** - * @dev Emitted when the admin starts the two-step transfer role setting a new pending admin - */ - event TransferAdminRole(address newPendingAdmin); - - /** - * @dev Emitted when the pending admin accepts the admin role - */ - event AcceptAdminRole(address newAdmin); - // General parameters that will have in common all networks that deploys rollup manager /** @@ -286,12 +204,14 @@ abstract contract PolygonRollupBaseEtrog is IERC20Upgradeable _pol, IPolygonZkEVMBridgeV2 _bridgeAddress, PolygonRollupManager _rollupManager - ) { - globalExitRootManager = _globalExitRootManager; - pol = _pol; - bridgeAddress = _bridgeAddress; - rollupManager = _rollupManager; - } + ) + PolygonConsensusBase( + _globalExitRootManager, + _pol, + _bridgeAddress, + _rollupManager + ) + {} /** * @param _admin Admin address @@ -309,7 +229,12 @@ abstract contract PolygonRollupBaseEtrog is address _gasTokenAddress, string memory sequencerURL, string memory _networkName - ) external virtual onlyRollupManager initializer { + ) + external + override(IPolygonConsensusBase, PolygonConsensusBase) + onlyRollupManager + initializer + { bytes memory gasTokenMetadata = _verifyOrigin(_gasTokenAddress); // Sequence transaction to initilize the bridge @@ -363,13 +288,6 @@ abstract contract PolygonRollupBaseEtrog is emit InitialSequenceBatches(transaction, lastGlobalExitRoot, sequencer); } - modifier onlyAdmin() { - if (admin != msg.sender) { - revert OnlyAdmin(); - } - _; - } - modifier onlyTrustedSequencer() { if (trustedSequencer != msg.sender) { revert OnlyTrustedSequencer(); @@ -388,13 +306,6 @@ abstract contract PolygonRollupBaseEtrog is _; } - modifier onlyRollupManager() { - if (address(rollupManager) != msg.sender) { - revert OnlyRollupManager(); - } - _; - } - ///////////////////////////////////// // Sequence/Verify batches functions //////////////////////////////////// @@ -402,7 +313,7 @@ abstract contract PolygonRollupBaseEtrog is /** * @notice Allows a sequencer to send multiple batches * @param batches Struct array which holds the necessary data to append new batches to the sequence - * @param l1InfoTreeLeafCount Index of the L1InfoRoot that will be used in this sequence + * @param l1InfoTreeLeafCount Count of the L1InfoTree leaf that will be used in this sequence * @param maxSequenceTimestamp Max timestamp of the sequence. This timestamp must be inside a safety range (actual + 36 seconds). * This timestamp should be equal or higher of the last block inside the sequence, otherwise this batch will be invalidated by circuit. * @param expectedFinalAccInputHash This parameter must match the acc input hash after hash all the batch data @@ -775,30 +686,6 @@ abstract contract PolygonRollupBaseEtrog is // admin functions ////////////////// - /** - * @notice Allow the admin to set a new trusted sequencer - * @param newTrustedSequencer Address of the new trusted sequencer - */ - function setTrustedSequencer( - address newTrustedSequencer - ) external onlyAdmin { - trustedSequencer = newTrustedSequencer; - - emit SetTrustedSequencer(newTrustedSequencer); - } - - /** - * @notice Allow the admin to set the trusted sequencer URL - * @param newTrustedSequencerURL URL of trusted sequencer - */ - function setTrustedSequencerURL( - string memory newTrustedSequencerURL - ) external onlyAdmin { - trustedSequencerURL = newTrustedSequencerURL; - - emit SetTrustedSequencerURL(newTrustedSequencerURL); - } - /** * @notice Allow the admin to change the force batch address, that will be allowed to force batches * If address 0 is set, then everyone is able to force batches, this action is irreversible @@ -837,28 +724,6 @@ abstract contract PolygonRollupBaseEtrog is emit SetForceBatchTimeout(newforceBatchTimeout); } - /** - * @notice Starts the admin role transfer - * This is a two step process, the pending admin must accepted to finalize the process - * @param newPendingAdmin Address of the new pending admin - */ - function transferAdminRole(address newPendingAdmin) external onlyAdmin { - pendingAdmin = newPendingAdmin; - emit TransferAdminRole(newPendingAdmin); - } - - /** - * @notice Allow the current pending admin to accept the admin role - */ - function acceptAdminRole() external { - if (pendingAdmin != msg.sender) { - revert OnlyPendingAdmin(); - } - - admin = pendingAdmin; - emit AcceptAdminRole(pendingAdmin); - } - ////////////////// // view/pure functions ////////////////// diff --git a/contracts/v2/mocks/BridgeReceiverMock.sol b/contracts/v2/mocks/BridgeReceiverMock.sol index 11364419b..46beea8dc 100644 --- a/contracts/v2/mocks/BridgeReceiverMock.sol +++ b/contracts/v2/mocks/BridgeReceiverMock.sol @@ -59,7 +59,7 @@ contract BridgeReceiverMock { * @param mainnetExitRoot Mainnet exit root * @param rollupExitRoot Rollup exit root * @param originNetwork Origin network - * @param originTokenAddress Origin token address, 0 address is reserved for ether + * @param originTokenAddress Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token * @param destinationNetwork Network destination * @param destinationAddress Address destination * @param amount Amount of tokens diff --git a/contracts/v2/mocks/PolygonRollupManagerMock.sol b/contracts/v2/mocks/PolygonRollupManagerMock.sol index a3de8c046..6d3b7a091 100644 --- a/contracts/v2/mocks/PolygonRollupManagerMock.sol +++ b/contracts/v2/mocks/PolygonRollupManagerMock.sol @@ -25,13 +25,13 @@ contract PolygonRollupManagerMock is PolygonRollupManager { address timelock, address emergencyCouncil ) external reinitializer(2) { - pendingStateTimeout = _pendingStateTimeout; - trustedAggregatorTimeout = _trustedAggregatorTimeout; + //pendingStateTimeout = _pendingStateTimeout; + //trustedAggregatorTimeout = _trustedAggregatorTimeout; // Constant deployment variables _batchFee = 0.1 ether; // 0.1 Matic - verifyBatchTimeTarget = 30 minutes; - multiplierBatchFee = 1002; + //verifyBatchTimeTarget = 30 minutes; + //multiplierBatchFee = 1002; // Initialize OZ contracts __AccessControl_init(); @@ -74,8 +74,24 @@ contract PolygonRollupManagerMock is PolygonRollupManager { // Add local Exit roots; for (uint256 i = 0; i < localExitRoots.length; i++) { - rollupIDToRollupData[uint32(i + 1)] + _rollupIDToRollupData[uint32(i + 1)] .lastLocalExitRoot = localExitRoots[i]; } } + + function exposed_checkStateRootInsidePrime( + uint256 newStateRoot + ) public pure returns (bool) { + return _checkStateRootInsidePrime(newStateRoot); + } + + function setRollupData( + uint32 rollupID, + bytes32 lastLocalExitRoot, + bytes32 lastPessimisticRoot + ) external { + RollupData storage rollup = _rollupIDToRollupData[rollupID]; + rollup.lastLocalExitRoot = lastLocalExitRoot; + rollup.lastPessimisticRoot = lastPessimisticRoot; + } } diff --git a/contracts/v2/mocks/PolygonRollupManagerMockInternalTest.sol b/contracts/v2/mocks/PolygonRollupManagerMockInternalTest.sol deleted file mode 100644 index 127705384..000000000 --- a/contracts/v2/mocks/PolygonRollupManagerMockInternalTest.sol +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0 -pragma solidity 0.8.20; -import "../PolygonRollupManager.sol"; - -/** - * PolygonRollupManager Test - */ -contract PolygonRollupManagerMockInternalTest is PolygonRollupManager { - /** - * @param _globalExitRootManager Global exit root manager address - * @param _pol MATIC token address - * @param _bridgeAddress Bridge address - */ - constructor( - IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, - IERC20Upgradeable _pol, - IPolygonZkEVMBridge _bridgeAddress - ) PolygonRollupManager(_globalExitRootManager, _pol, _bridgeAddress) {} - - function initialize( - address trustedAggregator, - uint64 _pendingStateTimeout, - uint64 _trustedAggregatorTimeout, - address admin, - address timelock, - address emergencyCouncil, - PolygonZkEVMExistentEtrog polygonZkEVM, - IVerifierRollup zkEVMVerifier, - uint64 zkEVMForkID, - uint64 zkEVMChainID - ) external reinitializer(2) { - pendingStateTimeout = _pendingStateTimeout; - trustedAggregatorTimeout = _trustedAggregatorTimeout; - - // Constant deployment variables - _batchFee = 0.1 ether; // 0.1 Matic - verifyBatchTimeTarget = 30 minutes; - multiplierBatchFee = 1002; - - // Initialize OZ contracts - __AccessControl_init(); - - // setup roles - - // trusted aggregator role - _setupRole(_TRUSTED_AGGREGATOR_ROLE, trustedAggregator); - - // Timelock roles - _setupRole(DEFAULT_ADMIN_ROLE, timelock); - _setupRole(_ADD_ROLLUP_TYPE_ROLE, timelock); - _setupRole(_ADD_EXISTING_ROLLUP_ROLE, timelock); - - // Even this role can only update to an already added verifier/consensus - // Could break the compatibility of them, changing the virtual state - _setupRole(_UPDATE_ROLLUP_ROLE, timelock); - - // Admin roles - _setupRole(_OBSOLETE_ROLLUP_TYPE_ROLE, admin); - _setupRole(_CREATE_ROLLUP_ROLE, admin); - _setupRole(_STOP_EMERGENCY_ROLE, admin); - _setupRole(_TWEAK_PARAMETERS_ROLE, admin); - _setRoleAdmin(_TRUSTED_AGGREGATOR_ROLE, _TRUSTED_AGGREGATOR_ROLE_ADMIN); - _setupRole(_TRUSTED_AGGREGATOR_ROLE_ADMIN, admin); - - _setupRole(_SET_FEE_ROLE, admin); - - // Emergency council roles - _setRoleAdmin(_EMERGENCY_COUNCIL_ROLE, _EMERGENCY_COUNCIL_ADMIN); - _setupRole(_EMERGENCY_COUNCIL_ROLE, emergencyCouncil); - _setupRole(_EMERGENCY_COUNCIL_ADMIN, emergencyCouncil); - - // Since it's mock, use admin for everything - _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); - } -} diff --git a/contracts/v2/mocks/PolygonZkEVMGlobalExitRootV2Mock.sol b/contracts/v2/mocks/PolygonZkEVMGlobalExitRootV2Mock.sol new file mode 100644 index 000000000..b3da0982b --- /dev/null +++ b/contracts/v2/mocks/PolygonZkEVMGlobalExitRootV2Mock.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity 0.8.20; +import "../PolygonZkEVMGlobalExitRootV2.sol"; + +/** + * PolygonRollupManager mock + */ +contract PolygonZkEVMGlobalExitRootV2Mock is PolygonZkEVMGlobalExitRootV2 { + /** + * @param _rollupManager Rollup manager contract address + * @param _bridgeAddress PolygonZkEVMBridge contract address + */ + constructor( + address _rollupManager, + address _bridgeAddress + ) PolygonZkEVMGlobalExitRootV2(_rollupManager, _bridgeAddress) {} + + function injectGER(bytes32 _root, uint32 depositCount) external { + globalExitRootMap[_root] = block.timestamp; + l1InfoRootMap[depositCount] = _root; + } +} \ No newline at end of file diff --git a/contracts/v2/newDeployments/PolygonRollupManagerNotUpgraded.sol b/contracts/v2/newDeployments/PolygonRollupManagerNotUpgraded.sol index 2d54bd750..9f72a78e3 100644 --- a/contracts/v2/newDeployments/PolygonRollupManagerNotUpgraded.sol +++ b/contracts/v2/newDeployments/PolygonRollupManagerNotUpgraded.sol @@ -19,23 +19,13 @@ contract PolygonRollupManagerNotUpgraded is PolygonRollupManager { function initialize( address trustedAggregator, - uint64 _pendingStateTimeout, - uint64 _trustedAggregatorTimeout, address admin, address timelock, - address emergencyCouncil, - PolygonZkEVMExistentEtrog /*polygonZkEVM*/, - IVerifierRollup /*zkEVMVerifier*/, - uint64 /*zkEVMForkID*/, - uint64 /*zkEVMChainID*/ + address emergencyCouncil ) external reinitializer(2) { - pendingStateTimeout = _pendingStateTimeout; - trustedAggregatorTimeout = _trustedAggregatorTimeout; // Constant deployment variables _batchFee = 0.1 ether; // 0.1 Matic - verifyBatchTimeTarget = 30 minutes; - multiplierBatchFee = 1002; // Initialize OZ contracts __AccessControl_init(); diff --git a/contracts/v2/periphery/BatchL2DataCreatedRollup.sol b/contracts/v2/periphery/BatchL2DataCreatedRollup.sol new file mode 100644 index 000000000..f56928b74 --- /dev/null +++ b/contracts/v2/periphery/BatchL2DataCreatedRollup.sol @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity ^0.8.20; + +import "../lib/PolygonRollupBaseEtrog.sol"; + + +// This contract is only used for a specific tool: zkevm-contracts/tools/batchL2DataCreatedRollup. +// This contract is part of the zkevm-contracts/contracts/v2/lib/PolygonRollupBaseEtrog.sol contract. +contract BatchL2DataCreatedRollup { + + uint8 public constant INITIALIZE_TX_BRIDGE_LIST_LEN_LEN = 0xf9; + bytes public constant INITIALIZE_TX_BRIDGE_PARAMS = hex"80808401c9c38094"; + uint16 public constant INITIALIZE_TX_CONSTANT_BYTES = 32; + bytes public constant INITIALIZE_TX_BRIDGE_PARAMS_AFTER_BRIDGE_ADDRESS = + hex"80b9"; + uint16 public constant INITIALIZE_TX_CONSTANT_BYTES_EMPTY_METADATA = 31; + uint8 public constant INITIALIZE_TX_DATA_LEN_EMPTY_METADATA = 228; + bytes + public constant INITIALIZE_TX_BRIDGE_PARAMS_AFTER_BRIDGE_ADDRESS_EMPTY_METADATA = + hex"80b8"; + + uint8 public constant SIGNATURE_INITIALIZE_TX_V = 27; + bytes32 public constant SIGNATURE_INITIALIZE_TX_R = + 0x00000000000000000000000000000000000000000000000000000005ca1ab1e0; + bytes32 public constant SIGNATURE_INITIALIZE_TX_S = + 0x000000000000000000000000000000000000000000000000000000005ca1ab1e; + bytes1 public constant INITIALIZE_TX_EFFECTIVE_PERCENTAGE = 0xFF; + IBasePolygonZkEVMGlobalExitRoot + public constant GLOBAL_EXIT_ROOT_MANAGER_L2 = + IBasePolygonZkEVMGlobalExitRoot( + 0xa40D5f56745a118D0906a34E69aeC8C0Db1cB8fA + ); + + /** + * @notice Generate Initialize transaction for hte bridge on L2 + * @param networkID Indicates the network identifier that will be used in the bridge + * @param bridgeAddress Indicates the bridge address + * @param _gasTokenAddress Indicates the token address that will be used to pay gas fees in the new rollup + * @param _gasTokenNetwork Indicates the native network of the token address + * @param _gasTokenMetadata Abi encoded gas token metadata + */ + function generateInitializeTransaction( + uint32 networkID, + address bridgeAddress, + address _gasTokenAddress, + uint32 _gasTokenNetwork, + bytes memory _gasTokenMetadata + ) public view returns (bytes memory) { + bytes memory initializeBrigeData = abi.encodeCall( + IPolygonZkEVMBridgeV2.initialize, + ( + networkID, + _gasTokenAddress, + _gasTokenNetwork, + GLOBAL_EXIT_ROOT_MANAGER_L2, + address(0), // Rollup manager on L2 does not exist + _gasTokenMetadata + ) + ); + + bytes memory bytesToSign; + uint16 initializeBrigeDataLen = uint16(initializeBrigeData.length); + + if (_gasTokenMetadata.length == 0) { + bytesToSign = abi.encodePacked( + INITIALIZE_TX_BRIDGE_LIST_LEN_LEN, + initializeBrigeDataLen + + INITIALIZE_TX_CONSTANT_BYTES_EMPTY_METADATA, // do not support more than 2 bytes of length, intended to revert on overflow + INITIALIZE_TX_BRIDGE_PARAMS, + bridgeAddress, + INITIALIZE_TX_BRIDGE_PARAMS_AFTER_BRIDGE_ADDRESS_EMPTY_METADATA, + INITIALIZE_TX_DATA_LEN_EMPTY_METADATA, + initializeBrigeData + ); + } else { + bytesToSign = abi.encodePacked( + INITIALIZE_TX_BRIDGE_LIST_LEN_LEN, + initializeBrigeDataLen + + INITIALIZE_TX_CONSTANT_BYTES, // do not support more than 2 bytes of length, intended to revert on overflow + INITIALIZE_TX_BRIDGE_PARAMS, + bridgeAddress, + INITIALIZE_TX_BRIDGE_PARAMS_AFTER_BRIDGE_ADDRESS, + initializeBrigeDataLen, + initializeBrigeData + ); + } + + // Sanity check that the ecrecover will work + // Should never happen that giving a valid signature, ecrecover "breaks" + address signer = ecrecover( + keccak256(bytesToSign), + SIGNATURE_INITIALIZE_TX_V, + SIGNATURE_INITIALIZE_TX_R, + SIGNATURE_INITIALIZE_TX_S + ); + + bytes memory transaction = abi.encodePacked( + bytesToSign, + SIGNATURE_INITIALIZE_TX_R, + SIGNATURE_INITIALIZE_TX_S, + SIGNATURE_INITIALIZE_TX_V, + INITIALIZE_TX_EFFECTIVE_PERCENTAGE + ); + + return transaction; + } +} \ No newline at end of file diff --git a/contracts/v2/previousVersions/IPolygonRollupManagerPrevious.sol b/contracts/v2/previousVersions/IPolygonRollupManagerPrevious.sol new file mode 100644 index 000000000..cdb66a96f --- /dev/null +++ b/contracts/v2/previousVersions/IPolygonRollupManagerPrevious.sol @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity ^0.8.20; + +interface IPolygonRollupManagerPrevious { + /** + * @dev Thrown when sender is not the PolygonZkEVM address + */ + error UpdateToSameRollupTypeID(); + + /** + * @dev Thrown when sender is not the PolygonZkEVM address + */ + error RollupMustExist(); + + /** + * @dev Thrown when sender is not the PolygonZkEVM address + */ + error SenderMustBeRollup(); + + /** + * @dev Thrown when sender is not the PolygonZkEVM address + */ + error TrustedAggregatorTimeoutNotExpired(); + + /** + * @dev Thrown when sender is not the PolygonZkEVM address + */ + error ExceedMaxVerifyBatches(); + + /** + * @dev Thrown when attempting to access a pending state that does not exist + */ + error PendingStateDoesNotExist(); + + /** + * @dev Thrown when the init num batch does not match with the one in the pending state + */ + error InitNumBatchDoesNotMatchPendingState(); + + /** + * @dev Thrown when the old state root of a certain batch does not exist + */ + error OldStateRootDoesNotExist(); + + /** + * @dev Thrown when the init verification batch is above the last verification batch + */ + error InitNumBatchAboveLastVerifiedBatch(); + + /** + * @dev Thrown when the final verification batch is below or equal the last verification batch + */ + error FinalNumBatchBelowLastVerifiedBatch(); + + /** + * @dev Thrown when the zkproof is not valid + */ + error InvalidProof(); + + /** + * @dev Thrown when attempting to consolidate a pending state not yet consolidable + */ + error PendingStateNotConsolidable(); + + /** + * @dev Thrown when attempting to consolidate a pending state that is already consolidated or does not exist + */ + error PendingStateInvalid(); + + /** + * @dev Thrown when the new accumulate input hash does not exist + */ + error NewAccInputHashDoesNotExist(); + + /** + * @dev Thrown when the new state root is not inside prime + */ + error NewStateRootNotInsidePrime(); + + /** + * @dev Thrown when the final pending state num is not in a valid range + */ + error FinalPendingStateNumInvalid(); + + /** + * @dev Thrown when the final num batch does not match with the one in the pending state + */ + error FinalNumBatchDoesNotMatchPendingState(); + + /** + * @dev Thrown when the stored root matches the new root proving a different state + */ + error StoredRootMustBeDifferentThanNewRoot(); + + /** + * @dev Thrown when the halt timeout is not expired when attempting to activate the emergency state + */ + error HaltTimeoutNotExpired(); + + /** + * @dev Thrown when the old accumulate input hash does not exist + */ + error OldAccInputHashDoesNotExist(); + + /** + * @dev Thrown when attempting to set a new trusted aggregator timeout equal or bigger than current one + */ + error NewTrustedAggregatorTimeoutMustBeLower(); + + /** + * @dev Thrown when attempting to set a new pending state timeout equal or bigger than current one + */ + error NewPendingStateTimeoutMustBeLower(); + + /** + * @dev Thrown when attempting to set a new multiplier batch fee in a invalid range of values + */ + error InvalidRangeMultiplierBatchFee(); + + /** + * @dev Thrown when attempting to set a batch time target in an invalid range of values + */ + error InvalidRangeBatchTimeTarget(); + + /** + * @dev Thrown when the caller is not the pending admin + */ + error ChainIDAlreadyExist(); + + /** + * @dev Thrown when the caller is not the pending admin + */ + error MustSequenceSomeBatch(); + + /** + * @dev When a rollup type does not exist + */ + error RollupTypeDoesNotExist(); + + /** + * @dev When a rollup type does not exist + */ + error RollupTypeObsolete(); + + /** + * @dev When a rollup type does not exist + */ + error InitBatchMustMatchCurrentForkID(); + + /** + * @dev When a rollup type does not exist + */ + error UpdateNotCompatible(); + + /** + * @dev When a rollup type does not exist + */ + error BatchFeeOutOfRange(); + + /** + * @dev When a rollup type does not exist + */ + error AllzkEVMSequencedBatchesMustBeVerified(); + + /** + * @dev When adding an existing rollup where the rollup address already was added + */ + error RollupAddressAlreadyExist(); + + /** + * @dev When verifying proof for multiple roolups and they are not ordered by ID + */ + error RollupIDNotAscendingOrder(); + + /** + * @dev When try to create a new rollup and set a chainID bigger than 32 bits + */ + error ChainIDOutOfRange(); + + /** + * @dev When try to upgrade a rollup a sender that's not the admin of the rollup + */ + error OnlyRollupAdmin(); + + /** + * @dev When try to update a rollup with sequences pending to verify + */ + error AllSequencedMustBeVerified(); + + /** + * @dev Thrown when do not sequence any blob + */ + error MustSequenceSomeBlob(); + + /** + * @dev Thrown when the final verification sequence is below or equal the last verification sequence + */ + error FinalNumSequenceBelowLastVerifiedSequence(); + + /** + * @dev When the init sequence was verified in another forkID + */ + error InitSequenceMustMatchCurrentForkID(); + + /** + * @dev Thrown when the init num sequence does not match with the one in the pending state + */ + error InitSequenceNumDoesNotMatchPendingState(); + + /** + * @dev Thrown when the final num sequence does not match with the one in the pending state + */ + error FinalNumSequenceDoesNotMatchPendingState(); + + /** + * @dev Thrown when attempting to set a new multiplier zkgas in a invalid range of values + */ + error InvalidRangeMultiplierZkGasPrice(); + + /** + * @dev Thrown when attempting to set a seuqnece time target in an invalid range of values + */ + error InvalidRangeSequenceTimeTarget(); + + /** + * @dev When a set a zkgasprice out of range + */ + error zkGasPriceOfRange(); + + /** + * @dev Cannot update from network admin with unconsolidated pending state + */ + error CannotUpdateWithUnconsolidatedPendingState(); + + /** + * @dev Try to verify batches without any sequence data + */ + error EmptyVerifySequencesData(); + + /** + * @dev Update to old rollup ID + */ + error UpdateToOldRollupTypeID(); + + /** + * @dev All batches must be verified before the upgrade + */ + error AllBatchesMustBeVerified(); + + /** + * @dev Rollback batch is not sequenced + */ + error RollbackBatchIsNotValid(); + + /** + * @dev Rollback batch is not the end of any sequence + */ + error RollbackBatchIsNotEndOfSequence(); + + /** + * @dev rollbackBatches is called from a non authorized address + */ + error NotAllowedAddress(); + + /** + * @dev Invalid Rollup type parameters + */ + error InvalidRollupType(); + + /** + * @dev Invalid Rollup parameters + */ + error InvalidRollup(); + + /** + * @dev Global exit root does not exists + */ + error GlobalExitRootNotExist(); +} diff --git a/contracts/v2/previousVersions/PolygonRollupBaseEtrogPrevious.sol b/contracts/v2/previousVersions/PolygonRollupBaseEtrogPrevious.sol index f9422cec1..8728c2204 100644 --- a/contracts/v2/previousVersions/PolygonRollupBaseEtrogPrevious.sol +++ b/contracts/v2/previousVersions/PolygonRollupBaseEtrogPrevious.sol @@ -5,7 +5,7 @@ import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeab import "../interfaces/IPolygonZkEVMGlobalExitRootV2.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "../../interfaces/IPolygonZkEVMErrors.sol"; -import "../interfaces/IPolygonZkEVMVEtrogErrors.sol"; +import "../interfaces/IPolygonZkEVMEtrogErrors.sol"; import "../PolygonRollupManager.sol"; import "./IPolygonRollupBasePrevious.sol"; import "../interfaces/IPolygonZkEVMBridgeV2.sol"; @@ -23,7 +23,7 @@ import "../lib/PolygonConstantsBase.sol"; abstract contract PolygonRollupBaseEtrogPrevious is Initializable, PolygonConstantsBase, - IPolygonZkEVMVEtrogErrors, + IPolygonZkEVMEtrogErrors, IPolygonRollupBasePrevious { using SafeERC20Upgradeable for IERC20Upgradeable; @@ -283,6 +283,9 @@ abstract contract PolygonRollupBaseEtrogPrevious is pol = _pol; bridgeAddress = _bridgeAddress; rollupManager = _rollupManager; + + // Disable initalizers on the implementation following the best practices + _disableInitializers(); } /** diff --git a/contracts/v2/previousVersions/PolygonRollupManagerPrevious.sol b/contracts/v2/previousVersions/PolygonRollupManagerPrevious.sol index c18c2c67b..2a498433b 100644 --- a/contracts/v2/previousVersions/PolygonRollupManagerPrevious.sol +++ b/contracts/v2/previousVersions/PolygonRollupManagerPrevious.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.20; -import "../interfaces/IPolygonRollupManager.sol"; +import "./IPolygonRollupManagerPrevious.sol"; import "../interfaces/IPolygonZkEVMGlobalExitRootV2.sol"; import "../../interfaces/IPolygonZkEVMBridge.sol"; import "../interfaces/IPolygonRollupBase.sol"; @@ -26,7 +26,7 @@ contract PolygonRollupManagerPrevious is EmergencyManager, LegacyZKEVMStateVariables, PolygonConstantsBase, - IPolygonRollupManager + IPolygonRollupManagerPrevious { using SafeERC20Upgradeable for IERC20Upgradeable; @@ -322,6 +322,15 @@ contract PolygonRollupManagerPrevious is address aggregator ); + /** + * @dev Emitted when rollback batches + */ + event RollbackBatches( + uint32 indexed rollupID, + uint64 indexed targetBatch, + bytes32 accInputHashToRollback + ); + /** * @dev Emitted when is updated the trusted aggregator timeout */ @@ -370,116 +379,6 @@ contract PolygonRollupManagerPrevious is _disableInitializers(); } - /** - * @param trustedAggregator Trusted aggregator address - * @param _pendingStateTimeout Pending state timeout - * @param _trustedAggregatorTimeout Trusted aggregator timeout - * @param admin Admin of the rollup manager - * @param timelock Timelock address - * @param emergencyCouncil Emergency council address - * @param polygonZkEVM New deployed Polygon zkEVM which will be initialized wiht previous values - * @param zkEVMVerifier Verifier of the new zkEVM deployed - * @param zkEVMForkID Fork id of the new zkEVM deployed - * @param zkEVMChainID Chain id of the new zkEVM deployed - */ - function initialize( - address trustedAggregator, - uint64 _pendingStateTimeout, - uint64 _trustedAggregatorTimeout, - address admin, - address timelock, - address emergencyCouncil, - PolygonZkEVMExistentEtrog polygonZkEVM, - IVerifierRollup zkEVMVerifier, - uint64 zkEVMForkID, - uint64 zkEVMChainID - ) external virtual reinitializer(2) { - pendingStateTimeout = _pendingStateTimeout; - trustedAggregatorTimeout = _trustedAggregatorTimeout; - - // Constant deployment variables - _batchFee = 0.1 ether; // 0.1 POL - verifyBatchTimeTarget = 30 minutes; - multiplierBatchFee = 1002; - - // Initialize OZ contracts - __AccessControl_init(); - - // setup roles - - // trusted aggregator role - _setupRole(_TRUSTED_AGGREGATOR_ROLE, trustedAggregator); - - // Timelock roles - _setupRole(DEFAULT_ADMIN_ROLE, timelock); - _setupRole(_ADD_ROLLUP_TYPE_ROLE, timelock); - _setupRole(_ADD_EXISTING_ROLLUP_ROLE, timelock); - - // note even this role can only update to an already added verifier/consensus - // Could break the compatibility of them, changing the virtual state - _setupRole(_UPDATE_ROLLUP_ROLE, timelock); - - // admin roles - _setupRole(_OBSOLETE_ROLLUP_TYPE_ROLE, admin); - _setupRole(_CREATE_ROLLUP_ROLE, admin); - _setupRole(_STOP_EMERGENCY_ROLE, admin); - _setupRole(_TWEAK_PARAMETERS_ROLE, admin); - - // admin should be able to update the trusted aggregator address - _setRoleAdmin(_TRUSTED_AGGREGATOR_ROLE, _TRUSTED_AGGREGATOR_ROLE_ADMIN); - _setupRole(_TRUSTED_AGGREGATOR_ROLE_ADMIN, admin); - _setupRole(_SET_FEE_ROLE, admin); - - // Emergency council roles - _setRoleAdmin(_EMERGENCY_COUNCIL_ROLE, _EMERGENCY_COUNCIL_ADMIN); - _setupRole(_EMERGENCY_COUNCIL_ROLE, emergencyCouncil); - _setupRole(_EMERGENCY_COUNCIL_ADMIN, emergencyCouncil); - - // Check last verified batch - uint64 zkEVMLastBatchSequenced = _legacylastBatchSequenced; - uint64 zkEVMLastVerifiedBatch = _legacyLastVerifiedBatch; - if (zkEVMLastBatchSequenced != zkEVMLastVerifiedBatch) { - revert AllzkEVMSequencedBatchesMustBeVerified(); - } - - // Initialize current zkEVM - RollupData storage currentZkEVM = _addExistingRollup( - IPolygonRollupBase(polygonZkEVM), - zkEVMVerifier, - zkEVMForkID, - zkEVMChainID, - 0, // Rollup compatibility ID is 0 - _legacyLastVerifiedBatch - ); - - // Copy variables from legacy - currentZkEVM.batchNumToStateRoot[ - zkEVMLastVerifiedBatch - ] = _legacyBatchNumToStateRoot[zkEVMLastVerifiedBatch]; - - // note previousLastBatchSequenced of the SequencedBatchData will be inconsistent, - // since there will not be a previous sequence stored in the sequence mapping. - // However since lastVerifiedBatch is equal to the lastBatchSequenced - // won't affect in any case - currentZkEVM.sequencedBatches[ - zkEVMLastBatchSequenced - ] = _legacySequencedBatches[zkEVMLastBatchSequenced]; - - currentZkEVM.lastBatchSequenced = zkEVMLastBatchSequenced; - currentZkEVM.lastVerifiedBatch = zkEVMLastVerifiedBatch; - currentZkEVM.lastVerifiedBatchBeforeUpgrade = zkEVMLastVerifiedBatch; - // rollupType and rollupCompatibilityID will be both 0 - - // Initialize polygon zkevm - polygonZkEVM.initializeUpgrade( - _legacyAdmin, - _legacyTrustedSequencer, - _legacyTrustedSequencerURL, - _legacyNetworkName, - _legacySequencedBatches[zkEVMLastBatchSequenced].accInputHash - ); - } - /////////////////////////////////////// // Rollups management functions /////////////////////////////////////// @@ -548,7 +447,7 @@ contract PolygonRollupManagerPrevious is /** * @notice Create a new rollup * @param rollupTypeID Rollup type to deploy - * @param chainID ChainID of the rollup, must be a new one + * @param chainID ChainID of the rollup, must be a new one, can not have more than 32 bits * @param admin Admin of the new created rollup * @param sequencer Sequencer of the new created rollup * @param gasTokenAddress Indicates the token address that will be used to pay gas fees in the new rollup @@ -576,6 +475,12 @@ contract PolygonRollupManagerPrevious is revert RollupTypeObsolete(); } + // check chainID max value + // Currently we have this limitation by the circuit, might be removed in a future + if (chainID > type(uint32).max) { + revert ChainIDOutOfRange(); + } + // Check chainID nullifier if (chainIDToRollupID[chainID] != 0) { revert ChainIDAlreadyExist(); @@ -650,6 +555,11 @@ contract PolygonRollupManagerPrevious is revert ChainIDAlreadyExist(); } + // check chainID max value + // Currently we have this limitation by the circuit, might be removed in a future + if (chainID > type(uint32).max) { + revert ChainIDOutOfRange(); + } // Check if rollup address was already added if (rollupAddressToID[address(rollupAddress)] != 0) { revert RollupAddressAlreadyExist(); @@ -660,8 +570,7 @@ contract PolygonRollupManagerPrevious is verifier, forkID, chainID, - rollupCompatibilityID, - 0 // last verified batch it's always 0 + rollupCompatibilityID ); rollup.batchNumToStateRoot[0] = genesis; } @@ -674,15 +583,13 @@ contract PolygonRollupManagerPrevious is * @param forkID Fork id of the added rollup * @param chainID Chain id of the added rollup * @param rollupCompatibilityID Compatibility ID for the added rollup - * @param lastVerifiedBatch Last verified batch before adding the rollup */ function _addExistingRollup( IPolygonRollupBase rollupAddress, IVerifierRollup verifier, uint64 forkID, uint64 chainID, - uint8 rollupCompatibilityID, - uint64 lastVerifiedBatch + uint8 rollupCompatibilityID ) internal returns (RollupData storage rollup) { uint32 rollupID = ++rollupCount; @@ -706,10 +613,43 @@ contract PolygonRollupManagerPrevious is address(rollupAddress), chainID, rollupCompatibilityID, - lastVerifiedBatch + 0 ); } + /** + * @notice Upgrade an existing rollup from the rollup admin address + * This address is able to udpate the rollup with more restrictions that the _UPDATE_ROLLUP_ROLE + * @param rollupContract Rollup consensus proxy address + * @param newRollupTypeID New rolluptypeID to upgrade to + */ + function updateRollupByRollupAdmin( + ITransparentUpgradeableProxy rollupContract, + uint32 newRollupTypeID + ) external { + // Check admin of the network is msg.sender + if (IPolygonRollupBase(address(rollupContract)).admin() != msg.sender) { + revert OnlyRollupAdmin(); + } + + // Check all sequences are verified before upgrading + RollupData storage rollup = rollupIDToRollupData[ + rollupAddressToID[address(rollupContract)] + ]; + + // Check all sequenced batches are verified + if (rollup.lastBatchSequenced != rollup.lastVerifiedBatch) { + revert AllSequencedMustBeVerified(); + } + + // review sanity check + if (rollup.rollupTypeID >= newRollupTypeID) { + revert UpdateToOldRollupTypeID(); + } + + _updateRollup(rollupContract, newRollupTypeID, new bytes(0)); + } + /** * @notice Upgrade an existing rollup * @param rollupContract Rollup consensus proxy address @@ -719,8 +659,22 @@ contract PolygonRollupManagerPrevious is function updateRollup( ITransparentUpgradeableProxy rollupContract, uint32 newRollupTypeID, - bytes calldata upgradeData + bytes memory upgradeData ) external onlyRole(_UPDATE_ROLLUP_ROLE) { + _updateRollup(rollupContract, newRollupTypeID, upgradeData); + } + + /** + * @notice Upgrade an existing rollup + * @param rollupContract Rollup consensus proxy address + * @param newRollupTypeID New rolluptypeID to upgrade to + * @param upgradeData Upgrade data + */ + function _updateRollup( + ITransparentUpgradeableProxy rollupContract, + uint32 newRollupTypeID, + bytes memory upgradeData + ) internal { // Check that rollup type exists if (newRollupTypeID == 0 || newRollupTypeID > rollupTypeCount) { revert RollupTypeDoesNotExist(); @@ -758,6 +712,11 @@ contract PolygonRollupManagerPrevious is rollup.forkID = newRollupType.forkID; rollup.rollupTypeID = newRollupTypeID; + // review fix to vulnerability front running attack + if (rollup.lastPendingState != rollup.lastPendingStateConsolidated) { + revert CannotUpdateWithUnconsolidatedPendingState(); + } + uint64 lastVerifiedBatch = getLastVerifiedBatch(rollupID); rollup.lastVerifiedBatchBeforeUpgrade = lastVerifiedBatch; @@ -770,6 +729,93 @@ contract PolygonRollupManagerPrevious is emit UpdateRollup(rollupID, newRollupTypeID, lastVerifiedBatch); } + /** + * @notice Rollback batches of the target rollup + * @param rollupContract Rollup consensus proxy address + * @param targetBatch Batch to rollback up to but not including this batch + */ + function rollbackBatches( + IPolygonRollupBase rollupContract, + uint64 targetBatch + ) external { + // Check msg.sender has _UPDATE_ROLLUP_ROLE rol or is the admin of the network + if ( + !hasRole(_UPDATE_ROLLUP_ROLE, msg.sender) && + IPolygonRollupBase(address(rollupContract)).admin() != msg.sender + ) { + revert NotAllowedAddress(); + } + + // Check the rollup exists + uint32 rollupID = rollupAddressToID[address(rollupContract)]; + if (rollupID == 0) { + revert RollupMustExist(); + } + + // Load rollup + RollupData storage rollup = rollupIDToRollupData[rollupID]; + uint64 lastBatchSequenced = rollup.lastBatchSequenced; + + // Batch to rollback should be already sequenced + if ( + targetBatch >= lastBatchSequenced || + targetBatch < rollup.lastVerifiedBatch + ) { + revert RollbackBatchIsNotValid(); + } + + uint64 currentBatch = lastBatchSequenced; + + // delete sequence batches structs until the targetBatch + while (currentBatch != targetBatch) { + // Load previous end of sequence batch + uint64 previousBatch = rollup + .sequencedBatches[currentBatch] + .previousLastBatchSequenced; + + // Batch to rollback must be end of a sequence + if (previousBatch < targetBatch) { + revert RollbackBatchIsNotEndOfSequence(); + } + + // delete sequence information + delete rollup.sequencedBatches[currentBatch]; + + // Update current batch for next iteration + currentBatch = previousBatch; + } + + // Update last batch sequenced on rollup data + rollup.lastBatchSequenced = targetBatch; + + // Update totalSequencedBatches + totalSequencedBatches -= lastBatchSequenced - targetBatch; + + // Check pending state + if (rollup.lastPendingState > 0) { + // update total verified batches + uint64 currentLastVerifiedBatch = _getLastVerifiedBatch(rollup); + totalVerifiedBatches -= + currentLastVerifiedBatch - + rollup.lastVerifiedBatch; + + rollup.lastPendingState = 0; + rollup.lastPendingStateConsolidated = 0; + } + + // Clean pending state if any + rollupContract.rollbackBatches( + targetBatch, + rollup.sequencedBatches[targetBatch].accInputHash + ); + + emit RollbackBatches( + rollupID, + targetBatch, + rollup.sequencedBatches[targetBatch].accInputHash + ); + } + ///////////////////////////////////// // Sequence/Verify batches functions //////////////////////////////////// diff --git a/contracts/v2/previousVersions/PolygonRollupManagerPreviousV1toV2.sol b/contracts/v2/previousVersions/PolygonRollupManagerPreviousV1toV2.sol new file mode 100644 index 000000000..8126e419a --- /dev/null +++ b/contracts/v2/previousVersions/PolygonRollupManagerPreviousV1toV2.sol @@ -0,0 +1,1911 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity 0.8.20; + +import "./IPolygonRollupManagerPrevious.sol"; +import "../interfaces/IPolygonZkEVMGlobalExitRootV2.sol"; +import "../../interfaces/IPolygonZkEVMBridge.sol"; +import "../interfaces/IPolygonRollupBase.sol"; +import "../../interfaces/IVerifierRollup.sol"; +import "../../lib/EmergencyManager.sol"; +import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; +import "../lib/PolygonTransparentProxy.sol"; +import "../lib/PolygonAccessControlUpgradeable.sol"; +import "../lib/LegacyZKEVMStateVariables.sol"; +import "../consensus/zkEVM/PolygonZkEVMExistentEtrog.sol"; +import "../lib/PolygonConstantsBase.sol"; + +/** + * Contract responsible for managing rollups and the verification of their batches. + * This contract will create and update rollups and store all the hashed sequenced data from them. + * The logic for sequence batches is moved to the `consensus` contracts, while the verification of all of + * them will be done in this one. In this way, the proof aggregation of the rollups will be easier on a close future. + */ +contract PolygonRollupManagerPreviousV1toV2 is + PolygonAccessControlUpgradeable, + EmergencyManager, + LegacyZKEVMStateVariables, + PolygonConstantsBase, + IPolygonRollupManagerPrevious +{ + using SafeERC20Upgradeable for IERC20Upgradeable; + + /** + * @notice Struct which to store the rollup type data + * @param consensusImplementation Consensus implementation ( contains the consensus logic for the transaparent proxy) + * @param verifier verifier + * @param forkID fork ID + * @param rollupCompatibilityID Rollup compatibility ID, to check upgradability between rollup types + * @param obsolete Indicates if the rollup type is obsolete + * @param genesis Genesis block of the rollup, note that will only be used on creating new rollups, not upgrade them + */ + struct RollupType { + address consensusImplementation; + IVerifierRollup verifier; + uint64 forkID; + uint8 rollupCompatibilityID; + bool obsolete; + bytes32 genesis; + } + + /** + * @notice Struct which to store the rollup data of each chain + * @param rollupContract Rollup consensus contract, which manages everything + * related to sequencing transactions + * @param chainID Chain ID of the rollup + * @param verifier Verifier contract + * @param forkID ForkID of the rollup + * @param batchNumToStateRoot State root mapping + * @param sequencedBatches Queue of batches that defines the virtual state + * @param pendingStateTransitions Pending state mapping + * @param lastLocalExitRoot Last exit root verified, used for compute the rollupExitRoot + * @param lastBatchSequenced Last batch sent by the consensus contract + * @param lastVerifiedBatch Last batch verified + * @param lastPendingState Last pending state + * @param lastPendingStateConsolidated Last pending state consolidated + * @param lastVerifiedBatchBeforeUpgrade Last batch verified before the last upgrade + * @param rollupTypeID Rollup type ID, can be 0 if it was added as an existing rollup + * @param rollupCompatibilityID Rollup ID used for compatibility checks when upgrading + */ + struct RollupData { + IPolygonRollupBase rollupContract; + uint64 chainID; + IVerifierRollup verifier; + uint64 forkID; + mapping(uint64 batchNum => bytes32) batchNumToStateRoot; + mapping(uint64 batchNum => SequencedBatchData) sequencedBatches; + mapping(uint256 pendingStateNum => PendingState) pendingStateTransitions; + bytes32 lastLocalExitRoot; + uint64 lastBatchSequenced; + uint64 lastVerifiedBatch; + uint64 lastPendingState; + uint64 lastPendingStateConsolidated; + uint64 lastVerifiedBatchBeforeUpgrade; + uint64 rollupTypeID; + uint8 rollupCompatibilityID; + } + + // Modulus zkSNARK + uint256 internal constant _RFIELD = + 21888242871839275222246405745257275088548364400416034343698204186575808495617; + + // Max batch multiplier per verification + uint256 internal constant _MAX_BATCH_MULTIPLIER = 12; + + // Max batch fee value + uint256 internal constant _MAX_BATCH_FEE = 1000 ether; + + // Min value batch fee + uint256 internal constant _MIN_BATCH_FEE = 1 gwei; + + // Goldilocks prime field + uint256 internal constant _GOLDILOCKS_PRIME_FIELD = 0xFFFFFFFF00000001; // 2 ** 64 - 2 ** 32 + 1 + + // Max uint64 + uint256 internal constant _MAX_UINT_64 = type(uint64).max; // 0xFFFFFFFFFFFFFFFF + + // Exit merkle tree levels + uint256 internal constant _EXIT_TREE_DEPTH = 32; + + // Roles + + // Be able to add a new rollup type + bytes32 internal constant _ADD_ROLLUP_TYPE_ROLE = + keccak256("ADD_ROLLUP_TYPE_ROLE"); + + // Be able to obsolete a rollup type, which means that new rollups cannot use this type + bytes32 internal constant _OBSOLETE_ROLLUP_TYPE_ROLE = + keccak256("OBSOLETE_ROLLUP_TYPE_ROLE"); + + // Be able to create a new rollup using a rollup type + bytes32 internal constant _CREATE_ROLLUP_ROLE = + keccak256("CREATE_ROLLUP_ROLE"); + + // Be able to create a new rollup which does not have to follow any rollup type. + // Also sets the genesis block for that network + bytes32 internal constant _ADD_EXISTING_ROLLUP_ROLE = + keccak256("ADD_EXISTING_ROLLUP_ROLE"); + + // Be able to update a rollup to a new rollup type that it's compatible + bytes32 internal constant _UPDATE_ROLLUP_ROLE = + keccak256("UPDATE_ROLLUP_ROLE"); + + // Be able to that has priority to verify batches and consolidates the state instantly + bytes32 internal constant _TRUSTED_AGGREGATOR_ROLE = + keccak256("TRUSTED_AGGREGATOR_ROLE"); + + // Be able to set the trusted aggregator address + bytes32 internal constant _TRUSTED_AGGREGATOR_ROLE_ADMIN = + keccak256("TRUSTED_AGGREGATOR_ROLE_ADMIN"); + + // Be able to tweak parameters + bytes32 internal constant _TWEAK_PARAMETERS_ROLE = + keccak256("TWEAK_PARAMETERS_ROLE"); + + // Be able to set the current batch fee + bytes32 internal constant _SET_FEE_ROLE = keccak256("SET_FEE_ROLE"); + + // Be able to stop the emergency state + bytes32 internal constant _STOP_EMERGENCY_ROLE = + keccak256("STOP_EMERGENCY_ROLE"); + + // Be able to activate the emergency state without any further condition + bytes32 internal constant _EMERGENCY_COUNCIL_ROLE = + keccak256("EMERGENCY_COUNCIL_ROLE"); + + // Be able to set the emergency council address + bytes32 internal constant _EMERGENCY_COUNCIL_ADMIN = + keccak256("EMERGENCY_COUNCIL_ADMIN"); + + // Global Exit Root address + IPolygonZkEVMGlobalExitRootV2 public immutable globalExitRootManager; + + // PolygonZkEVM Bridge Address + IPolygonZkEVMBridge public immutable bridgeAddress; + + // POL token address + IERC20Upgradeable public immutable pol; + + // Number of rollup types added, every new type will be assigned sequencially a new ID + uint32 public rollupTypeCount; + + // Rollup type mapping + mapping(uint32 rollupTypeID => RollupType) public rollupTypeMap; + + // Number of rollups added, every new rollup will be assigned sequencially a new ID + uint32 public rollupCount; + + // Rollups ID mapping + mapping(uint32 rollupID => RollupData) public rollupIDToRollupData; + + // Rollups address mapping + mapping(address rollupAddress => uint32 rollupID) public rollupAddressToID; + + // Chain ID mapping for nullifying + // note we will take care to avoid that current known chainIDs are not reused in our networks (example: 1) + mapping(uint64 chainID => uint32 rollupID) public chainIDToRollupID; + + // Total sequenced batches across all rollups + uint64 public totalSequencedBatches; + + // Total verified batches across all rollups + uint64 public totalVerifiedBatches; + + // Last timestamp when an aggregation happen + uint64 public lastAggregationTimestamp; + + // Trusted aggregator timeout, if a sequence is not verified in this time frame, + // everyone can verify that sequence + uint64 public trustedAggregatorTimeout; + + // Once a pending state exceeds this timeout it can be consolidated + uint64 public pendingStateTimeout; + + // Time target of the verification of a batch + // Adaptively the batchFee will be updated to achieve this target + uint64 public verifyBatchTimeTarget; + + // Batch fee multiplier with 3 decimals that goes from 1000 - 1023 + uint16 public multiplierBatchFee; + + // Current POL fee per batch sequenced + // note This variable is internal, since the view function getBatchFee is likely to be upgraded + uint256 internal _batchFee; + + // Timestamp when the last emergency state was deactivated + uint64 public lastDeactivatedEmergencyStateTimestamp; + + /** + * @dev Emitted when a new rollup type is added + */ + event AddNewRollupType( + uint32 indexed rollupTypeID, + address consensusImplementation, + address verifier, + uint64 forkID, + uint8 rollupCompatibilityID, + bytes32 genesis, + string description + ); + + /** + * @dev Emitted when a a rolup type is obsoleted + */ + event ObsoleteRollupType(uint32 indexed rollupTypeID); + + /** + * @dev Emitted when a new rollup is created based on a rollupType + */ + event CreateNewRollup( + uint32 indexed rollupID, + uint32 rollupTypeID, + address rollupAddress, + uint64 chainID, + address gasTokenAddress + ); + + /** + * @dev Emitted when an existing rollup is added + */ + event AddExistingRollup( + uint32 indexed rollupID, + uint64 forkID, + address rollupAddress, + uint64 chainID, + uint8 rollupCompatibilityID, + uint64 lastVerifiedBatchBeforeUpgrade + ); + + /** + * @dev Emitted when a rollup is udpated + */ + event UpdateRollup( + uint32 indexed rollupID, + uint32 newRollupTypeID, + uint64 lastVerifiedBatchBeforeUpgrade + ); + + /** + * @dev Emitted when a new verifier is added + */ + event OnSequenceBatches(uint32 indexed rollupID, uint64 lastBatchSequenced); + + /** + * @dev Emitted when an aggregator verifies batches + */ + event VerifyBatches( + uint32 indexed rollupID, + uint64 numBatch, + bytes32 stateRoot, + bytes32 exitRoot, + address indexed aggregator + ); + + /** + * @dev Emitted when the trusted aggregator verifies batches + */ + event VerifyBatchesTrustedAggregator( + uint32 indexed rollupID, + uint64 numBatch, + bytes32 stateRoot, + bytes32 exitRoot, + address indexed aggregator + ); + + /** + * @dev Emitted when pending state is consolidated + */ + event ConsolidatePendingState( + uint32 indexed rollupID, + uint64 numBatch, + bytes32 stateRoot, + bytes32 exitRoot, + uint64 pendingStateNum + ); + + /** + * @dev Emitted when is proved a different state given the same batches + */ + event ProveNonDeterministicPendingState( + bytes32 storedStateRoot, + bytes32 provedStateRoot + ); + + /** + * @dev Emitted when the trusted aggregator overrides pending state + */ + event OverridePendingState( + uint32 indexed rollupID, + uint64 numBatch, + bytes32 stateRoot, + bytes32 exitRoot, + address aggregator + ); + + /** + * @dev Emitted when is updated the trusted aggregator timeout + */ + event SetTrustedAggregatorTimeout(uint64 newTrustedAggregatorTimeout); + + /** + * @dev Emitted when is updated the pending state timeout + */ + event SetPendingStateTimeout(uint64 newPendingStateTimeout); + + /** + * @dev Emitted when is updated the multiplier batch fee + */ + event SetMultiplierBatchFee(uint16 newMultiplierBatchFee); + + /** + * @dev Emitted when is updated the verify batch timeout + */ + event SetVerifyBatchTimeTarget(uint64 newVerifyBatchTimeTarget); + + /** + * @dev Emitted when is updated the trusted aggregator address + */ + event SetTrustedAggregator(address newTrustedAggregator); + + /** + * @dev Emitted when is updated the batch fee + */ + event SetBatchFee(uint256 newBatchFee); + + /** + * @param _globalExitRootManager Global exit root manager address + * @param _pol POL token address + * @param _bridgeAddress Bridge address + */ + constructor( + IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, + IERC20Upgradeable _pol, + IPolygonZkEVMBridge _bridgeAddress + ) { + globalExitRootManager = _globalExitRootManager; + pol = _pol; + bridgeAddress = _bridgeAddress; + + // Disable initalizers on the implementation following the best practices + _disableInitializers(); + } + + /** + * @param trustedAggregator Trusted aggregator address + * @param _pendingStateTimeout Pending state timeout + * @param _trustedAggregatorTimeout Trusted aggregator timeout + * @param admin Admin of the rollup manager + * @param timelock Timelock address + * @param emergencyCouncil Emergency council address + * @param polygonZkEVM New deployed Polygon zkEVM which will be initialized wiht previous values + * @param zkEVMVerifier Verifier of the new zkEVM deployed + * @param zkEVMForkID Fork id of the new zkEVM deployed + * @param zkEVMChainID Chain id of the new zkEVM deployed + */ + function initialize( + address trustedAggregator, + uint64 _pendingStateTimeout, + uint64 _trustedAggregatorTimeout, + address admin, + address timelock, + address emergencyCouncil, + PolygonZkEVMExistentEtrog polygonZkEVM, + IVerifierRollup zkEVMVerifier, + uint64 zkEVMForkID, + uint64 zkEVMChainID + ) external virtual reinitializer(2) { + pendingStateTimeout = _pendingStateTimeout; + trustedAggregatorTimeout = _trustedAggregatorTimeout; + + // Constant deployment variables + _batchFee = 0.1 ether; // 0.1 POL + verifyBatchTimeTarget = 30 minutes; + multiplierBatchFee = 1002; + + // Initialize OZ contracts + __AccessControl_init(); + + // setup roles + + // trusted aggregator role + _setupRole(_TRUSTED_AGGREGATOR_ROLE, trustedAggregator); + + // Timelock roles + _setupRole(DEFAULT_ADMIN_ROLE, timelock); + _setupRole(_ADD_ROLLUP_TYPE_ROLE, timelock); + _setupRole(_ADD_EXISTING_ROLLUP_ROLE, timelock); + + // note even this role can only update to an already added verifier/consensus + // Could break the compatibility of them, changing the virtual state + _setupRole(_UPDATE_ROLLUP_ROLE, timelock); + + // admin roles + _setupRole(_OBSOLETE_ROLLUP_TYPE_ROLE, admin); + _setupRole(_CREATE_ROLLUP_ROLE, admin); + _setupRole(_STOP_EMERGENCY_ROLE, admin); + _setupRole(_TWEAK_PARAMETERS_ROLE, admin); + + // admin should be able to update the trusted aggregator address + _setRoleAdmin(_TRUSTED_AGGREGATOR_ROLE, _TRUSTED_AGGREGATOR_ROLE_ADMIN); + _setupRole(_TRUSTED_AGGREGATOR_ROLE_ADMIN, admin); + _setupRole(_SET_FEE_ROLE, admin); + + // Emergency council roles + _setRoleAdmin(_EMERGENCY_COUNCIL_ROLE, _EMERGENCY_COUNCIL_ADMIN); + _setupRole(_EMERGENCY_COUNCIL_ROLE, emergencyCouncil); + _setupRole(_EMERGENCY_COUNCIL_ADMIN, emergencyCouncil); + + // Check last verified batch + uint64 zkEVMLastBatchSequenced = _legacylastBatchSequenced; + uint64 zkEVMLastVerifiedBatch = _legacyLastVerifiedBatch; + if (zkEVMLastBatchSequenced != zkEVMLastVerifiedBatch) { + revert AllzkEVMSequencedBatchesMustBeVerified(); + } + + // Initialize current zkEVM + RollupData storage currentZkEVM = _addExistingRollup( + IPolygonRollupBase(polygonZkEVM), + zkEVMVerifier, + zkEVMForkID, + zkEVMChainID, + 0, // Rollup compatibility ID is 0 + _legacyLastVerifiedBatch + ); + + // Copy variables from legacy + currentZkEVM.batchNumToStateRoot[ + zkEVMLastVerifiedBatch + ] = _legacyBatchNumToStateRoot[zkEVMLastVerifiedBatch]; + + // note previousLastBatchSequenced of the SequencedBatchData will be inconsistent, + // since there will not be a previous sequence stored in the sequence mapping. + // However since lastVerifiedBatch is equal to the lastBatchSequenced + // won't affect in any case + currentZkEVM.sequencedBatches[ + zkEVMLastBatchSequenced + ] = _legacySequencedBatches[zkEVMLastBatchSequenced]; + + currentZkEVM.lastBatchSequenced = zkEVMLastBatchSequenced; + currentZkEVM.lastVerifiedBatch = zkEVMLastVerifiedBatch; + currentZkEVM.lastVerifiedBatchBeforeUpgrade = zkEVMLastVerifiedBatch; + // rollupType and rollupCompatibilityID will be both 0 + + // Initialize polygon zkevm + polygonZkEVM.initializeUpgrade( + _legacyAdmin, + _legacyTrustedSequencer, + _legacyTrustedSequencerURL, + _legacyNetworkName, + _legacySequencedBatches[zkEVMLastBatchSequenced].accInputHash + ); + } + + /////////////////////////////////////// + // Rollups management functions + /////////////////////////////////////// + + /** + * @notice Add a new rollup type + * @param consensusImplementation Consensus implementation + * @param verifier Verifier address + * @param forkID ForkID of the verifier + * @param genesis Genesis block of the rollup + * @param description Description of the rollup type + */ + function addNewRollupType( + address consensusImplementation, + IVerifierRollup verifier, + uint64 forkID, + uint8 rollupCompatibilityID, + bytes32 genesis, + string memory description + ) external onlyRole(_ADD_ROLLUP_TYPE_ROLE) { + uint32 rollupTypeID = ++rollupTypeCount; + + rollupTypeMap[rollupTypeID] = RollupType({ + consensusImplementation: consensusImplementation, + verifier: verifier, + forkID: forkID, + rollupCompatibilityID: rollupCompatibilityID, + obsolete: false, + genesis: genesis + }); + + emit AddNewRollupType( + rollupTypeID, + consensusImplementation, + address(verifier), + forkID, + rollupCompatibilityID, + genesis, + description + ); + } + + /** + * @notice Obsolete Rollup type + * @param rollupTypeID Rollup type to obsolete + */ + function obsoleteRollupType( + uint32 rollupTypeID + ) external onlyRole(_OBSOLETE_ROLLUP_TYPE_ROLE) { + // Check that rollup type exists + if (rollupTypeID == 0 || rollupTypeID > rollupTypeCount) { + revert RollupTypeDoesNotExist(); + } + + // Check rollup type is not obsolete + RollupType storage currentRollupType = rollupTypeMap[rollupTypeID]; + if (currentRollupType.obsolete == true) { + revert RollupTypeObsolete(); + } + + currentRollupType.obsolete = true; + + emit ObsoleteRollupType(rollupTypeID); + } + + /** + * @notice Create a new rollup + * @param rollupTypeID Rollup type to deploy + * @param chainID ChainID of the rollup, must be a new one + * @param admin Admin of the new created rollup + * @param sequencer Sequencer of the new created rollup + * @param gasTokenAddress Indicates the token address that will be used to pay gas fees in the new rollup + * Note if a wrapped token of the bridge is used, the original network and address of this wrapped will be used instead + * @param sequencerURL Sequencer URL of the new created rollup + * @param networkName Network name of the new created rollup + */ + function createNewRollup( + uint32 rollupTypeID, + uint64 chainID, + address admin, + address sequencer, + address gasTokenAddress, + string memory sequencerURL, + string memory networkName + ) external onlyRole(_CREATE_ROLLUP_ROLE) { + // Check that rollup type exists + if (rollupTypeID == 0 || rollupTypeID > rollupTypeCount) { + revert RollupTypeDoesNotExist(); + } + + // Check rollup type is not obsolete + RollupType storage rollupType = rollupTypeMap[rollupTypeID]; + if (rollupType.obsolete == true) { + revert RollupTypeObsolete(); + } + + // Check chainID nullifier + if (chainIDToRollupID[chainID] != 0) { + revert ChainIDAlreadyExist(); + } + + // Create a new Rollup, using a transparent proxy pattern + // Consensus will be the implementation, and this contract the admin + uint32 rollupID = ++rollupCount; + address rollupAddress = address( + new PolygonTransparentProxy( + rollupType.consensusImplementation, + address(this), + new bytes(0) + ) + ); + + // Set chainID nullifier + chainIDToRollupID[chainID] = rollupID; + + // Store rollup data + rollupAddressToID[rollupAddress] = rollupID; + + RollupData storage rollup = rollupIDToRollupData[rollupID]; + + rollup.rollupContract = IPolygonRollupBase(rollupAddress); + rollup.forkID = rollupType.forkID; + rollup.verifier = rollupType.verifier; + rollup.chainID = chainID; + rollup.batchNumToStateRoot[0] = rollupType.genesis; + rollup.rollupTypeID = rollupTypeID; + rollup.rollupCompatibilityID = rollupType.rollupCompatibilityID; + + emit CreateNewRollup( + rollupID, + rollupTypeID, + rollupAddress, + chainID, + gasTokenAddress + ); + + // Initialize new rollup + IPolygonRollupBase(rollupAddress).initialize( + admin, + sequencer, + rollupID, + gasTokenAddress, + sequencerURL, + networkName + ); + } + + /** + * @notice Add an already deployed rollup + * note that this rollup does not follow any rollupType + * @param rollupAddress Rollup address + * @param verifier Verifier address, must be added before + * @param forkID Fork id of the added rollup + * @param chainID Chain id of the added rollup + * @param genesis Genesis block for this rollup + * @param rollupCompatibilityID Compatibility ID for the added rollup + */ + function addExistingRollup( + IPolygonRollupBase rollupAddress, + IVerifierRollup verifier, + uint64 forkID, + uint64 chainID, + bytes32 genesis, + uint8 rollupCompatibilityID + ) external onlyRole(_ADD_EXISTING_ROLLUP_ROLE) { + // Check chainID nullifier + if (chainIDToRollupID[chainID] != 0) { + revert ChainIDAlreadyExist(); + } + + // Check if rollup address was already added + if (rollupAddressToID[address(rollupAddress)] != 0) { + revert RollupAddressAlreadyExist(); + } + + RollupData storage rollup = _addExistingRollup( + rollupAddress, + verifier, + forkID, + chainID, + rollupCompatibilityID, + 0 // last verified batch it's always 0 + ); + rollup.batchNumToStateRoot[0] = genesis; + } + + /** + * @notice Add an already deployed rollup + * note that this rollup does not follow any rollupType + * @param rollupAddress Rollup address + * @param verifier Verifier address, must be added before + * @param forkID Fork id of the added rollup + * @param chainID Chain id of the added rollup + * @param rollupCompatibilityID Compatibility ID for the added rollup + * @param lastVerifiedBatch Last verified batch before adding the rollup + */ + function _addExistingRollup( + IPolygonRollupBase rollupAddress, + IVerifierRollup verifier, + uint64 forkID, + uint64 chainID, + uint8 rollupCompatibilityID, + uint64 lastVerifiedBatch + ) internal returns (RollupData storage rollup) { + uint32 rollupID = ++rollupCount; + + // Set chainID nullifier + chainIDToRollupID[chainID] = rollupID; + + // Store rollup data + rollupAddressToID[address(rollupAddress)] = rollupID; + + rollup = rollupIDToRollupData[rollupID]; + rollup.rollupContract = rollupAddress; + rollup.forkID = forkID; + rollup.verifier = verifier; + rollup.chainID = chainID; + rollup.rollupCompatibilityID = rollupCompatibilityID; + // rollup type is 0, since it does not follow any rollup type + + emit AddExistingRollup( + rollupID, + forkID, + address(rollupAddress), + chainID, + rollupCompatibilityID, + lastVerifiedBatch + ); + } + + /** + * @notice Upgrade an existing rollup + * @param rollupContract Rollup consensus proxy address + * @param newRollupTypeID New rolluptypeID to upgrade to + * @param upgradeData Upgrade data + */ + function updateRollup( + ITransparentUpgradeableProxy rollupContract, + uint32 newRollupTypeID, + bytes calldata upgradeData + ) external onlyRole(_UPDATE_ROLLUP_ROLE) { + // Check that rollup type exists + if (newRollupTypeID == 0 || newRollupTypeID > rollupTypeCount) { + revert RollupTypeDoesNotExist(); + } + + // Check the rollup exists + uint32 rollupID = rollupAddressToID[address(rollupContract)]; + if (rollupID == 0) { + revert RollupMustExist(); + } + + RollupData storage rollup = rollupIDToRollupData[rollupID]; + + // The update must be to a new rollup type + if (rollup.rollupTypeID == newRollupTypeID) { + revert UpdateToSameRollupTypeID(); + } + + RollupType storage newRollupType = rollupTypeMap[newRollupTypeID]; + + // Check rollup type is not obsolete + if (newRollupType.obsolete == true) { + revert RollupTypeObsolete(); + } + + // Check compatibility of the rollups + if ( + rollup.rollupCompatibilityID != newRollupType.rollupCompatibilityID + ) { + revert UpdateNotCompatible(); + } + + // Update rollup parameters + rollup.verifier = newRollupType.verifier; + rollup.forkID = newRollupType.forkID; + rollup.rollupTypeID = newRollupTypeID; + + uint64 lastVerifiedBatch = getLastVerifiedBatch(rollupID); + rollup.lastVerifiedBatchBeforeUpgrade = lastVerifiedBatch; + + // Upgrade rollup + rollupContract.upgradeToAndCall( + newRollupType.consensusImplementation, + upgradeData + ); + + emit UpdateRollup(rollupID, newRollupTypeID, lastVerifiedBatch); + } + + ///////////////////////////////////// + // Sequence/Verify batches functions + //////////////////////////////////// + + /** + * @notice Sequence batches, callback called by one of the consensus managed by this contract + * @param newSequencedBatches Number of batches sequenced + * @param newAccInputHash New accumulate input hash + */ + function onSequenceBatches( + uint64 newSequencedBatches, + bytes32 newAccInputHash + ) external ifNotEmergencyState returns (uint64) { + // Check that the msg.sender is an added rollup + uint32 rollupID = rollupAddressToID[msg.sender]; + if (rollupID == 0) { + revert SenderMustBeRollup(); + } + + // This prevents overwritting sequencedBatches + if (newSequencedBatches == 0) { + revert MustSequenceSomeBatch(); + } + + RollupData storage rollup = rollupIDToRollupData[rollupID]; + + // Update total sequence parameters + totalSequencedBatches += newSequencedBatches; + + // Update sequenced batches of the current rollup + uint64 previousLastBatchSequenced = rollup.lastBatchSequenced; + uint64 newLastBatchSequenced = previousLastBatchSequenced + + newSequencedBatches; + + rollup.lastBatchSequenced = newLastBatchSequenced; + rollup.sequencedBatches[newLastBatchSequenced] = SequencedBatchData({ + accInputHash: newAccInputHash, + sequencedTimestamp: uint64(block.timestamp), + previousLastBatchSequenced: previousLastBatchSequenced + }); + + // Consolidate pending state if possible + _tryConsolidatePendingState(rollup); + + emit OnSequenceBatches(rollupID, newLastBatchSequenced); + + return newLastBatchSequenced; + } + + /** + * @notice Allows an aggregator to verify multiple batches + * @param rollupID Rollup identifier + * @param pendingStateNum Init pending state, 0 if consolidated state is used + * @param initNumBatch Batch which the aggregator starts the verification + * @param finalNewBatch Last batch aggregator intends to verify + * @param newLocalExitRoot New local exit root once the batch is processed + * @param newStateRoot New State root once the batch is processed + * @param beneficiary Address that will receive the verification reward + * @param proof Fflonk proof + */ + function verifyBatches( + uint32 rollupID, + uint64 pendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + address beneficiary, + bytes32[24] calldata proof + ) external ifNotEmergencyState { + RollupData storage rollup = rollupIDToRollupData[rollupID]; + + // Check if the trusted aggregator timeout expired, + // Note that the sequencedBatches struct must exists for this finalNewBatch, if not newAccInputHash will be 0 + if ( + rollup.sequencedBatches[finalNewBatch].sequencedTimestamp + + trustedAggregatorTimeout > + block.timestamp + ) { + revert TrustedAggregatorTimeoutNotExpired(); + } + + if (finalNewBatch - initNumBatch > _MAX_VERIFY_BATCHES) { + revert ExceedMaxVerifyBatches(); + } + + _verifyAndRewardBatches( + rollup, + pendingStateNum, + initNumBatch, + finalNewBatch, + newLocalExitRoot, + newStateRoot, + beneficiary, + proof + ); + + // Update batch fees + _updateBatchFee(rollup, finalNewBatch); + + if (pendingStateTimeout == 0) { + // Consolidate state + rollup.lastVerifiedBatch = finalNewBatch; + rollup.batchNumToStateRoot[finalNewBatch] = newStateRoot; + rollup.lastLocalExitRoot = newLocalExitRoot; + + // Clean pending state if any + if (rollup.lastPendingState > 0) { + rollup.lastPendingState = 0; + rollup.lastPendingStateConsolidated = 0; + } + + // Interact with globalExitRootManager + globalExitRootManager.updateExitRoot(getRollupExitRoot()); + } else { + // Consolidate pending state if possible + _tryConsolidatePendingState(rollup); + + // Update pending state + rollup.lastPendingState++; + rollup.pendingStateTransitions[ + rollup.lastPendingState + ] = PendingState({ + timestamp: uint64(block.timestamp), + lastVerifiedBatch: finalNewBatch, + exitRoot: newLocalExitRoot, + stateRoot: newStateRoot + }); + } + + emit VerifyBatches( + rollupID, + finalNewBatch, + newStateRoot, + newLocalExitRoot, + msg.sender + ); + } + + /** + * @notice Allows a trusted aggregator to verify multiple batches + * @param rollupID Rollup identifier + * @param pendingStateNum Init pending state, 0 if consolidated state is used + * @param initNumBatch Batch which the aggregator starts the verification + * @param finalNewBatch Last batch aggregator intends to verify + * @param newLocalExitRoot New local exit root once the batch is processed + * @param newStateRoot New State root once the batch is processed + * @param beneficiary Address that will receive the verification reward + * @param proof Fflonk proof + */ + function verifyBatchesTrustedAggregator( + uint32 rollupID, + uint64 pendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + address beneficiary, + bytes32[24] calldata proof + ) external onlyRole(_TRUSTED_AGGREGATOR_ROLE) { + RollupData storage rollup = rollupIDToRollupData[rollupID]; + + _verifyAndRewardBatches( + rollup, + pendingStateNum, + initNumBatch, + finalNewBatch, + newLocalExitRoot, + newStateRoot, + beneficiary, + proof + ); + + // Consolidate state + rollup.lastVerifiedBatch = finalNewBatch; + rollup.batchNumToStateRoot[finalNewBatch] = newStateRoot; + rollup.lastLocalExitRoot = newLocalExitRoot; + + // Clean pending state if any + if (rollup.lastPendingState > 0) { + rollup.lastPendingState = 0; + rollup.lastPendingStateConsolidated = 0; + } + + // Interact with globalExitRootManager + globalExitRootManager.updateExitRoot(getRollupExitRoot()); + + emit VerifyBatchesTrustedAggregator( + rollupID, + finalNewBatch, + newStateRoot, + newLocalExitRoot, + msg.sender + ); + } + + /** + * @notice Verify and reward batches internal function + * @param rollup Rollup Data storage pointer that will be used to the verification + * @param pendingStateNum Init pending state, 0 if consolidated state is used + * @param initNumBatch Batch which the aggregator starts the verification + * @param finalNewBatch Last batch aggregator intends to verify + * @param newLocalExitRoot New local exit root once the batch is processed + * @param newStateRoot New State root once the batch is processed + * @param beneficiary Address that will receive the verification reward + * @param proof Fflonk proof + */ + function _verifyAndRewardBatches( + RollupData storage rollup, + uint64 pendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + address beneficiary, + bytes32[24] calldata proof + ) internal virtual { + bytes32 oldStateRoot; + uint64 currentLastVerifiedBatch = _getLastVerifiedBatch(rollup); + + if (initNumBatch < rollup.lastVerifiedBatchBeforeUpgrade) { + revert InitBatchMustMatchCurrentForkID(); + } + + // Use pending state if specified, otherwise use consolidated state + if (pendingStateNum != 0) { + // Check that pending state exist + // Already consolidated pending states can be used aswell + if (pendingStateNum > rollup.lastPendingState) { + revert PendingStateDoesNotExist(); + } + + // Check choosen pending state + PendingState storage currentPendingState = rollup + .pendingStateTransitions[pendingStateNum]; + + // Get oldStateRoot from pending batch + oldStateRoot = currentPendingState.stateRoot; + + // Check initNumBatch matches the pending state + if (initNumBatch != currentPendingState.lastVerifiedBatch) { + revert InitNumBatchDoesNotMatchPendingState(); + } + } else { + // Use consolidated state + oldStateRoot = rollup.batchNumToStateRoot[initNumBatch]; + + if (oldStateRoot == bytes32(0)) { + revert OldStateRootDoesNotExist(); + } + + // Check initNumBatch is inside the range, sanity check + if (initNumBatch > currentLastVerifiedBatch) { + revert InitNumBatchAboveLastVerifiedBatch(); + } + } + + // Check final batch + if (finalNewBatch <= currentLastVerifiedBatch) { + revert FinalNumBatchBelowLastVerifiedBatch(); + } + + // Get snark bytes + bytes memory snarkHashBytes = _getInputSnarkBytes( + rollup, + initNumBatch, + finalNewBatch, + newLocalExitRoot, + oldStateRoot, + newStateRoot + ); + + // Calulate the snark input + uint256 inputSnark = uint256(sha256(snarkHashBytes)) % _RFIELD; + + // Verify proof + if (!rollup.verifier.verifyProof(proof, [inputSnark])) { + revert InvalidProof(); + } + + // Pay POL rewards + uint64 newVerifiedBatches = finalNewBatch - currentLastVerifiedBatch; + + pol.safeTransfer( + beneficiary, + calculateRewardPerBatch() * newVerifiedBatches + ); + + // Update aggregation parameters + totalVerifiedBatches += newVerifiedBatches; + lastAggregationTimestamp = uint64(block.timestamp); + + // Callback to the rollup address + rollup.rollupContract.onVerifyBatches( + finalNewBatch, + newStateRoot, + msg.sender + ); + } + + /** + * @notice Internal function to consolidate the state automatically once sequence or verify batches are called + * It tries to consolidate the first and the middle pending state in the queue + */ + function _tryConsolidatePendingState(RollupData storage rollup) internal { + // Check if there's any state to consolidate + if (rollup.lastPendingState > rollup.lastPendingStateConsolidated) { + // Check if it's possible to consolidate the next pending state + uint64 nextPendingState = rollup.lastPendingStateConsolidated + 1; + if (_isPendingStateConsolidable(rollup, nextPendingState)) { + // Check middle pending state ( binary search of 1 step) + uint64 middlePendingState = nextPendingState + + (rollup.lastPendingState - nextPendingState) / + 2; + + // Try to consolidate it, and if not, consolidate the nextPendingState + if (_isPendingStateConsolidable(rollup, middlePendingState)) { + _consolidatePendingState(rollup, middlePendingState); + } else { + _consolidatePendingState(rollup, nextPendingState); + } + } + } + } + + /** + * @notice Allows to consolidate any pending state that has already exceed the pendingStateTimeout + * Can be called by the trusted aggregator, which can consolidate any state without the timeout restrictions + * @param rollupID Rollup identifier + * @param pendingStateNum Pending state to consolidate + */ + function consolidatePendingState( + uint32 rollupID, + uint64 pendingStateNum + ) external { + RollupData storage rollup = rollupIDToRollupData[rollupID]; + // Check if pending state can be consolidated + // If trusted aggregator is the sender, do not check the timeout or the emergency state + if (!hasRole(_TRUSTED_AGGREGATOR_ROLE, msg.sender)) { + if (isEmergencyState) { + revert OnlyNotEmergencyState(); + } + + if (!_isPendingStateConsolidable(rollup, pendingStateNum)) { + revert PendingStateNotConsolidable(); + } + } + _consolidatePendingState(rollup, pendingStateNum); + } + + /** + * @notice Internal function to consolidate any pending state that has already exceed the pendingStateTimeout + * @param rollup Rollup data storage pointer + * @param pendingStateNum Pending state to consolidate + */ + function _consolidatePendingState( + RollupData storage rollup, + uint64 pendingStateNum + ) internal { + // Check if pendingStateNum is in correct range + // - not consolidated (implicity checks that is not 0) + // - exist ( has been added) + if ( + pendingStateNum <= rollup.lastPendingStateConsolidated || + pendingStateNum > rollup.lastPendingState + ) { + revert PendingStateInvalid(); + } + + PendingState storage currentPendingState = rollup + .pendingStateTransitions[pendingStateNum]; + + // Update state + uint64 newLastVerifiedBatch = currentPendingState.lastVerifiedBatch; + rollup.lastVerifiedBatch = newLastVerifiedBatch; + rollup.batchNumToStateRoot[newLastVerifiedBatch] = currentPendingState + .stateRoot; + rollup.lastLocalExitRoot = currentPendingState.exitRoot; + + // Update pending state + rollup.lastPendingStateConsolidated = pendingStateNum; + + // Interact with globalExitRootManager + globalExitRootManager.updateExitRoot(getRollupExitRoot()); + + emit ConsolidatePendingState( + rollupAddressToID[address(rollup.rollupContract)], + newLastVerifiedBatch, + currentPendingState.stateRoot, + currentPendingState.exitRoot, + pendingStateNum + ); + } + + ///////////////////////////////// + // Soundness protection functions + ///////////////////////////////// + + /** + * @notice Allows the trusted aggregator to override the pending state + * if it's possible to prove a different state root given the same batches + * @param rollupID Rollup identifier + * @param initPendingStateNum Init pending state, 0 if consolidated state is used + * @param finalPendingStateNum Final pending state, that will be used to compare with the newStateRoot + * @param initNumBatch Batch which the aggregator starts the verification + * @param finalNewBatch Last batch aggregator intends to verify + * @param newLocalExitRoot New local exit root once the batch is processed + * @param newStateRoot New State root once the batch is processed + * @param proof Fflonk proof + */ + function overridePendingState( + uint32 rollupID, + uint64 initPendingStateNum, + uint64 finalPendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + bytes32[24] calldata proof + ) external onlyRole(_TRUSTED_AGGREGATOR_ROLE) { + RollupData storage rollup = rollupIDToRollupData[rollupID]; + + _proveDistinctPendingState( + rollup, + initPendingStateNum, + finalPendingStateNum, + initNumBatch, + finalNewBatch, + newLocalExitRoot, + newStateRoot, + proof + ); + + // Consolidate state + rollup.lastVerifiedBatch = finalNewBatch; + rollup.batchNumToStateRoot[finalNewBatch] = newStateRoot; + rollup.lastLocalExitRoot = newLocalExitRoot; + + // Clean pending state if any + if (rollup.lastPendingState > 0) { + rollup.lastPendingState = 0; + rollup.lastPendingStateConsolidated = 0; + } + + // Interact with globalExitRootManager + globalExitRootManager.updateExitRoot(getRollupExitRoot()); + + // Update trusted aggregator timeout to max + trustedAggregatorTimeout = _HALT_AGGREGATION_TIMEOUT; + + emit OverridePendingState( + rollupID, + finalNewBatch, + newStateRoot, + newLocalExitRoot, + msg.sender + ); + } + + /** + * @notice Allows activate the emergency state if its possible to prove a different state root given the same batches + * @param rollupID Rollup identifier + * @param initPendingStateNum Init pending state, 0 if consolidated state is used + * @param finalPendingStateNum Final pending state, that will be used to compare with the newStateRoot + * @param initNumBatch Batch which the aggregator starts the verification + * @param finalNewBatch Last batch aggregator intends to verify + * @param newLocalExitRoot New local exit root once the batch is processed + * @param newStateRoot New State root once the batch is processed + * @param proof Fflonk proof + */ + function proveNonDeterministicPendingState( + uint32 rollupID, + uint64 initPendingStateNum, + uint64 finalPendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + bytes32[24] calldata proof + ) external ifNotEmergencyState { + RollupData storage rollup = rollupIDToRollupData[rollupID]; + + _proveDistinctPendingState( + rollup, + initPendingStateNum, + finalPendingStateNum, + initNumBatch, + finalNewBatch, + newLocalExitRoot, + newStateRoot, + proof + ); + + emit ProveNonDeterministicPendingState( + rollup.pendingStateTransitions[finalPendingStateNum].stateRoot, + newStateRoot + ); + + // Activate emergency state + _activateEmergencyState(); + } + + /** + * @notice Internal function that proves a different state root given the same batches to verify + * @param rollup Rollup Data struct that will be checked + * @param initPendingStateNum Init pending state, 0 if consolidated state is used + * @param finalPendingStateNum Final pending state, that will be used to compare with the newStateRoot + * @param initNumBatch Batch which the aggregator starts the verification + * @param finalNewBatch Last batch aggregator intends to verify + * @param newLocalExitRoot New local exit root once the batch is processed + * @param newStateRoot New State root once the batch is processed + * @param proof Fflonk proof + */ + function _proveDistinctPendingState( + RollupData storage rollup, + uint64 initPendingStateNum, + uint64 finalPendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + bytes32[24] calldata proof + ) internal view virtual { + bytes32 oldStateRoot; + + if (initNumBatch < rollup.lastVerifiedBatchBeforeUpgrade) { + revert InitBatchMustMatchCurrentForkID(); + } + + // Use pending state if specified, otherwise use consolidated state + if (initPendingStateNum != 0) { + // Check that pending state exist + // Already consolidated pending states can be used aswell + if (initPendingStateNum > rollup.lastPendingState) { + revert PendingStateDoesNotExist(); + } + + // Check choosen pending state + PendingState storage initPendingState = rollup + .pendingStateTransitions[initPendingStateNum]; + + // Get oldStateRoot from init pending state + oldStateRoot = initPendingState.stateRoot; + + // Check initNumBatch matches the init pending state + if (initNumBatch != initPendingState.lastVerifiedBatch) { + revert InitNumBatchDoesNotMatchPendingState(); + } + } else { + // Use consolidated state + oldStateRoot = rollup.batchNumToStateRoot[initNumBatch]; + if (oldStateRoot == bytes32(0)) { + revert OldStateRootDoesNotExist(); + } + + // Check initNumBatch is inside the range, sanity check + if (initNumBatch > rollup.lastVerifiedBatch) { + revert InitNumBatchAboveLastVerifiedBatch(); + } + } + + // Assert final pending state num is in correct range + // - exist ( has been added) + // - bigger than the initPendingstate + // - not consolidated + if ( + finalPendingStateNum > rollup.lastPendingState || + finalPendingStateNum <= initPendingStateNum || + finalPendingStateNum <= rollup.lastPendingStateConsolidated + ) { + revert FinalPendingStateNumInvalid(); + } + + // Check final num batch + if ( + finalNewBatch != + rollup + .pendingStateTransitions[finalPendingStateNum] + .lastVerifiedBatch + ) { + revert FinalNumBatchDoesNotMatchPendingState(); + } + + // Get snark bytes + bytes memory snarkHashBytes = _getInputSnarkBytes( + rollup, + initNumBatch, + finalNewBatch, + newLocalExitRoot, + oldStateRoot, + newStateRoot + ); + + // Calulate the snark input + uint256 inputSnark = uint256(sha256(snarkHashBytes)) % _RFIELD; + + // Verify proof + if (!rollup.verifier.verifyProof(proof, [inputSnark])) { + revert InvalidProof(); + } + + if ( + rollup.pendingStateTransitions[finalPendingStateNum].stateRoot == + newStateRoot + ) { + revert StoredRootMustBeDifferentThanNewRoot(); + } + } + + /** + * @notice Function to update the batch fee based on the new verified batches + * The batch fee will not be updated when the trusted aggregator verifies batches + * @param newLastVerifiedBatch New last verified batch + */ + function _updateBatchFee( + RollupData storage rollup, + uint64 newLastVerifiedBatch + ) internal { + uint64 currentLastVerifiedBatch = _getLastVerifiedBatch(rollup); + uint64 currentBatch = newLastVerifiedBatch; + + uint256 totalBatchesAboveTarget; + uint256 newBatchesVerified = newLastVerifiedBatch - + currentLastVerifiedBatch; + + uint256 targetTimestamp = block.timestamp - verifyBatchTimeTarget; + + while (currentBatch != currentLastVerifiedBatch) { + // Load sequenced batchdata + SequencedBatchData storage currentSequencedBatchData = rollup + .sequencedBatches[currentBatch]; + + // Check if timestamp is below the verifyBatchTimeTarget + if ( + targetTimestamp < currentSequencedBatchData.sequencedTimestamp + ) { + // update currentBatch + currentBatch = currentSequencedBatchData + .previousLastBatchSequenced; + } else { + // The rest of batches will be above + totalBatchesAboveTarget = + currentBatch - + currentLastVerifiedBatch; + break; + } + } + + uint256 totalBatchesBelowTarget = newBatchesVerified - + totalBatchesAboveTarget; + + // _MAX_BATCH_FEE --> (< 70 bits) + // multiplierBatchFee --> (< 10 bits) + // _MAX_BATCH_MULTIPLIER = 12 + // multiplierBatchFee ** _MAX_BATCH_MULTIPLIER --> (< 128 bits) + // batchFee * (multiplierBatchFee ** _MAX_BATCH_MULTIPLIER)--> + // (< 70 bits) * (< 128 bits) = < 256 bits + + // Since all the following operations cannot overflow, we can optimize this operations with unchecked + unchecked { + if (totalBatchesBelowTarget < totalBatchesAboveTarget) { + // There are more batches above target, fee is multiplied + uint256 diffBatches = totalBatchesAboveTarget - + totalBatchesBelowTarget; + + diffBatches = diffBatches > _MAX_BATCH_MULTIPLIER + ? _MAX_BATCH_MULTIPLIER + : diffBatches; + + // For every multiplierBatchFee multiplication we must shift 3 zeroes since we have 3 decimals + _batchFee = + (_batchFee * (uint256(multiplierBatchFee) ** diffBatches)) / + (uint256(1000) ** diffBatches); + } else { + // There are more batches below target, fee is divided + uint256 diffBatches = totalBatchesBelowTarget - + totalBatchesAboveTarget; + + diffBatches = diffBatches > _MAX_BATCH_MULTIPLIER + ? _MAX_BATCH_MULTIPLIER + : diffBatches; + + // For every multiplierBatchFee multiplication we must shift 3 zeroes since we have 3 decimals + uint256 accDivisor = (uint256(1 ether) * + (uint256(multiplierBatchFee) ** diffBatches)) / + (uint256(1000) ** diffBatches); + + // multiplyFactor = multiplierBatchFee ** diffBatches / 10 ** (diffBatches * 3) + // accDivisor = 1E18 * multiplyFactor + // 1E18 * batchFee / accDivisor = batchFee / multiplyFactor + // < 60 bits * < 70 bits / ~60 bits --> overflow not possible + _batchFee = (uint256(1 ether) * _batchFee) / accDivisor; + } + } + + // Batch fee must remain inside a range + if (_batchFee > _MAX_BATCH_FEE) { + _batchFee = _MAX_BATCH_FEE; + } else if (_batchFee < _MIN_BATCH_FEE) { + _batchFee = _MIN_BATCH_FEE; + } + } + + //////////////////////// + // Emergency state functions + //////////////////////// + + /** + * @notice Function to activate emergency state, which also enables the emergency mode on both PolygonRollupManager and PolygonZkEVMBridge contracts + * If not called by the owner must not have been aggregated in a _HALT_AGGREGATION_TIMEOUT period and an emergency state was not happened in the same period + */ + function activateEmergencyState() external { + if (!hasRole(_EMERGENCY_COUNCIL_ROLE, msg.sender)) { + if ( + lastAggregationTimestamp == 0 || + lastAggregationTimestamp + _HALT_AGGREGATION_TIMEOUT > + block.timestamp || + lastDeactivatedEmergencyStateTimestamp + + _HALT_AGGREGATION_TIMEOUT > + block.timestamp + ) { + revert HaltTimeoutNotExpired(); + } + } + _activateEmergencyState(); + } + + /** + * @notice Function to deactivate emergency state on both PolygonRollupManager and PolygonZkEVMBridge contracts + */ + function deactivateEmergencyState() + external + onlyRole(_STOP_EMERGENCY_ROLE) + { + // Set last deactivated emergency state + lastDeactivatedEmergencyStateTimestamp = uint64(block.timestamp); + + // Deactivate emergency state on PolygonZkEVMBridge + bridgeAddress.deactivateEmergencyState(); + + // Deactivate emergency state on this contract + super._deactivateEmergencyState(); + } + + /** + * @notice Internal function to activate emergency state on both PolygonRollupManager and PolygonZkEVMBridge contracts + */ + function _activateEmergencyState() internal override { + // Activate emergency state on PolygonZkEVM Bridge + bridgeAddress.activateEmergencyState(); + + // Activate emergency state on this contract + super._activateEmergencyState(); + } + + ////////////////// + // Setter functions + ////////////////// + + /** + * @notice Set a new pending state timeout + * The timeout can only be lowered, except if emergency state is active + * @param newTrustedAggregatorTimeout Trusted aggregator timeout + */ + function setTrustedAggregatorTimeout( + uint64 newTrustedAggregatorTimeout + ) external onlyRole(_TWEAK_PARAMETERS_ROLE) { + if (!isEmergencyState) { + if (newTrustedAggregatorTimeout >= trustedAggregatorTimeout) { + revert NewTrustedAggregatorTimeoutMustBeLower(); + } + } + + trustedAggregatorTimeout = newTrustedAggregatorTimeout; + emit SetTrustedAggregatorTimeout(newTrustedAggregatorTimeout); + } + + /** + * @notice Set a new trusted aggregator timeout + * The timeout can only be lowered, except if emergency state is active + * @param newPendingStateTimeout Trusted aggregator timeout + */ + function setPendingStateTimeout( + uint64 newPendingStateTimeout + ) external onlyRole(_TWEAK_PARAMETERS_ROLE) { + if (!isEmergencyState) { + if (newPendingStateTimeout >= pendingStateTimeout) { + revert NewPendingStateTimeoutMustBeLower(); + } + } + + pendingStateTimeout = newPendingStateTimeout; + emit SetPendingStateTimeout(newPendingStateTimeout); + } + + /** + * @notice Set a new multiplier batch fee + * @param newMultiplierBatchFee multiplier batch fee + */ + function setMultiplierBatchFee( + uint16 newMultiplierBatchFee + ) external onlyRole(_TWEAK_PARAMETERS_ROLE) { + if (newMultiplierBatchFee < 1000 || newMultiplierBatchFee > 1023) { + revert InvalidRangeMultiplierBatchFee(); + } + + multiplierBatchFee = newMultiplierBatchFee; + emit SetMultiplierBatchFee(newMultiplierBatchFee); + } + + /** + * @notice Set a new verify batch time target + * This value will only be relevant once the aggregation is decentralized, so + * the trustedAggregatorTimeout should be zero or very close to zero + * @param newVerifyBatchTimeTarget Verify batch time target + */ + function setVerifyBatchTimeTarget( + uint64 newVerifyBatchTimeTarget + ) external onlyRole(_TWEAK_PARAMETERS_ROLE) { + if (newVerifyBatchTimeTarget > 1 days) { + revert InvalidRangeBatchTimeTarget(); + } + verifyBatchTimeTarget = newVerifyBatchTimeTarget; + emit SetVerifyBatchTimeTarget(newVerifyBatchTimeTarget); + } + + /** + * @notice Set the current batch fee + * @param newBatchFee new batch fee + */ + function setBatchFee(uint256 newBatchFee) external onlyRole(_SET_FEE_ROLE) { + // check fees min and max + if (newBatchFee > _MAX_BATCH_FEE || newBatchFee < _MIN_BATCH_FEE) { + revert BatchFeeOutOfRange(); + } + _batchFee = newBatchFee; + emit SetBatchFee(newBatchFee); + } + + //////////////////////// + // view/pure functions + /////////////////////// + + /** + * @notice Get the current rollup exit root + * Compute using all the local exit roots of all rollups the rollup exit root + * Since it's expected to have no more than 10 rollups in this first version, even if this approach + * has a gas consumption that scales linearly with the rollups added, it's ok + * In a future versions this computation will be done inside the circuit + */ + function getRollupExitRoot() public view returns (bytes32) { + uint256 currentNodes = rollupCount; + + // If there are no nodes return 0 + if (currentNodes == 0) { + return bytes32(0); + } + + // This array will contain the nodes of the current iteration + bytes32[] memory tmpTree = new bytes32[](currentNodes); + + // In the first iteration the nodes will be the leafs which are the local exit roots of each network + for (uint256 i = 0; i < currentNodes; i++) { + // The first rollup ID starts on 1 + tmpTree[i] = rollupIDToRollupData[uint32(i + 1)].lastLocalExitRoot; + } + + // This variable will keep track of the zero hashes + bytes32 currentZeroHashHeight = 0; + + // This variable will keep track of the reamining levels to compute + uint256 remainingLevels = _EXIT_TREE_DEPTH; + + // Calculate the root of the sub-tree that contains all the localExitRoots + while (currentNodes != 1) { + uint256 nextIterationNodes = currentNodes / 2 + (currentNodes % 2); + bytes32[] memory nextTmpTree = new bytes32[](nextIterationNodes); + for (uint256 i = 0; i < nextIterationNodes; i++) { + // if we are on the last iteration of the current level and the nodes are odd + if (i == nextIterationNodes - 1 && (currentNodes % 2) == 1) { + nextTmpTree[i] = keccak256( + abi.encodePacked(tmpTree[i * 2], currentZeroHashHeight) + ); + } else { + nextTmpTree[i] = keccak256( + abi.encodePacked(tmpTree[i * 2], tmpTree[(i * 2) + 1]) + ); + } + } + + // Update tree variables + tmpTree = nextTmpTree; + currentNodes = nextIterationNodes; + currentZeroHashHeight = keccak256( + abi.encodePacked(currentZeroHashHeight, currentZeroHashHeight) + ); + remainingLevels--; + } + + bytes32 currentRoot = tmpTree[0]; + + // Calculate remaining levels, since it's a sequencial merkle tree, the rest of the tree are zeroes + for (uint256 i = 0; i < remainingLevels; i++) { + currentRoot = keccak256( + abi.encodePacked(currentRoot, currentZeroHashHeight) + ); + currentZeroHashHeight = keccak256( + abi.encodePacked(currentZeroHashHeight, currentZeroHashHeight) + ); + } + return currentRoot; + } + + /** + * @notice Get the last verified batch + */ + function getLastVerifiedBatch( + uint32 rollupID + ) public view returns (uint64) { + return _getLastVerifiedBatch(rollupIDToRollupData[rollupID]); + } + + /** + * @notice Get the last verified batch + */ + function _getLastVerifiedBatch( + RollupData storage rollup + ) internal view returns (uint64) { + if (rollup.lastPendingState > 0) { + return + rollup + .pendingStateTransitions[rollup.lastPendingState] + .lastVerifiedBatch; + } else { + return rollup.lastVerifiedBatch; + } + } + + /** + * @notice Returns a boolean that indicates if the pendingStateNum is or not consolidable + * @param rollupID Rollup id + * @param pendingStateNum Pending state number to check + * Note that his function does not check if the pending state currently exists, or if it's consolidated already + */ + function isPendingStateConsolidable( + uint32 rollupID, + uint64 pendingStateNum + ) public view returns (bool) { + return + _isPendingStateConsolidable( + rollupIDToRollupData[rollupID], + pendingStateNum + ); + } + + /** + * @notice Returns a boolean that indicates if the pendingStateNum is or not consolidable + * @param rollup Rollup data storage pointer + * @param pendingStateNum Pending state number to check + * Note that his function does not check if the pending state currently exists, or if it's consolidated already + */ + function _isPendingStateConsolidable( + RollupData storage rollup, + uint64 pendingStateNum + ) internal view returns (bool) { + return (rollup.pendingStateTransitions[pendingStateNum].timestamp + + pendingStateTimeout <= + block.timestamp); + } + + /** + * @notice Function to calculate the reward to verify a single batch + */ + function calculateRewardPerBatch() public view returns (uint256) { + uint256 currentBalance = pol.balanceOf(address(this)); + + // Total Batches to be verified = total Sequenced Batches - total verified Batches + uint256 totalBatchesToVerify = totalSequencedBatches - + totalVerifiedBatches; + + if (totalBatchesToVerify == 0) return 0; + return currentBalance / totalBatchesToVerify; + } + + /** + * @notice Get batch fee + * This function is used instad of the automatic public view one, + * because in a future might change the behaviour and we will be able to mantain the interface + */ + function getBatchFee() public view returns (uint256) { + return _batchFee; + } + + /** + * @notice Get forced batch fee + */ + function getForcedBatchFee() public view returns (uint256) { + return _batchFee * 100; + } + + /** + * @notice Function to calculate the input snark bytes + * @param rollupID Rollup id used to calculate the input snark bytes + * @param initNumBatch Batch which the aggregator starts the verification + * @param finalNewBatch Last batch aggregator intends to verify + * @param newLocalExitRoot New local exit root once the batch is processed + * @param oldStateRoot State root before batch is processed + * @param newStateRoot New State root once the batch is processed + */ + function getInputSnarkBytes( + uint32 rollupID, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 oldStateRoot, + bytes32 newStateRoot + ) public view returns (bytes memory) { + return + _getInputSnarkBytes( + rollupIDToRollupData[rollupID], + initNumBatch, + finalNewBatch, + newLocalExitRoot, + oldStateRoot, + newStateRoot + ); + } + + /** + * @notice Function to calculate the input snark bytes + * @param rollup Rollup data storage pointer + * @param initNumBatch Batch which the aggregator starts the verification + * @param finalNewBatch Last batch aggregator intends to verify + * @param newLocalExitRoot New local exit root once the batch is processed + * @param oldStateRoot State root before batch is processed + * @param newStateRoot New State root once the batch is processed + */ + function _getInputSnarkBytes( + RollupData storage rollup, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 oldStateRoot, + bytes32 newStateRoot + ) internal view returns (bytes memory) { + // Sanity check + bytes32 oldAccInputHash = rollup + .sequencedBatches[initNumBatch] + .accInputHash; + + bytes32 newAccInputHash = rollup + .sequencedBatches[finalNewBatch] + .accInputHash; + + // Sanity check + if (initNumBatch != 0 && oldAccInputHash == bytes32(0)) { + revert OldAccInputHashDoesNotExist(); + } + + if (newAccInputHash == bytes32(0)) { + revert NewAccInputHashDoesNotExist(); + } + + // Check that new state root is inside goldilocks field + if (!_checkStateRootInsidePrime(uint256(newStateRoot))) { + revert NewStateRootNotInsidePrime(); + } + + return + abi.encodePacked( + msg.sender, + oldStateRoot, + oldAccInputHash, + initNumBatch, + rollup.chainID, + rollup.forkID, + newStateRoot, + newAccInputHash, + newLocalExitRoot, + finalNewBatch + ); + } + + /** + * @notice Function to check if the state root is inside of the prime field + * @param newStateRoot New State root once the batch is processed + */ + function _checkStateRootInsidePrime( + uint256 newStateRoot + ) internal pure returns (bool) { + if ( + ((newStateRoot & _MAX_UINT_64) < _GOLDILOCKS_PRIME_FIELD) && + (((newStateRoot >> 64) & _MAX_UINT_64) < _GOLDILOCKS_PRIME_FIELD) && + (((newStateRoot >> 128) & _MAX_UINT_64) < + _GOLDILOCKS_PRIME_FIELD) && + ((newStateRoot >> 192) < _GOLDILOCKS_PRIME_FIELD) + ) { + return true; + } else { + return false; + } + } + + /** + * @notice Get rollup state root given a batch number + * @param rollupID Rollup identifier + * @param batchNum Batch number + */ + function getRollupBatchNumToStateRoot( + uint32 rollupID, + uint64 batchNum + ) public view returns (bytes32) { + return rollupIDToRollupData[rollupID].batchNumToStateRoot[batchNum]; + } + + /** + * @notice Get rollup sequence batches struct given a batch number + * @param rollupID Rollup identifier + * @param batchNum Batch number + */ + function getRollupSequencedBatches( + uint32 rollupID, + uint64 batchNum + ) public view returns (SequencedBatchData memory) { + return rollupIDToRollupData[rollupID].sequencedBatches[batchNum]; + } + + /** + * @notice Get rollup sequence pending state struct given a batch number + * @param rollupID Rollup identifier + * @param batchNum Batch number + */ + function getRollupPendingStateTransitions( + uint32 rollupID, + uint64 batchNum + ) public view returns (PendingState memory) { + return rollupIDToRollupData[rollupID].pendingStateTransitions[batchNum]; + } +} \ No newline at end of file diff --git a/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol b/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol new file mode 100644 index 000000000..11ee1c5a3 --- /dev/null +++ b/contracts/v2/sovereignChains/BridgeL2SovereignChain.sol @@ -0,0 +1,625 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity 0.8.20; + +import "../interfaces/IBridgeL2SovereignChains.sol"; +import "../PolygonZkEVMBridgeV2.sol"; + +/** + * Sovereign chains bridge that will be deployed on all Sovereign chains + * Contract responsible to manage the token interactions with other networks + * This contract is not meant to replace the current zkEVM bridge contract, but deployed on sovereign networks + */ +contract BridgeL2SovereignChain is + PolygonZkEVMBridgeV2, + IBridgeL2SovereignChains +{ + using SafeERC20Upgradeable for IERC20Upgradeable; + + // Map to store wrappedAddresses that are not mintable + mapping(address wrappedAddress => bool isNotMintable) + public wrappedAddressIsNotMintable; + + // Bridge manager address; can set custom mapping for any token. It's highly recommend to set a timelock at this address after bootstrapping phase + address public bridgeManager; + + /** + * @dev Emitted when a bridge manager is updated + */ + event SetBridgeManager(address bridgeManager); + + /** + * @dev Emitted when a claim is unset + */ + event UnsetClaim(uint32 leafIndex, uint32 sourceBridgeNetwork); + + /** + * @dev Emitted when a token address is remapped by a sovereign token address + */ + event SetSovereignTokenAddress( + uint32 originNetwork, + address originTokenAddress, + address sovereignTokenAddress, + bool isNotMintable + ); + + /** + * @dev Emitted when a legacy token is migrated to a new token + */ + event MigrateLegacyToken( + address sender, + address legacyTokenAddress, + address updatedTokenAddress, + uint256 amount + ); + + /** + * @dev Emitted when a remapped token is removed from mapping + */ + event RemoveLegacySovereignTokenAddress(address sovereignTokenAddress); + + /** + * @dev Emitted when a WETH address is remapped by a sovereign WETH address + */ + event SetSovereignWETHAddress( + address sovereignWETHTokenAddress, + bool isNotMintable + ); + + /** + * Disable initializers on the implementation following the best practices + */ + constructor() { + _disableInitializers(); + } + + /** + * @param _networkID networkID + * @param _gasTokenAddress gas token address + * @param _gasTokenNetwork gas token network + * @param _globalExitRootManager global exit root manager address + * @param _polygonRollupManager Rollup manager address + * @notice The value of `_polygonRollupManager` on the L2 deployment of the contract will be address(0), so + * emergency state is not possible for the L2 deployment of the bridge, intentionally + * @param _gasTokenMetadata Abi encoded gas token metadata + * @param _bridgeManager bridge manager address + * @param _sovereignWETHAddress sovereign WETH address + * @param _sovereignWETHAddressIsNotMintable Flag to indicate if the wrapped ETH is not mintable + */ + function initialize( + uint32 _networkID, + address _gasTokenAddress, + uint32 _gasTokenNetwork, + IBasePolygonZkEVMGlobalExitRoot _globalExitRootManager, + address _polygonRollupManager, + bytes memory _gasTokenMetadata, + address _bridgeManager, + address _sovereignWETHAddress, + bool _sovereignWETHAddressIsNotMintable + ) public virtual initializer { + networkID = _networkID; + globalExitRootManager = _globalExitRootManager; + polygonRollupManager = _polygonRollupManager; + bridgeManager = _bridgeManager; + + // Set gas token + if (_gasTokenAddress == address(0)) { + // Gas token will be ether + if (_gasTokenNetwork != 0) { + revert GasTokenNetworkMustBeZeroOnEther(); + } + // Health check for sovereign WETH address + if ( + _sovereignWETHAddress != address(0) || + _sovereignWETHAddressIsNotMintable + ) { + revert InvalidSovereignWETHAddressParams(); + } + // WETHToken, gasTokenAddress and gasTokenNetwork will be 0 + // gasTokenMetadata will be empty + } else { + // Gas token will be an erc20 + gasTokenAddress = _gasTokenAddress; + gasTokenNetwork = _gasTokenNetwork; + gasTokenMetadata = _gasTokenMetadata; + + // Set sovereign weth token or create new if not provided + if (_sovereignWETHAddress == address(0)) { + // Health check for sovereign WETH address is mintable + if (_sovereignWETHAddressIsNotMintable == true) { + revert InvalidSovereignWETHAddressParams(); + } + // Create a wrapped token for WETH, with salt == 0 + WETHToken = _deployWrappedToken( + 0, // salt + abi.encode("Wrapped Ether", "WETH", 18) + ); + } else { + WETHToken = TokenWrapped(_sovereignWETHAddress); + wrappedAddressIsNotMintable[ + _sovereignWETHAddress + ] = _sovereignWETHAddressIsNotMintable; + } + } + + // Initialize OZ contracts + __ReentrancyGuard_init(); + } + + /** + * @notice Override the function to prevent the contract from being initialized with this initializer + */ + function initialize( + uint32, // _networkID + address, //_gasTokenAddress + uint32, //_gasTokenNetwork + IBasePolygonZkEVMGlobalExitRoot, //_globalExitRootManager + address, //_polygonRollupManager + bytes memory //_gasTokenMetadata + ) + external + override(IPolygonZkEVMBridgeV2, PolygonZkEVMBridgeV2) + initializer + { + revert InvalidInitializeFunction(); + } + + modifier onlyBridgeManager() { + if (bridgeManager != msg.sender) { + revert OnlyBridgeManager(); + } + _; + } + + /** + * @notice Remap multiple wrapped tokens to a new sovereign token address + * @dev This function is a "multi/batch call" to `setSovereignTokenAddress` + * @param originNetworks Array of Origin networks + * @param originTokenAddresses Array od Origin token addresses, 0 address is reserved for ether + * @param sovereignTokenAddresses Array of Addresses of the sovereign wrapped token + * @param isNotMintable Array of Flags to indicate if the wrapped token is not mintable + */ + function setMultipleSovereignTokenAddress( + uint32[] memory originNetworks, + address[] memory originTokenAddresses, + address[] memory sovereignTokenAddresses, + bool[] memory isNotMintable + ) external onlyBridgeManager { + if ( + originNetworks.length != originTokenAddresses.length || + originNetworks.length != sovereignTokenAddresses.length || + originNetworks.length != isNotMintable.length + ) { + revert InputArraysLengthMismatch(); + } + + // Make multiple calls to setSovereignTokenAddress + for (uint256 i = 0; i < sovereignTokenAddresses.length; i++) { + _setSovereignTokenAddress( + originNetworks[i], + originTokenAddresses[i], + sovereignTokenAddresses[i], + isNotMintable[i] + ); + } + } + + /** + * @notice Remap a wrapped token to a new sovereign token address + * @dev This function is used to allow any existing token to be mapped with + * origin token. + * @notice If this function is called multiple times for the same existingTokenAddress, + * this will override the previous calls and only keep the last sovereignTokenAddress. + * @notice The tokenInfoToWrappedToken mapping value is replaced by the new sovereign address but it's not the case for the wrappedTokenToTokenInfo map where the value is added, this way user will always be able to withdraw their tokens + * @notice The number of decimals between sovereign token and origin token is not checked, it doesn't affect the bridge functionality but the UI. + * @param originNetwork Origin network + * @param originTokenAddress Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token + * @param sovereignTokenAddress Address of the sovereign wrapped token + * @param isNotMintable Flag to indicate if the wrapped token is not mintable + */ + function _setSovereignTokenAddress( + uint32 originNetwork, + address originTokenAddress, + address sovereignTokenAddress, + bool isNotMintable + ) internal { + // origin and sovereign token address are not 0 + if ( + originTokenAddress == address(0) || + sovereignTokenAddress == address(0) + ) { + revert InvalidZeroAddress(); + } + // originNetwork != current network, wrapped tokens are always from other networks + if (originNetwork == networkID) { + revert OriginNetworkInvalid(); + } + // Check if the token is already mapped + if ( + wrappedTokenToTokenInfo[sovereignTokenAddress].originTokenAddress != + address(0) + ) { + revert TokenAlreadyMapped(); + } + + // Compute token info hash + bytes32 tokenInfoHash = keccak256( + abi.encodePacked(originNetwork, originTokenAddress) + ); + // Set the address of the wrapper + tokenInfoToWrappedToken[tokenInfoHash] = sovereignTokenAddress; + // Set the token info mapping + // @note wrappedTokenToTokenInfo mapping is not overwritten while tokenInfoToWrappedToken it is + wrappedTokenToTokenInfo[sovereignTokenAddress] = TokenInformation( + originNetwork, + originTokenAddress + ); + wrappedAddressIsNotMintable[sovereignTokenAddress] = isNotMintable; + emit SetSovereignTokenAddress( + originNetwork, + originTokenAddress, + sovereignTokenAddress, + isNotMintable + ); + } + + /** + * @notice Remove the address of a remapped token from the mapping. Used to stop supporting legacy sovereign tokens + * @notice It also removes the token from the isNotMintable mapping + * @notice Although the token is removed from the mapping, the user will still be able to withdraw their tokens using tokenInfoToWrappedToken mapping + * @param legacySovereignTokenAddress Address of the sovereign wrapped token + */ + function removeLegacySovereignTokenAddress( + address legacySovereignTokenAddress + ) external onlyBridgeManager { + // Only allow to remove already remapped tokens + TokenInformation memory tokenInfo = wrappedTokenToTokenInfo[ + legacySovereignTokenAddress + ]; + bytes32 tokenInfoHash = keccak256( + abi.encodePacked( + tokenInfo.originNetwork, + tokenInfo.originTokenAddress + ) + ); + + if ( + tokenInfoToWrappedToken[tokenInfoHash] == address(0) || + tokenInfoToWrappedToken[tokenInfoHash] == + legacySovereignTokenAddress + ) { + revert TokenNotRemapped(); + } + delete wrappedTokenToTokenInfo[legacySovereignTokenAddress]; + delete wrappedAddressIsNotMintable[legacySovereignTokenAddress]; + emit RemoveLegacySovereignTokenAddress(legacySovereignTokenAddress); + } + + /** + * @notice Set the custom wrapper for weth + * @notice If this function is called multiple times this will override the previous calls and only keep the last WETHToken. + * @notice WETH will not maintain legacy versions.Users easily should be able to unwrapp the legacy WETH and unwrapp it with the new one. + * @param sovereignWETHTokenAddress Address of the sovereign weth token + * @param isNotMintable Flag to indicate if the wrapped token is not mintable + */ + function setSovereignWETHAddress( + address sovereignWETHTokenAddress, + bool isNotMintable + ) external onlyBridgeManager { + if (gasTokenAddress == address(0)) { + revert WETHRemappingNotSupportedOnGasTokenNetworks(); + } + WETHToken = TokenWrapped(sovereignWETHTokenAddress); + wrappedAddressIsNotMintable[sovereignWETHTokenAddress] = isNotMintable; + emit SetSovereignWETHAddress(sovereignWETHTokenAddress, isNotMintable); + } + + /** + * @notice Moves old native or remapped token (legacy) to the new mapped token. If the token is mintable, it will be burnt and minted, otherwise it will be transferred + * @param legacyTokenAddress Address of legacy token to migrate + * @param amount Legacy token balance to migrate + */ + function migrateLegacyToken( + address legacyTokenAddress, + uint256 amount + ) external { + // Get current wrapped token address + TokenInformation memory legacyTokenInfo = wrappedTokenToTokenInfo[ + legacyTokenAddress + ]; + if (legacyTokenInfo.originTokenAddress == address(0)) { + revert TokenNotMapped(); + } + + // Check current token mapped is proposed updatedTokenAddress + address currentTokenAddress = tokenInfoToWrappedToken[ + keccak256( + abi.encodePacked( + legacyTokenInfo.originNetwork, + legacyTokenInfo.originTokenAddress + ) + ) + ]; + + if (currentTokenAddress == legacyTokenAddress) { + revert TokenAlreadyUpdated(); + } + + // Proceed to migrate the token + _bridgeWrappedAsset(TokenWrapped(legacyTokenAddress), amount); + _claimWrappedAsset( + TokenWrapped(currentTokenAddress), + msg.sender, + amount + ); + + // Trigger event + emit MigrateLegacyToken( + msg.sender, + legacyTokenAddress, + currentTokenAddress, + amount + ); + } + + /** + * @notice unset multiple claims from the claimedBitmap + * @dev This function is a "multi/batch call" to `unsetClaimedBitmap` + * @param leafIndexes Array of Index + * @param sourceBridgeNetworks Array of Origin networks + */ + function unsetMultipleClaimedBitmap( + uint32[] memory leafIndexes, + uint32[] memory sourceBridgeNetworks + ) external onlyBridgeManager { + if (leafIndexes.length != sourceBridgeNetworks.length) { + revert InputArraysLengthMismatch(); + } + + for (uint256 i = 0; i < leafIndexes.length; i++) { + _unsetClaimedBitmap(leafIndexes[i], sourceBridgeNetworks[i]); + } + } + + /** + * @notice Updated bridge manager address, recommended to set a timelock at this address after bootstrapping phase + * @param _bridgeManager Bridge manager address + */ + function setBridgeManager( + address _bridgeManager + ) external onlyBridgeManager { + bridgeManager = _bridgeManager; + emit SetBridgeManager(bridgeManager); + } + + /** + * @notice Burn tokens from wrapped token to execute the bridge, if the token is not mintable it will be transferred + * note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain + * @param tokenWrapped Wrapped token to burnt + * @param amount Amount of tokens + */ + function _bridgeWrappedAsset( + TokenWrapped tokenWrapped, + uint256 amount + ) internal override { + // The token is either (1) a correctly wrapped token from another network + // or (2) wrapped with custom contract from origin network + if (wrappedAddressIsNotMintable[address(tokenWrapped)]) { + // Don't use burn but transfer to bridge + IERC20Upgradeable(address(tokenWrapped)).safeTransferFrom( + msg.sender, + address(this), + amount + ); + } else { + // Burn tokens + tokenWrapped.burn(msg.sender, amount); + } + } + + /** + * @notice Mints tokens from wrapped token to proceed with the claim, if the token is not mintable it will be transferred + * note This function has been extracted to be able to override it by other contracts like BridgeL2SovereignChain + * @param tokenWrapped Wrapped token to mint + * @param destinationAddress Minted token receiver + * @param amount Amount of tokens + */ + function _claimWrappedAsset( + TokenWrapped tokenWrapped, + address destinationAddress, + uint256 amount + ) internal override { + // If is not mintable transfer instead of mint + if (wrappedAddressIsNotMintable[address(tokenWrapped)]) { + // Transfer tokens + IERC20Upgradeable(address(tokenWrapped)).safeTransfer( + destinationAddress, + amount + ); + } else { + // Claim tokens + tokenWrapped.mint(destinationAddress, amount); + } + } + + /* + * @notice unset a claim from the claimedBitmap + * @param leafIndex Index + * @param sourceBridgeNetwork Origin network + */ + function _unsetClaimedBitmap( + uint32 leafIndex, + uint32 sourceBridgeNetwork + ) private { + uint256 globalIndex = uint256(leafIndex) + + uint256(sourceBridgeNetwork) * + _MAX_LEAFS_PER_NETWORK; + (uint256 wordPos, uint256 bitPos) = _bitmapPositions(globalIndex); + uint256 mask = 1 << bitPos; + uint256 flipped = claimedBitMap[wordPos] ^= mask; + if (flipped & mask != 0) { + revert ClaimNotSet(); + } + emit UnsetClaim(leafIndex, sourceBridgeNetwork); + } + + /** + * @notice Function to check if an index is claimed or not + * @dev function overridden to improve a bit the performance and bytecode not checking unnecessary conditions for sovereign chains context + * @param leafIndex Index + * @param sourceBridgeNetwork Origin network + */ + function isClaimed( + uint32 leafIndex, + uint32 sourceBridgeNetwork + ) external view override returns (bool) { + uint256 globalIndex = uint256(leafIndex) + + uint256(sourceBridgeNetwork) * + _MAX_LEAFS_PER_NETWORK; + + (uint256 wordPos, uint256 bitPos) = _bitmapPositions(globalIndex); + uint256 mask = (1 << bitPos); + return (claimedBitMap[wordPos] & mask) == mask; + } + + /** + * @notice Function to check that an index is not claimed and set it as claimed + * @dev function overridden to improve a bit the performance and bytecode not checking unnecessary conditions for sovereign chains context + * @param leafIndex Index + * @param sourceBridgeNetwork Origin network + */ + function _setAndCheckClaimed( + uint32 leafIndex, + uint32 sourceBridgeNetwork + ) internal override { + uint256 globalIndex = uint256(leafIndex) + + uint256(sourceBridgeNetwork) * + _MAX_LEAFS_PER_NETWORK; + (uint256 wordPos, uint256 bitPos) = _bitmapPositions(globalIndex); + uint256 mask = 1 << bitPos; + uint256 flipped = claimedBitMap[wordPos] ^= mask; + if (flipped & mask == 0) { + revert AlreadyClaimed(); + } + } + + /** + * @notice Function to call token permit method of extended ERC20 + * @dev function overridden from PolygonZkEVMBridgeV2 to improve a bit the performance and bytecode not checking unnecessary conditions for sovereign chains context + + @param token ERC20 token address + * @param amount Quantity that is expected to be allowed + * @param permitData Raw data of the call `permit` of the token + */ + function _permit( + address token, + uint256 amount, + bytes calldata permitData + ) internal override { + bytes4 sig = bytes4(permitData[:4]); + if (sig == _PERMIT_SIGNATURE) { + ( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s + ) = abi.decode( + permitData[4:], + ( + address, + address, + uint256, + uint256, + uint8, + bytes32, + bytes32 + ) + ); + + if (value != amount) { + revert NotValidAmount(); + } + + // we call without checking the result, in case it fails and he doesn't have enough balance + // the following transferFrom should be fail. This prevents DoS attacks from using a signature + // before the smartcontract call + /* solhint-disable avoid-low-level-calls */ + address(token).call( + abi.encodeWithSelector( + _PERMIT_SIGNATURE, + owner, + spender, + value, + deadline, + v, + r, + s + ) + ); + } else { + if (sig != _PERMIT_SIGNATURE_DAI) { + revert NotValidSignature(); + } + + ( + address holder, + address spender, + uint256 nonce, + uint256 expiry, + bool allowed, + uint8 v, + bytes32 r, + bytes32 s + ) = abi.decode( + permitData[4:], + ( + address, + address, + uint256, + uint256, + bool, + uint8, + bytes32, + bytes32 + ) + ); + + // we call without checking the result, in case it fails and he doesn't have enough balance + // the following transferFrom should be fail. This prevents DoS attacks from using a signature + // before the smartcontract call + /* solhint-disable avoid-low-level-calls */ + address(token).call( + abi.encodeWithSelector( + _PERMIT_SIGNATURE_DAI, + holder, + spender, + nonce, + expiry, + allowed, + v, + r, + s + ) + ); + } + } + + // @note This function is not used in the current implementation. We overwrite it to improve deployed bytecode size + function activateEmergencyState() + external + pure + override(IPolygonZkEVMBridgeV2, PolygonZkEVMBridgeV2) + { + revert EmergencyStateNotAllowed(); + } + + function deactivateEmergencyState() + external + pure + override(IPolygonZkEVMBridgeV2, PolygonZkEVMBridgeV2) + { + revert EmergencyStateNotAllowed(); + } +} diff --git a/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol b/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol new file mode 100644 index 000000000..f1b0e7cd2 --- /dev/null +++ b/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: AGPL-3.0 + +pragma solidity 0.8.20; +import "../../PolygonZkEVMGlobalExitRootL2.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; + +/** + * Contract responsible for managing the exit roots for the Sovereign chains and global exit roots + */ +contract GlobalExitRootManagerL2SovereignChain is + PolygonZkEVMGlobalExitRootL2, + Initializable +{ + // globalExitRootUpdater address + address public globalExitRootUpdater; + + // globalExitRootRemover address + // In case of initializing a chain with Full execution proofs, this address should be set to zero, otherwise, some malicious sequencer could insert invalid global exit roots, claim, go back and the execution would be correctly proved. + address public globalExitRootRemover; + + // Inserted GER counter + uint256 public insertedGERCount; + + /** + * @dev Emitted when a new global exit root is inserted + */ + event InsertGlobalExitRoot(bytes32 indexed newGlobalExitRoot); + + /** + * @dev Emitted when the last global exit root is removed + */ + event RemoveLastGlobalExitRoot(bytes32 indexed removedGlobalExitRoot); + + /** + * @dev Emitted when the globalExitRootUpdater is set + */ + event SetGlobalExitRootUpdater(address indexed newGlobalExitRootUpdater); + + /** + * @dev Emitted when the globalExitRootRemover is set + */ + event SetGlobalExitRootRemover(address indexed newGlobalExitRootRemover); + + /** + * @param _bridgeAddress PolygonZkEVMBridge contract address + */ + constructor( + address _bridgeAddress + ) PolygonZkEVMGlobalExitRootL2(_bridgeAddress) { + _disableInitializers(); + } + + /** + * @notice Initialize contract + * @param _globalExitRootUpdater setting the globalExitRootUpdater. + * @param _globalExitRootRemover In case of initializing a chain with Full execution proofs, this address should be set to zero, otherwise, some malicious sequencer could insert invalid global exit roots, claim and go back and the execution would be correctly proved. + */ + function initialize( + address _globalExitRootUpdater, + address _globalExitRootRemover + ) external virtual initializer { + // set globalExitRootUpdater + globalExitRootUpdater = _globalExitRootUpdater; + // set globalExitRootRemover + globalExitRootRemover = _globalExitRootRemover; + } + + modifier onlyGlobalExitRootUpdater() { + // Only allowed to be called by GlobalExitRootUpdater or coinbase if GlobalExitRootUpdater is zero + if (globalExitRootUpdater == address(0)) { + if (block.coinbase != msg.sender) { + revert OnlyGlobalExitRootUpdater(); + } + } else { + if (globalExitRootUpdater != msg.sender) { + revert OnlyGlobalExitRootUpdater(); + } + } + _; + } + + modifier onlyGlobalExitRootRemover() { + // Only allowed to be called by GlobalExitRootRemover + if (globalExitRootRemover != msg.sender) { + revert OnlyGlobalExitRootRemover(); + } + _; + } + /** + * @notice Insert a new global exit root + * @param _newRoot new global exit root to insert + */ + function insertGlobalExitRoot( + bytes32 _newRoot + ) external onlyGlobalExitRootUpdater { + // do not insert GER if already set + if (globalExitRootMap[_newRoot] == 0) { + globalExitRootMap[_newRoot] = ++insertedGERCount; + emit InsertGlobalExitRoot(_newRoot); + } else { + revert GlobalExitRootAlreadySet(); + } + } + + /** + * @notice Remove last global exit roots + * @param gersToRemove Array of gers to remove in inserted order where first element of the array is the last inserted + */ + function removeLastGlobalExitRoots( + bytes32[] calldata gersToRemove + ) external onlyGlobalExitRootRemover { + uint256 insertedGERCountCache = insertedGERCount; + // Can't remove if not enough roots have been inserted + if (gersToRemove.length > insertedGERCountCache) { + revert NotEnoughGlobalExitRootsInserted(); + } + // Iterate through the array of roots to remove them one by one + for (uint256 i = 0; i < gersToRemove.length; i++) { + bytes32 rootToRemove = gersToRemove[i]; + + // Check that the root to remove is the last inserted + uint256 lastInsertedIndex = globalExitRootMap[rootToRemove]; + if (lastInsertedIndex != insertedGERCountCache) { + revert NotLastInsertedGlobalExitRoot(); + } + + // Remove from the mapping + delete globalExitRootMap[rootToRemove]; + // Decrement the counter + insertedGERCountCache--; + + // Emit the removal event + emit RemoveLastGlobalExitRoot(rootToRemove); + } + // Update the counter + insertedGERCount = insertedGERCountCache; + } + + /** + * @notice Set the globalExitRootUpdater + * @param _globalExitRootUpdater new globalExitRootUpdater address + */ + function setGlobalExitRootUpdater( + address _globalExitRootUpdater + ) external onlyGlobalExitRootUpdater { + globalExitRootUpdater = _globalExitRootUpdater; + emit SetGlobalExitRootUpdater(_globalExitRootUpdater); + } + + /** + * @notice Set the globalExitRootRemover + * @param _globalExitRootRemover new globalExitRootRemover address + */ + function setGlobalExitRootRemover( + address _globalExitRootRemover + ) external onlyGlobalExitRootRemover { + globalExitRootRemover = _globalExitRootRemover; + emit SetGlobalExitRootRemover(_globalExitRootRemover); + } +} diff --git a/contracts/verifiers/v4.0.0-rc.3/PlonkVerifier.sol b/contracts/verifiers/v4.0.0-rc.3/PlonkVerifier.sol new file mode 100644 index 000000000..10aa7b15e --- /dev/null +++ b/contracts/verifiers/v4.0.0-rc.3/PlonkVerifier.sol @@ -0,0 +1,1379 @@ +// SPDX-License-Identifier: Apache-2.0 + +// Copyright 2023 Consensys Software Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by gnark DO NOT EDIT + +pragma solidity ^0.8.0; + +contract PlonkVerifier { + uint256 private constant R_MOD = + 21888242871839275222246405745257275088548364400416034343698204186575808495617; + uint256 private constant R_MOD_MINUS_ONE = + 21888242871839275222246405745257275088548364400416034343698204186575808495616; + uint256 private constant P_MOD = + 21888242871839275222246405745257275088696311157297823662689037894645226208583; + + uint256 private constant G2_SRS_0_X_0 = + 11559732032986387107991004021392285783925812861821192530917403151452391805634; + uint256 private constant G2_SRS_0_X_1 = + 10857046999023057135944570762232829481370756359578518086990519993285655852781; + uint256 private constant G2_SRS_0_Y_0 = + 4082367875863433681332203403145435568316851327593401208105741076214120093531; + uint256 private constant G2_SRS_0_Y_1 = + 8495653923123431417604973247489272438418190587263600148770280649306958101930; + + uint256 private constant G2_SRS_1_X_0 = + 15805639136721018565402881920352193254830339253282065586954346329754995870280; + uint256 private constant G2_SRS_1_X_1 = + 19089565590083334368588890253123139704298730990782503769911324779715431555531; + uint256 private constant G2_SRS_1_Y_0 = + 9779648407879205346559610309258181044130619080926897934572699915909528404984; + uint256 private constant G2_SRS_1_Y_1 = + 6779728121489434657638426458390319301070371227460768374343986326751507916979; + + uint256 private constant G1_SRS_X = + 14312776538779914388377568895031746459131577658076416373430523308756343304251; + uint256 private constant G1_SRS_Y = + 11763105256161367503191792604679297387056316997144156930871823008787082098465; + + // ----------------------- vk --------------------- + uint256 private constant VK_NB_PUBLIC_INPUTS = 2; + uint256 private constant VK_DOMAIN_SIZE = 16777216; + uint256 private constant VK_INV_DOMAIN_SIZE = + 21888241567198334088790460357988866238279339518792980768180410072331574733841; + uint256 private constant VK_OMEGA = + 5709868443893258075976348696661355716898495876243883251619397131511003808859; + uint256 private constant VK_QL_COM_X = + 17984004271810887111892332882651374483612811613160171882231530673955342124072; + uint256 private constant VK_QL_COM_Y = + 13277994607875064672295433418223618455646015691912141325106751561841646085822; + uint256 private constant VK_QR_COM_X = + 16336286973672788525637509231329701034039020185740400021577697914995487271901; + uint256 private constant VK_QR_COM_Y = + 88284377293612431075210969180485407669835075356048788125030179865751136579; + uint256 private constant VK_QM_COM_X = + 10856514239855788242760873537198968126773773371401212930763195728908952457266; + uint256 private constant VK_QM_COM_Y = + 9275209459688740642101488227886989724826404626746083670876354123229317070279; + uint256 private constant VK_QO_COM_X = + 11483266664351462882096699260743761962335837409017508503826409502538996076321; + uint256 private constant VK_QO_COM_Y = + 17394959804451514544078291653193154652690985857122468223674247897665667008225; + uint256 private constant VK_QK_COM_X = + 6378083169737830823085597784511445554718388062388953364429190548392020833332; + uint256 private constant VK_QK_COM_Y = + 12423874058816725405347015291038805106767729770869142043443023930694783565135; + + uint256 private constant VK_S1_COM_X = + 8432363989348148399267595343996871949745756313266171098803972147558566645391; + uint256 private constant VK_S1_COM_Y = + 21830041218908693046173167152196424202345484683169853420596524951634570306585; + + uint256 private constant VK_S2_COM_X = + 2889872191603241225798623124219684248629415321428218534303823116357979417612; + uint256 private constant VK_S2_COM_Y = + 8446598484540146291961338772594737249603462456099116591415979984815127389111; + + uint256 private constant VK_S3_COM_X = + 12894021857927799668653295424700631150139887020229360316861211114803005826079; + uint256 private constant VK_S3_COM_Y = + 5332155988317853016248818837542073627058808403298822656476772250044723938116; + + uint256 private constant VK_COSET_SHIFT = 5; + + uint256 private constant VK_QCP_0_X = + 16113316688614670925300831064391815772431716488200414163545127725991745431527; + uint256 private constant VK_QCP_0_Y = + 18613967203673816695007264416375047840688367875268537453854528850830700989951; + + uint256 private constant VK_INDEX_COMMIT_API_0 = 10853426; + uint256 private constant VK_NB_CUSTOM_GATES = 1; + + // ------------------------------------------------ + + // size of the proof without call custom gate + uint256 private constant FIXED_PROOF_SIZE = 0x300; + + // offset proof + + uint256 private constant PROOF_L_COM_X = 0x0; + uint256 private constant PROOF_L_COM_Y = 0x20; + uint256 private constant PROOF_R_COM_X = 0x40; + uint256 private constant PROOF_R_COM_Y = 0x60; + uint256 private constant PROOF_O_COM_X = 0x80; + uint256 private constant PROOF_O_COM_Y = 0xa0; + + // h = h_0 + x^{n+2}h_1 + x^{2(n+2)}h_2 + uint256 private constant PROOF_H_0_COM_X = 0xc0; + uint256 private constant PROOF_H_0_COM_Y = 0xe0; + uint256 private constant PROOF_H_1_COM_X = 0x100; + uint256 private constant PROOF_H_1_COM_Y = 0x120; + uint256 private constant PROOF_H_2_COM_X = 0x140; + uint256 private constant PROOF_H_2_COM_Y = 0x160; + + // "evaluations of wire polynomials at zeta + uint256 private constant PROOF_L_AT_ZETA = 0x180; + uint256 private constant PROOF_R_AT_ZETA = 0x1a0; + uint256 private constant PROOF_O_AT_ZETA = 0x1c0; + + // S1(zeta),S2(zeta) + uint256 private constant PROOF_S1_AT_ZETA = 0x1e0; // Sσ1(zeta) + uint256 private constant PROOF_S2_AT_ZETA = 0x200; // Sσ2(zeta) + + // [Z] + uint256 private constant PROOF_GRAND_PRODUCT_COMMITMENT_X = 0x220; + uint256 private constant PROOF_GRAND_PRODUCT_COMMITMENT_Y = 0x240; + + uint256 private constant PROOF_GRAND_PRODUCT_AT_ZETA_OMEGA = 0x260; // z(w*zeta) + + // Folded proof for the opening of linearised poly, l, r, o, s_1, s_2, qcp + uint256 private constant PROOF_BATCH_OPENING_AT_ZETA_X = 0x280; + uint256 private constant PROOF_BATCH_OPENING_AT_ZETA_Y = 0x2a0; + + uint256 private constant PROOF_OPENING_AT_ZETA_OMEGA_X = 0x2c0; + uint256 private constant PROOF_OPENING_AT_ZETA_OMEGA_Y = 0x2e0; + + uint256 private constant PROOF_OPENING_QCP_AT_ZETA = 0x300; + uint256 private constant PROOF_BSB_COMMITMENTS = 0x320; + + // -------- offset state + + // challenges to check the claimed quotient + + uint256 private constant STATE_ALPHA = 0x0; + uint256 private constant STATE_BETA = 0x20; + uint256 private constant STATE_GAMMA = 0x40; + uint256 private constant STATE_ZETA = 0x60; + uint256 private constant STATE_ALPHA_SQUARE_LAGRANGE_0 = 0x80; + uint256 private constant STATE_FOLDED_H_X = 0xa0; + uint256 private constant STATE_FOLDED_H_Y = 0xc0; + uint256 private constant STATE_LINEARISED_POLYNOMIAL_X = 0xe0; + uint256 private constant STATE_LINEARISED_POLYNOMIAL_Y = 0x100; + uint256 private constant STATE_OPENING_LINEARISED_POLYNOMIAL_ZETA = 0x120; + uint256 private constant STATE_FOLDED_CLAIMED_VALUES = 0x140; // Folded proof for the opening of H, linearised poly, l, r, o, s_1, s_2, qcp + uint256 private constant STATE_FOLDED_DIGESTS_X = 0x160; // linearised poly, l, r, o, s_1, s_2, qcp + uint256 private constant STATE_FOLDED_DIGESTS_Y = 0x180; + uint256 private constant STATE_PI = 0x1a0; + uint256 private constant STATE_ZETA_POWER_N_MINUS_ONE = 0x1c0; + uint256 private constant STATE_GAMMA_KZG = 0x1e0; + uint256 private constant STATE_SUCCESS = 0x200; + uint256 private constant STATE_CHECK_VAR = 0x220; // /!\ this slot is used for debugging only + uint256 private constant STATE_LAST_MEM = 0x240; + + // -------- utils (for Fiat Shamir) + uint256 private constant FS_ALPHA = 0x616C706861; // "alpha" + uint256 private constant FS_BETA = 0x62657461; // "beta" + uint256 private constant FS_GAMMA = 0x67616d6d61; // "gamma" + uint256 private constant FS_ZETA = 0x7a657461; // "zeta" + uint256 private constant FS_GAMMA_KZG = 0x67616d6d61; // "gamma" + + // -------- errors + uint256 private constant ERROR_STRING_ID = + 0x08c379a000000000000000000000000000000000000000000000000000000000; // selector for function Error(string) + + // -------- utils (for hash_fr) + uint256 private constant HASH_FR_BB = 340282366920938463463374607431768211456; // 2**128 + uint256 private constant HASH_FR_ZERO_UINT256 = 0; + uint8 private constant HASH_FR_LEN_IN_BYTES = 48; + uint8 private constant HASH_FR_SIZE_DOMAIN = 11; + uint8 private constant HASH_FR_ONE = 1; + uint8 private constant HASH_FR_TWO = 2; + + // -------- precompiles + uint8 private constant SHA2 = 0x2; + uint8 private constant MOD_EXP = 0x5; + uint8 private constant EC_ADD = 0x6; + uint8 private constant EC_MUL = 0x7; + uint8 private constant EC_PAIR = 0x8; + + /// Verify a Plonk proof. + /// Reverts if the proof or the public inputs are malformed. + /// @param proof serialised plonk proof (using gnark's MarshalSolidity) + /// @param public_inputs (must be reduced) + /// @return success true if the proof passes false otherwise + function Verify(bytes calldata proof, uint256[] calldata public_inputs) + public + view + returns (bool success) + { + assembly { + let mem := mload(0x40) + let freeMem := add(mem, STATE_LAST_MEM) + + // sanity checks + check_number_of_public_inputs(public_inputs.length) + check_inputs_size(public_inputs.length, public_inputs.offset) + check_proof_size(proof.length) + check_proof_openings_size(proof.offset) + + // compute the challenges + let prev_challenge_non_reduced + prev_challenge_non_reduced := + derive_gamma(proof.offset, public_inputs.length, public_inputs.offset) + prev_challenge_non_reduced := derive_beta(prev_challenge_non_reduced) + prev_challenge_non_reduced := derive_alpha(proof.offset, prev_challenge_non_reduced) + derive_zeta(proof.offset, prev_challenge_non_reduced) + + // evaluation of Z=Xⁿ-1 at ζ, we save this value + let zeta := mload(add(mem, STATE_ZETA)) + let zeta_power_n_minus_one := + addmod(pow(zeta, VK_DOMAIN_SIZE, freeMem), sub(R_MOD, 1), R_MOD) + mstore(add(mem, STATE_ZETA_POWER_N_MINUS_ONE), zeta_power_n_minus_one) + + // public inputs contribution + let l_pi := sum_pi_wo_api_commit(public_inputs.offset, public_inputs.length, freeMem) + let l_pi_commit := sum_pi_commit(proof.offset, public_inputs.length, freeMem) + l_pi := addmod(l_pi_commit, l_pi, R_MOD) + mstore(add(mem, STATE_PI), l_pi) + + compute_alpha_square_lagrange_0() + compute_opening_linearised_polynomial(proof.offset) + fold_h(proof.offset) + compute_commitment_linearised_polynomial(proof.offset) + compute_gamma_kzg(proof.offset) + fold_state(proof.offset) + batch_verify_multi_points(proof.offset) + + success := mload(add(mem, STATE_SUCCESS)) + + // Beginning errors ------------------------------------------------- + + function error_nb_public_inputs() { + let ptError := mload(0x40) + mstore(ptError, ERROR_STRING_ID) // selector for function Error(string) + mstore(add(ptError, 0x4), 0x20) + mstore(add(ptError, 0x24), 0x1d) + mstore(add(ptError, 0x44), "wrong number of public inputs") + revert(ptError, 0x64) + } + + /// Called when an exponentiation mod r fails + function error_mod_exp() { + let ptError := mload(0x40) + mstore(ptError, ERROR_STRING_ID) // selector for function Error(string) + mstore(add(ptError, 0x4), 0x20) + mstore(add(ptError, 0x24), 0xc) + mstore(add(ptError, 0x44), "error mod exp") + revert(ptError, 0x64) + } + + /// Called when an operation on Bn254 fails + /// @dev for instance when calling EcMul on a point not on Bn254. + function error_ec_op() { + let ptError := mload(0x40) + mstore(ptError, ERROR_STRING_ID) // selector for function Error(string) + mstore(add(ptError, 0x4), 0x20) + mstore(add(ptError, 0x24), 0x12) + mstore(add(ptError, 0x44), "error ec operation") + revert(ptError, 0x64) + } + + /// Called when one of the public inputs is not reduced. + function error_inputs_size() { + let ptError := mload(0x40) + mstore(ptError, ERROR_STRING_ID) // selector for function Error(string) + mstore(add(ptError, 0x4), 0x20) + mstore(add(ptError, 0x24), 0x18) + mstore(add(ptError, 0x44), "inputs are bigger than r") + revert(ptError, 0x64) + } + + /// Called when the size proof is not as expected + /// @dev to avoid overflow attack for instance + function error_proof_size() { + let ptError := mload(0x40) + mstore(ptError, ERROR_STRING_ID) // selector for function Error(string) + mstore(add(ptError, 0x4), 0x20) + mstore(add(ptError, 0x24), 0x10) + mstore(add(ptError, 0x44), "wrong proof size") + revert(ptError, 0x64) + } + + /// Called when one the openings is bigger than r + /// The openings are the claimed evalutions of a polynomial + /// in a Kzg proof. + function error_proof_openings_size() { + let ptError := mload(0x40) + mstore(ptError, ERROR_STRING_ID) // selector for function Error(string) + mstore(add(ptError, 0x4), 0x20) + mstore(add(ptError, 0x24), 0x16) + mstore(add(ptError, 0x44), "openings bigger than r") + revert(ptError, 0x64) + } + + function error_pairing() { + let ptError := mload(0x40) + mstore(ptError, ERROR_STRING_ID) // selector for function Error(string) + mstore(add(ptError, 0x4), 0x20) + mstore(add(ptError, 0x24), 0xd) + mstore(add(ptError, 0x44), "error pairing") + revert(ptError, 0x64) + } + + function error_verify() { + let ptError := mload(0x40) + mstore(ptError, ERROR_STRING_ID) // selector for function Error(string) + mstore(add(ptError, 0x4), 0x20) + mstore(add(ptError, 0x24), 0xc) + mstore(add(ptError, 0x44), "error verify") + revert(ptError, 0x64) + } + + function error_random_generation() { + let ptError := mload(0x40) + mstore(ptError, ERROR_STRING_ID) // selector for function Error(string) + mstore(add(ptError, 0x4), 0x20) + mstore(add(ptError, 0x24), 0x14) + mstore(add(ptError, 0x44), "error random gen kzg") + revert(ptError, 0x64) + } + // end errors ------------------------------------------------- + + // Beginning checks ------------------------------------------------- + + /// @param s actual number of public inputs + function check_number_of_public_inputs(s) { + if iszero(eq(s, VK_NB_PUBLIC_INPUTS)) { error_nb_public_inputs() } + } + + /// Checks that the public inputs are < R_MOD. + /// @param s number of public inputs + /// @param p pointer to the public inputs array + function check_inputs_size(s, p) { + for { let i } lt(i, s) { i := add(i, 1) } { + if gt(calldataload(p), R_MOD_MINUS_ONE) { error_inputs_size() } + p := add(p, 0x20) + } + } + + /// Checks if the proof is of the correct size + /// @param actual_proof_size size of the proof (not the expected size) + function check_proof_size(actual_proof_size) { + let expected_proof_size := add(FIXED_PROOF_SIZE, mul(VK_NB_CUSTOM_GATES, 0x60)) + if iszero(eq(actual_proof_size, expected_proof_size)) { error_proof_size() } + } + + /// Checks if the multiple openings of the polynomials are < R_MOD. + /// @param aproof pointer to the beginning of the proof + /// @dev the 'a' prepending proof is to have a local name + function check_proof_openings_size(aproof) { + // PROOF_L_AT_ZETA + let p := add(aproof, PROOF_L_AT_ZETA) + if gt(calldataload(p), R_MOD_MINUS_ONE) { error_proof_openings_size() } + + // PROOF_R_AT_ZETA + p := add(aproof, PROOF_R_AT_ZETA) + if gt(calldataload(p), R_MOD_MINUS_ONE) { error_proof_openings_size() } + + // PROOF_O_AT_ZETA + p := add(aproof, PROOF_O_AT_ZETA) + if gt(calldataload(p), R_MOD_MINUS_ONE) { error_proof_openings_size() } + + // PROOF_S1_AT_ZETA + p := add(aproof, PROOF_S1_AT_ZETA) + if gt(calldataload(p), R_MOD_MINUS_ONE) { error_proof_openings_size() } + + // PROOF_S2_AT_ZETA + p := add(aproof, PROOF_S2_AT_ZETA) + if gt(calldataload(p), R_MOD_MINUS_ONE) { error_proof_openings_size() } + + // PROOF_GRAND_PRODUCT_AT_ZETA_OMEGA + p := add(aproof, PROOF_GRAND_PRODUCT_AT_ZETA_OMEGA) + if gt(calldataload(p), R_MOD_MINUS_ONE) { error_proof_openings_size() } + + // PROOF_OPENING_QCP_AT_ZETA + + p := add(aproof, PROOF_OPENING_QCP_AT_ZETA) + for { let i := 0 } lt(i, VK_NB_CUSTOM_GATES) { i := add(i, 1) } { + if gt(calldataload(p), R_MOD_MINUS_ONE) { error_proof_openings_size() } + p := add(p, 0x20) + } + } + // end checks ------------------------------------------------- + + // Beginning challenges ------------------------------------------------- + + /// Derive gamma as Sha256() + /// @param aproof pointer to the proof + /// @param nb_pi number of public inputs + /// @param pi pointer to the array of public inputs + /// @return the challenge gamma, not reduced + /// @notice The transcript is the concatenation (in this order) of: + /// * the word "gamma" in ascii, equal to [0x67,0x61,0x6d, 0x6d, 0x61] and encoded as a uint256. + /// * the commitments to the permutation polynomials S1, S2, S3, where we concatenate the coordinates of those points + /// * the commitments of Ql, Qr, Qm, Qo, Qk + /// * the public inputs + /// * the commitments of the wires related to the custom gates (commitments_wires_commit_api) + /// * commitments to L, R, O (proof__com_) + /// The data described above is written starting at mPtr. "gamma" lies on 5 bytes, + /// and is encoded as a uint256 number n. In basis b = 256, the number looks like this + /// [0 0 0 .. 0x67 0x61 0x6d, 0x6d, 0x61]. The first non zero entry is at position 27=0x1b + /// Gamma reduced (the actual challenge) is stored at add(state, state_gamma) + function derive_gamma(aproof, nb_pi, pi) -> gamma_not_reduced { + let state := mload(0x40) + let mPtr := add(state, STATE_LAST_MEM) + + mstore(mPtr, FS_GAMMA) // "gamma" + + mstore(add(mPtr, 0x20), VK_S1_COM_X) + mstore(add(mPtr, 0x40), VK_S1_COM_Y) + mstore(add(mPtr, 0x60), VK_S2_COM_X) + mstore(add(mPtr, 0x80), VK_S2_COM_Y) + mstore(add(mPtr, 0xa0), VK_S3_COM_X) + mstore(add(mPtr, 0xc0), VK_S3_COM_Y) + mstore(add(mPtr, 0xe0), VK_QL_COM_X) + mstore(add(mPtr, 0x100), VK_QL_COM_Y) + mstore(add(mPtr, 0x120), VK_QR_COM_X) + mstore(add(mPtr, 0x140), VK_QR_COM_Y) + mstore(add(mPtr, 0x160), VK_QM_COM_X) + mstore(add(mPtr, 0x180), VK_QM_COM_Y) + mstore(add(mPtr, 0x1a0), VK_QO_COM_X) + mstore(add(mPtr, 0x1c0), VK_QO_COM_Y) + mstore(add(mPtr, 0x1e0), VK_QK_COM_X) + mstore(add(mPtr, 0x200), VK_QK_COM_Y) + + mstore(add(mPtr, 0x220), VK_QCP_0_X) + mstore(add(mPtr, 0x240), VK_QCP_0_Y) + + // public inputs + let _mPtr := add(mPtr, 0x260) + let size_pi_in_bytes := mul(nb_pi, 0x20) + calldatacopy(_mPtr, pi, size_pi_in_bytes) + _mPtr := add(_mPtr, size_pi_in_bytes) + + // commitments to l, r, o + let size_commitments_lro_in_bytes := 0xc0 + calldatacopy(_mPtr, aproof, size_commitments_lro_in_bytes) + _mPtr := add(_mPtr, size_commitments_lro_in_bytes) + + // total size is : + // sizegamma(=0x5) + 11*64(=0x2c0) + // + nb_public_inputs*0x20 + // + nb_custom gates*0x40 + let size := add(0x2c5, size_pi_in_bytes) + + size := add(size, mul(VK_NB_CUSTOM_GATES, 0x40)) + let l_success := staticcall(gas(), SHA2, add(mPtr, 0x1b), size, mPtr, 0x20) //0x1b -> 000.."gamma" + if iszero(l_success) { error_verify() } + gamma_not_reduced := mload(mPtr) + mstore(add(state, STATE_GAMMA), mod(gamma_not_reduced, R_MOD)) + } + + /// derive beta as Sha256 + /// @param gamma_not_reduced the previous challenge (gamma) not reduced + /// @return beta_not_reduced the next challenge, beta, not reduced + /// @notice the transcript consists of the previous challenge only. + /// The reduced version of beta is stored at add(state, state_beta) + function derive_beta(gamma_not_reduced) -> beta_not_reduced { + let state := mload(0x40) + let mPtr := add(mload(0x40), STATE_LAST_MEM) + + // beta + mstore(mPtr, FS_BETA) // "beta" + mstore(add(mPtr, 0x20), gamma_not_reduced) + let l_success := staticcall(gas(), SHA2, add(mPtr, 0x1c), 0x24, mPtr, 0x20) //0x1b -> 000.."gamma" + if iszero(l_success) { error_verify() } + beta_not_reduced := mload(mPtr) + mstore(add(state, STATE_BETA), mod(beta_not_reduced, R_MOD)) + } + + /// derive alpha as sha256 + /// @param aproof pointer to the proof object + /// @param beta_not_reduced the previous challenge (beta) not reduced + /// @return alpha_not_reduced the next challenge, alpha, not reduced + /// @notice the transcript consists of the previous challenge (beta) + /// not reduced, the commitments to the wires associated to the QCP_i, + /// and the commitment to the grand product polynomial + function derive_alpha(aproof, beta_not_reduced) -> alpha_not_reduced { + let state := mload(0x40) + let mPtr := add(mload(0x40), STATE_LAST_MEM) + let full_size := 0x65 // size("alpha") + 0x20 (previous challenge) + + // alpha + mstore(mPtr, FS_ALPHA) // "alpha" + let _mPtr := add(mPtr, 0x20) + mstore(_mPtr, beta_not_reduced) + _mPtr := add(_mPtr, 0x20) + + // Bsb22Commitments + let proof_bsb_commitments := add(aproof, PROOF_BSB_COMMITMENTS) + let size_bsb_commitments := mul(0x40, VK_NB_CUSTOM_GATES) + calldatacopy(_mPtr, proof_bsb_commitments, size_bsb_commitments) + _mPtr := add(_mPtr, size_bsb_commitments) + full_size := add(full_size, size_bsb_commitments) + + // [Z], the commitment to the grand product polynomial + calldatacopy(_mPtr, add(aproof, PROOF_GRAND_PRODUCT_COMMITMENT_X), 0x40) + let l_success := staticcall(gas(), SHA2, add(mPtr, 0x1b), full_size, mPtr, 0x20) + if iszero(l_success) { error_verify() } + + alpha_not_reduced := mload(mPtr) + mstore(add(state, STATE_ALPHA), mod(alpha_not_reduced, R_MOD)) + } + + /// derive zeta as sha256 + /// @param aproof pointer to the proof object + /// @param alpha_not_reduced the previous challenge (alpha) not reduced + /// The transcript consists of the previous challenge and the commitment to + /// the quotient polynomial h. + function derive_zeta(aproof, alpha_not_reduced) { + let state := mload(0x40) + let mPtr := add(mload(0x40), STATE_LAST_MEM) + + // zeta + mstore(mPtr, FS_ZETA) // "zeta" + mstore(add(mPtr, 0x20), alpha_not_reduced) + calldatacopy(add(mPtr, 0x40), add(aproof, PROOF_H_0_COM_X), 0xc0) + let l_success := staticcall(gas(), SHA2, add(mPtr, 0x1c), 0xe4, mPtr, 0x20) + if iszero(l_success) { error_verify() } + let zeta_not_reduced := mload(mPtr) + mstore(add(state, STATE_ZETA), mod(zeta_not_reduced, R_MOD)) + } + // END challenges ------------------------------------------------- + + // BEGINNING compute_pi ------------------------------------------------- + + /// sum_pi_wo_api_commit computes the public inputs contributions, + /// except for the public inputs coming from the custom gate + /// @param ins pointer to the public inputs + /// @param n number of public inputs + /// @param mPtr free memory + /// @return pi_wo_commit public inputs contribution (except the public inputs coming from the custom gate) + function sum_pi_wo_api_commit(ins, n, mPtr) -> pi_wo_commit { + let state := mload(0x40) + let z := mload(add(state, STATE_ZETA)) + let zpnmo := mload(add(state, STATE_ZETA_POWER_N_MINUS_ONE)) + + let li := mPtr + batch_compute_lagranges_at_z(z, zpnmo, n, li) + + let tmp := 0 + for { let i := 0 } lt(i, n) { i := add(i, 1) } { + tmp := mulmod(mload(li), calldataload(ins), R_MOD) + pi_wo_commit := addmod(pi_wo_commit, tmp, R_MOD) + li := add(li, 0x20) + ins := add(ins, 0x20) + } + } + + /// batch_compute_lagranges_at_z computes [L_0(z), .., L_{n-1}(z)] + /// @param z point at which the Lagranges are evaluated + /// @param zpnmo ζⁿ-1 + /// @param n_pub number of public inputs (number of Lagranges to compute) + /// @param mPtr pointer to which the results are stored + function batch_compute_lagranges_at_z(z, zpnmo, n_pub, mPtr) { + let zn := mulmod(zpnmo, VK_INV_DOMAIN_SIZE, R_MOD) // 1/n * (ζⁿ - 1) + + let _w := 1 + let _mPtr := mPtr + for { let i := 0 } lt(i, n_pub) { i := add(i, 1) } { + mstore(_mPtr, addmod(z, sub(R_MOD, _w), R_MOD)) + _w := mulmod(_w, VK_OMEGA, R_MOD) + _mPtr := add(_mPtr, 0x20) + } + batch_invert(mPtr, n_pub, _mPtr) + _mPtr := mPtr + _w := 1 + for { let i := 0 } lt(i, n_pub) { i := add(i, 1) } { + mstore(_mPtr, mulmod(mulmod(mload(_mPtr), zn, R_MOD), _w, R_MOD)) + _mPtr := add(_mPtr, 0x20) + _w := mulmod(_w, VK_OMEGA, R_MOD) + } + } + + /// @notice Montgomery trick for batch inversion mod R_MOD + /// @param ins pointer to the data to batch invert + /// @param number of elements to batch invert + /// @param mPtr free memory + function batch_invert(ins, nb_ins, mPtr) { + mstore(mPtr, 1) + let offset := 0 + for { let i := 0 } lt(i, nb_ins) { i := add(i, 1) } { + let prev := mload(add(mPtr, offset)) + let cur := mload(add(ins, offset)) + cur := mulmod(prev, cur, R_MOD) + offset := add(offset, 0x20) + mstore(add(mPtr, offset), cur) + } + ins := add(ins, sub(offset, 0x20)) + mPtr := add(mPtr, offset) + let inv := pow(mload(mPtr), sub(R_MOD, 2), add(mPtr, 0x20)) + for { let i := 0 } lt(i, nb_ins) { i := add(i, 1) } { + mPtr := sub(mPtr, 0x20) + let tmp := mload(ins) + let cur := mulmod(inv, mload(mPtr), R_MOD) + mstore(ins, cur) + inv := mulmod(inv, tmp, R_MOD) + ins := sub(ins, 0x20) + } + } + + /// Public inputs (the ones coming from the custom gate) contribution + /// @param aproof pointer to the proof + /// @param nb_public_inputs number of public inputs + /// @param mPtr pointer to free memory + /// @return pi_commit custom gate public inputs contribution + function sum_pi_commit(aproof, nb_public_inputs, mPtr) -> pi_commit { + let state := mload(0x40) + let z := mload(add(state, STATE_ZETA)) + let zpnmo := mload(add(state, STATE_ZETA_POWER_N_MINUS_ONE)) + + let p := add(aproof, PROOF_BSB_COMMITMENTS) + + let h_fr, ith_lagrange + + h_fr := hash_fr(calldataload(p), calldataload(add(p, 0x20)), mPtr) + ith_lagrange := + compute_ith_lagrange_at_z( + z, zpnmo, add(nb_public_inputs, VK_INDEX_COMMIT_API_0), mPtr + ) + pi_commit := addmod(pi_commit, mulmod(h_fr, ith_lagrange, R_MOD), R_MOD) + } + + /// Computes L_i(zeta) = ωⁱ/n * (ζⁿ-1)/(ζ-ωⁱ) where: + /// @param z zeta + /// @param zpmno ζⁿ-1 + /// @param i i-th lagrange + /// @param mPtr free memory + /// @return res = ωⁱ/n * (ζⁿ-1)/(ζ-ωⁱ) + function compute_ith_lagrange_at_z(z, zpnmo, i, mPtr) -> res { + let w := pow(VK_OMEGA, i, mPtr) // w**i + i := addmod(z, sub(R_MOD, w), R_MOD) // z-w**i + w := mulmod(w, VK_INV_DOMAIN_SIZE, R_MOD) // w**i/n + i := pow(i, sub(R_MOD, 2), mPtr) // (z-w**i)**-1 + w := mulmod(w, i, R_MOD) // w**i/n*(z-w)**-1 + res := mulmod(w, zpnmo, R_MOD) + } + + /// @dev https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-5.2 + /// @param x x coordinate of a point on Bn254(𝔽_p) + /// @param y y coordinate of a point on Bn254(𝔽_p) + /// @param mPtr free memory + /// @return res an element mod R_MOD + function hash_fr(x, y, mPtr) -> res { + // [0x00, .. , 0x00 || x, y, || 0, 48, 0, dst, HASH_FR_SIZE_DOMAIN] + // <- 64 bytes -> <-64b -> <- 1 bytes each -> + + // [0x00, .., 0x00] 64 bytes of zero + mstore(mPtr, HASH_FR_ZERO_UINT256) + mstore(add(mPtr, 0x20), HASH_FR_ZERO_UINT256) + + // msg = x || y , both on 32 bytes + mstore(add(mPtr, 0x40), x) + mstore(add(mPtr, 0x60), y) + + // 0 || 48 || 0 all on 1 byte + mstore8(add(mPtr, 0x80), 0) + mstore8(add(mPtr, 0x81), HASH_FR_LEN_IN_BYTES) + mstore8(add(mPtr, 0x82), 0) + + // "BSB22-Plonk" = [42, 53, 42, 32, 32, 2d, 50, 6c, 6f, 6e, 6b,] + mstore8(add(mPtr, 0x83), 0x42) + mstore8(add(mPtr, 0x84), 0x53) + mstore8(add(mPtr, 0x85), 0x42) + mstore8(add(mPtr, 0x86), 0x32) + mstore8(add(mPtr, 0x87), 0x32) + mstore8(add(mPtr, 0x88), 0x2d) + mstore8(add(mPtr, 0x89), 0x50) + mstore8(add(mPtr, 0x8a), 0x6c) + mstore8(add(mPtr, 0x8b), 0x6f) + mstore8(add(mPtr, 0x8c), 0x6e) + mstore8(add(mPtr, 0x8d), 0x6b) + + // size domain + mstore8(add(mPtr, 0x8e), HASH_FR_SIZE_DOMAIN) + + let l_success := staticcall(gas(), SHA2, mPtr, 0x8f, mPtr, 0x20) + if iszero(l_success) { error_verify() } + + let b0 := mload(mPtr) + + // [b0 || one || dst || HASH_FR_SIZE_DOMAIN] + // <-64bytes -> <- 1 byte each -> + mstore8(add(mPtr, 0x20), HASH_FR_ONE) // 1 + + mstore8(add(mPtr, 0x21), 0x42) // dst + mstore8(add(mPtr, 0x22), 0x53) + mstore8(add(mPtr, 0x23), 0x42) + mstore8(add(mPtr, 0x24), 0x32) + mstore8(add(mPtr, 0x25), 0x32) + mstore8(add(mPtr, 0x26), 0x2d) + mstore8(add(mPtr, 0x27), 0x50) + mstore8(add(mPtr, 0x28), 0x6c) + mstore8(add(mPtr, 0x29), 0x6f) + mstore8(add(mPtr, 0x2a), 0x6e) + mstore8(add(mPtr, 0x2b), 0x6b) + + mstore8(add(mPtr, 0x2c), HASH_FR_SIZE_DOMAIN) // size domain + l_success := staticcall(gas(), SHA2, mPtr, 0x2d, mPtr, 0x20) + if iszero(l_success) { error_verify() } + + // b1 is located at mPtr. We store b2 at add(mPtr, 0x20) + + // [b0^b1 || two || dst || HASH_FR_SIZE_DOMAIN] + // <-64bytes -> <- 1 byte each -> + mstore(add(mPtr, 0x20), xor(mload(mPtr), b0)) + mstore8(add(mPtr, 0x40), HASH_FR_TWO) + + mstore8(add(mPtr, 0x41), 0x42) // dst + mstore8(add(mPtr, 0x42), 0x53) + mstore8(add(mPtr, 0x43), 0x42) + mstore8(add(mPtr, 0x44), 0x32) + mstore8(add(mPtr, 0x45), 0x32) + mstore8(add(mPtr, 0x46), 0x2d) + mstore8(add(mPtr, 0x47), 0x50) + mstore8(add(mPtr, 0x48), 0x6c) + mstore8(add(mPtr, 0x49), 0x6f) + mstore8(add(mPtr, 0x4a), 0x6e) + mstore8(add(mPtr, 0x4b), 0x6b) + + mstore8(add(mPtr, 0x4c), HASH_FR_SIZE_DOMAIN) // size domain + + let offset := add(mPtr, 0x20) + l_success := staticcall(gas(), SHA2, offset, 0x2d, offset, 0x20) + if iszero(l_success) { error_verify() } + + // at this point we have mPtr = [ b1 || b2] where b1 is on 32byes and b2 in 16bytes. + // we interpret it as a big integer mod r in big endian (similar to regular decimal notation) + // the result is then 2**(8*16)*mPtr[:32] + mPtr[32:48] + res := mulmod(mload(mPtr), HASH_FR_BB, R_MOD) // <- res = 2**128 * mPtr[:32] + let b1 := shr(128, mload(add(mPtr, 0x20))) // b1 <- [0, 0, .., 0 || b2[:16] ] + res := addmod(res, b1, R_MOD) + } + + // END compute_pi ------------------------------------------------- + + /// @notice compute α² * 1/n * (ζ{n}-1)/(ζ - 1) where + /// * α = challenge derived in derive_gamma_beta_alpha_zeta + /// * n = vk_domain_size + /// * ω = vk_omega (generator of the multiplicative cyclic group of order n in (ℤ/rℤ)*) + /// * ζ = zeta (challenge derived with Fiat Shamir) + function compute_alpha_square_lagrange_0() { + let state := mload(0x40) + let mPtr := add(mload(0x40), STATE_LAST_MEM) + + let res := mload(add(state, STATE_ZETA_POWER_N_MINUS_ONE)) + let den := addmod(mload(add(state, STATE_ZETA)), sub(R_MOD, 1), R_MOD) + den := pow(den, sub(R_MOD, 2), mPtr) + den := mulmod(den, VK_INV_DOMAIN_SIZE, R_MOD) + res := mulmod(den, res, R_MOD) + + let l_alpha := mload(add(state, STATE_ALPHA)) + res := mulmod(res, l_alpha, R_MOD) + res := mulmod(res, l_alpha, R_MOD) + mstore(add(state, STATE_ALPHA_SQUARE_LAGRANGE_0), res) + } + + /// @notice follows alg. p.13 of https://eprint.iacr.org/2019/953.pdf + /// with t₁ = t₂ = 1, and the proofs are ([digest] + [quotient] +purported evaluation): + /// * [state_folded_state_digests], [proof_batch_opening_at_zeta_x], state_folded_evals + /// * [proof_grand_product_commitment], [proof_opening_at_zeta_omega_x], [proof_grand_product_at_zeta_omega] + /// @param aproof pointer to the proof + function batch_verify_multi_points(aproof) { + let state := mload(0x40) + let mPtr := add(state, STATE_LAST_MEM) + + // derive a random number. As there is no random generator, we + // do an FS like challenge derivation, depending on both digests and + // ζ to ensure that the prover cannot control the random number. + // Note: adding the other point ζω is not needed, as ω is known beforehand. + mstore(mPtr, mload(add(state, STATE_FOLDED_DIGESTS_X))) + mstore(add(mPtr, 0x20), mload(add(state, STATE_FOLDED_DIGESTS_Y))) + mstore(add(mPtr, 0x40), calldataload(add(aproof, PROOF_BATCH_OPENING_AT_ZETA_X))) + mstore(add(mPtr, 0x60), calldataload(add(aproof, PROOF_BATCH_OPENING_AT_ZETA_Y))) + mstore(add(mPtr, 0x80), calldataload(add(aproof, PROOF_GRAND_PRODUCT_COMMITMENT_X))) + mstore(add(mPtr, 0xa0), calldataload(add(aproof, PROOF_GRAND_PRODUCT_COMMITMENT_Y))) + mstore(add(mPtr, 0xc0), calldataload(add(aproof, PROOF_OPENING_AT_ZETA_OMEGA_X))) + mstore(add(mPtr, 0xe0), calldataload(add(aproof, PROOF_OPENING_AT_ZETA_OMEGA_Y))) + mstore(add(mPtr, 0x100), mload(add(state, STATE_ZETA))) + mstore(add(mPtr, 0x120), mload(add(state, STATE_GAMMA_KZG))) + let random := staticcall(gas(), SHA2, mPtr, 0x140, mPtr, 0x20) + if iszero(random) { error_random_generation() } + random := mod(mload(mPtr), R_MOD) // use the same variable as we are one variable away from getting stack-too-deep error... + + let folded_quotients := mPtr + mPtr := add(folded_quotients, 0x40) + mstore(folded_quotients, calldataload(add(aproof, PROOF_BATCH_OPENING_AT_ZETA_X))) + mstore( + add(folded_quotients, 0x20), + calldataload(add(aproof, PROOF_BATCH_OPENING_AT_ZETA_Y)) + ) + point_acc_mul_calldata( + folded_quotients, add(aproof, PROOF_OPENING_AT_ZETA_OMEGA_X), random, mPtr + ) + + let folded_digests := add(state, STATE_FOLDED_DIGESTS_X) + point_acc_mul_calldata( + folded_digests, add(aproof, PROOF_GRAND_PRODUCT_COMMITMENT_X), random, mPtr + ) + + let folded_evals := add(state, STATE_FOLDED_CLAIMED_VALUES) + fr_acc_mul_calldata( + folded_evals, add(aproof, PROOF_GRAND_PRODUCT_AT_ZETA_OMEGA), random + ) + + let folded_evals_commit := mPtr + mPtr := add(folded_evals_commit, 0x40) + mstore(folded_evals_commit, G1_SRS_X) + mstore(add(folded_evals_commit, 0x20), G1_SRS_Y) + mstore(add(folded_evals_commit, 0x40), mload(folded_evals)) + let check_staticcall := + staticcall(gas(), 7, folded_evals_commit, 0x60, folded_evals_commit, 0x40) + if iszero(check_staticcall) { error_verify() } + + let folded_evals_commit_y := add(folded_evals_commit, 0x20) + mstore(folded_evals_commit_y, sub(P_MOD, mload(folded_evals_commit_y))) + point_add(folded_digests, folded_digests, folded_evals_commit, mPtr) + + let folded_points_quotients := mPtr + mPtr := add(mPtr, 0x40) + point_mul_calldata( + folded_points_quotients, + add(aproof, PROOF_BATCH_OPENING_AT_ZETA_X), + mload(add(state, STATE_ZETA)), + mPtr + ) + let zeta_omega := mulmod(mload(add(state, STATE_ZETA)), VK_OMEGA, R_MOD) + random := mulmod(random, zeta_omega, R_MOD) + point_acc_mul_calldata( + folded_points_quotients, + add(aproof, PROOF_OPENING_AT_ZETA_OMEGA_X), + random, + mPtr + ) + + point_add(folded_digests, folded_digests, folded_points_quotients, mPtr) + + let folded_quotients_y := add(folded_quotients, 0x20) + mstore(folded_quotients_y, sub(P_MOD, mload(folded_quotients_y))) + + mstore(mPtr, mload(folded_digests)) + + mstore(add(mPtr, 0x20), mload(add(folded_digests, 0x20))) + mstore(add(mPtr, 0x40), G2_SRS_0_X_0) // the 4 lines are the canonical G2 point on BN254 + mstore(add(mPtr, 0x60), G2_SRS_0_X_1) + mstore(add(mPtr, 0x80), G2_SRS_0_Y_0) + mstore(add(mPtr, 0xa0), G2_SRS_0_Y_1) + mstore(add(mPtr, 0xc0), mload(folded_quotients)) + mstore(add(mPtr, 0xe0), mload(add(folded_quotients, 0x20))) + mstore(add(mPtr, 0x100), G2_SRS_1_X_0) + mstore(add(mPtr, 0x120), G2_SRS_1_X_1) + mstore(add(mPtr, 0x140), G2_SRS_1_Y_0) + mstore(add(mPtr, 0x160), G2_SRS_1_Y_1) + check_pairing_kzg(mPtr) + } + + /// @notice check_pairing_kzg checks the result of the final pairing product of the batched + /// kzg verification. The purpose of this function is to avoid exhausting the stack + /// in the function batch_verify_multi_points. + /// @param mPtr pointer storing the tuple of pairs + function check_pairing_kzg(mPtr) { + let state := mload(0x40) + + let l_success := staticcall(gas(), 8, mPtr, 0x180, 0x00, 0x20) + if iszero(l_success) { error_pairing() } + let res_pairing := mload(0x00) + mstore(add(state, STATE_SUCCESS), res_pairing) + } + + /// @notice Fold the opening proofs at ζ: + /// * at state+state_folded_digest we store: [Linearised_polynomial]+γ[L] + γ²[R] + γ³[O] + γ⁴[S₁] +γ⁵[S₂] + ∑ᵢγ⁵⁺ⁱ[Pi_{i}] + /// * at state+state_folded_claimed_values we store: Linearised_polynomial(ζ)+γL(ζ) + γ²R(ζ)+ γ³O(ζ) + γ⁴S₁(ζ) +γ⁵S₂(ζ) + ∑ᵢγ⁵⁺ⁱPi_{i}(ζ) + /// @param aproof pointer to the proof + /// acc_gamma stores the γⁱ + function fold_state(aproof) { + let state := mload(0x40) + let mPtr := add(mload(0x40), STATE_LAST_MEM) + let mPtr20 := add(mPtr, 0x20) + let mPtr40 := add(mPtr, 0x40) + + let l_gamma_kzg := mload(add(state, STATE_GAMMA_KZG)) + let acc_gamma := l_gamma_kzg + let state_folded_digests := add(state, STATE_FOLDED_DIGESTS_X) + + mstore(state_folded_digests, mload(add(state, STATE_LINEARISED_POLYNOMIAL_X))) + mstore( + add(state, STATE_FOLDED_DIGESTS_Y), + mload(add(state, STATE_LINEARISED_POLYNOMIAL_Y)) + ) + mstore( + add(state, STATE_FOLDED_CLAIMED_VALUES), + mload(add(state, STATE_OPENING_LINEARISED_POLYNOMIAL_ZETA)) + ) + + point_acc_mul_calldata( + state_folded_digests, add(aproof, PROOF_L_COM_X), acc_gamma, mPtr + ) + fr_acc_mul_calldata( + add(state, STATE_FOLDED_CLAIMED_VALUES), add(aproof, PROOF_L_AT_ZETA), acc_gamma + ) + + acc_gamma := mulmod(acc_gamma, l_gamma_kzg, R_MOD) + point_acc_mul_calldata( + state_folded_digests, add(aproof, PROOF_R_COM_X), acc_gamma, mPtr + ) + fr_acc_mul_calldata( + add(state, STATE_FOLDED_CLAIMED_VALUES), add(aproof, PROOF_R_AT_ZETA), acc_gamma + ) + + acc_gamma := mulmod(acc_gamma, l_gamma_kzg, R_MOD) + point_acc_mul_calldata( + state_folded_digests, add(aproof, PROOF_O_COM_X), acc_gamma, mPtr + ) + fr_acc_mul_calldata( + add(state, STATE_FOLDED_CLAIMED_VALUES), add(aproof, PROOF_O_AT_ZETA), acc_gamma + ) + + acc_gamma := mulmod(acc_gamma, l_gamma_kzg, R_MOD) + mstore(mPtr, VK_S1_COM_X) + mstore(mPtr20, VK_S1_COM_Y) + point_acc_mul(state_folded_digests, mPtr, acc_gamma, mPtr40) + fr_acc_mul_calldata( + add(state, STATE_FOLDED_CLAIMED_VALUES), + add(aproof, PROOF_S1_AT_ZETA), + acc_gamma + ) + + acc_gamma := mulmod(acc_gamma, l_gamma_kzg, R_MOD) + mstore(mPtr, VK_S2_COM_X) + mstore(mPtr20, VK_S2_COM_Y) + point_acc_mul(state_folded_digests, mPtr, acc_gamma, mPtr40) + fr_acc_mul_calldata( + add(state, STATE_FOLDED_CLAIMED_VALUES), + add(aproof, PROOF_S2_AT_ZETA), + acc_gamma + ) + let poqaz := add(aproof, PROOF_OPENING_QCP_AT_ZETA) + + acc_gamma := mulmod(acc_gamma, l_gamma_kzg, R_MOD) + mstore(mPtr, VK_QCP_0_X) + mstore(mPtr20, VK_QCP_0_Y) + point_acc_mul(state_folded_digests, mPtr, acc_gamma, mPtr40) + fr_acc_mul_calldata(add(state, STATE_FOLDED_CLAIMED_VALUES), poqaz, acc_gamma) + poqaz := add(poqaz, 0x20) + } + + /// @notice generate the challenge (using Fiat Shamir) to fold the opening proofs + /// at ζ. + /// The process for deriving γ is the same as in derive_gamma but this time the inputs are + /// in this order (the [] means it's a commitment): + /// * ζ + /// * [Linearised polynomial] + /// * [L], [R], [O] + /// * [S₁] [S₂] + /// * [Pi_{i}] (wires associated to custom gates) + /// Then there are the purported evaluations of the previous committed polynomials: + /// * Linearised_polynomial(ζ) + /// * L(ζ), R(ζ), O(ζ), S₁(ζ), S₂(ζ) + /// * Pi_{i}(ζ) + /// * Z(ζω) + /// @param aproof pointer to the proof + function compute_gamma_kzg(aproof) { + let state := mload(0x40) + let mPtr := add(mload(0x40), STATE_LAST_MEM) + mstore(mPtr, FS_GAMMA_KZG) // "gamma" + mstore(add(mPtr, 0x20), mload(add(state, STATE_ZETA))) + mstore(add(mPtr, 0x40), mload(add(state, STATE_LINEARISED_POLYNOMIAL_X))) + mstore(add(mPtr, 0x60), mload(add(state, STATE_LINEARISED_POLYNOMIAL_Y))) + calldatacopy(add(mPtr, 0x80), add(aproof, PROOF_L_COM_X), 0xc0) + mstore(add(mPtr, 0x140), VK_S1_COM_X) + mstore(add(mPtr, 0x160), VK_S1_COM_Y) + mstore(add(mPtr, 0x180), VK_S2_COM_X) + mstore(add(mPtr, 0x1a0), VK_S2_COM_Y) + + let offset := 0x1c0 + + mstore(add(mPtr, offset), VK_QCP_0_X) + mstore(add(mPtr, add(offset, 0x20)), VK_QCP_0_Y) + offset := add(offset, 0x40) + mstore( + add(mPtr, offset), mload(add(state, STATE_OPENING_LINEARISED_POLYNOMIAL_ZETA)) + ) + mstore(add(mPtr, add(offset, 0x20)), calldataload(add(aproof, PROOF_L_AT_ZETA))) + mstore(add(mPtr, add(offset, 0x40)), calldataload(add(aproof, PROOF_R_AT_ZETA))) + mstore(add(mPtr, add(offset, 0x60)), calldataload(add(aproof, PROOF_O_AT_ZETA))) + mstore(add(mPtr, add(offset, 0x80)), calldataload(add(aproof, PROOF_S1_AT_ZETA))) + mstore(add(mPtr, add(offset, 0xa0)), calldataload(add(aproof, PROOF_S2_AT_ZETA))) + + let _mPtr := add(mPtr, add(offset, 0xc0)) + + let _poqaz := add(aproof, PROOF_OPENING_QCP_AT_ZETA) + calldatacopy(_mPtr, _poqaz, mul(VK_NB_CUSTOM_GATES, 0x20)) + _mPtr := add(_mPtr, mul(VK_NB_CUSTOM_GATES, 0x20)) + + mstore(_mPtr, calldataload(add(aproof, PROOF_GRAND_PRODUCT_AT_ZETA_OMEGA))) + + let start_input := 0x1b // 00.."gamma" + let size_input := add(0x14, mul(VK_NB_CUSTOM_GATES, 3)) // number of 32bytes elmts = 0x14 (zeta+3*6 for the digests+openings) + 3*VK_NB_CUSTOM_GATES (for the commitments of the selectors) + 1 (opening of Z at ζω) + size_input := add(0x5, mul(size_input, 0x20)) // size in bytes: 15*32 bytes + 5 bytes for gamma + let check_staticcall := + staticcall( + gas(), + SHA2, + add(mPtr, start_input), + size_input, + add(state, STATE_GAMMA_KZG), + 0x20 + ) + if iszero(check_staticcall) { error_verify() } + mstore(add(state, STATE_GAMMA_KZG), mod(mload(add(state, STATE_GAMMA_KZG)), R_MOD)) + } + + function compute_commitment_linearised_polynomial_ec(aproof, s1, s2) { + let state := mload(0x40) + let mPtr := add(mload(0x40), STATE_LAST_MEM) + + mstore(mPtr, VK_QL_COM_X) + mstore(add(mPtr, 0x20), VK_QL_COM_Y) + point_mul( + add(state, STATE_LINEARISED_POLYNOMIAL_X), + mPtr, + calldataload(add(aproof, PROOF_L_AT_ZETA)), + add(mPtr, 0x40) + ) + + mstore(mPtr, VK_QR_COM_X) + mstore(add(mPtr, 0x20), VK_QR_COM_Y) + point_acc_mul( + add(state, STATE_LINEARISED_POLYNOMIAL_X), + mPtr, + calldataload(add(aproof, PROOF_R_AT_ZETA)), + add(mPtr, 0x40) + ) + + let rl := + mulmod( + calldataload(add(aproof, PROOF_L_AT_ZETA)), + calldataload(add(aproof, PROOF_R_AT_ZETA)), + R_MOD + ) + mstore(mPtr, VK_QM_COM_X) + mstore(add(mPtr, 0x20), VK_QM_COM_Y) + point_acc_mul(add(state, STATE_LINEARISED_POLYNOMIAL_X), mPtr, rl, add(mPtr, 0x40)) + + mstore(mPtr, VK_QO_COM_X) + mstore(add(mPtr, 0x20), VK_QO_COM_Y) + point_acc_mul( + add(state, STATE_LINEARISED_POLYNOMIAL_X), + mPtr, + calldataload(add(aproof, PROOF_O_AT_ZETA)), + add(mPtr, 0x40) + ) + + mstore(mPtr, VK_QK_COM_X) + mstore(add(mPtr, 0x20), VK_QK_COM_Y) + point_add( + add(state, STATE_LINEARISED_POLYNOMIAL_X), + add(state, STATE_LINEARISED_POLYNOMIAL_X), + mPtr, + add(mPtr, 0x40) + ) + + let qcp_opening_at_zeta := add(aproof, PROOF_OPENING_QCP_AT_ZETA) + let bsb_commitments := add(aproof, PROOF_BSB_COMMITMENTS) + for { let i := 0 } lt(i, VK_NB_CUSTOM_GATES) { i := add(i, 1) } { + mstore(mPtr, calldataload(bsb_commitments)) + mstore(add(mPtr, 0x20), calldataload(add(bsb_commitments, 0x20))) + point_acc_mul( + add(state, STATE_LINEARISED_POLYNOMIAL_X), + mPtr, + calldataload(qcp_opening_at_zeta), + add(mPtr, 0x40) + ) + qcp_opening_at_zeta := add(qcp_opening_at_zeta, 0x20) + bsb_commitments := add(bsb_commitments, 0x40) + } + + mstore(mPtr, VK_S3_COM_X) + mstore(add(mPtr, 0x20), VK_S3_COM_Y) + point_acc_mul(add(state, STATE_LINEARISED_POLYNOMIAL_X), mPtr, s1, add(mPtr, 0x40)) + + mstore(mPtr, calldataload(add(aproof, PROOF_GRAND_PRODUCT_COMMITMENT_X))) + mstore(add(mPtr, 0x20), calldataload(add(aproof, PROOF_GRAND_PRODUCT_COMMITMENT_Y))) + point_acc_mul(add(state, STATE_LINEARISED_POLYNOMIAL_X), mPtr, s2, add(mPtr, 0x40)) + + point_add( + add(state, STATE_LINEARISED_POLYNOMIAL_X), + add(state, STATE_LINEARISED_POLYNOMIAL_X), + add(state, STATE_FOLDED_H_X), + mPtr + ) + } + + /// @notice Compute the commitment to the linearized polynomial equal to + /// L(ζ)[Qₗ]+r(ζ)[Qᵣ]+R(ζ)L(ζ)[Qₘ]+O(ζ)[Qₒ]+[Qₖ]+Σᵢqc'ᵢ(ζ)[BsbCommitmentᵢ] + + /// α*( Z(μζ)(L(ζ)+β*S₁(ζ)+γ)*(R(ζ)+β*S₂(ζ)+γ)[S₃]-[Z](L(ζ)+β*id_{1}(ζ)+γ)*(R(ζ)+β*id_{2}(ζ)+γ)*(O(ζ)+β*id_{3}(ζ)+γ) ) + + /// α²*L₁(ζ)[Z] - Z_{H}(ζ)*(([H₀] + ζᵐ⁺²*[H₁] + ζ²⁽ᵐ⁺²⁾*[H₂]) + /// where + /// * id_1 = id, id_2 = vk_coset_shift*id, id_3 = vk_coset_shift^{2}*id + /// * the [] means that it's a commitment (i.e. a point on Bn254(F_p)) + /// * Z_{H}(ζ) = ζ^n-1 + /// @param aproof pointer to the proof + function compute_commitment_linearised_polynomial(aproof) { + let state := mload(0x40) + let l_beta := mload(add(state, STATE_BETA)) + let l_gamma := mload(add(state, STATE_GAMMA)) + let l_zeta := mload(add(state, STATE_ZETA)) + let l_alpha := mload(add(state, STATE_ALPHA)) + + let u := + mulmod(calldataload(add(aproof, PROOF_GRAND_PRODUCT_AT_ZETA_OMEGA)), l_beta, R_MOD) + let v := mulmod(l_beta, calldataload(add(aproof, PROOF_S1_AT_ZETA)), R_MOD) + v := addmod(v, calldataload(add(aproof, PROOF_L_AT_ZETA)), R_MOD) + v := addmod(v, l_gamma, R_MOD) + + let w := mulmod(l_beta, calldataload(add(aproof, PROOF_S2_AT_ZETA)), R_MOD) + w := addmod(w, calldataload(add(aproof, PROOF_R_AT_ZETA)), R_MOD) + w := addmod(w, l_gamma, R_MOD) + + let s1 := mulmod(u, v, R_MOD) + s1 := mulmod(s1, w, R_MOD) + s1 := mulmod(s1, l_alpha, R_MOD) + + let coset_square := mulmod(VK_COSET_SHIFT, VK_COSET_SHIFT, R_MOD) + let betazeta := mulmod(l_beta, l_zeta, R_MOD) + u := addmod(betazeta, calldataload(add(aproof, PROOF_L_AT_ZETA)), R_MOD) + u := addmod(u, l_gamma, R_MOD) + + v := mulmod(betazeta, VK_COSET_SHIFT, R_MOD) + v := addmod(v, calldataload(add(aproof, PROOF_R_AT_ZETA)), R_MOD) + v := addmod(v, l_gamma, R_MOD) + + w := mulmod(betazeta, coset_square, R_MOD) + w := addmod(w, calldataload(add(aproof, PROOF_O_AT_ZETA)), R_MOD) + w := addmod(w, l_gamma, R_MOD) + + let s2 := mulmod(u, v, R_MOD) + s2 := mulmod(s2, w, R_MOD) + s2 := sub(R_MOD, s2) + s2 := mulmod(s2, l_alpha, R_MOD) + s2 := addmod(s2, mload(add(state, STATE_ALPHA_SQUARE_LAGRANGE_0)), R_MOD) + + // at this stage: + // * s₁ = α*Z(μζ)(l(ζ)+β*s₁(ζ)+γ)*(r(ζ)+β*s₂(ζ)+γ)*β + // * s₂ = -α*(l(ζ)+β*ζ+γ)*(r(ζ)+β*u*ζ+γ)*(o(ζ)+β*u²*ζ+γ) + α²*L₁(ζ) + + compute_commitment_linearised_polynomial_ec(aproof, s1, s2) + } + + /// @notice compute -z_h(ζ)*([H₁] + ζⁿ⁺²[H₂] + ζ²⁽ⁿ⁺²⁾[H₃]) and store the result at + /// state + state_folded_h + /// @param aproof pointer to the proof + function fold_h(aproof) { + let state := mload(0x40) + let n_plus_two := add(VK_DOMAIN_SIZE, 2) + let mPtr := add(mload(0x40), STATE_LAST_MEM) + let zeta_power_n_plus_two := pow(mload(add(state, STATE_ZETA)), n_plus_two, mPtr) + point_mul_calldata( + add(state, STATE_FOLDED_H_X), + add(aproof, PROOF_H_2_COM_X), + zeta_power_n_plus_two, + mPtr + ) + point_add_calldata( + add(state, STATE_FOLDED_H_X), + add(state, STATE_FOLDED_H_X), + add(aproof, PROOF_H_1_COM_X), + mPtr + ) + point_mul( + add(state, STATE_FOLDED_H_X), + add(state, STATE_FOLDED_H_X), + zeta_power_n_plus_two, + mPtr + ) + point_add_calldata( + add(state, STATE_FOLDED_H_X), + add(state, STATE_FOLDED_H_X), + add(aproof, PROOF_H_0_COM_X), + mPtr + ) + point_mul( + add(state, STATE_FOLDED_H_X), + add(state, STATE_FOLDED_H_X), + mload(add(state, STATE_ZETA_POWER_N_MINUS_ONE)), + mPtr + ) + let folded_h_y := mload(add(state, STATE_FOLDED_H_Y)) + folded_h_y := sub(P_MOD, folded_h_y) + mstore(add(state, STATE_FOLDED_H_Y), folded_h_y) + } + + /// @notice check that the opening of the linearised polynomial at zeta is equal to + /// - [ PI(ζ) - α²*L₁(ζ) + α(l(ζ)+β*s1(ζ)+γ)(r(ζ)+β*s2(ζ)+γ)(o(ζ)+γ)*z(ωζ) ] + /// @param aproof pointer to the proof + function compute_opening_linearised_polynomial(aproof) { + let state := mload(0x40) + + // (l(ζ)+β*s1(ζ)+γ) + let s1 + s1 := + mulmod( + calldataload(add(aproof, PROOF_S1_AT_ZETA)), + mload(add(state, STATE_BETA)), + R_MOD + ) + s1 := addmod(s1, mload(add(state, STATE_GAMMA)), R_MOD) + s1 := addmod(s1, calldataload(add(aproof, PROOF_L_AT_ZETA)), R_MOD) + + // (r(ζ)+β*s2(ζ)+γ) + let s2 + s2 := + mulmod( + calldataload(add(aproof, PROOF_S2_AT_ZETA)), + mload(add(state, STATE_BETA)), + R_MOD + ) + s2 := addmod(s2, mload(add(state, STATE_GAMMA)), R_MOD) + s2 := addmod(s2, calldataload(add(aproof, PROOF_R_AT_ZETA)), R_MOD) + + // (o(ζ)+γ) + let o + o := + addmod( + calldataload(add(aproof, PROOF_O_AT_ZETA)), + mload(add(state, STATE_GAMMA)), + R_MOD + ) + + // α*Z(μζ)*(l(ζ)+β*s1(ζ)+γ)*(r(ζ)+β*s2(ζ)+γ)*(o(ζ)+γ) + s1 := mulmod(s1, s2, R_MOD) + s1 := mulmod(s1, o, R_MOD) + s1 := mulmod(s1, mload(add(state, STATE_ALPHA)), R_MOD) + s1 := + mulmod(s1, calldataload(add(aproof, PROOF_GRAND_PRODUCT_AT_ZETA_OMEGA)), R_MOD) + + // PI(ζ) - α²*L₁(ζ) + α(l(ζ)+β*s1(ζ)+γ)(r(ζ)+β*s2(ζ)+γ)(o(ζ)+γ)*z(ωζ) + s1 := addmod(s1, mload(add(state, STATE_PI)), R_MOD) + s2 := mload(add(state, STATE_ALPHA_SQUARE_LAGRANGE_0)) + s2 := sub(R_MOD, s2) + s1 := addmod(s1, s2, R_MOD) + s1 := sub(R_MOD, s1) + + mstore(add(state, STATE_OPENING_LINEARISED_POLYNOMIAL_ZETA), s1) + } + + // BEGINNING utils math functions ------------------------------------------------- + + /// @param dst pointer storing the result + /// @param p pointer to the first point + /// @param q pointer to the second point + /// @param mPtr pointer to free memory + function point_add(dst, p, q, mPtr) { + mstore(mPtr, mload(p)) + mstore(add(mPtr, 0x20), mload(add(p, 0x20))) + mstore(add(mPtr, 0x40), mload(q)) + mstore(add(mPtr, 0x60), mload(add(q, 0x20))) + let l_success := staticcall(gas(), EC_ADD, mPtr, 0x80, dst, 0x40) + if iszero(l_success) { error_ec_op() } + } + + /// @param dst pointer storing the result + /// @param p pointer to the first point (calldata) + /// @param q pointer to the second point (calladata) + /// @param mPtr pointer to free memory + function point_add_calldata(dst, p, q, mPtr) { + mstore(mPtr, mload(p)) + mstore(add(mPtr, 0x20), mload(add(p, 0x20))) + mstore(add(mPtr, 0x40), calldataload(q)) + mstore(add(mPtr, 0x60), calldataload(add(q, 0x20))) + let l_success := staticcall(gas(), EC_ADD, mPtr, 0x80, dst, 0x40) + if iszero(l_success) { error_ec_op() } + } + + /// @parma dst pointer storing the result + /// @param src pointer to a point on Bn254(𝔽_p) + /// @param s scalar + /// @param mPtr free memory + function point_mul(dst, src, s, mPtr) { + mstore(mPtr, mload(src)) + mstore(add(mPtr, 0x20), mload(add(src, 0x20))) + mstore(add(mPtr, 0x40), s) + let l_success := staticcall(gas(), EC_MUL, mPtr, 0x60, dst, 0x40) + if iszero(l_success) { error_ec_op() } + } + + /// @parma dst pointer storing the result + /// @param src pointer to a point on Bn254(𝔽_p) on calldata + /// @param s scalar + /// @param mPtr free memory + function point_mul_calldata(dst, src, s, mPtr) { + mstore(mPtr, calldataload(src)) + mstore(add(mPtr, 0x20), calldataload(add(src, 0x20))) + mstore(add(mPtr, 0x40), s) + let l_success := staticcall(gas(), EC_MUL, mPtr, 0x60, dst, 0x40) + if iszero(l_success) { error_ec_op() } + } + + /// @notice dst <- dst + [s]src (Elliptic curve) + /// @param dst pointer accumulator point storing the result + /// @param src pointer to the point to multiply and add + /// @param s scalar + /// @param mPtr free memory + function point_acc_mul(dst, src, s, mPtr) { + mstore(mPtr, mload(src)) + mstore(add(mPtr, 0x20), mload(add(src, 0x20))) + mstore(add(mPtr, 0x40), s) + let l_success := staticcall(gas(), 7, mPtr, 0x60, mPtr, 0x40) + mstore(add(mPtr, 0x40), mload(dst)) + mstore(add(mPtr, 0x60), mload(add(dst, 0x20))) + l_success := and(l_success, staticcall(gas(), EC_ADD, mPtr, 0x80, dst, 0x40)) + if iszero(l_success) { error_ec_op() } + } + + /// @notice dst <- dst + [s]src (Elliptic curve) + /// @param dst pointer accumulator point storing the result + /// @param src pointer to the point to multiply and add (on calldata) + /// @param s scalar + /// @mPtr free memory + function point_acc_mul_calldata(dst, src, s, mPtr) { + mstore(mPtr, calldataload(src)) + mstore(add(mPtr, 0x20), calldataload(add(src, 0x20))) + mstore(add(mPtr, 0x40), s) + let l_success := staticcall(gas(), 7, mPtr, 0x60, mPtr, 0x40) + mstore(add(mPtr, 0x40), mload(dst)) + mstore(add(mPtr, 0x60), mload(add(dst, 0x20))) + l_success := and(l_success, staticcall(gas(), EC_ADD, mPtr, 0x80, dst, 0x40)) + if iszero(l_success) { error_ec_op() } + } + + /// @notice dst <- dst + src*s (Fr) dst,src are addresses, s is a value + /// @param dst pointer storing the result + /// @param src pointer to the scalar to multiply and add (on calldata) + /// @param s scalar + function fr_acc_mul_calldata(dst, src, s) { + let tmp := mulmod(calldataload(src), s, R_MOD) + mstore(dst, addmod(mload(dst), tmp, R_MOD)) + } + + /// @param x element to exponentiate + /// @param e exponent + /// @param mPtr free memory + /// @return res x ** e mod r + function pow(x, e, mPtr) -> res { + mstore(mPtr, 0x20) + mstore(add(mPtr, 0x20), 0x20) + mstore(add(mPtr, 0x40), 0x20) + mstore(add(mPtr, 0x60), x) + mstore(add(mPtr, 0x80), e) + mstore(add(mPtr, 0xa0), R_MOD) + let check_staticcall := staticcall(gas(), MOD_EXP, mPtr, 0xc0, mPtr, 0x20) + if eq(check_staticcall, 0) { error_mod_exp() } + res := mload(mPtr) + } + } + } +} diff --git a/contracts/verifiers/v4.0.0-rc.3/SP1VerifierPlonk.sol b/contracts/verifiers/v4.0.0-rc.3/SP1VerifierPlonk.sol new file mode 100644 index 000000000..69953eec3 --- /dev/null +++ b/contracts/verifiers/v4.0.0-rc.3/SP1VerifierPlonk.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {ISP1Verifier, ISP1VerifierWithHash} from "../../v2/interfaces/ISP1Verifier.sol"; +import {PlonkVerifier} from "./PlonkVerifier.sol"; + +/// @title SP1 Verifier +/// @author Succinct Labs +/// @notice This contracts implements a solidity verifier for SP1. +contract SP1VerifierPlonk is PlonkVerifier, ISP1VerifierWithHash { + /// @notice Thrown when the verifier selector from this proof does not match the one in this + /// verifier. This indicates that this proof was sent to the wrong verifier. + /// @param received The verifier selector from the first 4 bytes of the proof. + /// @param expected The verifier selector from the first 4 bytes of the VERIFIER_HASH(). + error WrongVerifierSelector(bytes4 received, bytes4 expected); + + /// @notice Thrown when the proof is invalid. + error InvalidProof(); + + function VERSION() external pure returns (string memory) { + return "v4.0.0-rc.3"; + } + + /// @inheritdoc ISP1VerifierWithHash + function VERIFIER_HASH() public pure returns (bytes32) { + return + 0x1b34fe11a637737f0c75c88241669dcf9ca3c03713659265b8241f398a2d286d; + } + + /// @notice Hashes the public values to a field elements inside Bn254. + /// @param publicValues The public values. + function hashPublicValues( + bytes calldata publicValues + ) public pure returns (bytes32) { + return sha256(publicValues) & bytes32(uint256((1 << 253) - 1)); + } + + /// @notice Verifies a proof with given public values and vkey. + /// @param programVKey The verification key for the RISC-V program. + /// @param publicValues The public values encoded as bytes. + /// @param proofBytes The proof of the program execution the SP1 zkVM encoded as bytes. + function verifyProof( + bytes32 programVKey, + bytes calldata publicValues, + bytes calldata proofBytes + ) external view { + bytes4 receivedSelector = bytes4(proofBytes[:4]); + bytes4 expectedSelector = bytes4(VERIFIER_HASH()); + if (receivedSelector != expectedSelector) { + revert WrongVerifierSelector(receivedSelector, expectedSelector); + } + + bytes32 publicValuesDigest = hashPublicValues(publicValues); + uint256[] memory inputs = new uint256[](2); + inputs[0] = uint256(programVKey); + inputs[1] = uint256(publicValuesDigest); + bool success = this.Verify(proofBytes[4:], inputs); + if (!success) { + revert InvalidProof(); + } + } +} diff --git a/deployment/helpers/deployment-helpers.ts b/deployment/helpers/deployment-helpers.ts index 97318a213..189ddefa7 100644 --- a/deployment/helpers/deployment-helpers.ts +++ b/deployment/helpers/deployment-helpers.ts @@ -78,7 +78,7 @@ export async function deployPolygonZkEVMDeployer( } export async function create2Deployment( - polgonZKEVMDeployerContract: PolygonZkEVMDeployer, + polygonZKEVMDeployerContract: PolygonZkEVMDeployer, salt: string, deployTransaction: string, dataCall: string | null, @@ -90,7 +90,7 @@ export async function create2Deployment( // Precalculate create2 address const precalculatedAddressDeployed = ethers.getCreate2Address( - polgonZKEVMDeployerContract.target as string, + polygonZKEVMDeployerContract.target as string, salt, hashInitCode ); @@ -104,7 +104,7 @@ export async function create2Deployment( // Deploy using create2 and call if (hardcodedGasLimit) { const populatedTransaction = - await polgonZKEVMDeployerContract.deployDeterministicAndCall.populateTransaction( + await polygonZKEVMDeployerContract.deployDeterministicAndCall.populateTransaction( amount, salt, deployTransaction, @@ -114,13 +114,13 @@ export async function create2Deployment( await (await deployer.sendTransaction(populatedTransaction)).wait(); } else { await ( - await polgonZKEVMDeployerContract.deployDeterministicAndCall(amount, salt, deployTransaction, dataCall) + await polygonZKEVMDeployerContract.deployDeterministicAndCall(amount, salt, deployTransaction, dataCall) ).wait(); } } else { // Deploy using create2 if (hardcodedGasLimit) { - const populatedTransaction = await polgonZKEVMDeployerContract.deployDeterministic.populateTransaction( + const populatedTransaction = await polygonZKEVMDeployerContract.deployDeterministic.populateTransaction( amount, salt, deployTransaction @@ -128,7 +128,7 @@ export async function create2Deployment( populatedTransaction.gasLimit = hardcodedGasLimit; await (await deployer.sendTransaction(populatedTransaction)).wait(); } else { - await (await polgonZKEVMDeployerContract.deployDeterministic(amount, salt, deployTransaction)).wait(); + await (await polygonZKEVMDeployerContract.deployDeterministic(amount, salt, deployTransaction)).wait(); } } return [precalculatedAddressDeployed, true]; diff --git a/deployment/testnet/prepareTestnet.ts b/deployment/testnet/prepareTestnet.ts index 5f208fb87..d8b189d55 100644 --- a/deployment/testnet/prepareTestnet.ts +++ b/deployment/testnet/prepareTestnet.ts @@ -23,6 +23,7 @@ const argv = yargs(process.argv.slice(2)) const pathDeployParameters = path.join(__dirname, argv.input); const deployParameters = require(argv.input); +const pathCreateRollupParameters = path.join(__dirname, argv.createRollupInput); const createRollupParameters = require(argv.createRollupInput); async function main() { @@ -132,6 +133,24 @@ async function main() { } deployParameters.polTokenAddress = polTokenContract.target; + + if (createRollupParameters.gasTokenAddress == "deploy") { + /* + * Deployment gasToken address + * A erc20 is deployed in this testnet in case it's wanted to deploy a rollup that uses this token as the gas token + */ + const gasTokenName = "Gas Token"; + const gasTokenSymbol = "GAS"; + + const gasTokenFactory = await ethers.getContractFactory("ERC20", deployer); + const gasTokenContract = await gasTokenFactory.deploy(gasTokenName, gasTokenSymbol); + await gasTokenContract.waitForDeployment(); + createRollupParameters.gasTokenAddress = gasTokenContract.target; + console.log("#######################\n"); + console.log("gas token deployed to:", gasTokenContract.target); + fs.writeFileSync(pathCreateRollupParameters, JSON.stringify(createRollupParameters, null, 1)); + } + fs.writeFileSync(pathDeployParameters, JSON.stringify(deployParameters, null, 1)); } diff --git a/deployment/v2/1_createGenesis.ts b/deployment/v2/1_createGenesis.ts index 702003af8..45f52dc95 100644 --- a/deployment/v2/1_createGenesis.ts +++ b/deployment/v2/1_createGenesis.ts @@ -59,7 +59,7 @@ const zkevmAddressL2 = ethers.ZeroAddress; async function main() { // Constant variables const attemptsDeployProxy = 20; - const balanceBrige = BigInt("0xffffffffffffffffffffffffffffffff"); // 128 bits + const balanceBridge = BigInt("0xffffffffffffffffffffffffffffffff"); // 128 bits let timelockAdminAddress; let initialZkEVMDeployerOwner; @@ -75,9 +75,9 @@ async function main() { let proxyAdminAddress; let finalProxyAdminAddress; - let finalTimelockContractAdress; + let finalTimelockContractAddress; - let finalzkEVMDeployerAdress; + let finalZkEVMDeployerAddress; const finalGlobalExitRootL2ProxyAddress = globalExitRootL2Address; @@ -97,8 +97,8 @@ async function main() { salt = "0x0000000000000000000000000000000000000000000000000000000000000000"; // salt mock initialZkEVMDeployerOwner = mainnetInitialZkEVMDeployerOwner; - finalzkEVMDeployerAdress = mainnetZkEVMDeployerAddress; - finalTimelockContractAdress = mainnetZkEVMTimelockAddress; + finalZkEVMDeployerAddress = mainnetZkEVMDeployerAddress; + finalTimelockContractAddress = mainnetZkEVMTimelockAddress; finalProxyAdminAddress = mainnetProxyAdminAddress; finalBridgeImplAddress = mainnetZkEVMBridgeImplementationAddress; finalBridgeProxyAddress = mainnetZkEVMBridgeProxyAddress; @@ -135,7 +135,7 @@ async function main() { if (isMainnet === false) { finalDeployer = deployer.address; finalKeylessDeployer = keylessDeployer; - finalzkEVMDeployerAdress = zkEVMDeployerContract.target; + finalZkEVMDeployerAddress = zkEVMDeployerContract.target; } /* * Deploy Bridge @@ -163,7 +163,8 @@ async function main() { } // Deploy implementation PolygonZkEVMBridge - const polygonZkEVMBridgeFactory = await ethers.getContractFactory("PolygonZkEVMBridgeV2", deployer); + const bridgeContractName = "PolygonZkEVMBridgeV2"; + const polygonZkEVMBridgeFactory = await ethers.getContractFactory(bridgeContractName, deployer); const deployTransactionBridge = (await polygonZkEVMBridgeFactory.getDeployTransaction()).data; // Mandatory to override the gasLimit since the estimation with create are mess up D: const overrideGasLimit = BigInt(5500000); @@ -211,14 +212,15 @@ async function main() { finalBridgeProxyAddress = proxyBridgeAddress; } - // Import OZ manifest the deployed contracts, its enough to import just the proyx, the rest are imported automatically ( admin/impl) + // Import OZ manifest the deployed contracts, its enough to import just the proxy, the rest are imported automatically ( admin/impl) await upgrades.forceImport(proxyBridgeAddress as string, polygonZkEVMBridgeFactory, "transparent" as any); /* *Deployment Global exit root manager */ + const globalExitRootContractName = "PolygonZkEVMGlobalExitRootL2"; const PolygonZkEVMGlobalExitRootL2Factory = await ethers.getContractFactory( - "PolygonZkEVMGlobalExitRootL2", + globalExitRootContractName, deployer ); let polygonZkEVMGlobalExitRootL2; @@ -257,12 +259,12 @@ async function main() { ); await timelockContract.waitForDeployment(); if (isMainnet === false) { - finalTimelockContractAdress = timelockContract.target; + finalTimelockContractAddress = timelockContract.target; } // Transfer ownership of the proxyAdmin to timelock const proxyAdminInstance = proxyAdminFactory.attach(proxyAdminAddress as string) as ProxyAdmin; - await (await proxyAdminInstance.connect(deployer).transferOwnership(finalTimelockContractAdress as string)).wait(); + await (await proxyAdminInstance.connect(deployer).transferOwnership(finalTimelockContractAddress as string)).wait(); // Recreate genesis with the current information: @@ -272,7 +274,7 @@ async function main() { contractName: "PolygonZkEVMDeployer", balance: "0", nonce: zkEVMDeployerInfo.nonce.toString(), - address: finalzkEVMDeployerAdress, + address: finalZkEVMDeployerAddress, bytecode: zkEVMDeployerInfo.bytecode, storage: zkEVMDeployerInfo.storage, }); @@ -291,7 +293,7 @@ async function main() { // Bridge implementation const bridgeImplementationInfo = await getAddressInfo(bridgeImplementationAddress as string); genesis.push({ - contractName: "PolygonZkEVMBridge implementation", + contractName: `${bridgeContractName} implementation`, balance: "0", nonce: bridgeImplementationInfo.nonce.toString(), address: finalBridgeImplAddress, @@ -306,8 +308,8 @@ async function main() { bridgeProxyInfo.storage[_IMPLEMENTATION_SLOT] = ethers.zeroPadValue(finalBridgeImplAddress as string, 32); genesis.push({ - contractName: "PolygonZkEVMBridge proxy", - balance: balanceBrige, + contractName: `${bridgeContractName} proxy`, + balance: balanceBridge, nonce: bridgeProxyInfo.nonce.toString(), address: finalBridgeProxyAddress, bytecode: bridgeProxyInfo.bytecode, @@ -325,7 +327,7 @@ async function main() { } genesis.push({ - contractName: "PolygonZkEVMGlobalExitRootL2 implementation", + contractName: `${globalExitRootContractName} implementation`, balance: "0", nonce: implGlobalExitRootL2Info.nonce.toString(), address: finalGlobalExitRootL2ImplAddress, @@ -343,7 +345,7 @@ async function main() { ); genesis.push({ - contractName: "PolygonZkEVMGlobalExitRootL2 proxy", + contractName: `${globalExitRootContractName} proxy`, balance: "0", nonce: proxyGlobalExitRootL2Info.nonce.toString(), address: finalGlobalExitRootL2ProxyAddress, @@ -355,7 +357,7 @@ async function main() { const timelockInfo = await getAddressInfo(timelockContract.target); /* - * Since roles are used, most storage are writted in peusdoRandom storage slots + * Since roles are used, most storage is written in pseudoRandom storage slots * bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256("TIMELOCK_ADMIN_ROLE"); * bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE"); * bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); @@ -398,7 +400,7 @@ async function main() { contractName: "PolygonZkEVMTimelock", balance: "0", nonce: timelockInfo.nonce.toString(), - address: finalTimelockContractAdress, + address: finalTimelockContractAddress, bytecode: timelockInfo.bytecode, storage: timelockInfo.storage, }); @@ -483,9 +485,9 @@ async function getAddressInfo(address: string | Addressable) { if (valueAdminSlot !== "0x0000000000000000000000000000000000000000000000000000000000000000") { storage[_ADMIN_SLOT] = valueAdminSlot; } - const valuImplementationSlot = await ethers.provider.getStorage(address, _IMPLEMENTATION_SLOT); - if (valuImplementationSlot !== "0x0000000000000000000000000000000000000000000000000000000000000000") { - storage[_IMPLEMENTATION_SLOT] = valuImplementationSlot; + const valueImplementationSlot = await ethers.provider.getStorage(address, _IMPLEMENTATION_SLOT); + if (valueImplementationSlot !== "0x0000000000000000000000000000000000000000000000000000000000000000") { + storage[_IMPLEMENTATION_SLOT] = valueImplementationSlot; } return {nonce, bytecode, storage}; diff --git a/deployment/v2/3_deployContracts.ts b/deployment/v2/3_deployContracts.ts index 7879f9285..682137107 100644 --- a/deployment/v2/3_deployContracts.ts +++ b/deployment/v2/3_deployContracts.ts @@ -418,18 +418,12 @@ async function main() { PolygonRollupManagerFactory, [ trustedAggregator, - pendingStateTimeout, - trustedAggregatorTimeout, admin, timelockAddressRollupManager, emergencyCouncilAddress, - ethers.ZeroAddress, // unused parameter - ethers.ZeroAddress, // unused parameter - 0, // unused parameter - 0, // unused parameter ], { - initializer: "initialize", + initializer: "initialize(address,address,address,address)", constructorArgs: [ polygonZkEVMGlobalExitRoot?.target, polTokenAddress, @@ -490,9 +484,6 @@ async function main() { console.log("polTokenAddress:", await polygonRollupManagerContract.pol()); console.log("polygonZkEVMBridgeContract:", await polygonRollupManagerContract.bridgeAddress()); - console.log("pendingStateTimeout:", await polygonRollupManagerContract.pendingStateTimeout()); - console.log("trustedAggregatorTimeout:", await polygonRollupManagerContract.trustedAggregatorTimeout()); - // Check roles expect(await polygonRollupManagerContract.hasRole(DEFAULT_ADMIN_ROLE, timelockAddressRollupManager)).to.be.equal( true diff --git a/deployment/v2/4_createRollup.ts b/deployment/v2/4_createRollup.ts index 7d28556e6..1d4033d3d 100644 --- a/deployment/v2/4_createRollup.ts +++ b/deployment/v2/4_createRollup.ts @@ -7,24 +7,25 @@ import fs = require("fs"); import * as dotenv from "dotenv"; dotenv.config({path: path.resolve(__dirname, "../../.env")}); import {ethers, upgrades} from "hardhat"; -import {HardhatEthersSigner} from "@nomicfoundation/hardhat-ethers/signers"; -const {create2Deployment} = require("../helpers/deployment-helpers"); const pathGenesis = path.join(__dirname, "./genesis.json"); +const pathGenesisSovereign = path.join(__dirname, "./genesis_sovereign.json"); +import {processorUtils, Constants} from "@0xpolygonhermez/zkevm-commonjs"; const createRollupParameters = require("./create_rollup_parameters.json"); -const genesis = require("./genesis.json"); +let genesis = require(pathGenesis); const deployOutput = require("./deploy_output.json"); import "../helpers/utils"; +import updateVanillaGenesis from "./utils/updateVanillaGenesis"; const pathOutputJson = path.join(__dirname, "./create_rollup_output.json"); import { PolygonRollupManager, - PolygonZkEVMV2, + PolygonZkEVMEtrog, PolygonZkEVMBridgeV2, - PolygonValidium, PolygonValidiumEtrog, + PolygonPessimisticConsensus, } from "../../typechain-types"; async function main() { @@ -64,24 +65,47 @@ async function main() { adminZkEVM, forkID, consensusContract, + isVanillaClient, + sovereignParams, } = createRollupParameters; - const supportedConensus = ["PolygonZkEVMEtrog", "PolygonValidiumEtrog"]; + const supportedConsensus = ["PolygonZkEVMEtrog", "PolygonValidiumEtrog", "PolygonPessimisticConsensus"]; - if (!supportedConensus.includes(consensusContract)) { - throw new Error(`Consensus contract not supported, supported contracts are: ${supportedConensus}`); + if (!supportedConsensus.includes(consensusContract)) { + throw new Error(`Consensus contract not supported, supported contracts are: ${supportedConsensus}`); + } + + // Check consensus compatibility + if (isVanillaClient) { + if (consensusContract !== "PolygonPessimisticConsensus") { + throw new Error(`Vanilla client only supports PolygonPessimisticConsensus`); + } + + // Check sovereign params + const mandatorySovereignParams = [ + "bridgeManager", + "sovereignWETHAddress", + "sovereignWETHAddressIsNotMintable", + "globalExitRootUpdater", + "globalExitRootRemover", + ]; + for (const parameterName of mandatorySovereignParams) { + if (typeof sovereignParams[parameterName] === undefined || sovereignParams[parameterName] === "") { + throw new Error(`Missing sovereign parameter: ${parameterName}`); + } + } } const dataAvailabilityProtocol = createRollupParameters.dataAvailabilityProtocol || "PolygonDataCommittee"; - const supporteDataAvailabilityProtocols = ["PolygonDataCommittee"]; + const supportedDataAvailabilityProtocols = ["PolygonDataCommittee"]; if ( - consensusContract.includes("PolygonValidium") && - !supporteDataAvailabilityProtocols.includes(dataAvailabilityProtocol) + consensusContract.includes("PolygonValidiumEtrog") && + !supportedDataAvailabilityProtocols.includes(dataAvailabilityProtocol) ) { throw new Error( - `Data availability protocol not supported, supported data availability protocols are: ${supporteDataAvailabilityProtocols}` + `Data availability protocol not supported, supported data availability protocols are: ${supportedDataAvailabilityProtocols}` ); } @@ -133,11 +157,17 @@ async function main() { } // Load Rollup manager - const PolgonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); - const rollupManagerContract = PolgonRollupManagerFactory.attach( + const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); + const rollupManagerContract = PolygonRollupManagerFactory.attach( deployOutput.polygonRollupManagerAddress ) as PolygonRollupManager; + // Load global exit root manager + const globalExitRootManagerFactory = await ethers.getContractFactory("PolygonZkEVMGlobalExitRootV2", deployer); + const globalExitRootManagerContract = globalExitRootManagerFactory.attach( + deployOutput.polygonZkEVMGlobalExitRootAddress + ) as PolygonRollupManager; + const DEFAULT_ADMIN_ROLE = ethers.ZeroHash; if ((await rollupManagerContract.hasRole(DEFAULT_ADMIN_ROLE, deployer.address)) == false) { throw new Error( @@ -146,18 +176,28 @@ async function main() { } let verifierContract; + let verifierName; if (realVerifier === true) { - let verifierName = `FflonkVerifier_${forkID}`; + if (consensusContract != "PolygonPessimisticConsensus") { + verifierName = `FflonkVerifier_${forkID}`; - const VerifierRollup = await ethers.getContractFactory(verifierName, deployer); - verifierContract = await VerifierRollup.deploy(); - await verifierContract.waitForDeployment(); + const VerifierRollup = await ethers.getContractFactory(verifierName, deployer); + verifierContract = await VerifierRollup.deploy(); + await verifierContract.waitForDeployment(); + } else { + verifierName = "SP1VerifierPlonk"; + const VerifierRollup = await ethers.getContractFactory(verifierName, deployer); + verifierContract = await VerifierRollup.deploy(); + await verifierContract.waitForDeployment(); + } } else { - const VerifierRollupHelperFactory = await ethers.getContractFactory("VerifierRollupHelperMock", deployer); + verifierName = "VerifierRollupHelperMock"; + const VerifierRollupHelperFactory = await ethers.getContractFactory(verifierName, deployer); verifierContract = await VerifierRollupHelperFactory.deploy(); await verifierContract.waitForDeployment(); } console.log("#######################\n"); + console.log("Verifier name:", verifierName); console.log("Verifier deployed to:", verifierContract.target); // Since it's a mock deployment deployer has all the rights @@ -185,15 +225,29 @@ async function main() { await PolygonconsensusContract.waitForDeployment(); // Add a new rollup type with timelock - const rollupCompatibilityID = 0; + let rollupVerifierType; + let genesisFinal; + let programVKey; + + if (consensusContract == "PolygonPessimisticConsensus") { + rollupVerifierType = 1; + genesisFinal = ethers.ZeroHash; + programVKey = createRollupParameters.programVKey || ethers.ZeroHash; + } else { + rollupVerifierType = 0; + genesisFinal = genesis.root; + programVKey = ethers.ZeroHash; + } + await ( await rollupManagerContract.addNewRollupType( PolygonconsensusContract.target, verifierContract.target, forkID, - rollupCompatibilityID, - genesis.root, - description + rollupVerifierType, + genesisFinal, + description, + programVKey ) ).wait(); @@ -203,20 +257,25 @@ async function main() { let gasTokenAddress, gasTokenNetwork, gasTokenMetadata; + // Get bridge instance + const bridgeFactory = await ethers.getContractFactory("PolygonZkEVMBridgeV2", deployer); + const polygonZkEVMBridgeContract = bridgeFactory.attach( + deployOutput.polygonZkEVMBridgeAddress + ) as PolygonZkEVMBridgeV2; if ( createRollupParameters.gasTokenAddress && - createRollupParameters.gasTokenAddress != "" && - createRollupParameters.gasTokenAddress != ethers.ZeroAddress + createRollupParameters.gasTokenAddress !== "" && + createRollupParameters.gasTokenAddress !== ethers.ZeroAddress ) { - // Get bridge instance - const bridgeFactory = await ethers.getContractFactory("PolygonZkEVMBridgeV2", deployer); - const polygonZkEVMBridgeContract = bridgeFactory.attach( - deployOutput.polygonZkEVMBridgeAddress - ) as PolygonZkEVMBridgeV2; - // Get token metadata gasTokenMetadata = await polygonZkEVMBridgeContract.getTokenMetadata(createRollupParameters.gasTokenAddress); - + outputJson.gasTokenMetadata = gasTokenMetadata; + // If gas token metadata includes `0x124e4f545f56414c49445f454e434f44494e47 (NOT_VALID_ENCODING)` means there is no erc20 token deployed at the selected gas token network + if (gasTokenMetadata.includes("124e4f545f56414c49445f454e434f44494e47")) { + throw new Error( + `Invalid gas token address, no ERC20 token deployed at the selected gas token network ${createRollupParameters.gasTokenAddress}` + ); + } const wrappedData = await polygonZkEVMBridgeContract.wrappedTokenToTokenInfo( createRollupParameters.gasTokenAddress ); @@ -234,10 +293,11 @@ async function main() { gasTokenNetwork = 0; gasTokenMetadata = "0x"; } - + outputJson.gasTokenAddress = gasTokenAddress; + const nonce = await currentProvider.getTransactionCount(rollupManagerContract.target); const newZKEVMAddress = ethers.getCreateAddress({ from: rollupManagerContract.target as string, - nonce: await currentProvider.getTransactionCount(rollupManagerContract.target), + nonce: nonce, }); // Create new rollup @@ -257,10 +317,10 @@ async function main() { const rollupID = await rollupManagerContract.chainIDToRollupID(chainID); console.log("#######################\n"); - console.log("Created new Rollup:", newZKEVMAddress); + console.log(`Created new ${consensusContract} Rollup:`, newZKEVMAddress); - if (consensusContract.includes("PolygonValidium") && dataAvailabilityProtocol === "PolygonDataCommittee") { - // deploy data commitee + if (consensusContract.includes("PolygonValidiumEtrog") && dataAvailabilityProtocol === "PolygonDataCommittee") { + // deploy data committee const PolygonDataCommitteeContract = (await ethers.getContractFactory("PolygonDataCommittee", deployer)) as any; let polygonDataCommittee; @@ -282,7 +342,7 @@ async function main() { await polygonDataCommittee?.waitForDeployment(); // Load data commitee - const PolygonValidiumContract = (await PolygonconsensusFactory.attach(newZKEVMAddress)) as PolygonValidium; + const PolygonValidiumContract = (await PolygonconsensusFactory.attach(newZKEVMAddress)) as PolygonValidiumEtrog; // add data commitee to the consensus contract if ((await PolygonValidiumContract.admin()) == deployer.address) { await ( @@ -315,27 +375,120 @@ async function main() { } } - // Add the first batch of the created rollup - const newZKEVMContract = (await PolygonconsensusFactory.attach(newZKEVMAddress)) as PolygonZkEVMV2; - const batchData = { - transactions: await newZKEVMContract.generateInitializeTransaction( - rollupID, + let batchData = ""; + /** + If the system is running a "vanilla client" (i.e., a basic, unmodified Ethereum client or rollup setup), the genesis block should include the deployment of the sovereign contracts, and these contracts should already be initialized with their required initial state and configurations. This means that the genesis block will contain the initial state for these contracts, allowing the system to start running without needing any additional initialization steps. However, for other rollups, additional configuration is needed. In this case, instead of having everything pre-initialized in the genesis block, we must inject an "initialization batch" into the genesis file. This batch will contain specific instructions for initializing the contracts at the time of rollup deployment. The injected initialization batch allows the system to be configured dynamically during deployment. + */ + if (isVanillaClient) { + const initializeParams = { + rollupID: rollupID, gasTokenAddress, gasTokenNetwork, - gasTokenMetadata as any - ), - globalExitRoot: globalExitRoot, - timestamp: timestampReceipt, - sequencer: trustedSequencer, - }; + polygonRollupManager: ethers.ZeroAddress, + gasTokenMetadata, + bridgeManager: sovereignParams.bridgeManager, + sovereignWETHAddress: sovereignParams.sovereignWETHAddress, + sovereignWETHAddressIsNotMintable: sovereignParams.sovereignWETHAddressIsNotMintable, + globalExitRootUpdater: sovereignParams.globalExitRootUpdater, + globalExitRootRemover: sovereignParams.globalExitRootRemover, + }; + genesis = await updateVanillaGenesis(genesis, chainID, initializeParams); + // Add weth address to deployment output if gas token address is provided and sovereignWETHAddress is not provided + if ( + gasTokenAddress !== ethers.ZeroAddress && + ethers.isAddress(gasTokenAddress) && + (sovereignParams.sovereignWETHAddress === ethers.ZeroAddress || + !ethers.isAddress(sovereignParams.sovereignWETHAddress)) + ) { + const wethObject = genesis.genesis.find(function (obj) { + return obj.contractName == "WETH"; + }); + outputJson.WETHAddress = wethObject.address; + } + } else { + if (consensusContract === "PolygonPessimisticConsensus") { + // Add the first batch of the created rollup + const newZKEVMContract = (await PolygonconsensusFactory.attach( + newZKEVMAddress + )) as PolygonPessimisticConsensus; + + // Get last GER + const lastGER = await globalExitRootManagerContract.getLastGlobalExitRoot(); + + const dataInjectedTx = await polygonZkEVMBridgeContract.interface.encodeFunctionData("initialize", [ + rollupID, + gasTokenAddress, + gasTokenNetwork, + Constants.ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2, // Global exit root address on L2 + ethers.ZeroAddress, // Rollup manager on L2 does not exist + gasTokenMetadata as any, + ]); + + // check maximum length is 65535 + if ((dataInjectedTx.length - 2) / 2 > 0xffff) { + // throw error + throw new Error(`HugeTokenMetadataNotSupported`); + } + const injectedTx = { + type: 0, // force ethers to parse it as a legacy transaction + chainId: 0, // force ethers to parse it as a pre-EIP155 transaction + to: await newZKEVMContract.bridgeAddress(), + value: 0, + gasPrice: 0, + gasLimit: 30000000, + nonce: 0, + data: dataInjectedTx, + signature: { + v: "0x1b", + r: "0x00000000000000000000000000000000000000000000000000000005ca1ab1e0", + s: "0x000000000000000000000000000000000000000000000000000000005ca1ab1e", + }, + }; + + // serialize transactions + const txObject = ethers.Transaction.from(injectedTx); + + const customData = processorUtils.rawTxToCustomRawTx(txObject.serialized); + batchData = { + batchL2Data: customData, + globalExitRoot: lastGER, + timestamp: blockDeploymentRollup.timestamp, + sequencer: trustedSequencer, + l1BlockNumber: blockDeploymentRollup.number, + l1BlockHash: blockDeploymentRollup.hash, + l1ParentHash: blockDeploymentRollup.parentHash, + }; + } else { + // Add the first batch of the created rollup + const newZKEVMContract = (await PolygonconsensusFactory.attach(newZKEVMAddress)) as PolygonZkEVMEtrog; + batchData = { + batchL2Data: await newZKEVMContract.generateInitializeTransaction( + rollupID, + gasTokenAddress, + gasTokenNetwork, + gasTokenMetadata as any + ), + globalExitRoot: globalExitRoot, + timestamp: timestampReceipt, + sequencer: trustedSequencer, + }; + } + } outputJson.firstBatchData = batchData; outputJson.genesis = genesis.root; outputJson.createRollupBlockNumber = blockDeploymentRollup.number; outputJson.rollupAddress = newZKEVMAddress; outputJson.verifierAddress = verifierContract.target; outputJson.consensusContract = consensusContract; + outputJson.consensusContractAddress = PolygonconsensusContract.target; + outputJson.rollupTypeId = newRollupTypeID; + outputJson.programVKey = programVKey; + // Rewrite updated genesis in case of vanilla client + if (isVanillaClient) { + fs.writeFileSync(pathGenesisSovereign, JSON.stringify(genesis, null, 1)); + } fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); } diff --git a/deployment/v2/README.md b/deployment/v2/README.md index 3e4e37a62..93715907b 100644 --- a/deployment/v2/README.md +++ b/deployment/v2/README.md @@ -20,12 +20,12 @@ cd deployment cp deploy_parameters.json.example deploy_parameters.json ``` -Fill created `deploy_parameters.json` with appropiate parameters. +Fill created `deploy_parameters.json` with appropriate parameters. See below for more information about the `deploy_parameters.json` The first step is deploying and verifying the `PolygonZkEVMDeployer`, this will be the factory for deterministic contracts, the address of the contracts will depend on the `salt` and the `initialZkEVMDeployerOwner` -This contrat is deployed using a keyless deployment, therefore the gasPrice is hardcoded. +This contract is deployed using a keyless deployment, therefore the gasPrice is hardcoded. The value is on `100 gweis`, if it's necessary to update it go to `helpers/deployment-helpers.js` and update the `gasPriceKeylessDeployment` constant. Note that this operation will change all the deterministic address deployed. @@ -38,7 +38,7 @@ To deploy on testnet is necessary a token MATIC contract, therefore, there's ano To deploy on testnet use:`deploy:testnet:ZkEVM:${network}` -In other cases use fullfill `maticTokenAddress` in the `deploy_parameters.json` and run `deploy:ZkEVM:${network}` +In other cases use fulfill `maticTokenAddress` in the `deploy_parameters.json` and run `deploy:ZkEVM:${network}` ``` npm run deploy:testnet:ZkEVM:goerli @@ -51,12 +51,12 @@ To verify contracts use `npm run verify:ZkEVM:${network}` npm run verify:ZkEVM:goerli ``` -A new folder will be created witth the following name `deployments/${network}_$(date +%s)` with all the output information and the OZ proxy information. +A new folder will be created with the following name `deployments/${network}_$(date +%s)` with all the output information and the OZ proxy information. ## deploy-parameters.json - `test`: bool, Indicate if it's a test deployment, which will fund the deployer address with pre minted ether and will give more powers to the deployer address to make easier the flow. -- `timelockAdminAddress`: address, Timelock owner address, able to send start an upgradability process via timelock +- `timelockAdminAddress`: address, Timelock owner address, able to send start an upgradeability process via timelock - `minDelayTimelock`: number, Minimum timelock delay, - `salt`: bytes32, Salt used in `PolygonZkEVMDeployer` to deploy deterministic contracts, such as the PolygonZkEVMBridge - `initialZkEVMDeployerOwner`: address, Initial owner of the `PolygonZkEVMDeployer` @@ -64,9 +64,9 @@ A new folder will be created witth the following name `deployments/${network}_$( - `trustedAggregator`: address, Trusted aggregator address - `trustedAggregatorTimeout`: uint64, If a sequence is not verified in this timeout everyone can verify it - `pendingStateTimeout`: uint64, Once a pending state exceeds this timeout it can be consolidated by everyone -- `emergencyCouncilAddress`:address, Emergency council addres -- `polTokenAddress`: address, Matic token address, only if deploy on testnet can be left blank and will fullfilled by the scripts. -- `zkEVMDeployerAddress`: address, Address of the `PolygonZkEVMDeployer`. Can be left blank, will be fullfilled automatically with the `deploy:deployer:ZkEVM:goerli` script. +- `emergencyCouncilAddress`: address, Emergency council address +- `polTokenAddress`: address, POL token address, only if deploy on testnet can be left blank and will fulfilled by the scripts. +- `zkEVMDeployerAddress`: address, Address of the `PolygonZkEVMDeployer`. Can be left blank, will be fulfilled automatically with the `deploy:deployer:ZkEVM:goerli` script. ## create_rollup_parameters.json @@ -74,7 +74,7 @@ A new folder will be created witth the following name `deployments/${network}_$( - `trustedSequencerURL`: string, trustedSequencer URL - `networkName`: string, networkName - `description`: string, Description of the new rollup type -- `trustedSequencer`: address, trusted sequencer addresss +- `trustedSequencer`: address, trusted sequencer address - `chainID`: uint64, chainID of the new rollup - `adminZkEVM`: address, Admin address, can adjust Rollup parameters - `forkID`: uint64, Fork ID of the new rollup, indicates the prover (zkROM/executor) version @@ -84,13 +84,13 @@ A new folder will be created witth the following name `deployments/${network}_$( ### Optional Parameters on both parameters - `deployerPvtKey`: string, pvtKey of the deployer, overrides the address in `MNEMONIC` of `.env` if exist -- `maxFeePerGas`: string, Set `maxFeePerGas`, must define aswell `maxPriorityFeePerGas` to use it -- `maxPriorityFeePerGas`: string, Set `maxPriorityFeePerGas`, must define aswell `maxFeePerGas` to use it +- `maxFeePerGas`: string, Set `maxFeePerGas`, must define as well `maxPriorityFeePerGas` to use it +- `maxPriorityFeePerGas`: string, Set `maxPriorityFeePerGas`, must define as well `maxFeePerGas` to use it - `multiplierGas`: number, Gas multiplier with 3 decimals. If `maxFeePerGas` and `maxPriorityFeePerGas` are set, this will not take effect -- `dataAvailabilityProtocol`: string, Data availability protocol, only mandatory/used when consensus contract is a Validiums, currently the only supported value is: `PolygonDataCommittee` +- `dataAvailabilityProtocol`: string, Data availability protocol, only mandatory/used when consensus contract is a Validium, currently the only supported value is: `PolygonDataCommittee` ## Notes - Since there are deterministic address you cannot deploy twice on the same network using the same `salt` and `initialZkEVMDeployerOwner`. Changing one of them is enough to make a new deployment. -- It's mandatory to delete the `.openzeppelin` upgradebility information in order to make a new deployment -- `genesis.json` has been generated using the tool: `1_createGenesis`, this script depends on the `deploy_parameters` aswell. +- It's mandatory to delete the `.openzeppelin` upgradeability information in order to make a new deployment +- `genesis.json` has been generated using the tool: `1_createGenesis`, this script depends on the `deploy_parameters` as well. diff --git a/deployment/v2/create_rollup_parameters.json.example b/deployment/v2/create_rollup_parameters.json.example index 57ddf47f9..034cf1b35 100644 --- a/deployment/v2/create_rollup_parameters.json.example +++ b/deployment/v2/create_rollup_parameters.json.example @@ -8,9 +8,18 @@ "adminZkEVM":"0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "forkID": 12, "consensusContract": "PolygonZkEVMEtrog", + "programVKey": "0x0000000000000000000000000000000000000000000000000000000000000000", "gasTokenAddress":"", "deployerPvtKey": "", "maxFeePerGas":"", "maxPriorityFeePerGas":"", - "multiplierGas": "" + "multiplierGas": "", + "isVanillaClient": false, + "sovereignParams": { + "bridgeManager": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "sovereignWETHAddress": "0x0000000000000000000000000000000000000000", + "sovereignWETHAddressIsNotMintable": false, + "globalExitRootUpdater": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "globalExitRootRemover": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } } diff --git a/deployment/v2/utils/deployment-utils.ts b/deployment/v2/utils/deployment-utils.ts new file mode 100644 index 000000000..30bc04ce2 --- /dev/null +++ b/deployment/v2/utils/deployment-utils.ts @@ -0,0 +1,12 @@ +const padTo32Bytes = (value) => { + const hexValue = value.startsWith("0x") ? value.slice(2) : value; // Remove '0x' + return "0x" + hexValue.padStart(64, "0"); // Pad to 64 hex digits +}; +const padTo20Bytes = (value) => { + const hexValue = value.startsWith("0x") ? value.slice(2) : value; // Remove '0x' + return "0x" + hexValue.padStart(40, "0"); // Pad to 40 hex digits +}; +export { + padTo32Bytes, + padTo20Bytes +} \ No newline at end of file diff --git a/deployment/v2/utils/updateVanillaGenesis.ts b/deployment/v2/utils/updateVanillaGenesis.ts new file mode 100644 index 000000000..46eb0b1c0 --- /dev/null +++ b/deployment/v2/utils/updateVanillaGenesis.ts @@ -0,0 +1,399 @@ +import {expect} from "chai"; +import {ethers} from "hardhat"; + +import {MemDB, ZkEVMDB, getPoseidon, smtUtils, processorUtils} from "@0xpolygonhermez/zkevm-commonjs"; +const {getContractAddress} = require("@ethersproject/address"); + +import {padTo32Bytes, padTo20Bytes} from "./deployment-utils"; + +// constants +// Those contracts names came from the genesis creation: +// - https://github.com/0xPolygonHermez/zkevm-contracts/blob/main/deployment/v2/1_createGenesis.ts#L294 +// - https://github.com/0xPolygonHermez/zkevm-contracts/blob/main/deployment/v2/1_createGenesis.ts#L328 +// Genesis files have been created previously and so they have old naming, as it shown in the links above +// Those genesis are already imported on different tooling and added as a metedata on-chain. Therefore, this util aims +// to support them too +const bridgeContractName = "BridgeL2SovereignChain"; +const supportedGERManagers = ["PolygonZkEVMGlobalExitRootL2 implementation"]; +const supportedBridgeContracts = ['PolygonZkEVMBridge implementation', 'PolygonZkEVMBridgeV2 implementation']; +const supportedBridgeContractsProxy = ['PolygonZkEVMBridgeV2 proxy', 'PolygonZkEVMBridge proxy']; + +async function updateVanillaGenesis(genesis, chainID, initializeParams) { + // Load genesis on a zkEVMDB + const poseidon = await getPoseidon(); + const {F} = poseidon; + const db = new MemDB(F); + const genesisRoot = [F.zero, F.zero, F.zero, F.zero]; + const accHashInput = [F.zero, F.zero, F.zero, F.zero]; + const zkEVMDB = await ZkEVMDB.newZkEVM( + db, + poseidon, + genesisRoot, + accHashInput, + genesis.genesis, + null, + null, + chainID + ); + const batch = await zkEVMDB.buildBatch( + 1000, //limitTimestamp + ethers.ZeroAddress, //trustedSequencer + smtUtils.stringToH4(ethers.ZeroHash) // l1InfoRoot + ); + // Add changeL2Block tx + const txChangeL2Block = { + type: 11, + deltaTimestamp: 3, + l1Info: { + globalExitRoot: ethers.ZeroAddress, // Can be any value + blockHash: "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", // Can be any value + timestamp: "42", + }, + indexL1InfoTree: 0, + }; + const rawChangeL2BlockTx = processorUtils.serializeChangeL2Block(txChangeL2Block); + batch.addRawTx(`0x${rawChangeL2BlockTx}`); + + // Create deploy bridge transaction + const sovereignBridgeFactory = await ethers.getContractFactory("BridgeL2SovereignChain"); + // Get deploy transaction for bridge + const deployBridgeData = await sovereignBridgeFactory.getDeployTransaction(); + const injectedTx = { + type: 0, // force ethers to parse it as a legacy transaction + chainId: 0, // force ethers to parse it as a pre-EIP155 transaction + to: null, + value: 0, + gasPrice: 0, + gasLimit: 30000000, + nonce: 0, + data: deployBridgeData.data, + signature: { + v: "0x1b", + r: "0x00000000000000000000000000000000000000000000000000000005ca1ab1e0", + s: "0x000000000000000000000000000000000000000000000000000000005ca1ab1e", + }, + }; + let txObject = ethers.Transaction.from(injectedTx); + const txDeployBridge = processorUtils.rawTxToCustomRawTx(txObject.serialized); + // Check ecrecover + expect(txObject.from).to.equal(ethers.recoverAddress(txObject.unsignedHash, txObject.signature as any)); + batch.addRawTx(txDeployBridge); + const sovereignBridgeAddress = getContractAddress({from: txObject.from, nonce: injectedTx.nonce}); + + // Create deploy GER transaction + const gerContractName = "GlobalExitRootManagerL2SovereignChain"; + const gerFactory = await ethers.getContractFactory(gerContractName); + const oldBridge = genesis.genesis.find(function (obj) { + return supportedBridgeContracts.includes(obj.contractName); + }); + // Get bridge proxy address + const bridgeProxy = genesis.genesis.find(function (obj) { + return supportedBridgeContractsProxy.includes(obj.contractName); + }); + const deployGERData = await gerFactory.getDeployTransaction(bridgeProxy.address); + injectedTx.data = deployGERData.data; + txObject = ethers.Transaction.from(injectedTx); + const txDeployGER = processorUtils.rawTxToCustomRawTx(txObject.serialized); + // Check ecrecover + expect(txObject.from).to.equal(ethers.recoverAddress(txObject.unsignedHash, txObject.signature as any)); + batch.addRawTx(txDeployGER); + const GERAddress = getContractAddress({from: txObject.from, nonce: injectedTx.nonce}); + + await batch.executeTxs(); + await zkEVMDB.consolidate(batch); + + // replace old bridge and ger manager by sovereign contracts bytecode + oldBridge.contractName = bridgeContractName + " implementation"; + oldBridge.bytecode = `0x${await zkEVMDB.getBytecode(sovereignBridgeAddress)}`; + + const oldGer = genesis.genesis.find(function (obj) { + return supportedGERManagers.includes(obj.contractName); + }); + oldGer.contractName = gerContractName + " implementation"; + oldGer.bytecode = `0x${await zkEVMDB.getBytecode(GERAddress)}`; + + // Setup a second zkEVM to initialize both contracts + const zkEVMDB2 = await ZkEVMDB.newZkEVM( + new MemDB(F), + poseidon, + genesisRoot, + accHashInput, + genesis.genesis, + null, + null, + chainID + ); + const batch2 = await zkEVMDB2.buildBatch( + 1000, //limitTimestamp + ethers.ZeroAddress, //trustedSequencer + smtUtils.stringToH4(ethers.ZeroHash) // l1InfoRoot + ); + // Add changeL2Block tx + batch2.addRawTx(`0x${rawChangeL2BlockTx}`); + const gerProxy = genesis.genesis.find(function (obj) { + return obj.contractName == "PolygonZkEVMGlobalExitRootL2 proxy"; + }); + // Initialize bridge + const { + rollupID, + gasTokenAddress, + gasTokenNetwork, + polygonRollupManager, + gasTokenMetadata, + bridgeManager, + sovereignWETHAddress, + sovereignWETHAddressIsNotMintable, + globalExitRootUpdater, + globalExitRootRemover, + } = initializeParams; + const initializeData = sovereignBridgeFactory.interface.encodeFunctionData( + "initialize(uint32,address,uint32,address,address,bytes,address,address,bool)", + [ + rollupID, + gasTokenAddress, + gasTokenNetwork, + gerProxy.address, // Global exit root manager address from base genesis + polygonRollupManager, + gasTokenMetadata, + bridgeManager, + sovereignWETHAddress, + sovereignWETHAddressIsNotMintable, + ] + ); + injectedTx.to = bridgeProxy.address; + injectedTx.data = initializeData; + txObject = ethers.Transaction.from(injectedTx); + const txInitializeBridge = processorUtils.rawTxToCustomRawTx(txObject.serialized); + // Check ecrecover + expect(txObject.from).to.equal(ethers.recoverAddress(txObject.unsignedHash, txObject.signature as any)); + batch2.addRawTx(txInitializeBridge); + + // Initialize GER Manager + const initializeGERData = gerFactory.interface.encodeFunctionData("initialize", [ + globalExitRootUpdater, + globalExitRootRemover, + ]); + // Update injectedTx to initialize GER + injectedTx.to = gerProxy.address; + injectedTx.data = initializeGERData; + + const txObject2 = ethers.Transaction.from(injectedTx); + const txInitializeGER = processorUtils.rawTxToCustomRawTx(txObject2.serialized); + // Check ecrecover + expect(txObject.from).to.equal(ethers.recoverAddress(txObject.unsignedHash, txObject.signature as any)); + batch2.addRawTx(txInitializeGER); + + // Execute batch + await batch2.executeTxs(); + await zkEVMDB2.consolidate(batch2); + + // Update bridgeProxy storage and nonce + bridgeProxy.contractName = bridgeContractName + " proxy"; + bridgeProxy.storage = await zkEVMDB2.dumpStorage(bridgeProxy.address); + // Update nonce, in case weth is deployed at initialize, it is increased + const bridgeProxyState = await zkEVMDB2.getCurrentAccountState(bridgeProxy.address) + bridgeProxy.nonce = String(Number(bridgeProxyState.nonce)); + // If bridge initialized with a zero sovereign weth address and a non zero gas token, we should add created erc20 weth contract to the genesis + let wethAddress; + if ( + gasTokenAddress !== ethers.ZeroAddress && + ethers.isAddress(gasTokenAddress) && + (sovereignWETHAddress === ethers.ZeroAddress || !ethers.isAddress(sovereignWETHAddress)) + ) { + wethAddress = padTo20Bytes( + bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006f"] + ); + const wethGenesis = { + contractName: "WETH", + balance: "0", + nonce: "1", + address: wethAddress, + bytecode: `0x${await zkEVMDB2.getBytecode(wethAddress)}`, + }; + const wethStorage = await zkEVMDB2.dumpStorage(wethAddress); + wethGenesis.storage = Object.entries(wethStorage).reduce((acc, [key, value]) => { + acc[key] = padTo32Bytes(value); + return acc; + }, {}); + genesis.genesis.push(wethGenesis); + } + + // Pad storage values with zeros + bridgeProxy.storage = Object.entries(bridgeProxy.storage).reduce((acc, [key, value]) => { + acc[key] = padTo32Bytes(value); + return acc; + }, {}); + + // CHECK BRIDGE PROXY STORAGE + // Storage value pointing bridge implementation + expect(bridgeProxy.storage["0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"]).to.include( + oldBridge.address.toLowerCase().slice(2) + ); + + // Storage value of proxyAdmin + const proxyAdminObject = genesis.genesis.find(function (obj) { + return obj.contractName == "ProxyAdmin"; + }); + expect(bridgeProxy.storage["0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"]).to.include( + proxyAdminObject.address.toLowerCase().slice(2) + ); + + // Storage value of bridge manager + expect(bridgeProxy.storage["0x00000000000000000000000000000000000000000000000000000000000000a3"]).to.include( + bridgeManager.toLowerCase().slice(2) + ); + + // Storage value for the _initialized uint8 variable of Initializable.sol contract, incremented each time the contract is successfully initialized. It also stores the _initializing param set to true when an initialization function is being executed, and it reverts to false once the initialization completed. + expect(bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000000"]).to.equal( + "0x0000000000000000000000000000000000000000000000000000000000000001" + ); + + // Storage value for the _status variable of ReentrancyGuardUpgradeable contract. Tracks the current "status" of the contract to enforce the non-reentrant behavior. Default value is 1 (_NOT_ENTERED) + expect(bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000001"]).to.equal( + "0x0000000000000000000000000000000000000000000000000000000000000001" + ); + + // Storage value for global exit root manager (proxy) address + expect(bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000068"]).to.include( + gerProxy.address.toLowerCase().slice(2) + ); + + // Storage value for rollup/network id + // RollupID value is stored at position 68 with globalExitRootManager address. Slice from byte 2 to 2-8 to get the rollupID + expect( + bridgeProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000068"].slice( + 2 + 54, + 2 + 54 + 8 + ) + ).to.include(rollupID.toString(16)); + + // Storage value for gas token address + if (gasTokenAddress !== ethers.ZeroAddress && ethers.isAddress(gasTokenAddress)) { + expect( + ethers.toBigInt(bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006d"]) + ).to.equal( + ethers.toBigInt(`${ethers.toBeHex(gasTokenNetwork)}${gasTokenAddress.replace(/^0x/, "")}`.toLowerCase()) + ); + if (ethers.isAddress(sovereignWETHAddress) && sovereignWETHAddress !== ethers.ZeroAddress) { + // Storage value for sovereignWETH address (ony if network with native gas token) and sovereignWethAddress is set + expect( + bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006f"] + ).to.include(sovereignWETHAddress.toLowerCase().slice(2)); + + // Storage address for sovereignWETHAddressIsNotMintable mapping + // To get the key we encode the key of the mapping with the position in the mapping + if (sovereignWETHAddressIsNotMintable) { + const mappingSlot = 162; // Slot of the mapping in the bridge contract + const key = ethers.keccak256( + ethers.AbiCoder.defaultAbiCoder().encode( + ["address", "uint256"], + [sovereignWETHAddress, mappingSlot] + ) + ); + expect(bridgeProxy.storage[key]).to.equal( + "0x0000000000000000000000000000000000000000000000000000000000000001" + ); + } + } else { + // Storage value for WETH address (ony if network with native gas token), deployed at bridge initialization + expect( + bridgeProxy.storage["0x000000000000000000000000000000000000000000000000000000000000006f"] + ).to.include(wethAddress.toLowerCase().slice(2)); + + // CHECK WETH STORAGE + const wethOject = genesis.genesis.find(function (obj) { + return obj.contractName == "WETH"; + }); + + // Storage for erc20 name 'Wrapped Ether' + expect(wethOject.storage["0x0000000000000000000000000000000000000000000000000000000000000003"]).to.equal( + "0x577261707065642045746865720000000000000000000000000000000000001a" + ); + + // Storage for erc20 code 'WETH' + expect(wethOject.storage["0x0000000000000000000000000000000000000000000000000000000000000004"]).to.equal( + "0x5745544800000000000000000000000000000000000000000000000000000008" + ); + } + + // Storage values for gasTokenMetadata, its a bytes variable + let offset = 2 + 64; + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142a"]).to.include( + gasTokenMetadata.slice(2, offset) + ); + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142b"]).to.include( + gasTokenMetadata.slice(offset, offset + 64) + ); + offset += 64; + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142c"]).to.include( + gasTokenMetadata.slice(offset, offset + 64) + ); + offset += 64; + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142d"]).to.include( + gasTokenMetadata.slice(offset, offset + 64) + ); + offset += 64; + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142e"]).to.include( + gasTokenMetadata.slice(offset, offset + 64) + ); + offset += 64; + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db7142f"]).to.include( + gasTokenMetadata.slice(offset, offset + 64) + ); + offset += 64; + expect(bridgeProxy.storage["0x9930d9ff0dee0ef5ca2f7710ea66b8f84dd0f5f5351ecffe72b952cd9db71430"]).to.include( + gasTokenMetadata.slice(offset, offset + 64) + ); + } + + // Check bridge proxy Address is included in ger bytecode + expect(oldGer.bytecode).to.include(bridgeProxy.address.toLowerCase().slice(2)); + + // Update bridgeProxy storage + gerProxy.contractName = gerContractName + " proxy"; + gerProxy.storage = await zkEVMDB2.dumpStorage(gerProxy.address); + gerProxy.storage = Object.entries(gerProxy.storage).reduce((acc, [key, value]) => { + acc[key] = padTo32Bytes(value); + return acc; + }, {}); + + // CHECK GER PROXY STORAGE + // Storage value of proxy implementation + expect(gerProxy.storage["0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"]).to.include( + oldGer.address.toLowerCase().slice(2) + ); + + // Storage value of proxyAdmin + expect(gerProxy.storage["0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103"]).to.include( + proxyAdminObject.address.toLowerCase().slice(2) + ); + + // Storage value of global exit root updater + expect(gerProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000034"]).to.include( + globalExitRootUpdater.toLowerCase().slice(2) + ); + if (ethers.isAddress(globalExitRootRemover) && globalExitRootRemover !== ethers.ZeroAddress) { + // Storage value of global exit root updater + expect(gerProxy.storage["0x0000000000000000000000000000000000000000000000000000000000000035"]).to.include( + globalExitRootRemover.toLowerCase().slice(2) + ); + } + + // Create a new zkEVM to generate a genesis an empty system address storage + const zkEVMDB3 = await ZkEVMDB.newZkEVM( + new MemDB(F), + poseidon, + genesisRoot, + accHashInput, + genesis.genesis, + null, + null, + chainID + ); + // update genesis root + genesis.root = smtUtils.h4toString(zkEVMDB3.getCurrentStateRoot()); + + return genesis; +} + +export default updateVanillaGenesis; diff --git a/docker/README.md b/docker/README.md index af92beb28..65fdfc2eb 100644 --- a/docker/README.md +++ b/docker/README.md @@ -13,10 +13,57 @@ You can change the deployment `mnemonic` creating a `.env` file in the project r - docker - docker-compose -## Build dockers +## Config files -In project root execute: +- Complete config `/docker/scripts/v2/create_rollup_parameters_docker.json` + +## deploy_parameters.json + +- `test`: Flag to point if is a testing environment, in such case, an account with balance will be created at the rollup and no timelock addresses will be used +- `timelockAdminAddress`: address, Timelock owner address, able to send start an upgradeability process via timelock +- `minDelayTimelock`: number, Minimum timelock delay, +- `salt`: bytes32, Salt used in `PolygonZkEVMDeployer` to deploy deterministic contracts, such as the PolygonZkEVMBridge +- `initialZkEVMDeployerOwner`: address, Initial owner of the `PolygonZkEVMDeployer` +- `admin`: address, Admin address, can adjust RollupManager parameters or stop the emergency state +- `trustedAggregator`: address, Trusted aggregator address +- `trustedAggregatorTimeout`: uint64, If a sequence is not verified in this timeout everyone can verify it +- `pendingStateTimeout`: uint64, Once a pending state exceeds this timeout it can be consolidated by everyone +- `emergencyCouncilAddress`: address, Emergency council address +- `polTokenAddress`: address, POL token address, only if deploy on testnet can be left blank and will fulfilled by the scripts. +- `zkEVMDeployerAddress`: address, Address of the `PolygonZkEVMDeployer`. Can be left blank, will be fulfilled automatically with the `deploy:deployer:ZkEVM:goerli` script +- `deployerPvtKey`: string, pvtKey of the deployer, overrides the address in `MNEMONIC` of `.env` if exist +- `maxFeePerGas`: string, Set `maxFeePerGas`, must define as well `maxPriorityFeePerGas` to use it +- `maxPriorityFeePerGas`: string, Set `maxPriorityFeePerGas`, must define as well `maxFeePerGas` to use it +- `multiplierGas`: number, Gas multiplier with 3 decimals. If `maxFeePerGas` and `maxPriorityFeePerGas` are set, this will not take effect + +## create_rollup_parameters.json +- `realVerifier`: bool, Indicates whether deploy a real verifier or not for the new created +- `trustedSequencerURL`: string, trustedSequencer URL +- `networkName`: string, networkName +- `description`: string, Description of the new rollup type +- `trustedSequencer`: address, trusted sequencer address +- `chainID`: uint64, chainID of the new rollup +- `adminZkEVM`: address, Admin address, can adjust Rollup parameters +- `forkID`: uint64, Fork ID of the new rollup, indicates the prover (zkROM/executor) version +- `consensusContract`: select between consensus contract. Supported: `["PolygonZkEVMEtrog", "PolygonValidiumEtrog", "PolygonPessimisticConsensus"]`. This is the name of the consensus of the rollupType of the rollup to be created +- `gasTokenAddress`: Address of the native gas token of the rollup, zero if ether +- `deployerPvtKey`: Not mandatory, used to deploy from specific wallet +- `maxFeePerGas(optional)`: string, Set `maxFeePerGas`, must define as well `maxPriorityFeePerGas` to use it +- `maxPriorityFeePerGas(optional)`: string, Set `maxPriorityFeePerGas`, must define as well `maxFeePerGas` to use it +- `multiplierGas(optional)`: number, Gas multiplier with 3 decimals. If `maxFeePerGas` and `maxPriorityFeePerGas` are set, this will not take effect +- `programVKey`: program key for pessimistic consensus +- `isVanillaClient`: Flag for vanilla/sovereign clients handling +- `sovereignParams`: Only mandatory if isVanillaClient = true + - `bridgeManager`: bridge manager address + - `sovereignWETHAddress`: sovereign WETH address + - `sovereignWETHAddressIsNotMintable`: Flag to indicate if the wrapped ETH is not mintable + - `globalExitRootUpdater`: Address of globalExitRootUpdater for sovereign chains + - `globalExitRootRemover`: Address of globalExitRootRemover for sovereign chains + +## Run script + +In project root execute: ``` npm i npm run docker:contracts @@ -24,5 +71,8 @@ npm run docker:contracts A new docker `geth-zkevm-contracts:latest` will be created This docker will contain a geth node with the deployed contracts -The deployment output can be found in: `docker/deploymentOutput/deploy_output.json` +The deployment output can be found in: +- `docker/deploymentOutput/create_rollup_output.json` +- `docker/deploymentOutput/deploy_output.json` +- `docker/deploymentOutput/genesis.json` To run the docker you can use: `docker run -p 8545:8545 geth-zkevm-contracts:latest` diff --git a/docker/scripts/tools/check-docker-deploy.js b/docker/scripts/tools/check-docker-deploy.js new file mode 100644 index 000000000..c21933bc4 --- /dev/null +++ b/docker/scripts/tools/check-docker-deploy.js @@ -0,0 +1,36 @@ +/* eslint-disable no-console */ + +const ethers = require('ethers'); +require('dotenv').config(); + +const rollupManagerAbi = require('../../../compiled-contracts/PolygonRollupManager.json').abi; + +async function main() { + const currentProvider = ethers.getDefaultProvider('http://localhost:8545'); + const signerNode = await currentProvider.getSigner(); + + const rollupManagerContract = new ethers.Contract('0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e', rollupManagerAbi, signerNode); + const infoContract = await rollupManagerContract.rollupIDToRollupDataV2(1); + const info = { + rollupContract: infoContract[0], + chainID: infoContract[1], + verifier: infoContract[2], + forkID: infoContract[3], + lastLocalExitRoot: infoContract[4], + lastBatchSequenced: infoContract[5], + lastVerifiedBatch: infoContract[6], + lastVerifiedBatchBeforeUpgrade: infoContract[7], + rollupTypeID: infoContract[8], + rollupVerifierType: infoContract[9], + lastPessimisticRoot: infoContract[10], + programVKey: infoContract[11], + }; + console.log(info); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/docker/scripts/v2/create_rollup_parameters_docker.json b/docker/scripts/v2/create_rollup_parameters_docker.json index dd19411bc..6f9a8d704 100644 --- a/docker/scripts/v2/create_rollup_parameters_docker.json +++ b/docker/scripts/v2/create_rollup_parameters_docker.json @@ -6,11 +6,20 @@ "trustedSequencer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "chainID": 1001, "adminZkEVM": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "forkID": 8, - "consensusContract": "PolygonZkEVMEtrog", - "gasTokenAddress":"", + "forkID": 11, + "consensusContract": "PolygonPessimisticConsensus", + "gasTokenAddress": "deploy", "deployerPvtKey": "", - "maxFeePerGas":"", - "maxPriorityFeePerGas":"", - "multiplierGas": "" + "maxFeePerGas": "", + "maxPriorityFeePerGas": "", + "multiplierGas": "", + "programVKey": "0xac51a6a2e513d02e4f39ea51d4d133cec200b940805f1054eabbb6d6412c959f", + "isVanillaClient": false, + "sovereignParams": { + "bridgeManager": "0xC7899Ff6A3aC2FF59261bD960A8C880DF06E1041", + "sovereignWETHAddress": "0x0000000000000000000000000000000000000000", + "sovereignWETHAddressIsNotMintable": false, + "globalExitRootUpdater": "0xB55B27Cca633A73108893985350bc26B8A00C43a", + "globalExitRootRemover": "0xB55B27Cca633A73108893985350bc26B8A00C43a" + } } diff --git a/docker/scripts/v2/deploy-docker.sh b/docker/scripts/v2/deploy-docker.sh index 08fffa4b5..1dde3f284 100755 --- a/docker/scripts/v2/deploy-docker.sh +++ b/docker/scripts/v2/deploy-docker.sh @@ -1,6 +1,13 @@ #!/bin/bash # Set the -e option to stop the script if any command fails set -e +# Define cleanup function +cleanup() { + sudo DEV_PERIOD=1 docker-compose -f docker/docker-compose.yml down +} +# Configure "trap" in case there's an error +trap cleanup ERR + sudo rm -rf docker/gethData/geth_data sudo DEV_PERIOD=1 docker-compose -f docker/docker-compose.yml up -d geth sleep 5 @@ -8,12 +15,13 @@ node docker/scripts/fund-accounts.js cp docker/scripts/v2/deploy_parameters_docker.json deployment/v2/deploy_parameters.json cp docker/scripts/v2/create_rollup_parameters_docker.json deployment/v2/create_rollup_parameters.json npm run deploy:testnet:v2:localhost -rm -rf docker/deploymentOutput +sudo rm -rf docker/deploymentOutput mkdir docker/deploymentOutput sudo mv deployment/v2/deploy_output.json docker/deploymentOutput sudo mv deployment/v2/genesis.json docker/deploymentOutput +[ -f deployment/v2/genesis_sovereign.json ] && sudo mv deployment/v2/genesis_sovereign.json docker/deploymentOutput sudo mv deployment/v2/create_rollup_output.json docker/deploymentOutput sudo DEV_PERIOD=1 docker-compose -f docker/docker-compose.yml down sudo docker build -t hermeznetwork/geth-zkevm-contracts -f docker/Dockerfile . # Let it readable for the multiplatform build coming later! -sudo chmod -R go+rxw docker/gethData \ No newline at end of file +sudo chmod -R go+rxw docker/gethData diff --git a/docker/scripts/v2/deploy-dockerv2.sh b/docker/scripts/v2/deploy-dockerv2.sh index bd744334b..406c16051 100755 --- a/docker/scripts/v2/deploy-dockerv2.sh +++ b/docker/scripts/v2/deploy-dockerv2.sh @@ -1,6 +1,13 @@ #!/bin/bash # Set the -e option to stop the script if any command fails set -e +# Define cleanup function +cleanup() { + sudo DEV_PERIOD=1 docker compose -f docker/docker-compose.yml down +} +# Configure "trap" in case there's an error +trap cleanup ERR + sudo rm -rf docker/gethData/geth_data sudo DEV_PERIOD=1 docker compose -f docker/docker-compose.yml up -d geth sleep 5 @@ -8,10 +15,11 @@ node docker/scripts/fund-accounts.js cp docker/scripts/v2/deploy_parameters_docker.json deployment/v2/deploy_parameters.json cp docker/scripts/v2/create_rollup_parameters_docker.json deployment/v2/create_rollup_parameters.json npm run deploy:testnet:v2:localhost -rm -rf docker/deploymentOutput +sudo rm -rf docker/deploymentOutput mkdir docker/deploymentOutput sudo mv deployment/v2/deploy_output.json docker/deploymentOutput sudo mv deployment/v2/genesis.json docker/deploymentOutput +[ -f deployment/v2/genesis_sovereign.json ] && sudo mv deployment/v2/genesis_sovereign.json docker/deploymentOutput sudo mv deployment/v2/create_rollup_output.json docker/deploymentOutput sudo DEV_PERIOD=1 docker compose -f docker/docker-compose.yml down sudo docker build -t hermeznetwork/geth-zkevm-contracts -f docker/Dockerfile . diff --git a/docker/scripts/v2/deploy_parameters_docker.json b/docker/scripts/v2/deploy_parameters_docker.json index b58f28476..2e810bf78 100644 --- a/docker/scripts/v2/deploy_parameters_docker.json +++ b/docker/scripts/v2/deploy_parameters_docker.json @@ -11,8 +11,6 @@ "emergencyCouncilAddress": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "polTokenAddress": "", "zkEVMDeployerAddress": "", - "gasTokenAddress": "", - "gasTokenNetwork": 0, "deployerPvtKey": "", "maxFeePerGas": "", "maxPriorityFeePerGas": "", diff --git a/docker/scripts/v2/tests-docker.sh b/docker/scripts/v2/tests-docker.sh index 6adbac73f..d154886c7 100755 --- a/docker/scripts/v2/tests-docker.sh +++ b/docker/scripts/v2/tests-docker.sh @@ -6,6 +6,8 @@ set -e docker run -p 8545:8545 -d --name docker_test hermeznetwork/geth-zkevm-contracts # Run docker tests npx hardhat test docker/docker-tests.test.ts --network localhost +# Run tooling tests to docker +npx hardhat test docker/tools-docker-tests.test.ts --network localhost # stop container docker stop docker_test # remove container diff --git a/docker/tools-docker-tests.test.ts b/docker/tools-docker-tests.test.ts new file mode 100644 index 000000000..ae0df9fc8 --- /dev/null +++ b/docker/tools-docker-tests.test.ts @@ -0,0 +1,151 @@ +import {expect} from "chai"; +import {ethers} from "hardhat"; +import fs from "fs"; +import path from "path"; +import shelljs from "shelljs"; +import {ConsensusContracts} from "../src/pessimistic-utils"; + +const deployOutput = JSON.parse(fs.readFileSync(path.join(__dirname, "./deploymentOutput/deploy_output.json"), "utf8")); +const {polygonRollupManagerAddress, polygonZkEVMBridgeAddress, polygonZkEVMGlobalExitRootAddress, polTokenAddress} = + deployOutput; +const createRollupOutput = JSON.parse( + fs.readFileSync(path.join(__dirname, "./deploymentOutput/create_rollup_output.json"), "utf8") +); +const {rollupAddress} = createRollupOutput; +import { + PolygonRollupManager, + PolygonPessimisticConsensus, + PolygonValidiumEtrog, + PolygonZkEVMEtrog, +} from "../typechain-types"; + +describe("Tooling docker build tests Contract", () => { + it("Create a new rollup", async () => { + // Read docker deployment output + const dockerCreateRollupOutput = JSON.parse( + fs.readFileSync(path.join(__dirname, "./deploymentOutput/create_rollup_output.json"), "utf8") + ); + const dockerDeploymentOutput = JSON.parse( + fs.readFileSync(path.join(__dirname, "./deploymentOutput/deploy_output.json"), "utf8") + ); + // Read create rollup config file + const createRollupConfig = JSON.parse( + fs.readFileSync(path.join(__dirname, "../tools/createNewRollup/create_new_rollup.json.example"), "utf8") + ); + + // Update example config from docker deployment output + createRollupConfig.consensusContractName = dockerCreateRollupOutput.consensusContract; + createRollupConfig.gasTokenAddress = dockerCreateRollupOutput.gasTokenAddress; + createRollupConfig.outputPath = "create_new_rollup_output.json"; + createRollupConfig.chainID = 12; + createRollupConfig.rollupManagerAddress = dockerDeploymentOutput.polygonRollupManagerAddress; + fs.writeFileSync( + path.join(__dirname, "../tools/createNewRollup/create_new_rollup.json"), + JSON.stringify(createRollupConfig, null, 2) + ); + + // Run tool + shelljs.exec("npx hardhat run ./tools/createNewRollup/createNewRollup.ts --network localhost"); + + // Read create rollup output + const createRollupOutput = JSON.parse( + fs.readFileSync(path.join(__dirname, "../tools/createNewRollup/create_new_rollup_output.json"), "utf8") + ); + // Check output values with current docker environment + const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager"); + const rollupManagerContract = PolygonRollupManagerFactory.attach( + createRollupOutput.rollupManagerAddress + ) as PolygonRollupManager; + + expect(createRollupConfig.rollupManagerAddress).to.equal(rollupManagerContract.target); + // Get rollup data + const rollupId = await rollupManagerContract.rollupAddressToID(createRollupOutput.rollupAddress); + expect(Number(rollupId)).to.equal(createRollupOutput.rollupID); + expect(await rollupManagerContract.chainIDToRollupID(createRollupConfig.chainID)).to.equal( + createRollupOutput.rollupID + ); + const rollupFactory = (await ethers.getContractFactory(createRollupConfig.consensusContractName)) as any; + let rollupContract; + switch (createRollupConfig.consensusContractName) { + case ConsensusContracts.PolygonZkEVMEtrog: + rollupContract = rollupFactory.attach(createRollupOutput.rollupAddress) as PolygonZkEVMEtrog; + break; + case ConsensusContracts.PolygonValidiumEtrog: + rollupContract = rollupFactory.attach(createRollupOutput.rollupAddress) as PolygonValidiumEtrog; + break; + case ConsensusContracts.PolygonPessimisticConsensus: + rollupContract = rollupFactory.attach(createRollupOutput.rollupAddress) as PolygonPessimisticConsensus; + break; + default: + throw new Error("Invalid consensus contract"); + } + + expect(await rollupContract.rollupManager()).to.equal(createRollupConfig.rollupManagerAddress); + expect(await rollupContract.gasTokenAddress()).to.equal(createRollupConfig.gasTokenAddress); + expect(await rollupContract.trustedSequencer()).to.equal(createRollupConfig.trustedSequencer); + }); + + it("Create a new rollup type", async () => { + // Read docker deployment output + const dockerCreateRollupOutput = JSON.parse( + fs.readFileSync(path.join(__dirname, "./deploymentOutput/create_rollup_output.json"), "utf8") + ); + const dockerDeploymentOutput = JSON.parse( + fs.readFileSync(path.join(__dirname, "./deploymentOutput/deploy_output.json"), "utf8") + ); + // Read create rollup config file + const createRollupTypeConfig = JSON.parse( + fs.readFileSync(path.join(__dirname, "../tools/addRollupType/add_rollup_type.json.example"), "utf8") + ); + + // Update example config from docker deployment output + createRollupTypeConfig.consensusContract = dockerCreateRollupOutput.consensusContract; + createRollupTypeConfig.polygonRollupManagerAddress = dockerCreateRollupOutput.rollupManagerAddress; + createRollupTypeConfig.verifierAddress = dockerCreateRollupOutput.verifierAddress; + if (dockerCreateRollupOutput.consensusContract === ConsensusContracts.PolygonPessimisticConsensus) { + createRollupTypeConfig.genesisRoot = ethers.ZeroHash; + createRollupTypeConfig.programVKey = dockerCreateRollupOutput.programVKey; + } else { + createRollupTypeConfig.genesisRoot = dockerCreateRollupOutput.genesis; + createRollupTypeConfig.programVKey = ethers.ZeroHash; + } + + createRollupTypeConfig.polygonRollupManagerAddress = dockerDeploymentOutput.polygonRollupManagerAddress; + createRollupTypeConfig.outputPath = "add_rollup_type_output.json"; + fs.writeFileSync( + path.join(__dirname, "../tools/addRollupType/add_rollup_type.json"), + JSON.stringify(createRollupTypeConfig, null, 2) + ); + + // Copy genesis file + fs.copyFileSync( + path.join(__dirname, "../tools/addRollupType/genesis.json.example"), + path.join(__dirname, "../tools/addRollupType/genesis.json") + ); + // Run tool + shelljs.exec("npx hardhat run ./tools/addRollupType/addRollupType.ts --network localhost"); + + // Read create rollup output + const createRollupTypeOutput = JSON.parse( + fs.readFileSync(path.join(__dirname, "../tools/addRollupType/add_rollup_type_output.json"), "utf8") + ); + // Check output values with current docker environment + const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager"); + const rollupManagerContract = PolygonRollupManagerFactory.attach( + dockerDeploymentOutput.polygonRollupManagerAddress + ) as PolygonRollupManager; + + const rollupType = await rollupManagerContract.rollupTypeMap(Number(createRollupTypeOutput.rollupTypeID)); + + // Consensus contract address + expect(rollupType[0]).to.equal(createRollupTypeOutput.consensusContractAddress); + // verifier address + expect(rollupType[1]).to.equal(createRollupTypeConfig.verifierAddress); + // ForkID + expect(Number(rollupType[2])).to.equal(createRollupTypeConfig.forkID); + // Genesis root + expect(rollupType[5]).to.equal(createRollupTypeConfig.genesisRoot); + // Program VKey + expect(rollupType[6]).to.equal(createRollupTypeConfig.programVKey); + }); +}); diff --git a/docs/L2/PolygonZkEVMBridgeL2.md b/docs/L2/PolygonZkEVMBridgeL2.md deleted file mode 100644 index 435aca286..000000000 --- a/docs/L2/PolygonZkEVMBridgeL2.md +++ /dev/null @@ -1,364 +0,0 @@ -PolygonZkEVMBridge that will be deployed on both networks Ethereum and Polygon zkEVM -Contract responsible to manage the token interactions with other networks - - -## Functions -### initialize -```solidity - function initialize( - uint32 _networkID, - contract IBasePolygonZkEVMGlobalExitRoot _globalExitRootManager, - address _polygonZkEVMaddress - ) external -``` -The value of `_polygonZkEVMaddress` on the L2 deployment of the contract will be address(0), so -emergency state is not possible for the L2 deployment of the bridge, intentionally - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`_networkID` | uint32 | networkID -|`_globalExitRootManager` | contract IBasePolygonZkEVMGlobalExitRoot | global exit root manager address -|`_polygonZkEVMaddress` | address | polygonZkEVM address - - -### bridgeAsset -```solidity - function bridgeAsset( - uint32 destinationNetwork, - address destinationAddress, - uint256 amount, - address token, - bool forceUpdateGlobalExitRoot, - bytes permitData - ) public -``` -Deposit add a new leaf to the merkle tree - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`destinationNetwork` | uint32 | Network destination -|`destinationAddress` | address | Address destination -|`amount` | uint256 | Amount of tokens -|`token` | address | Token address, 0 address is reserved for ether -|`forceUpdateGlobalExitRoot` | bool | Indicates if the new global exit root is updated or not -|`permitData` | bytes | Raw data of the call `permit` of the token - -### bridgeMessage -```solidity - function bridgeMessage( - uint32 destinationNetwork, - address destinationAddress, - uint256 amountWETH, - bool forceUpdateGlobalExitRoot, - bytes metadata - ) external -``` -Bridge message and send ETH value - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`destinationNetwork` | uint32 | Network destination -|`destinationAddress` | address | Address destination -|`amountWETH` | uint256 | Amount of WETH tokens -|`forceUpdateGlobalExitRoot` | bool | Indicates if the new global exit root is updated or not -|`metadata` | bytes | Message metadata - -### claimAsset -```solidity - function claimAsset( - bytes32[32] smtProof, - uint32 index, - bytes32 mainnetExitRoot, - bytes32 rollupExitRoot, - uint32 originNetwork, - address originTokenAddress, - uint32 destinationNetwork, - address destinationAddress, - uint256 amount, - bytes metadata - ) external -``` -Verify merkle proof and withdraw tokens/ether - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`smtProof` | bytes32[32] | Smt proof -|`index` | uint32 | Index of the leaf -|`mainnetExitRoot` | bytes32 | Mainnet exit root -|`rollupExitRoot` | bytes32 | Rollup exit root -|`originNetwork` | uint32 | Origin network -|`originTokenAddress` | address | Origin token address, 0 address is reserved for ether -|`destinationNetwork` | uint32 | Network destination -|`destinationAddress` | address | Address destination -|`amount` | uint256 | Amount of tokens -|`metadata` | bytes | Abi encoded metadata if any, empty otherwise - -### claimMessage -```solidity - function claimMessage( - bytes32[32] smtProof, - uint32 index, - bytes32 mainnetExitRoot, - bytes32 rollupExitRoot, - uint32 originNetwork, - address originAddress, - uint32 destinationNetwork, - address destinationAddress, - uint256 amount, - bytes metadata - ) external -``` -Verify merkle proof and execute message -If the receiving address is an EOA, the call will result as a success -Which means that the amount of ether will be transferred correctly, but the message -will not trigger any execution - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`smtProof` | bytes32[32] | Smt proof -|`index` | uint32 | Index of the leaf -|`mainnetExitRoot` | bytes32 | Mainnet exit root -|`rollupExitRoot` | bytes32 | Rollup exit root -|`originNetwork` | uint32 | Origin network -|`originAddress` | address | Origin address -|`destinationNetwork` | uint32 | Network destination -|`destinationAddress` | address | Address destination -|`amount` | uint256 | message value -|`metadata` | bytes | Abi encoded metadata if any, empty otherwise - -### precalculatedWrapperAddress -```solidity - function precalculatedWrapperAddress( - uint32 originNetwork, - address originTokenAddress, - string name, - string symbol, - uint8 decimals - ) external returns (address) -``` -Returns the precalculated address of a wrapper using the token information -Note Updating the metadata of a token is not supported. -Since the metadata has relevance in the address deployed, this function will not return a valid -wrapped address if the metadata provided is not the original one. - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`originNetwork` | uint32 | Origin network -|`originTokenAddress` | address | Origin token address, 0 address is reserved for ether -|`name` | string | Name of the token -|`symbol` | string | Symbol of the token -|`decimals` | uint8 | Decimals of the token - -### getTokenWrappedAddress -```solidity - function getTokenWrappedAddress( - uint32 originNetwork, - address originTokenAddress - ) external returns (address) -``` -Returns the address of a wrapper using the token information if already exist - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`originNetwork` | uint32 | Origin network -|`originTokenAddress` | address | Origin token address, 0 address is reserved for ether - -### activateEmergencyState -```solidity - function activateEmergencyState( - ) external -``` -Function to activate the emergency state - " Only can be called by the Polygon ZK-EVM in extreme situations - - - -### deactivateEmergencyState -```solidity - function deactivateEmergencyState( - ) external -``` -Function to deactivate the emergency state - " Only can be called by the Polygon ZK-EVM - - - -### _verifyLeaf -```solidity - function _verifyLeaf( - bytes32[32] smtProof, - uint32 index, - bytes32 mainnetExitRoot, - bytes32 rollupExitRoot, - uint32 originNetwork, - address originAddress, - uint32 destinationNetwork, - address destinationAddress, - uint256 amount, - bytes metadata, - uint8 leafType - ) internal -``` -Verify leaf and checks that it has not been claimed - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`smtProof` | bytes32[32] | Smt proof -|`index` | uint32 | Index of the leaf -|`mainnetExitRoot` | bytes32 | Mainnet exit root -|`rollupExitRoot` | bytes32 | Rollup exit root -|`originNetwork` | uint32 | Origin network -|`originAddress` | address | Origin address -|`destinationNetwork` | uint32 | Network destination -|`destinationAddress` | address | Address destination -|`amount` | uint256 | Amount of tokens -|`metadata` | bytes | Abi encoded metadata if any, empty otherwise -|`leafType` | uint8 | Leaf type --> [0] transfer Ether / ERC20 tokens, [1] message - -### isClaimed -```solidity - function isClaimed( - uint256 index - ) external returns (bool) -``` -Function to check if an index is claimed or not - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`index` | uint256 | Index - -### updateGlobalExitRoot -```solidity - function updateGlobalExitRoot( - ) external -``` -Function to update the globalExitRoot if the last deposit is not submitted - - - -### _updateGlobalExitRoot -```solidity - function _updateGlobalExitRoot( - ) internal -``` -Function to update the globalExitRoot - - - -### _permit -```solidity - function _permit( - address amount, - uint256 permitData - ) internal -``` -Function to call token permit method of extended ERC20 - + @param token ERC20 token address - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`amount` | address | Quantity that is expected to be allowed -|`permitData` | uint256 | Raw data of the call `permit` of the token - -### _safeSymbol -```solidity - function _safeSymbol( - address token - ) internal returns (string) -``` -Provides a safe ERC20.symbol version which returns 'NO_SYMBOL' as fallback string - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`token` | address | The address of the ERC-20 token contract - -### _safeName -```solidity - function _safeName( - address token - ) internal returns (string) -``` - Provides a safe ERC20.name version which returns 'NO_NAME' as fallback string. - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`token` | address | The address of the ERC-20 token contract. - -### _safeDecimals -```solidity - function _safeDecimals( - address token - ) internal returns (uint8) -``` -Provides a safe ERC20.decimals version which returns '18' as fallback value. -Note Tokens with (decimals > 255) are not supported - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`token` | address | The address of the ERC-20 token contract - -### _returnDataToString -```solidity - function _returnDataToString( - bytes data - ) internal returns (string) -``` -Function to convert returned data to string -returns 'NOT_VALID_ENCODING' as fallback value. - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`data` | bytes | returned data - -## Events -### BridgeEvent -```solidity - event BridgeEvent( - ) -``` - -Emitted when bridge assets or messages to another network - -### ClaimEvent -```solidity - event ClaimEvent( - ) -``` - -Emitted when a claim is done from another network - -### NewWrappedToken -```solidity - event NewWrappedToken( - ) -``` - -Emitted when a new wrapped token is created - diff --git a/docs/PolygonZkEVMBridge.md b/docs/PolygonZkEVMBridge.md index 5a94edf48..a0d9bc9ce 100644 --- a/docs/PolygonZkEVMBridge.md +++ b/docs/PolygonZkEVMBridge.md @@ -46,7 +46,7 @@ do not call any external address in that case |`destinationNetwork` | uint32 | Network destination |`destinationAddress` | address | Address destination |`amount` | uint256 | Amount of tokens -|`token` | address | Token address, 0 address is reserved for ether +|`token` | address | Token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token |`forceUpdateGlobalExitRoot` | bool | Indicates if the new global exit root is updated or not |`permitData` | bytes | Raw data of the call `permit` of the token @@ -96,7 +96,7 @@ Verify merkle proof and withdraw tokens/ether |`mainnetExitRoot` | bytes32 | Mainnet exit root |`rollupExitRoot` | bytes32 | Rollup exit root |`originNetwork` | uint32 | Origin network -|`originTokenAddress` | address | Origin token address, 0 address is reserved for ether +|`originTokenAddress` | address | Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token |`destinationNetwork` | uint32 | Network destination |`destinationAddress` | address | Address destination |`amount` | uint256 | Amount of tokens @@ -157,7 +157,7 @@ wrapped address if the metadata provided is not the original one. | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`originNetwork` | uint32 | Origin network -|`originTokenAddress` | address | Origin token address, 0 address is reserved for ether +|`originTokenAddress` | address | Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token |`name` | string | Name of the token |`symbol` | string | Symbol of the token |`decimals` | uint8 | Decimals of the token @@ -176,7 +176,7 @@ Returns the address of a wrapper using the token information if already exist | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`originNetwork` | uint32 | Origin network -|`originTokenAddress` | address | Origin token address, 0 address is reserved for ether +|`originTokenAddress` | address | Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token ### activateEmergencyState ```solidity diff --git a/docs/lib/DepositContractLib.md b/docs/lib/DepositContractLib.md deleted file mode 100644 index 98d0b10b3..000000000 --- a/docs/lib/DepositContractLib.md +++ /dev/null @@ -1,66 +0,0 @@ -This contract will be used as a helper for all the sparse merkle tree related functions -Based on the implementation of the deposit eth2.0 contract https://github.com/ethereum/consensus-specs/blob/dev/solidity_deposit_contract/deposit_contract.sol - - -## Functions -### getRoot -```solidity - function getRoot( - ) public returns (bytes32) -``` -Computes and returns the merkle root - - - -### _addLeaf -```solidity - function _addLeaf( - bytes32 leaf - ) internal -``` -Add a new leaf to the merkle tree - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`leaf` | bytes32 | Leaf - -### verifyMerkleProof -```solidity - function verifyMerkleProof( - bytes32 leafHash, - bytes32[32] smtProof, - uint32 index, - bytes32 root - ) public returns (bool) -``` -Verify merkle proof - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`leafHash` | bytes32 | Leaf hash -|`smtProof` | bytes32[32] | Smt proof -|`index` | uint32 | Index of the leaf -|`root` | bytes32 | Merkle root - -### calculateRoot -```solidity - function calculateRoot( - bytes32 leafHash, - bytes32[32] smtProof, - uint32 index - ) public returns (bytes32) -``` -calcualte root from merkle proof - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`leafHash` | bytes32 | Leaf hash -|`smtProof` | bytes32[32] | Smt proof -|`index` | uint32 | Index of the leaf - diff --git a/docs/selectors.txt b/docs/selectors.txt new file mode 100644 index 000000000..e69de29bb diff --git a/docs/L2/WETHzkEVM.md b/docs/token-wrapped-bridge/TokenWrappedBridge.md similarity index 82% rename from docs/L2/WETHzkEVM.md rename to docs/token-wrapped-bridge/TokenWrappedBridge.md index b75e00ada..44107d840 100644 --- a/docs/L2/WETHzkEVM.md +++ b/docs/token-wrapped-bridge/TokenWrappedBridge.md @@ -29,6 +29,15 @@ +### decimals +```solidity + function decimals( + ) public returns (uint8) +``` + + + + ### permit ```solidity function permit( diff --git a/docs/v2/PolygonRollupManager.md b/docs/v2/PolygonRollupManager.md index ce920e59d..17d48c670 100644 --- a/docs/v2/PolygonRollupManager.md +++ b/docs/v2/PolygonRollupManager.md @@ -22,14 +22,25 @@ them will be done in this one. In this way, the proof aggregation of the rollups |`_pol` | contract IERC20Upgradeable | POL token address |`_bridgeAddress` | contract IPolygonZkEVMBridge | Bridge address +### initialize +```solidity + function initialize( + ) external +``` +Initializer function to set new rollup manager version + + + ### addNewRollupType ```solidity function addNewRollupType( address consensusImplementation, - contract IVerifierRollup verifier, + address verifier, uint64 forkID, - uint8 genesis, - bytes32 description + enum IPolygonRollupManager.VerifierType rollupVerifierType, + bytes32 genesis, + string description, + bytes32 programVKey ) external ``` Add a new rollup type @@ -39,10 +50,12 @@ Add a new rollup type | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`consensusImplementation` | address | Consensus implementation -|`verifier` | contract IVerifierRollup | Verifier address +|`verifier` | address | Verifier address |`forkID` | uint64 | ForkID of the verifier -|`genesis` | uint8 | Genesis block of the rollup -|`description` | bytes32 | Description of the rollup type +|`rollupVerifierType` | enum IPolygonRollupManager.VerifierType | rollup verifier type +|`genesis` | bytes32 | Genesis block of the rollup +|`description` | string | Description of the rollup type +|`programVKey` | bytes32 | Hashed program that will be executed in case of using a "general purpose ZK verifier" e.g SP1 ### obsoleteRollupType ```solidity @@ -89,11 +102,12 @@ Note if a wrapped token of the bridge is used, the original network and address ```solidity function addExistingRollup( contract IPolygonRollupBase rollupAddress, - contract IVerifierRollup verifier, + address verifier, uint64 forkID, uint64 chainID, - bytes32 genesis, - uint8 rollupCompatibilityID + bytes32 initRoot, + enum IPolygonRollupManager.VerifierType rollupVerifierType, + bytes32 programVKey ) external ``` Add an already deployed rollup @@ -104,34 +118,12 @@ note that this rollup does not follow any rollupType | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`rollupAddress` | contract IPolygonRollupBase | Rollup address -|`verifier` | contract IVerifierRollup | Verifier address, must be added before -|`forkID` | uint64 | Fork id of the added rollup -|`chainID` | uint64 | Chain id of the added rollup -|`genesis` | bytes32 | Genesis block for this rollup -|`rollupCompatibilityID` | uint8 | Compatibility ID for the added rollup - -### _addExistingRollup -```solidity - function _addExistingRollup( - contract IPolygonRollupBase rollupAddress, - contract IVerifierRollup verifier, - uint64 forkID, - uint64 chainID, - uint8 rollupCompatibilityID - ) internal returns (struct PolygonRollupManager.RollupData rollup) -``` -Add an already deployed rollup -note that this rollup does not follow any rollupType - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`rollupAddress` | contract IPolygonRollupBase | Rollup address -|`verifier` | contract IVerifierRollup | Verifier address, must be added before +|`verifier` | address | Verifier address, must be added before |`forkID` | uint64 | Fork id of the added rollup |`chainID` | uint64 | Chain id of the added rollup -|`rollupCompatibilityID` | uint8 | Compatibility ID for the added rollup +|`initRoot` | bytes32 | Genesis block for StateTransitionChains & localExitRoot for pessimistic chain +|`rollupVerifierType` | enum IPolygonRollupManager.VerifierType | Compatibility ID for the added rollup +|`programVKey` | bytes32 | Hashed program that will be executed in case of using a "general purpose ZK verifier" e.g SP1 ### updateRollupByRollupAdmin ```solidity @@ -194,6 +186,7 @@ Upgrade an existing rollup ) external ``` Rollback batches of the target rollup +Only applies to state transition rollups #### Parameters: @@ -218,34 +211,6 @@ Sequence batches, callback called by one of the consensus managed by this contra |`newSequencedBatches` | uint64 | Number of batches sequenced |`newAccInputHash` | bytes32 | New accumulate input hash -### verifyBatches -```solidity - function verifyBatches( - uint32 rollupID, - uint64 pendingStateNum, - uint64 initNumBatch, - uint64 finalNewBatch, - bytes32 newLocalExitRoot, - bytes32 newStateRoot, - address beneficiary, - bytes32[24] proof - ) external -``` -Allows an aggregator to verify multiple batches - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`rollupID` | uint32 | Rollup identifier -|`pendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used -|`initNumBatch` | uint64 | Batch which the aggregator starts the verification -|`finalNewBatch` | uint64 | Last batch aggregator intends to verify -|`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed -|`newStateRoot` | bytes32 | New State root once the batch is processed -|`beneficiary` | address | Address that will receive the verification reward -|`proof` | bytes32[24] | Fflonk proof - ### verifyBatchesTrustedAggregator ```solidity function verifyBatchesTrustedAggregator( @@ -266,7 +231,7 @@ Allows a trusted aggregator to verify multiple batches | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`rollupID` | uint32 | Rollup identifier -|`pendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used +|`pendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used (deprecated) |`initNumBatch` | uint64 | Batch which the aggregator starts the verification |`finalNewBatch` | uint64 | Last batch aggregator intends to verify |`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed @@ -278,7 +243,6 @@ Allows a trusted aggregator to verify multiple batches ```solidity function _verifyAndRewardBatches( struct PolygonRollupManager.RollupData rollup, - uint64 pendingStateNum, uint64 initNumBatch, uint64 finalNewBatch, bytes32 newLocalExitRoot, @@ -294,7 +258,6 @@ Verify and reward batches internal function | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`rollup` | struct PolygonRollupManager.RollupData | Rollup Data storage pointer that will be used to the verification -|`pendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used |`initNumBatch` | uint64 | Batch which the aggregator starts the verification |`finalNewBatch` | uint64 | Last batch aggregator intends to verify |`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed @@ -302,148 +265,27 @@ Verify and reward batches internal function |`beneficiary` | address | Address that will receive the verification reward |`proof` | bytes32[24] | Fflonk proof -### _tryConsolidatePendingState -```solidity - function _tryConsolidatePendingState( - ) internal -``` -Internal function to consolidate the state automatically once sequence or verify batches are called -It tries to consolidate the first and the middle pending state in the queue - - - -### consolidatePendingState -```solidity - function consolidatePendingState( - uint32 rollupID, - uint64 pendingStateNum - ) external -``` -Allows to consolidate any pending state that has already exceed the pendingStateTimeout -Can be called by the trusted aggregator, which can consolidate any state without the timeout restrictions - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`rollupID` | uint32 | Rollup identifier -|`pendingStateNum` | uint64 | Pending state to consolidate - -### _consolidatePendingState -```solidity - function _consolidatePendingState( - struct PolygonRollupManager.RollupData rollup, - uint64 pendingStateNum - ) internal -``` -Internal function to consolidate any pending state that has already exceed the pendingStateTimeout - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`rollup` | struct PolygonRollupManager.RollupData | Rollup data storage pointer -|`pendingStateNum` | uint64 | Pending state to consolidate - -### overridePendingState -```solidity - function overridePendingState( - uint32 rollupID, - uint64 initPendingStateNum, - uint64 finalPendingStateNum, - uint64 initNumBatch, - uint64 finalNewBatch, - bytes32 newLocalExitRoot, - bytes32 newStateRoot, - bytes32[24] proof - ) external -``` -Allows the trusted aggregator to override the pending state -if it's possible to prove a different state root given the same batches - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`rollupID` | uint32 | Rollup identifier -|`initPendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used -|`finalPendingStateNum` | uint64 | Final pending state, that will be used to compare with the newStateRoot -|`initNumBatch` | uint64 | Batch which the aggregator starts the verification -|`finalNewBatch` | uint64 | Last batch aggregator intends to verify -|`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed -|`newStateRoot` | bytes32 | New State root once the batch is processed -|`proof` | bytes32[24] | Fflonk proof - -### proveNonDeterministicPendingState +### verifyPessimisticTrustedAggregator ```solidity - function proveNonDeterministicPendingState( + function verifyPessimisticTrustedAggregator( uint32 rollupID, - uint64 initPendingStateNum, - uint64 finalPendingStateNum, - uint64 initNumBatch, - uint64 finalNewBatch, + uint32 l1InfoTreeLeafCount, bytes32 newLocalExitRoot, - bytes32 newStateRoot, - bytes32[24] proof + bytes32 newPessimisticRoot, + bytes proof ) external ``` -Allows activate the emergency state if its possible to prove a different state root given the same batches +Allows a trusted aggregator to verify pessimistic proof #### Parameters: | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`rollupID` | uint32 | Rollup identifier -|`initPendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used -|`finalPendingStateNum` | uint64 | Final pending state, that will be used to compare with the newStateRoot -|`initNumBatch` | uint64 | Batch which the aggregator starts the verification -|`finalNewBatch` | uint64 | Last batch aggregator intends to verify -|`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed -|`newStateRoot` | bytes32 | New State root once the batch is processed -|`proof` | bytes32[24] | Fflonk proof - -### _proveDistinctPendingState -```solidity - function _proveDistinctPendingState( - struct PolygonRollupManager.RollupData rollup, - uint64 initPendingStateNum, - uint64 finalPendingStateNum, - uint64 initNumBatch, - uint64 finalNewBatch, - bytes32 newLocalExitRoot, - bytes32 newStateRoot, - bytes32[24] proof - ) internal -``` -Internal function that proves a different state root given the same batches to verify - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`rollup` | struct PolygonRollupManager.RollupData | Rollup Data struct that will be checked -|`initPendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used -|`finalPendingStateNum` | uint64 | Final pending state, that will be used to compare with the newStateRoot -|`initNumBatch` | uint64 | Batch which the aggregator starts the verification -|`finalNewBatch` | uint64 | Last batch aggregator intends to verify -|`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed -|`newStateRoot` | bytes32 | New State root once the batch is processed -|`proof` | bytes32[24] | Fflonk proof - -### _updateBatchFee -```solidity - function _updateBatchFee( - struct PolygonRollupManager.RollupData newLastVerifiedBatch - ) internal -``` -Function to update the batch fee based on the new verified batches -The batch fee will not be updated when the trusted aggregator verifies batches - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newLastVerifiedBatch` | struct PolygonRollupManager.RollupData | New last verified batch +|`l1InfoTreeLeafCount` | uint32 | Count of the L1InfoTree leaf that will be used to verify imported bridge exits +|`newLocalExitRoot` | bytes32 | New local exit root +|`newPessimisticRoot` | bytes32 | New pessimistic information, Hash(localBalanceTreeRoot, nullifierTreeRoot) +|`proof` | bytes | SP1 proof (Plonk) ### activateEmergencyState ```solidity @@ -473,66 +315,6 @@ Internal function to activate emergency state on both PolygonRollupManager and P -### setTrustedAggregatorTimeout -```solidity - function setTrustedAggregatorTimeout( - uint64 newTrustedAggregatorTimeout - ) external -``` -Set a new pending state timeout -The timeout can only be lowered, except if emergency state is active - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newTrustedAggregatorTimeout` | uint64 | Trusted aggregator timeout - -### setPendingStateTimeout -```solidity - function setPendingStateTimeout( - uint64 newPendingStateTimeout - ) external -``` -Set a new trusted aggregator timeout -The timeout can only be lowered, except if emergency state is active - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newPendingStateTimeout` | uint64 | Trusted aggregator timeout - -### setMultiplierBatchFee -```solidity - function setMultiplierBatchFee( - uint16 newMultiplierBatchFee - ) external -``` -Set a new multiplier batch fee - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newMultiplierBatchFee` | uint16 | multiplier batch fee - -### setVerifyBatchTimeTarget -```solidity - function setVerifyBatchTimeTarget( - uint64 newVerifyBatchTimeTarget - ) external -``` -Set a new verify batch time target -This value will only be relevant once the aggregation is decentralized, so -the trustedAggregatorTimeout should be zero or very close to zero - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newVerifyBatchTimeTarget` | uint64 | Verify batch time target - ### setBatchFee ```solidity function setBatchFee( @@ -578,40 +360,6 @@ Get the last verified batch -### isPendingStateConsolidable -```solidity - function isPendingStateConsolidable( - uint32 rollupID, - uint64 pendingStateNum - ) public returns (bool) -``` -Returns a boolean that indicates if the pendingStateNum is or not consolidable - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`rollupID` | uint32 | Rollup id -|`pendingStateNum` | uint64 | Pending state number to check -Note that his function does not check if the pending state currently exists, or if it's consolidated already - -### _isPendingStateConsolidable -```solidity - function _isPendingStateConsolidable( - struct PolygonRollupManager.RollupData rollup, - uint64 pendingStateNum - ) internal returns (bool) -``` -Returns a boolean that indicates if the pendingStateNum is or not consolidable - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`rollup` | struct PolygonRollupManager.RollupData | Rollup data storage pointer -|`pendingStateNum` | uint64 | Pending state number to check -Note that his function does not check if the pending state currently exists, or if it's consolidated already - ### calculateRewardPerBatch ```solidity function calculateRewardPerBatch( @@ -641,6 +389,48 @@ Get forced batch fee +### getInputPessimisticBytes +```solidity + function getInputPessimisticBytes( + uint32 rollupID, + bytes32 l1InfoTreeRoot, + bytes32 newLocalExitRoot, + bytes32 newPessimisticRoot + ) external returns (bytes) +``` +Function to calculate the pessimistic input bytes + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup id used to calculate the input snark bytes +|`l1InfoTreeRoot` | bytes32 | L1 Info tree root to proof imported bridges +|`newLocalExitRoot` | bytes32 | New local exit root +|`newPessimisticRoot` | bytes32 | New pessimistic information, Hash(localBalanceTreeRoot, nullifierTreeRoot) + +### _getInputPessimisticBytes +```solidity + function _getInputPessimisticBytes( + uint32 rollupID, + struct PolygonRollupManager.RollupData rollup, + bytes32 l1InfoTreeRoot, + bytes32 newLocalExitRoot, + bytes32 newPessimisticRoot + ) internal returns (bytes) +``` +Function to calculate the input snark bytes + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup identifier +|`rollup` | struct PolygonRollupManager.RollupData | Rollup data storage pointer +|`l1InfoTreeRoot` | bytes32 | L1 Info tree root to proof imported bridges +|`newLocalExitRoot` | bytes32 | New local exit root +|`newPessimisticRoot` | bytes32 | New pessimistic information, Hash(localBalanceTreeRoot, nullifierTreeRoot) + ### getInputSnarkBytes ```solidity function getInputSnarkBytes( @@ -735,21 +525,33 @@ Get rollup sequence batches struct given a batch number |`rollupID` | uint32 | Rollup identifier |`batchNum` | uint64 | Batch number -### getRollupPendingStateTransitions +### rollupIDToRollupData ```solidity - function getRollupPendingStateTransitions( - uint32 rollupID, - uint64 batchNum - ) public returns (struct LegacyZKEVMStateVariables.PendingState) + function rollupIDToRollupData( + uint32 rollupID + ) public returns (struct PolygonRollupManager.RollupDataReturn rollupData) ``` -Get rollup sequence pending state struct given a batch number +Get rollup data: VerifierType StateTransition + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup identifier + +### rollupIDToRollupDataV2 +```solidity + function rollupIDToRollupDataV2( + uint32 rollupID + ) public returns (struct PolygonRollupManager.RollupDataReturnV2 rollupData) +``` +Get rollup data: VerifierType Pessimistic #### Parameters: | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`rollupID` | uint32 | Rollup identifier -|`batchNum` | uint64 | Batch number ## Events ### AddNewRollupType @@ -800,14 +602,6 @@ Emitted when a rollup is udpated Emitted when a new verifier is added -### VerifyBatches -```solidity - event VerifyBatches( - ) -``` - -Emitted when an aggregator verifies batches - ### VerifyBatchesTrustedAggregator ```solidity event VerifyBatchesTrustedAggregator( @@ -816,30 +610,6 @@ Emitted when an aggregator verifies batches Emitted when the trusted aggregator verifies batches -### ConsolidatePendingState -```solidity - event ConsolidatePendingState( - ) -``` - -Emitted when pending state is consolidated - -### ProveNonDeterministicPendingState -```solidity - event ProveNonDeterministicPendingState( - ) -``` - -Emitted when is proved a different state given the same batches - -### OverridePendingState -```solidity - event OverridePendingState( - ) -``` - -Emitted when the trusted aggregator overrides pending state - ### RollbackBatches ```solidity event RollbackBatches( @@ -848,38 +618,6 @@ Emitted when the trusted aggregator overrides pending state Emitted when rollback batches -### SetTrustedAggregatorTimeout -```solidity - event SetTrustedAggregatorTimeout( - ) -``` - -Emitted when is updated the trusted aggregator timeout - -### SetPendingStateTimeout -```solidity - event SetPendingStateTimeout( - ) -``` - -Emitted when is updated the pending state timeout - -### SetMultiplierBatchFee -```solidity - event SetMultiplierBatchFee( - ) -``` - -Emitted when is updated the multiplier batch fee - -### SetVerifyBatchTimeTarget -```solidity - event SetVerifyBatchTimeTarget( - ) -``` - -Emitted when is updated the verify batch timeout - ### SetTrustedAggregator ```solidity event SetTrustedAggregator( @@ -896,3 +634,11 @@ Emitted when is updated the trusted aggregator address Emitted when is updated the batch fee +### UpdateRollupManagerVersion +```solidity + event UpdateRollupManagerVersion( + ) +``` + +Emitted when rollup manager is upgraded + diff --git a/docs/v2/PolygonZkEVMBridgeV2.md b/docs/v2/PolygonZkEVMBridgeV2.md index c42e14a56..fa5c16754 100644 --- a/docs/v2/PolygonZkEVMBridgeV2.md +++ b/docs/v2/PolygonZkEVMBridgeV2.md @@ -62,7 +62,7 @@ note User/UI must be aware of the existing/available networks when choosing the |`destinationNetwork` | uint32 | Network destination |`destinationAddress` | address | Address destination |`amount` | uint256 | Amount of tokens -|`token` | address | Token address, 0 address is reserved for ether +|`token` | address | Token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token |`forceUpdateGlobalExitRoot` | bool | Indicates if the new global exit root is updated or not |`permitData` | bytes | Raw data of the call `permit` of the token @@ -166,7 +166,7 @@ to avoid possible synch attacks |`mainnetExitRoot` | bytes32 | Mainnet exit root |`rollupExitRoot` | bytes32 | Rollup exit root |`originNetwork` | uint32 | Origin network -|`originTokenAddress` | address | Origin token address, 0 address is reserved for ether +|`originTokenAddress` | address | Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token |`destinationNetwork` | uint32 | Network destination |`destinationAddress` | address | Address destination |`amount` | uint256 | Amount of tokens @@ -235,7 +235,7 @@ wrapped address if the metadata provided is not the original one. | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`originNetwork` | uint32 | Origin network -|`originTokenAddress` | address | Origin token address, 0 address is reserved for ether +|`originTokenAddress` | address | Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token |`name` | string | Name of the token |`symbol` | string | Symbol of the token |`decimals` | uint8 | Decimals of the token @@ -254,7 +254,7 @@ Returns the address of a wrapper using the token information if already exist | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`originNetwork` | uint32 | Origin network -|`originTokenAddress` | address | Origin token address, 0 address is reserved for ether +|`originTokenAddress` | address | Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token ### activateEmergencyState ```solidity @@ -310,6 +310,22 @@ Verify leaf and checks that it has not been claimed Function to check if an index is claimed or not +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`leafIndex` | uint32 | Index +|`sourceBridgeNetwork` | uint32 | Origin network + +### _setAndCheckClaimed +```solidity + function _setAndCheckClaimed( + uint32 leafIndex, + uint32 sourceBridgeNetwork + ) internal +``` +Function to check that an index is not claimed and set it as claimed + + #### Parameters: | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | @@ -334,6 +350,56 @@ Function to update the globalExitRoot +### _bridgeWrappedAsset +```solidity + function _bridgeWrappedAsset( + contract TokenWrapped tokenWrapped, + uint256 amount + ) internal +``` +Burn tokens from wrapped token to execute the bridge +note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`tokenWrapped` | contract TokenWrapped | Wrapped token to burnt +|`amount` | uint256 | Amount of tokens + +### _claimWrappedAsset +```solidity + function _claimWrappedAsset( + contract TokenWrapped tokenWrapped, + address destinationAddress, + uint256 amount + ) internal +``` +Mints tokens from wrapped token to proceed with the claim +note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`tokenWrapped` | contract TokenWrapped | Wrapped token to mint +|`destinationAddress` | address | Minted token receiver +|`amount` | uint256 | Amount of tokens + +### _bitmapPositions +```solidity + function _bitmapPositions( + uint256 index + ) internal returns (uint256 wordPos, uint256 bitPos) +``` +Function decode an index into a wordPos and bitPos + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`index` | uint256 | Index + ### _permit ```solidity function _permit( @@ -458,7 +524,7 @@ wrapped address if the metadata provided is not the original one. | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`originNetwork` | uint32 | Origin network -|`originTokenAddress` | address | Origin token address, 0 address is reserved for ether +|`originTokenAddress` | address | Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token |`token` | address | Address of the token to calculate the wrapper address ## Events diff --git a/docs/v2/PolygonZkEVMGlobalExitRootV2.md b/docs/v2/PolygonZkEVMGlobalExitRootV2.md index 9b896e023..481824309 100644 --- a/docs/v2/PolygonZkEVMGlobalExitRootV2.md +++ b/docs/v2/PolygonZkEVMGlobalExitRootV2.md @@ -73,7 +73,7 @@ Given the leaf data returns the leaf hash | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`newGlobalExitRoot` | bytes32 | Last global exit root -|`lastBlockHash` | uint256 | Last accesible block hash +|`lastBlockHash` | uint256 | Last accessible block hash |`timestamp` | uint64 | Ethereum timestamp in seconds ## Events diff --git a/docs/v2/consensus/dataComittee/CDKDataCommittee.md b/docs/v2/consensus/dataComittee/CDKDataCommittee.md deleted file mode 100644 index b43f7504d..000000000 --- a/docs/v2/consensus/dataComittee/CDKDataCommittee.md +++ /dev/null @@ -1,75 +0,0 @@ - - - -## Functions -### initialize -```solidity - function initialize( - ) external -``` - - - - -### setupCommittee -```solidity - function setupCommittee( - uint256 _requiredAmountOfSignatures, - string[] urls, - bytes addrsBytes - ) external -``` -Allows the admin to setup the members of the committee. Note that: -The system will require N / M signatures where N => _requiredAmountOfSignatures and M => urls.length -There must be the same amount of urls than addressess encoded in the addrsBytes -A member is represented by the url and the address contained in urls[i] and addrsBytes[i*_ADDR_SIZE : i*_ADDR_SIZE + _ADDR_SIZE] - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`_requiredAmountOfSignatures` | uint256 | Required amount of signatures -|`urls` | string[] | List of urls of the members of the committee -|`addrsBytes` | bytes | Byte array that contains the addressess of the members of the committee - -### getAmountOfMembers -```solidity - function getAmountOfMembers( - ) public returns (uint256) -``` - - - - -### verifySignatures -```solidity - function verifySignatures( - bytes32 signedHash, - bytes signaturesAndAddrs - ) external -``` -Verifies that the given signedHash has been signed by requiredAmountOfSignatures committee members - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`signedHash` | bytes32 | Hash that must have been signed by requiredAmountOfSignatures of committee members -|`signaturesAndAddrs` | bytes | Byte array containing the signatures and all the addresses of the committee in ascending order -[signature 0, ..., signature requiredAmountOfSignatures -1, address 0, ... address N] -note that each ECDSA signatures are used, therefore each one must be 65 bytes - -## Events -### CommitteeUpdated -```solidity - event CommitteeUpdated( - bytes32 committeeHash - ) -``` - -Emitted when the committee is updated - -#### Parameters: -| Name | Type | Description | -| :----------------------------- | :------------ | :--------------------------------------------- | -|`committeeHash`| bytes32 | hash of the addresses of the committee members diff --git a/docs/v2/consensus/dataComittee/PolygonDataComittee.md b/docs/v2/consensus/dataComittee/PolygonDataComittee.md deleted file mode 100644 index d5bba03dd..000000000 --- a/docs/v2/consensus/dataComittee/PolygonDataComittee.md +++ /dev/null @@ -1,76 +0,0 @@ -Contract responsible for managing the states and the updates of L2 network. -There will be a trusted sequencer, which is able to send transactions. -Any user can force some transaction and the sequencer will have a timeout to add them in the queue. -The sequenced state is deterministic and can be precalculated before it's actually verified by a zkProof. -The aggregators will be able to verify the sequenced state with zkProofs and therefore make available the withdrawals from L2 network. -To enter and exit of the L2 network will be used a PolygonZkEVMBridge smart contract that will be deployed in both networks. - - -## Functions -### constructor -```solidity - function constructor( - contract IPolygonZkEVMGlobalExitRoot _globalExitRootManager, - contract IERC20Upgradeable _pol, - contract IPolygonZkEVMBridge _bridgeAddress, - contract PolygonRollupManager _rollupManager - ) public -``` - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`_globalExitRootManager` | contract IPolygonZkEVMGlobalExitRoot | Global exit root manager address -|`_pol` | contract IERC20Upgradeable | POL token address -|`_bridgeAddress` | contract IPolygonZkEVMBridge | Bridge address -|`_rollupManager` | contract PolygonRollupManager | Global exit root manager address - -### sequenceBatches -```solidity - function sequenceBatches( - ) public -``` - - - - -### sequenceBatchesDataCommittee -```solidity - function sequenceBatchesDataCommittee( - struct PolygonDataComittee.ValidiumBatchData[] batches, - address l2Coinbase, - bytes dataAvailabilityMessage - ) external -``` -Allows a sequencer to send multiple batches - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`batches` | struct PolygonDataComittee.ValidiumBatchData[] | Struct array which holds the necessary data to append new batches to the sequence -|`l2Coinbase` | address | Address that will receive the fees from L2 -|`dataAvailabilityMessage` | bytes | Byte array containing the signatures and all the addresses of the committee in ascending order -[signature 0, ..., signature requiredAmountOfSignatures -1, address 0, ... address N] -note that each ECDSA signatures are used, therefore each one must be 65 bytes - -### switchSequenceWithDataAvailability -```solidity - function switchSequenceWithDataAvailability( - ) external -``` -Allow the admin to turn on the force batches -This action is not reversible - - - -## Events -### SwitchSequenceWithDataAvailability -```solidity - event SwitchSequenceWithDataAvailability( - ) -``` - -Emitted when switch the ability to sequence with data availability - diff --git a/docs/v2/mocks/PolygonRollupManagerMockInternalTest.md b/docs/v2/consensus/pessimistic/PolygonPessimisticConsensus.md similarity index 52% rename from docs/v2/mocks/PolygonRollupManagerMockInternalTest.md rename to docs/v2/consensus/pessimistic/PolygonPessimisticConsensus.md index dd333a250..1a3b33bc9 100644 --- a/docs/v2/mocks/PolygonRollupManagerMockInternalTest.md +++ b/docs/v2/consensus/pessimistic/PolygonPessimisticConsensus.md @@ -1,4 +1,4 @@ -PolygonRollupManager Test + ## Functions @@ -7,7 +7,8 @@ PolygonRollupManager Test function constructor( contract IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, contract IERC20Upgradeable _pol, - contract IPolygonZkEVMBridge _bridgeAddress + contract IPolygonZkEVMBridgeV2 _bridgeAddress, + contract PolygonRollupManager _rollupManager ) public ``` @@ -16,15 +17,16 @@ PolygonRollupManager Test | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`_globalExitRootManager` | contract IPolygonZkEVMGlobalExitRootV2 | Global exit root manager address -|`_pol` | contract IERC20Upgradeable | MATIC token address -|`_bridgeAddress` | contract IPolygonZkEVMBridge | Bridge address +|`_pol` | contract IERC20Upgradeable | POL token address +|`_bridgeAddress` | contract IPolygonZkEVMBridgeV2 | Bridge address +|`_rollupManager` | contract PolygonRollupManager | Rollup manager address -### initialize +### getConsensusHash ```solidity - function initialize( - ) external + function getConsensusHash( + ) public returns (bytes32) ``` - +Note Return the necessary consensus information for the proof hashed diff --git a/docs/v2/consensus/validium/PolygonValidiumEtrog.md b/docs/v2/consensus/validium/PolygonValidiumEtrog.md index 35e01094e..863d7269c 100644 --- a/docs/v2/consensus/validium/PolygonValidiumEtrog.md +++ b/docs/v2/consensus/validium/PolygonValidiumEtrog.md @@ -45,7 +45,7 @@ Allows a sequencer to send multiple batches | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`batches` | struct PolygonValidiumEtrog.ValidiumBatchData[] | Struct array which holds the necessary data to append new batches to the sequence -|`l1InfoTreeLeafCount` | uint32 | leaf count of the L1InfoRoot that will be used in this sequence +|`l1InfoTreeLeafCount` | uint32 | Count of the L1InfoTree leaf that will be used in this sequence |`maxSequenceTimestamp` | uint64 | Max timestamp of the sequence. This timestamp must be inside a safety range (actual + 36 seconds). This timestamp should be equal or higher of the last block inside the sequence, otherwise this batch will be invalidated by circuit. |`expectedFinalAccInputHash` | bytes32 | This parameter must match the acc input hash after hash all the batch data @@ -73,7 +73,7 @@ Allows a sequencer to send multiple batches | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`batches` | struct PolygonRollupBaseEtrog.BatchData[] | Struct array which holds the necessary data to append new batches to the sequence -|`l1InfoTreeLeafCount` | uint32 | Index of the L1InfoRoot that will be used in this sequence +|`l1InfoTreeLeafCount` | uint32 | Count of the L1InfoTree leaf that will be used in this sequence |`maxSequenceTimestamp` | uint64 | Max timestamp of the sequence. This timestamp must be inside a safety range (actual + 36 seconds). This timestamp should be equal or higher of the last block inside the sequence, otherwise this batch will be invalidated by circuit. |`expectedFinalAccInputHash` | bytes32 | This parameter must match the acc input hash after hash all the batch data diff --git a/docs/v2/consensus/validium/migration/PolygonRollupBaseEtrogNoGap.md b/docs/v2/consensus/validium/migration/PolygonRollupBaseEtrogNoGap.md deleted file mode 100644 index 9d1dcba8e..000000000 --- a/docs/v2/consensus/validium/migration/PolygonRollupBaseEtrogNoGap.md +++ /dev/null @@ -1,327 +0,0 @@ -Contract responsible for managing the states and the updates of L2 network. -There will be a trusted sequencer, which is able to send transactions. -Any user can force some transaction and the sequencer will have a timeout to add them in the queue. -The sequenced state is deterministic and can be precalculated before it's actually verified by a zkProof. -The aggregators will be able to verify the sequenced state with zkProofs and therefore make available the withdrawals from L2 network. -To enter and exit of the L2 network will be used a PolygonZkEVMBridge smart contract that will be deployed in both networks. - - -## Functions -### constructor -```solidity - function constructor( - contract IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, - contract IERC20Upgradeable _pol, - contract IPolygonZkEVMBridgeV2 _bridgeAddress, - contract PolygonRollupManager _rollupManager - ) internal -``` - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`_globalExitRootManager` | contract IPolygonZkEVMGlobalExitRootV2 | Global exit root manager address -|`_pol` | contract IERC20Upgradeable | POL token address -|`_bridgeAddress` | contract IPolygonZkEVMBridgeV2 | Bridge address -|`_rollupManager` | contract PolygonRollupManager | Global exit root manager address - -### initialize -```solidity - function initialize( - address _admin, - address sequencer, - uint32 networkID, - address _gasTokenAddress, - string sequencerURL, - string _networkName - ) external -``` - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`_admin` | address | Admin address -|`sequencer` | address | Trusted sequencer address -|`networkID` | uint32 | Indicates the network identifier that will be used in the bridge -|`_gasTokenAddress` | address | Indicates the token address in mainnet that will be used as a gas token -Note if a wrapped token of the bridge is used, the original network and address of this wrapped are used instead -|`sequencerURL` | string | Trusted sequencer URL -|`_networkName` | string | L2 network name - -### sequenceBatches -```solidity - function sequenceBatches( - struct PolygonRollupBaseEtrogNoGap.BatchData[] batches, - uint64 maxSequenceTimestamp, - uint64 initSequencedBatch, - address l2Coinbase - ) public -``` -Allows a sequencer to send multiple batches - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`batches` | struct PolygonRollupBaseEtrogNoGap.BatchData[] | Struct array which holds the necessary data to append new batches to the sequence -|`maxSequenceTimestamp` | uint64 | Max timestamp of the sequence. This timestamp must be inside a safety range (actual + 36 seconds). -This timestamp should be equal or higher of the last block inside the sequence, otherwise this batch will be invalidated by circuit. -|`initSequencedBatch` | uint64 | This parameter must match the current last batch sequenced. -This will be a protection for the sequencer to avoid sending undesired data -|`l2Coinbase` | address | Address that will receive the fees from L2 -note Pol is not a reentrant token - -### onVerifyBatches -```solidity - function onVerifyBatches( - uint64 lastVerifiedBatch, - bytes32 newStateRoot, - address aggregator - ) public -``` -Callback on verify batches, can only be called by the rollup manager - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`lastVerifiedBatch` | uint64 | Last verified batch -|`newStateRoot` | bytes32 | new state root -|`aggregator` | address | Aggregator address - -### forceBatch -```solidity - function forceBatch( - bytes transactions, - uint256 polAmount - ) public -``` -Allows a sequencer/user to force a batch of L2 transactions. -This should be used only in extreme cases where the trusted sequencer does not work as expected -Note The sequencer has certain degree of control on how non-forced and forced batches are ordered -In order to assure that users force transactions will be processed properly, user must not sign any other transaction -with the same nonce - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`transactions` | bytes | L2 ethereum transactions EIP-155 or pre-EIP-155 with signature: -|`polAmount` | uint256 | Max amount of pol tokens that the sender is willing to pay - -### sequenceForceBatches -```solidity - function sequenceForceBatches( - struct PolygonRollupBaseEtrogNoGap.BatchData[] batches - ) external -``` -Allows anyone to sequence forced Batches if the trusted sequencer has not done so in the timeout period - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`batches` | struct PolygonRollupBaseEtrogNoGap.BatchData[] | Struct array which holds the necessary data to append force batches - -### setTrustedSequencer -```solidity - function setTrustedSequencer( - address newTrustedSequencer - ) external -``` -Allow the admin to set a new trusted sequencer - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newTrustedSequencer` | address | Address of the new trusted sequencer - -### setTrustedSequencerURL -```solidity - function setTrustedSequencerURL( - string newTrustedSequencerURL - ) external -``` -Allow the admin to set the trusted sequencer URL - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newTrustedSequencerURL` | string | URL of trusted sequencer - -### setForceBatchAddress -```solidity - function setForceBatchAddress( - address newForceBatchAddress - ) external -``` -Allow the admin to change the force batch address, that will be allowed to force batches -If address 0 is set, then everyone is able to force batches, this action is irreversible - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newForceBatchAddress` | address | New force batch address - -### setForceBatchTimeout -```solidity - function setForceBatchTimeout( - uint64 newforceBatchTimeout - ) external -``` -Allow the admin to set the forcedBatchTimeout -The new value can only be lower, except if emergency state is active - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newforceBatchTimeout` | uint64 | New force batch timeout - -### transferAdminRole -```solidity - function transferAdminRole( - address newPendingAdmin - ) external -``` -Starts the admin role transfer -This is a two step process, the pending admin must accepted to finalize the process - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newPendingAdmin` | address | Address of the new pending admin - -### acceptAdminRole -```solidity - function acceptAdminRole( - ) external -``` -Allow the current pending admin to accept the admin role - - - -### calculatePolPerForceBatch -```solidity - function calculatePolPerForceBatch( - ) public returns (uint256) -``` -Function to calculate the reward for a forced batch - - - -### generateInitializeTransaction -```solidity - function generateInitializeTransaction( - uint32 networkID, - address _gasTokenAddress, - uint32 _gasTokenNetwork, - bytes _gasTokenMetadata - ) public returns (bytes) -``` -Generate Initialize transaction for hte bridge on L2 - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`networkID` | uint32 | Indicates the network identifier that will be used in the bridge -|`_gasTokenAddress` | address | Indicates the token address that will be used to pay gas fees in the new rollup -|`_gasTokenNetwork` | uint32 | Indicates the native network of the token address -|`_gasTokenMetadata` | bytes | Abi encoded gas token metadata - -## Events -### SequenceBatches -```solidity - event SequenceBatches( - ) -``` - -Emitted when the trusted sequencer sends a new batch of transactions - -### ForceBatch -```solidity - event ForceBatch( - ) -``` - -Emitted when a batch is forced - -### SequenceForceBatches -```solidity - event SequenceForceBatches( - ) -``` - -Emitted when forced batches are sequenced by not the trusted sequencer - -### InitialSequenceBatches -```solidity - event InitialSequenceBatches( - ) -``` - -Emitted when the contract is initialized, contain the first sequenced transaction - -### VerifyBatches -```solidity - event VerifyBatches( - ) -``` - -Emitted when a aggregator verifies batches - -### SetTrustedSequencer -```solidity - event SetTrustedSequencer( - ) -``` - -Emitted when the admin updates the trusted sequencer address - -### SetTrustedSequencerURL -```solidity - event SetTrustedSequencerURL( - ) -``` - -Emitted when the admin updates the sequencer URL - -### SetForceBatchTimeout -```solidity - event SetForceBatchTimeout( - ) -``` - -Emitted when the admin update the force batch timeout - -### SetForceBatchAddress -```solidity - event SetForceBatchAddress( - ) -``` - -Emitted when the admin update the force batch address - -### TransferAdminRole -```solidity - event TransferAdminRole( - ) -``` - -Emitted when the admin starts the two-step transfer role setting a new pending admin - -### AcceptAdminRole -```solidity - event AcceptAdminRole( - ) -``` - -Emitted when the pending admin accepts the admin role - diff --git a/docs/v2/consensus/validium/migration/PolygonValidiumStorageMigration.md b/docs/v2/consensus/validium/migration/PolygonValidiumStorageMigration.md deleted file mode 100644 index 7a45c586d..000000000 --- a/docs/v2/consensus/validium/migration/PolygonValidiumStorageMigration.md +++ /dev/null @@ -1,133 +0,0 @@ -Contract responsible for managing the states and the updates of L2 network. -There will be a trusted sequencer, which is able to send transactions. -Any user can force some transaction and the sequencer will have a timeout to add them in the queue. -The sequenced state is deterministic and can be precalculated before it's actually verified by a zkProof. -The aggregators will be able to verify the sequenced state with zkProofs and therefore make available the withdrawals from L2 network. -To enter and exit of the L2 network will be used a PolygonZkEVMBridge smart contract that will be deployed in both networks. -It is advised to use timelocks for the admin address in case of Validium since if can change the dataAvailabilityProtocol - - -## Functions -### constructor -```solidity - function constructor( - contract IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, - contract IERC20Upgradeable _pol, - contract IPolygonZkEVMBridgeV2 _bridgeAddress, - contract PolygonRollupManager _rollupManager - ) public -``` - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`_globalExitRootManager` | contract IPolygonZkEVMGlobalExitRootV2 | Global exit root manager address -|`_pol` | contract IERC20Upgradeable | POL token address -|`_bridgeAddress` | contract IPolygonZkEVMBridgeV2 | Bridge address -|`_rollupManager` | contract PolygonRollupManager | Global exit root manager address - -### initializeMigration -```solidity - function initializeMigration( - ) external -``` - - - - -### sequenceBatchesValidium -```solidity - function sequenceBatchesValidium( - struct PolygonValidiumStorageMigration.ValidiumBatchData[] batches, - uint64 maxSequenceTimestamp, - uint64 initSequencedBatch, - address l2Coinbase, - bytes dataAvailabilityMessage - ) external -``` -Allows a sequencer to send multiple batches - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`batches` | struct PolygonValidiumStorageMigration.ValidiumBatchData[] | Struct array which holds the necessary data to append new batches to the sequence -|`maxSequenceTimestamp` | uint64 | Max timestamp of the sequence. This timestamp must be inside a safety range (actual + 36 seconds). -This timestamp should be equal or higher of the last block inside the sequence, otherwise this batch will be invalidated by circuit. -|`initSequencedBatch` | uint64 | This parameter must match the current last batch sequenced. -This will be a protection for the sequencer to avoid sending undesired data -|`l2Coinbase` | address | Address that will receive the fees from L2 -|`dataAvailabilityMessage` | bytes | Byte array containing the signatures and all the addresses of the committee in ascending order -[signature 0, ..., signature requiredAmountOfSignatures -1, address 0, ... address N] -note that each ECDSA signatures are used, therefore each one must be 65 bytes -note Pol is not a reentrant token - -### sequenceBatches -```solidity - function sequenceBatches( - struct PolygonRollupBaseEtrogNoGap.BatchData[] batches, - uint64 maxSequenceTimestamp, - uint64 initSequencedBatch, - address l2Coinbase - ) public -``` -Allows a sequencer to send multiple batches - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`batches` | struct PolygonRollupBaseEtrogNoGap.BatchData[] | Struct array which holds the necessary data to append new batches to the sequence -|`maxSequenceTimestamp` | uint64 | Max timestamp of the sequence. This timestamp must be inside a safety range (actual + 36 seconds). -This timestamp should be equal or higher of the last block inside the sequence, otherwise this batch will be invalidated by circuit. -|`initSequencedBatch` | uint64 | This parameter must match the current last batch sequenced. -This will be a protection for the sequencer to avoid sending undesired data -|`l2Coinbase` | address | Address that will receive the fees from L2 -note Pol is not a reentrant token - -### setDataAvailabilityProtocol -```solidity - function setDataAvailabilityProtocol( - contract IDataAvailabilityProtocol newDataAvailabilityProtocol - ) external -``` -Allow the admin to set a new data availability protocol - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newDataAvailabilityProtocol` | contract IDataAvailabilityProtocol | Address of the new data availability protocol - -### switchSequenceWithDataAvailability -```solidity - function switchSequenceWithDataAvailability( - bool newIsSequenceWithDataAvailabilityAllowed - ) external -``` -Allow the admin to switch the sequence with data availability - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newIsSequenceWithDataAvailabilityAllowed` | bool | Boolean to switch - -## Events -### SetDataAvailabilityProtocol -```solidity - event SetDataAvailabilityProtocol( - ) -``` - -Emitted when the admin updates the data availability protocol - -### SwitchSequenceWithDataAvailability -```solidity - event SwitchSequenceWithDataAvailability( - ) -``` - -Emitted when switch the ability to sequence with data availability - diff --git a/docs/v2/consensus/zkEVM/PolygonZkEVMV2.md b/docs/v2/consensus/zkEVM/PolygonZkEVMV2.md deleted file mode 100644 index 05626cf12..000000000 --- a/docs/v2/consensus/zkEVM/PolygonZkEVMV2.md +++ /dev/null @@ -1,28 +0,0 @@ -Contract responsible for managing the states and the updates of L2 network. -There will be a trusted sequencer, which is able to send transactions. -Any user can force some transaction and the sequencer will have a timeout to add them in the queue. -The sequenced state is deterministic and can be precalculated before it's actually verified by a zkProof. -The aggregators will be able to verify the sequenced state with zkProofs and therefore make available the withdrawals from L2 network. -To enter and exit of the L2 network will be used a PolygonZkEVMBridge smart contract that will be deployed in both networks. - - -## Functions -### constructor -```solidity - function constructor( - contract IPolygonZkEVMGlobalExitRoot _globalExitRootManager, - contract IERC20Upgradeable _pol, - contract IPolygonZkEVMBridge _bridgeAddress, - contract PolygonRollupManager _rollupManager - ) public -``` - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`_globalExitRootManager` | contract IPolygonZkEVMGlobalExitRoot | Global exit root manager address -|`_pol` | contract IERC20Upgradeable | POL token address -|`_bridgeAddress` | contract IPolygonZkEVMBridge | Bridge address -|`_rollupManager` | contract PolygonRollupManager | Global exit root manager address - diff --git a/docs/v2/consensus/zkEVM/PolygonZkEVMV2Existent.md b/docs/v2/consensus/zkEVM/PolygonZkEVMV2Existent.md deleted file mode 100644 index eb04f3948..000000000 --- a/docs/v2/consensus/zkEVM/PolygonZkEVMV2Existent.md +++ /dev/null @@ -1,53 +0,0 @@ -Contract responsible for managing the states and the updates of L2 network. -There will be a trusted sequencer, which is able to send transactions. -Any user can force some transaction and the sequencer will have a timeout to add them in the queue. -The sequenced state is deterministic and can be precalculated before it's actually verified by a zkProof. -The aggregators will be able to verify the sequenced state with zkProofs and therefore make available the withdrawals from L2 network. -To enter and exit of the L2 network will be used a PolygonZkEVMBridge smart contract that will be deployed in both networks. - - -## Functions -### constructor -```solidity - function constructor( - contract IPolygonZkEVMGlobalExitRoot _globalExitRootManager, - contract IERC20Upgradeable _pol, - contract IPolygonZkEVMBridge _bridgeAddress, - contract PolygonRollupManager _rollupManager - ) public -``` - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`_globalExitRootManager` | contract IPolygonZkEVMGlobalExitRoot | Global exit root manager address -|`_pol` | contract IERC20Upgradeable | POL token address -|`_bridgeAddress` | contract IPolygonZkEVMBridge | Bridge address -|`_rollupManager` | contract PolygonRollupManager | Global exit root manager address - -### initializeUpgrade -```solidity - function initializeUpgrade( - address _admin, - address _trustedSequencer, - string _trustedSequencerURL, - string _networkName, - bytes32 _lastAccInputHash, - uint64 _lastTimestamp - ) external -``` -note This initializer will be called instead of the PolygonRollupBase -This is a especial initializer since the zkEVM it's an already created network - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`_admin` | address | Admin address -|`_trustedSequencer` | address | Trusted sequencer address -|`_trustedSequencerURL` | string | Trusted sequencer URL -|`_networkName` | string | L2 network name -|`_lastAccInputHash` | bytes32 | Acc input hash -|`_lastTimestamp` | uint64 | Timestamp - diff --git a/docs/v2/interfaces/IBridgeL2SovereignChains.md b/docs/v2/interfaces/IBridgeL2SovereignChains.md new file mode 100644 index 000000000..884a286e2 --- /dev/null +++ b/docs/v2/interfaces/IBridgeL2SovereignChains.md @@ -0,0 +1,13 @@ + + + +## Functions +### initialize +```solidity + function initialize( + ) external +``` + + + + diff --git a/docs/v2/interfaces/ICDKDataCommittee.md b/docs/v2/interfaces/ICDKDataCommittee.md deleted file mode 100644 index 13b0d302b..000000000 --- a/docs/v2/interfaces/ICDKDataCommittee.md +++ /dev/null @@ -1,13 +0,0 @@ - - - -## Functions -### verifySignatures -```solidity - function verifySignatures( - ) external -``` - - - - diff --git a/docs/v2/interfaces/IPolygonConsensusBase.md b/docs/v2/interfaces/IPolygonConsensusBase.md new file mode 100644 index 000000000..a20ee8247 --- /dev/null +++ b/docs/v2/interfaces/IPolygonConsensusBase.md @@ -0,0 +1,22 @@ + + + +## Functions +### initialize +```solidity + function initialize( + ) external +``` + + + + +### admin +```solidity + function admin( + ) external returns (address) +``` + + + + diff --git a/docs/v2/interfaces/IPolygonPessimisticConsensus.md b/docs/v2/interfaces/IPolygonPessimisticConsensus.md new file mode 100644 index 000000000..8f208b00a --- /dev/null +++ b/docs/v2/interfaces/IPolygonPessimisticConsensus.md @@ -0,0 +1,13 @@ + + + +## Functions +### getConsensusHash +```solidity + function getConsensusHash( + ) external returns (bytes32) +``` + + + + diff --git a/docs/v2/interfaces/IPolygonRollupBase.md b/docs/v2/interfaces/IPolygonRollupBase.md index 9127d4dd3..07ef4640d 100644 --- a/docs/v2/interfaces/IPolygonRollupBase.md +++ b/docs/v2/interfaces/IPolygonRollupBase.md @@ -2,15 +2,6 @@ ## Functions -### initialize -```solidity - function initialize( - ) external -``` - - - - ### onVerifyBatches ```solidity function onVerifyBatches( @@ -20,15 +11,6 @@ -### admin -```solidity - function admin( - ) external returns (address) -``` - - - - ### rollbackBatches ```solidity function rollbackBatches( diff --git a/docs/v2/interfaces/IPolygonRollupManager.md b/docs/v2/interfaces/IPolygonRollupManager.md index b28b04f64..6f3d63fc8 100644 --- a/docs/v2/interfaces/IPolygonRollupManager.md +++ b/docs/v2/interfaces/IPolygonRollupManager.md @@ -1,3 +1,202 @@ +## Functions +### addNewRollupType +```solidity + function addNewRollupType( + ) external +``` + + + + +### obsoleteRollupType +```solidity + function obsoleteRollupType( + ) external +``` + + + + +### createNewRollup +```solidity + function createNewRollup( + ) external +``` + + + + +### addExistingRollup +```solidity + function addExistingRollup( + ) external +``` + + + + +### updateRollupByRollupAdmin +```solidity + function updateRollupByRollupAdmin( + ) external +``` + + + + +### updateRollup +```solidity + function updateRollup( + ) external +``` + + + + +### rollbackBatches +```solidity + function rollbackBatches( + ) external +``` + + + + +### onSequenceBatches +```solidity + function onSequenceBatches( + ) external returns (uint64) +``` + + + + +### verifyBatchesTrustedAggregator +```solidity + function verifyBatchesTrustedAggregator( + ) external +``` + + + + +### verifyPessimisticTrustedAggregator +```solidity + function verifyPessimisticTrustedAggregator( + ) external +``` + + + + +### activateEmergencyState +```solidity + function activateEmergencyState( + ) external +``` + + + + +### deactivateEmergencyState +```solidity + function deactivateEmergencyState( + ) external +``` + + + + +### setBatchFee +```solidity + function setBatchFee( + ) external +``` + + + + +### getRollupExitRoot +```solidity + function getRollupExitRoot( + ) external returns (bytes32) +``` + + + + +### getLastVerifiedBatch +```solidity + function getLastVerifiedBatch( + ) external returns (uint64) +``` + + + + +### calculateRewardPerBatch +```solidity + function calculateRewardPerBatch( + ) external returns (uint256) +``` + + + + +### getBatchFee +```solidity + function getBatchFee( + ) external returns (uint256) +``` + + + + +### getForcedBatchFee +```solidity + function getForcedBatchFee( + ) external returns (uint256) +``` + + + + +### getInputPessimisticBytes +```solidity + function getInputPessimisticBytes( + ) external returns (bytes) +``` + + + + +### getInputSnarkBytes +```solidity + function getInputSnarkBytes( + ) external returns (bytes) +``` + + + + +### getRollupBatchNumToStateRoot +```solidity + function getRollupBatchNumToStateRoot( + ) external returns (bytes32) +``` + + + + +### lastDeactivatedEmergencyStateTimestamp +```solidity + function lastDeactivatedEmergencyStateTimestamp( + ) external returns (uint64) +``` + + + + diff --git a/docs/v2/interfaces/IPolygonZkEVMBaseBridge.md b/docs/v2/interfaces/IPolygonZkEVMBaseBridge.md deleted file mode 100644 index 64dcd6b89..000000000 --- a/docs/v2/interfaces/IPolygonZkEVMBaseBridge.md +++ /dev/null @@ -1,49 +0,0 @@ - - - -## Functions -### bridgeAsset -```solidity - function bridgeAsset( - ) external -``` - - - - -### bridgeMessage -```solidity - function bridgeMessage( - ) external -``` - - - - -### claimAsset -```solidity - function claimAsset( - ) external -``` - - - - -### claimMessage -```solidity - function claimMessage( - ) external -``` - - - - -### updateGlobalExitRoot -```solidity - function updateGlobalExitRoot( - ) external -``` - - - - diff --git a/docs/v2/interfaces/ICDKDataCommitteeErrors.md b/docs/v2/interfaces/IPolygonZkEVMEtrogErrors.md similarity index 100% rename from docs/v2/interfaces/ICDKDataCommitteeErrors.md rename to docs/v2/interfaces/IPolygonZkEVMEtrogErrors.md diff --git a/docs/v2/interfaces/IPolygonZkEVMV2Errors.md b/docs/v2/interfaces/IPolygonZkEVMV2Errors.md deleted file mode 100644 index b28b04f64..000000000 --- a/docs/v2/interfaces/IPolygonZkEVMV2Errors.md +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/docs/v2/interfaces/IPolygonZkEVMVEtrogErrors.md b/docs/v2/interfaces/IPolygonZkEVMVEtrogErrors.md deleted file mode 100644 index b28b04f64..000000000 --- a/docs/v2/interfaces/IPolygonZkEVMVEtrogErrors.md +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/docs/v2/interfaces/ISP1Verifier.md b/docs/v2/interfaces/ISP1Verifier.md new file mode 100644 index 000000000..b1ce147d4 --- /dev/null +++ b/docs/v2/interfaces/ISP1Verifier.md @@ -0,0 +1,24 @@ +This contract is the interface for the SP1 Verifier. + + +## Functions +### verifyProof +```solidity + function verifyProof( + bytes32 programVKey, + bytes publicValues, + bytes proofBytes + ) external +``` +Verifies a proof with given public values and vkey. + +It is expected that the first 4 bytes of proofBytes must match the first 4 bytes of +target verifier's VERIFIER_HASH. + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`programVKey` | bytes32 | The verification key for the RISC-V program. +|`publicValues` | bytes | The public values encoded as bytes. +|`proofBytes` | bytes | The proof of the program execution the SP1 zkVM encoded as bytes. + diff --git a/docs/v2/interfaces/ISP1VerifierWithHash.md b/docs/v2/interfaces/ISP1VerifierWithHash.md new file mode 100644 index 000000000..cfc841639 --- /dev/null +++ b/docs/v2/interfaces/ISP1VerifierWithHash.md @@ -0,0 +1,13 @@ + + + +## Functions +### VERIFIER_HASH +```solidity + function VERIFIER_HASH( + ) external returns (bytes32) +``` +Returns the hash of the verifier. + + + diff --git a/docs/v2/lib/DepositContractLib.md b/docs/v2/lib/DepositContractLib.md deleted file mode 100644 index 36b40f1e9..000000000 --- a/docs/v2/lib/DepositContractLib.md +++ /dev/null @@ -1,48 +0,0 @@ -This contract will be used as a helper for all the sparse merkle tree related functions -Based on the implementation of the deposit eth2.0 contract https://github.com/ethereum/consensus-specs/blob/dev/solidity_deposit_contract/deposit_contract.sol - - -## Functions -### getRoot -```solidity - function getRoot( - ) public returns (bytes32) -``` -Computes and returns the merkle root - - - -### _addLeaf -```solidity - function _addLeaf( - bytes32 leaf - ) internal -``` -Add a new leaf to the merkle tree - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`leaf` | bytes32 | Leaf - -### verifyMerkleProof -```solidity - function verifyMerkleProof( - bytes32 leaf, - bytes32[32] smtProof, - uint32 index, - bytes32 root - ) public returns (bool) -``` -Verify merkle proof - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`leaf` | bytes32 | Leaf -|`smtProof` | bytes32[32] | Smt proof -|`index` | uint32 | Index of the leaf -|`root` | bytes32 | Merkle root - diff --git a/docs/v2/lib/DepositContractV2.md b/docs/v2/lib/DepositContractV2.md index 1357d1199..b1df37529 100644 --- a/docs/v2/lib/DepositContractV2.md +++ b/docs/v2/lib/DepositContractV2.md @@ -23,7 +23,7 @@ Given the leaf data returns the leaf value | :--- | :--- | :------------------------------------------------------------------- | |`leafType` | uint8 | Leaf type --> [0] transfer Ether / ERC20 tokens, [1] message |`originNetwork` | uint32 | Origin Network -|`originAddress` | address | [0] Origin token address, 0 address is reserved for ether, [1] msg.sender of the message +|`originAddress` | address | [0] Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token, [1] msg.sender of the message |`destinationNetwork` | uint32 | Destination network |`destinationAddress` | address | Destination address |`amount` | uint256 | [0] Amount of tokens/ether, [1] Amount of ether diff --git a/docs/v2/lib/PolygonConsensusBase.md b/docs/v2/lib/PolygonConsensusBase.md new file mode 100644 index 000000000..e81bec15d --- /dev/null +++ b/docs/v2/lib/PolygonConsensusBase.md @@ -0,0 +1,135 @@ +Contract responsible for managing the states and the updates of L2 network. +There will be a trusted sequencer, which is able to send transactions. +Any user can force some transaction and the sequencer will have a timeout to add them in the queue. +The sequenced state is deterministic and can be precalculated before it's actually verified by a zkProof. +The aggregators will be able to verify the sequenced state with zkProofs and therefore make available the withdrawals from L2 network. +To enter and exit of the L2 network will be used a PolygonZkEVMBridge smart contract that will be deployed in both networks. + + +## Functions +### constructor +```solidity + function constructor( + contract IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, + contract IERC20Upgradeable _pol, + contract IPolygonZkEVMBridgeV2 _bridgeAddress, + contract PolygonRollupManager _rollupManager + ) internal +``` + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`_globalExitRootManager` | contract IPolygonZkEVMGlobalExitRootV2 | Global exit root manager address +|`_pol` | contract IERC20Upgradeable | POL token address +|`_bridgeAddress` | contract IPolygonZkEVMBridgeV2 | Bridge address +|`_rollupManager` | contract PolygonRollupManager | Global exit root manager address + +### initialize +```solidity + function initialize( + address _admin, + address sequencer, + uint32 _gasTokenAddress, + address sequencerURL, + string _networkName + ) external +``` + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`_admin` | address | Admin address +|`sequencer` | address | Trusted sequencer address +|`_gasTokenAddress` | uint32 | Indicates the token address in mainnet that will be used as a gas token +Note if a wrapped token of the bridge is used, the original network and address of this wrapped are used instead +|`sequencerURL` | address | Trusted sequencer URL +|`_networkName` | string | L2 network name + +### setTrustedSequencer +```solidity + function setTrustedSequencer( + address newTrustedSequencer + ) external +``` +Allow the admin to set a new trusted sequencer + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`newTrustedSequencer` | address | Address of the new trusted sequencer + +### setTrustedSequencerURL +```solidity + function setTrustedSequencerURL( + string newTrustedSequencerURL + ) external +``` +Allow the admin to set the trusted sequencer URL + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`newTrustedSequencerURL` | string | URL of trusted sequencer + +### transferAdminRole +```solidity + function transferAdminRole( + address newPendingAdmin + ) external +``` +Starts the admin role transfer +This is a two step process, the pending admin must accepted to finalize the process + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`newPendingAdmin` | address | Address of the new pending admin + +### acceptAdminRole +```solidity + function acceptAdminRole( + ) external +``` +Allow the current pending admin to accept the admin role + + + +## Events +### SetTrustedSequencer +```solidity + event SetTrustedSequencer( + ) +``` + +Emitted when the admin updates the trusted sequencer address + +### SetTrustedSequencerURL +```solidity + event SetTrustedSequencerURL( + ) +``` + +Emitted when the admin updates the sequencer URL + +### TransferAdminRole +```solidity + event TransferAdminRole( + ) +``` + +Emitted when the admin starts the two-step transfer role setting a new pending admin + +### AcceptAdminRole +```solidity + event AcceptAdminRole( + ) +``` + +Emitted when the pending admin accepts the admin role + diff --git a/docs/v2/lib/PolygonRollupBase.md b/docs/v2/lib/PolygonRollupBase.md deleted file mode 100644 index 49cb6dd34..000000000 --- a/docs/v2/lib/PolygonRollupBase.md +++ /dev/null @@ -1,306 +0,0 @@ -Contract responsible for managing the states and the updates of L2 network. -There will be a trusted sequencer, which is able to send transactions. -Any user can force some transaction and the sequencer will have a timeout to add them in the queue. -The sequenced state is deterministic and can be precalculated before it's actually verified by a zkProof. -The aggregators will be able to verify the sequenced state with zkProofs and therefore make available the withdrawals from L2 network. -To enter and exit of the L2 network will be used a PolygonZkEVMBridge smart contract that will be deployed in both networks. - - -## Functions -### constructor -```solidity - function constructor( - contract IPolygonZkEVMGlobalExitRoot _globalExitRootManager, - contract IERC20Upgradeable _pol, - contract IPolygonZkEVMBridge _bridgeAddress, - contract PolygonRollupManager _rollupManager - ) public -``` - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`_globalExitRootManager` | contract IPolygonZkEVMGlobalExitRoot | Global exit root manager address -|`_pol` | contract IERC20Upgradeable | POL token address -|`_bridgeAddress` | contract IPolygonZkEVMBridge | Bridge address -|`_rollupManager` | contract PolygonRollupManager | Global exit root manager address - -### initialize -```solidity - function initialize( - address _admin, - address sequencer, - uint32 networkID, - address _gasTokenAddress, - uint32 _gasTokenNetwork, - string sequencerURL, - string _networkName - ) external -``` - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`_admin` | address | Admin address -|`sequencer` | address | Trusted sequencer address -|`networkID` | uint32 | Indicates the network identifier that will be used in the bridge -|`_gasTokenAddress` | address | Indicates the token address that will be used to pay gas fees in the new rollup -|`_gasTokenNetwork` | uint32 | Indicates the native network of the token address -|`sequencerURL` | string | Trusted sequencer URL -|`_networkName` | string | L2 network name - -### sequenceBatches -```solidity - function sequenceBatches( - struct PolygonRollupBase.BatchData[] batches, - address l2Coinbase - ) public -``` -Allows a sequencer to send multiple batches - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`batches` | struct PolygonRollupBase.BatchData[] | Struct array which holds the necessary data to append new batches to the sequence -|`l2Coinbase` | address | Address that will receive the fees from L2 - -### onVerifyBatches -```solidity - function onVerifyBatches( - uint64 lastVerifiedBatch, - bytes32 newStateRoot, - address aggregator - ) public -``` -Callback on verify batches, can only be called by the rollup manager - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`lastVerifiedBatch` | uint64 | Last verified batch -|`newStateRoot` | bytes32 | new state root -|`aggregator` | address | Aggregator address - -### forceBatch -```solidity - function forceBatch( - bytes transactions, - uint256 polAmount - ) public -``` -Allows a sequencer/user to force a batch of L2 transactions. -This should be used only in extreme cases where the trusted sequencer does not work as expected -Note The sequencer has certain degree of control on how non-forced and forced batches are ordered -In order to assure that users force transactions will be processed properly, user must not sign any other transaction -with the same nonce - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`transactions` | bytes | L2 ethereum transactions EIP-155 or pre-EIP-155 with signature: -|`polAmount` | uint256 | Max amount of pol tokens that the sender is willing to pay - -### sequenceForceBatches -```solidity - function sequenceForceBatches( - struct PolygonRollupBase.ForcedBatchData[] batches - ) external -``` -Allows anyone to sequence forced Batches if the trusted sequencer has not done so in the timeout period - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`batches` | struct PolygonRollupBase.ForcedBatchData[] | Struct array which holds the necessary data to append force batches - -### setTrustedSequencer -```solidity - function setTrustedSequencer( - address newTrustedSequencer - ) external -``` -Allow the admin to set a new trusted sequencer - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newTrustedSequencer` | address | Address of the new trusted sequencer - -### setTrustedSequencerURL -```solidity - function setTrustedSequencerURL( - string newTrustedSequencerURL - ) external -``` -Allow the admin to set the trusted sequencer URL - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newTrustedSequencerURL` | string | URL of trusted sequencer - -### setForceBatchTimeout -```solidity - function setForceBatchTimeout( - uint64 newforceBatchTimeout - ) external -``` -Allow the admin to set the forcedBatchTimeout -The new value can only be lower, except if emergency state is active - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newforceBatchTimeout` | uint64 | New force batch timeout - -### activateForceBatches -```solidity - function activateForceBatches( - ) external -``` -Allow the admin to turn on the force batches -This action is not reversible - - - -### transferAdminRole -```solidity - function transferAdminRole( - address newPendingAdmin - ) external -``` -Starts the admin role transfer -This is a two step process, the pending admin must accepted to finalize the process - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newPendingAdmin` | address | Address of the new pending admin - -### acceptAdminRole -```solidity - function acceptAdminRole( - ) external -``` -Allow the current pending admin to accept the admin role - - - -### calculatePolPerForceBatch -```solidity - function calculatePolPerForceBatch( - ) public returns (uint256) -``` -Function to calculate the reward for a forced batch - - - -### generateInitializeTransaction -```solidity - function generateInitializeTransaction( - uint32 networkID, - address _gasTokenAddress, - uint32 _gasTokenNetwork - ) public returns (bytes) -``` -Generate Initialize transaction for hte bridge on L2 - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`networkID` | uint32 | Indicates the network identifier that will be used in the bridge -|`_gasTokenAddress` | address | Indicates the token address that will be used to pay gas fees in the new rollup -|`_gasTokenNetwork` | uint32 | Indicates the native network of the token address - -## Events -### SequenceBatches -```solidity - event SequenceBatches( - ) -``` - -Emitted when the trusted sequencer sends a new batch of transactions - -### ForceBatch -```solidity - event ForceBatch( - ) -``` - -Emitted when a batch is forced - -### SequenceForceBatches -```solidity - event SequenceForceBatches( - ) -``` - -Emitted when forced batches are sequenced by not the trusted sequencer - -### VerifyBatches -```solidity - event VerifyBatches( - ) -``` - -Emitted when a aggregator verifies batches - -### SetTrustedSequencer -```solidity - event SetTrustedSequencer( - ) -``` - -Emitted when the admin updates the trusted sequencer address - -### SetTrustedSequencerURL -```solidity - event SetTrustedSequencerURL( - ) -``` - -Emitted when the admin updates the sequencer URL - -### SetForceBatchTimeout -```solidity - event SetForceBatchTimeout( - ) -``` - -Emitted when the admin update the force batch timeout - -### ActivateForceBatches -```solidity - event ActivateForceBatches( - ) -``` - -Emitted when activate force batches - -### TransferAdminRole -```solidity - event TransferAdminRole( - ) -``` - -Emitted when the admin starts the two-step transfer role setting a new pending admin - -### AcceptAdminRole -```solidity - event AcceptAdminRole( - ) -``` - -Emitted when the pending admin accepts the admin role - diff --git a/docs/v2/lib/PolygonRollupBaseEtrog.md b/docs/v2/lib/PolygonRollupBaseEtrog.md index cd39418ce..d244e936c 100644 --- a/docs/v2/lib/PolygonRollupBaseEtrog.md +++ b/docs/v2/lib/PolygonRollupBaseEtrog.md @@ -67,7 +67,7 @@ Allows a sequencer to send multiple batches | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`batches` | struct PolygonRollupBaseEtrog.BatchData[] | Struct array which holds the necessary data to append new batches to the sequence -|`l1InfoTreeLeafCount` | uint32 | Index of the L1InfoRoot that will be used in this sequence +|`l1InfoTreeLeafCount` | uint32 | Count of the L1InfoTree leaf that will be used in this sequence |`maxSequenceTimestamp` | uint64 | Max timestamp of the sequence. This timestamp must be inside a safety range (actual + 36 seconds). This timestamp should be equal or higher of the last block inside the sequence, otherwise this batch will be invalidated by circuit. |`expectedFinalAccInputHash` | bytes32 | This parameter must match the acc input hash after hash all the batch data @@ -143,34 +143,6 @@ Allows anyone to sequence forced Batches if the trusted sequencer has not done s | :--- | :--- | :------------------------------------------------------------------- | |`batches` | struct PolygonRollupBaseEtrog.BatchData[] | Struct array which holds the necessary data to append force batches -### setTrustedSequencer -```solidity - function setTrustedSequencer( - address newTrustedSequencer - ) external -``` -Allow the admin to set a new trusted sequencer - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newTrustedSequencer` | address | Address of the new trusted sequencer - -### setTrustedSequencerURL -```solidity - function setTrustedSequencerURL( - string newTrustedSequencerURL - ) external -``` -Allow the admin to set the trusted sequencer URL - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newTrustedSequencerURL` | string | URL of trusted sequencer - ### setForceBatchAddress ```solidity function setForceBatchAddress( @@ -201,30 +173,6 @@ The new value can only be lower, except if emergency state is active | :--- | :--- | :------------------------------------------------------------------- | |`newforceBatchTimeout` | uint64 | New force batch timeout -### transferAdminRole -```solidity - function transferAdminRole( - address newPendingAdmin - ) external -``` -Starts the admin role transfer -This is a two step process, the pending admin must accepted to finalize the process - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`newPendingAdmin` | address | Address of the new pending admin - -### acceptAdminRole -```solidity - function acceptAdminRole( - ) external -``` -Allow the current pending admin to accept the admin role - - - ### calculatePolPerForceBatch ```solidity function calculatePolPerForceBatch( @@ -312,22 +260,6 @@ Emitted when a aggregator verifies batches Emitted when a aggregator verifies batches -### SetTrustedSequencer -```solidity - event SetTrustedSequencer( - ) -``` - -Emitted when the admin updates the trusted sequencer address - -### SetTrustedSequencerURL -```solidity - event SetTrustedSequencerURL( - ) -``` - -Emitted when the admin updates the sequencer URL - ### SetForceBatchTimeout ```solidity event SetForceBatchTimeout( @@ -344,19 +276,3 @@ Emitted when the admin update the force batch timeout Emitted when the admin update the force batch address -### TransferAdminRole -```solidity - event TransferAdminRole( - ) -``` - -Emitted when the admin starts the two-step transfer role setting a new pending admin - -### AcceptAdminRole -```solidity - event AcceptAdminRole( - ) -``` - -Emitted when the pending admin accepts the admin role - diff --git a/docs/v2/mocks/BridgeReceiverMock.md b/docs/v2/mocks/BridgeReceiverMock.md index e10a14c29..e92489d81 100644 --- a/docs/v2/mocks/BridgeReceiverMock.md +++ b/docs/v2/mocks/BridgeReceiverMock.md @@ -36,7 +36,7 @@ to avoid possible synch attacks |`mainnetExitRoot` | bytes32 | Mainnet exit root |`rollupExitRoot` | bytes32 | Rollup exit root |`originNetwork` | uint32 | Origin network -|`originTokenAddress` | address | Origin token address, 0 address is reserved for ether +|`originTokenAddress` | address | Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token |`destinationNetwork` | uint32 | Network destination |`destinationAddress` | address | Address destination |`amount` | uint256 | Amount of tokens diff --git a/docs/v2/mocks/PolygonRollupManagerMock.md b/docs/v2/mocks/PolygonRollupManagerMock.md index 4ef467459..98c0a8b34 100644 --- a/docs/v2/mocks/PolygonRollupManagerMock.md +++ b/docs/v2/mocks/PolygonRollupManagerMock.md @@ -37,3 +37,21 @@ PolygonRollupManager mock +### exposed_checkStateRootInsidePrime +```solidity + function exposed_checkStateRootInsidePrime( + ) public returns (bool) +``` + + + + +### setRollupData +```solidity + function setRollupData( + ) external +``` + + + + diff --git a/docs/v2/mocks/PolygonZkEVMGlobalExitRootV2Mock.md b/docs/v2/mocks/PolygonZkEVMGlobalExitRootV2Mock.md new file mode 100644 index 000000000..3409eafa9 --- /dev/null +++ b/docs/v2/mocks/PolygonZkEVMGlobalExitRootV2Mock.md @@ -0,0 +1,28 @@ +PolygonRollupManager mock + + +## Functions +### constructor +```solidity + function constructor( + address _rollupManager, + address _bridgeAddress + ) public +``` + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`_rollupManager` | address | Rollup manager contract address +|`_bridgeAddress` | address | PolygonZkEVMBridge contract address + +### injectGER +```solidity + function injectGER( + ) external +``` + + + + diff --git a/docs/v2/periphery/BatchL2DataCreatedRollup.md b/docs/v2/periphery/BatchL2DataCreatedRollup.md new file mode 100644 index 000000000..bc46857dc --- /dev/null +++ b/docs/v2/periphery/BatchL2DataCreatedRollup.md @@ -0,0 +1,26 @@ + + + +## Functions +### generateInitializeTransaction +```solidity + function generateInitializeTransaction( + uint32 networkID, + address bridgeAddress, + address _gasTokenAddress, + uint32 _gasTokenNetwork, + bytes _gasTokenMetadata + ) public returns (bytes) +``` +Generate Initialize transaction for hte bridge on L2 + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`networkID` | uint32 | Indicates the network identifier that will be used in the bridge +|`bridgeAddress` | address | Indicates the bridge address +|`_gasTokenAddress` | address | Indicates the token address that will be used to pay gas fees in the new rollup +|`_gasTokenNetwork` | uint32 | Indicates the native network of the token address +|`_gasTokenMetadata` | bytes | Abi encoded gas token metadata + diff --git a/docs/v2/interfaces/IPolygonDataComittee.md b/docs/v2/previousVersions/IPolygonRollupManagerPrevious.md similarity index 100% rename from docs/v2/interfaces/IPolygonDataComittee.md rename to docs/v2/previousVersions/IPolygonRollupManagerPrevious.md diff --git a/docs/v2/previousVersions/PolygonRollupManagerPrevious.md b/docs/v2/previousVersions/PolygonRollupManagerPrevious.md index fc5d48ce8..e4e702426 100644 --- a/docs/v2/previousVersions/PolygonRollupManagerPrevious.md +++ b/docs/v2/previousVersions/PolygonRollupManagerPrevious.md @@ -22,37 +22,6 @@ them will be done in this one. In this way, the proof aggregation of the rollups |`_pol` | contract IERC20Upgradeable | POL token address |`_bridgeAddress` | contract IPolygonZkEVMBridge | Bridge address -### initialize -```solidity - function initialize( - address trustedAggregator, - uint64 _pendingStateTimeout, - uint64 _trustedAggregatorTimeout, - address admin, - address timelock, - address emergencyCouncil, - contract PolygonZkEVMExistentEtrog polygonZkEVM, - contract IVerifierRollup zkEVMVerifier, - uint64 zkEVMForkID, - uint64 zkEVMChainID - ) external -``` - - -#### Parameters: -| Name | Type | Description | -| :--- | :--- | :------------------------------------------------------------------- | -|`trustedAggregator` | address | Trusted aggregator address -|`_pendingStateTimeout` | uint64 | Pending state timeout -|`_trustedAggregatorTimeout` | uint64 | Trusted aggregator timeout -|`admin` | address | Admin of the rollup manager -|`timelock` | address | Timelock address -|`emergencyCouncil` | address | Emergency council address -|`polygonZkEVM` | contract PolygonZkEVMExistentEtrog | New deployed Polygon zkEVM which will be initialized wiht previous values -|`zkEVMVerifier` | contract IVerifierRollup | Verifier of the new zkEVM deployed -|`zkEVMForkID` | uint64 | Fork id of the new zkEVM deployed -|`zkEVMChainID` | uint64 | Chain id of the new zkEVM deployed - ### addNewRollupType ```solidity function addNewRollupType( @@ -108,7 +77,7 @@ Create a new rollup | Name | Type | Description | | :--- | :--- | :------------------------------------------------------------------- | |`rollupTypeID` | uint32 | Rollup type to deploy -|`chainID` | uint64 | ChainID of the rollup, must be a new one +|`chainID` | uint64 | ChainID of the rollup, must be a new one, can not have more than 32 bits |`admin` | address | Admin of the new created rollup |`sequencer` | address | Sequencer of the new created rollup |`gasTokenAddress` | address | Indicates the token address that will be used to pay gas fees in the new rollup @@ -148,8 +117,7 @@ note that this rollup does not follow any rollupType contract IVerifierRollup verifier, uint64 forkID, uint64 chainID, - uint8 rollupCompatibilityID, - uint64 lastVerifiedBatch + uint8 rollupCompatibilityID ) internal returns (struct PolygonRollupManagerPrevious.RollupData rollup) ``` Add an already deployed rollup @@ -164,7 +132,23 @@ note that this rollup does not follow any rollupType |`forkID` | uint64 | Fork id of the added rollup |`chainID` | uint64 | Chain id of the added rollup |`rollupCompatibilityID` | uint8 | Compatibility ID for the added rollup -|`lastVerifiedBatch` | uint64 | Last verified batch before adding the rollup + +### updateRollupByRollupAdmin +```solidity + function updateRollupByRollupAdmin( + contract ITransparentUpgradeableProxy rollupContract, + uint32 newRollupTypeID + ) external +``` +Upgrade an existing rollup from the rollup admin address +This address is able to udpate the rollup with more restrictions that the _UPDATE_ROLLUP_ROLE + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupContract` | contract ITransparentUpgradeableProxy | Rollup consensus proxy address +|`newRollupTypeID` | uint32 | New rolluptypeID to upgrade to ### updateRollup ```solidity @@ -184,6 +168,40 @@ Upgrade an existing rollup |`newRollupTypeID` | uint32 | New rolluptypeID to upgrade to |`upgradeData` | bytes | Upgrade data +### _updateRollup +```solidity + function _updateRollup( + contract ITransparentUpgradeableProxy rollupContract, + uint32 newRollupTypeID, + bytes upgradeData + ) internal +``` +Upgrade an existing rollup + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupContract` | contract ITransparentUpgradeableProxy | Rollup consensus proxy address +|`newRollupTypeID` | uint32 | New rolluptypeID to upgrade to +|`upgradeData` | bytes | Upgrade data + +### rollbackBatches +```solidity + function rollbackBatches( + contract IPolygonRollupBase rollupContract, + uint64 targetBatch + ) external +``` +Rollback batches of the target rollup + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupContract` | contract IPolygonRollupBase | Rollup consensus proxy address +|`targetBatch` | uint64 | Batch to rollback up to but not including this batch + ### onSequenceBatches ```solidity function onSequenceBatches( @@ -822,6 +840,14 @@ Emitted when is proved a different state given the same batches Emitted when the trusted aggregator overrides pending state +### RollbackBatches +```solidity + event RollbackBatches( + ) +``` + +Emitted when rollback batches + ### SetTrustedAggregatorTimeout ```solidity event SetTrustedAggregatorTimeout( diff --git a/docs/v2/previousVersions/PolygonRollupManagerPreviousV1toV2.md b/docs/v2/previousVersions/PolygonRollupManagerPreviousV1toV2.md new file mode 100644 index 000000000..c3a659561 --- /dev/null +++ b/docs/v2/previousVersions/PolygonRollupManagerPreviousV1toV2.md @@ -0,0 +1,872 @@ +Contract responsible for managing rollups and the verification of their batches. +This contract will create and update rollups and store all the hashed sequenced data from them. +The logic for sequence batches is moved to the `consensus` contracts, while the verification of all of +them will be done in this one. In this way, the proof aggregation of the rollups will be easier on a close future. + + +## Functions +### constructor +```solidity + function constructor( + contract IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, + contract IERC20Upgradeable _pol, + contract IPolygonZkEVMBridge _bridgeAddress + ) public +``` + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`_globalExitRootManager` | contract IPolygonZkEVMGlobalExitRootV2 | Global exit root manager address +|`_pol` | contract IERC20Upgradeable | POL token address +|`_bridgeAddress` | contract IPolygonZkEVMBridge | Bridge address + +### initialize +```solidity + function initialize( + address trustedAggregator, + uint64 _pendingStateTimeout, + uint64 _trustedAggregatorTimeout, + address admin, + address timelock, + address emergencyCouncil, + contract PolygonZkEVMExistentEtrog polygonZkEVM, + contract IVerifierRollup zkEVMVerifier, + uint64 zkEVMForkID, + uint64 zkEVMChainID + ) external +``` + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`trustedAggregator` | address | Trusted aggregator address +|`_pendingStateTimeout` | uint64 | Pending state timeout +|`_trustedAggregatorTimeout` | uint64 | Trusted aggregator timeout +|`admin` | address | Admin of the rollup manager +|`timelock` | address | Timelock address +|`emergencyCouncil` | address | Emergency council address +|`polygonZkEVM` | contract PolygonZkEVMExistentEtrog | New deployed Polygon zkEVM which will be initialized wiht previous values +|`zkEVMVerifier` | contract IVerifierRollup | Verifier of the new zkEVM deployed +|`zkEVMForkID` | uint64 | Fork id of the new zkEVM deployed +|`zkEVMChainID` | uint64 | Chain id of the new zkEVM deployed + +### addNewRollupType +```solidity + function addNewRollupType( + address consensusImplementation, + contract IVerifierRollup verifier, + uint64 forkID, + uint8 genesis, + bytes32 description + ) external +``` +Add a new rollup type + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`consensusImplementation` | address | Consensus implementation +|`verifier` | contract IVerifierRollup | Verifier address +|`forkID` | uint64 | ForkID of the verifier +|`genesis` | uint8 | Genesis block of the rollup +|`description` | bytes32 | Description of the rollup type + +### obsoleteRollupType +```solidity + function obsoleteRollupType( + uint32 rollupTypeID + ) external +``` +Obsolete Rollup type + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupTypeID` | uint32 | Rollup type to obsolete + +### createNewRollup +```solidity + function createNewRollup( + uint32 rollupTypeID, + uint64 chainID, + address admin, + address sequencer, + address gasTokenAddress, + string sequencerURL, + string networkName + ) external +``` +Create a new rollup + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupTypeID` | uint32 | Rollup type to deploy +|`chainID` | uint64 | ChainID of the rollup, must be a new one +|`admin` | address | Admin of the new created rollup +|`sequencer` | address | Sequencer of the new created rollup +|`gasTokenAddress` | address | Indicates the token address that will be used to pay gas fees in the new rollup +Note if a wrapped token of the bridge is used, the original network and address of this wrapped will be used instead +|`sequencerURL` | string | Sequencer URL of the new created rollup +|`networkName` | string | Network name of the new created rollup + +### addExistingRollup +```solidity + function addExistingRollup( + contract IPolygonRollupBase rollupAddress, + contract IVerifierRollup verifier, + uint64 forkID, + uint64 chainID, + bytes32 genesis, + uint8 rollupCompatibilityID + ) external +``` +Add an already deployed rollup +note that this rollup does not follow any rollupType + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupAddress` | contract IPolygonRollupBase | Rollup address +|`verifier` | contract IVerifierRollup | Verifier address, must be added before +|`forkID` | uint64 | Fork id of the added rollup +|`chainID` | uint64 | Chain id of the added rollup +|`genesis` | bytes32 | Genesis block for this rollup +|`rollupCompatibilityID` | uint8 | Compatibility ID for the added rollup + +### _addExistingRollup +```solidity + function _addExistingRollup( + contract IPolygonRollupBase rollupAddress, + contract IVerifierRollup verifier, + uint64 forkID, + uint64 chainID, + uint8 rollupCompatibilityID, + uint64 lastVerifiedBatch + ) internal returns (struct PolygonRollupManagerPreviousV1toV2.RollupData rollup) +``` +Add an already deployed rollup +note that this rollup does not follow any rollupType + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupAddress` | contract IPolygonRollupBase | Rollup address +|`verifier` | contract IVerifierRollup | Verifier address, must be added before +|`forkID` | uint64 | Fork id of the added rollup +|`chainID` | uint64 | Chain id of the added rollup +|`rollupCompatibilityID` | uint8 | Compatibility ID for the added rollup +|`lastVerifiedBatch` | uint64 | Last verified batch before adding the rollup + +### updateRollup +```solidity + function updateRollup( + contract ITransparentUpgradeableProxy rollupContract, + uint32 newRollupTypeID, + bytes upgradeData + ) external +``` +Upgrade an existing rollup + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupContract` | contract ITransparentUpgradeableProxy | Rollup consensus proxy address +|`newRollupTypeID` | uint32 | New rolluptypeID to upgrade to +|`upgradeData` | bytes | Upgrade data + +### onSequenceBatches +```solidity + function onSequenceBatches( + uint64 newSequencedBatches, + bytes32 newAccInputHash + ) external returns (uint64) +``` +Sequence batches, callback called by one of the consensus managed by this contract + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`newSequencedBatches` | uint64 | Number of batches sequenced +|`newAccInputHash` | bytes32 | New accumulate input hash + +### verifyBatches +```solidity + function verifyBatches( + uint32 rollupID, + uint64 pendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + address beneficiary, + bytes32[24] proof + ) external +``` +Allows an aggregator to verify multiple batches + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup identifier +|`pendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used +|`initNumBatch` | uint64 | Batch which the aggregator starts the verification +|`finalNewBatch` | uint64 | Last batch aggregator intends to verify +|`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed +|`newStateRoot` | bytes32 | New State root once the batch is processed +|`beneficiary` | address | Address that will receive the verification reward +|`proof` | bytes32[24] | Fflonk proof + +### verifyBatchesTrustedAggregator +```solidity + function verifyBatchesTrustedAggregator( + uint32 rollupID, + uint64 pendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + address beneficiary, + bytes32[24] proof + ) external +``` +Allows a trusted aggregator to verify multiple batches + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup identifier +|`pendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used +|`initNumBatch` | uint64 | Batch which the aggregator starts the verification +|`finalNewBatch` | uint64 | Last batch aggregator intends to verify +|`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed +|`newStateRoot` | bytes32 | New State root once the batch is processed +|`beneficiary` | address | Address that will receive the verification reward +|`proof` | bytes32[24] | Fflonk proof + +### _verifyAndRewardBatches +```solidity + function _verifyAndRewardBatches( + struct PolygonRollupManagerPreviousV1toV2.RollupData rollup, + uint64 pendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + address beneficiary, + bytes32[24] proof + ) internal +``` +Verify and reward batches internal function + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollup` | struct PolygonRollupManagerPreviousV1toV2.RollupData | Rollup Data storage pointer that will be used to the verification +|`pendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used +|`initNumBatch` | uint64 | Batch which the aggregator starts the verification +|`finalNewBatch` | uint64 | Last batch aggregator intends to verify +|`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed +|`newStateRoot` | bytes32 | New State root once the batch is processed +|`beneficiary` | address | Address that will receive the verification reward +|`proof` | bytes32[24] | Fflonk proof + +### _tryConsolidatePendingState +```solidity + function _tryConsolidatePendingState( + ) internal +``` +Internal function to consolidate the state automatically once sequence or verify batches are called +It tries to consolidate the first and the middle pending state in the queue + + + +### consolidatePendingState +```solidity + function consolidatePendingState( + uint32 rollupID, + uint64 pendingStateNum + ) external +``` +Allows to consolidate any pending state that has already exceed the pendingStateTimeout +Can be called by the trusted aggregator, which can consolidate any state without the timeout restrictions + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup identifier +|`pendingStateNum` | uint64 | Pending state to consolidate + +### _consolidatePendingState +```solidity + function _consolidatePendingState( + struct PolygonRollupManagerPreviousV1toV2.RollupData rollup, + uint64 pendingStateNum + ) internal +``` +Internal function to consolidate any pending state that has already exceed the pendingStateTimeout + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollup` | struct PolygonRollupManagerPreviousV1toV2.RollupData | Rollup data storage pointer +|`pendingStateNum` | uint64 | Pending state to consolidate + +### overridePendingState +```solidity + function overridePendingState( + uint32 rollupID, + uint64 initPendingStateNum, + uint64 finalPendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + bytes32[24] proof + ) external +``` +Allows the trusted aggregator to override the pending state +if it's possible to prove a different state root given the same batches + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup identifier +|`initPendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used +|`finalPendingStateNum` | uint64 | Final pending state, that will be used to compare with the newStateRoot +|`initNumBatch` | uint64 | Batch which the aggregator starts the verification +|`finalNewBatch` | uint64 | Last batch aggregator intends to verify +|`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed +|`newStateRoot` | bytes32 | New State root once the batch is processed +|`proof` | bytes32[24] | Fflonk proof + +### proveNonDeterministicPendingState +```solidity + function proveNonDeterministicPendingState( + uint32 rollupID, + uint64 initPendingStateNum, + uint64 finalPendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + bytes32[24] proof + ) external +``` +Allows activate the emergency state if its possible to prove a different state root given the same batches + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup identifier +|`initPendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used +|`finalPendingStateNum` | uint64 | Final pending state, that will be used to compare with the newStateRoot +|`initNumBatch` | uint64 | Batch which the aggregator starts the verification +|`finalNewBatch` | uint64 | Last batch aggregator intends to verify +|`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed +|`newStateRoot` | bytes32 | New State root once the batch is processed +|`proof` | bytes32[24] | Fflonk proof + +### _proveDistinctPendingState +```solidity + function _proveDistinctPendingState( + struct PolygonRollupManagerPreviousV1toV2.RollupData rollup, + uint64 initPendingStateNum, + uint64 finalPendingStateNum, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 newStateRoot, + bytes32[24] proof + ) internal +``` +Internal function that proves a different state root given the same batches to verify + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollup` | struct PolygonRollupManagerPreviousV1toV2.RollupData | Rollup Data struct that will be checked +|`initPendingStateNum` | uint64 | Init pending state, 0 if consolidated state is used +|`finalPendingStateNum` | uint64 | Final pending state, that will be used to compare with the newStateRoot +|`initNumBatch` | uint64 | Batch which the aggregator starts the verification +|`finalNewBatch` | uint64 | Last batch aggregator intends to verify +|`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed +|`newStateRoot` | bytes32 | New State root once the batch is processed +|`proof` | bytes32[24] | Fflonk proof + +### _updateBatchFee +```solidity + function _updateBatchFee( + struct PolygonRollupManagerPreviousV1toV2.RollupData newLastVerifiedBatch + ) internal +``` +Function to update the batch fee based on the new verified batches +The batch fee will not be updated when the trusted aggregator verifies batches + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`newLastVerifiedBatch` | struct PolygonRollupManagerPreviousV1toV2.RollupData | New last verified batch + +### activateEmergencyState +```solidity + function activateEmergencyState( + ) external +``` +Function to activate emergency state, which also enables the emergency mode on both PolygonRollupManager and PolygonZkEVMBridge contracts +If not called by the owner must not have been aggregated in a _HALT_AGGREGATION_TIMEOUT period and an emergency state was not happened in the same period + + + +### deactivateEmergencyState +```solidity + function deactivateEmergencyState( + ) external +``` +Function to deactivate emergency state on both PolygonRollupManager and PolygonZkEVMBridge contracts + + + +### _activateEmergencyState +```solidity + function _activateEmergencyState( + ) internal +``` +Internal function to activate emergency state on both PolygonRollupManager and PolygonZkEVMBridge contracts + + + +### setTrustedAggregatorTimeout +```solidity + function setTrustedAggregatorTimeout( + uint64 newTrustedAggregatorTimeout + ) external +``` +Set a new pending state timeout +The timeout can only be lowered, except if emergency state is active + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`newTrustedAggregatorTimeout` | uint64 | Trusted aggregator timeout + +### setPendingStateTimeout +```solidity + function setPendingStateTimeout( + uint64 newPendingStateTimeout + ) external +``` +Set a new trusted aggregator timeout +The timeout can only be lowered, except if emergency state is active + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`newPendingStateTimeout` | uint64 | Trusted aggregator timeout + +### setMultiplierBatchFee +```solidity + function setMultiplierBatchFee( + uint16 newMultiplierBatchFee + ) external +``` +Set a new multiplier batch fee + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`newMultiplierBatchFee` | uint16 | multiplier batch fee + +### setVerifyBatchTimeTarget +```solidity + function setVerifyBatchTimeTarget( + uint64 newVerifyBatchTimeTarget + ) external +``` +Set a new verify batch time target +This value will only be relevant once the aggregation is decentralized, so +the trustedAggregatorTimeout should be zero or very close to zero + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`newVerifyBatchTimeTarget` | uint64 | Verify batch time target + +### setBatchFee +```solidity + function setBatchFee( + uint256 newBatchFee + ) external +``` +Set the current batch fee + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`newBatchFee` | uint256 | new batch fee + +### getRollupExitRoot +```solidity + function getRollupExitRoot( + ) public returns (bytes32) +``` +Get the current rollup exit root +Compute using all the local exit roots of all rollups the rollup exit root +Since it's expected to have no more than 10 rollups in this first version, even if this approach +has a gas consumption that scales linearly with the rollups added, it's ok +In a future versions this computation will be done inside the circuit + + + +### getLastVerifiedBatch +```solidity + function getLastVerifiedBatch( + ) public returns (uint64) +``` +Get the last verified batch + + + +### _getLastVerifiedBatch +```solidity + function _getLastVerifiedBatch( + ) internal returns (uint64) +``` +Get the last verified batch + + + +### isPendingStateConsolidable +```solidity + function isPendingStateConsolidable( + uint32 rollupID, + uint64 pendingStateNum + ) public returns (bool) +``` +Returns a boolean that indicates if the pendingStateNum is or not consolidable + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup id +|`pendingStateNum` | uint64 | Pending state number to check +Note that his function does not check if the pending state currently exists, or if it's consolidated already + +### _isPendingStateConsolidable +```solidity + function _isPendingStateConsolidable( + struct PolygonRollupManagerPreviousV1toV2.RollupData rollup, + uint64 pendingStateNum + ) internal returns (bool) +``` +Returns a boolean that indicates if the pendingStateNum is or not consolidable + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollup` | struct PolygonRollupManagerPreviousV1toV2.RollupData | Rollup data storage pointer +|`pendingStateNum` | uint64 | Pending state number to check +Note that his function does not check if the pending state currently exists, or if it's consolidated already + +### calculateRewardPerBatch +```solidity + function calculateRewardPerBatch( + ) public returns (uint256) +``` +Function to calculate the reward to verify a single batch + + + +### getBatchFee +```solidity + function getBatchFee( + ) public returns (uint256) +``` +Get batch fee +This function is used instad of the automatic public view one, +because in a future might change the behaviour and we will be able to mantain the interface + + + +### getForcedBatchFee +```solidity + function getForcedBatchFee( + ) public returns (uint256) +``` +Get forced batch fee + + + +### getInputSnarkBytes +```solidity + function getInputSnarkBytes( + uint32 rollupID, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 oldStateRoot, + bytes32 newStateRoot + ) public returns (bytes) +``` +Function to calculate the input snark bytes + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup id used to calculate the input snark bytes +|`initNumBatch` | uint64 | Batch which the aggregator starts the verification +|`finalNewBatch` | uint64 | Last batch aggregator intends to verify +|`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed +|`oldStateRoot` | bytes32 | State root before batch is processed +|`newStateRoot` | bytes32 | New State root once the batch is processed + +### _getInputSnarkBytes +```solidity + function _getInputSnarkBytes( + struct PolygonRollupManagerPreviousV1toV2.RollupData rollup, + uint64 initNumBatch, + uint64 finalNewBatch, + bytes32 newLocalExitRoot, + bytes32 oldStateRoot, + bytes32 newStateRoot + ) internal returns (bytes) +``` +Function to calculate the input snark bytes + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollup` | struct PolygonRollupManagerPreviousV1toV2.RollupData | Rollup data storage pointer +|`initNumBatch` | uint64 | Batch which the aggregator starts the verification +|`finalNewBatch` | uint64 | Last batch aggregator intends to verify +|`newLocalExitRoot` | bytes32 | New local exit root once the batch is processed +|`oldStateRoot` | bytes32 | State root before batch is processed +|`newStateRoot` | bytes32 | New State root once the batch is processed + +### _checkStateRootInsidePrime +```solidity + function _checkStateRootInsidePrime( + uint256 newStateRoot + ) internal returns (bool) +``` +Function to check if the state root is inside of the prime field + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`newStateRoot` | uint256 | New State root once the batch is processed + +### getRollupBatchNumToStateRoot +```solidity + function getRollupBatchNumToStateRoot( + uint32 rollupID, + uint64 batchNum + ) public returns (bytes32) +``` +Get rollup state root given a batch number + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup identifier +|`batchNum` | uint64 | Batch number + +### getRollupSequencedBatches +```solidity + function getRollupSequencedBatches( + uint32 rollupID, + uint64 batchNum + ) public returns (struct LegacyZKEVMStateVariables.SequencedBatchData) +``` +Get rollup sequence batches struct given a batch number + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup identifier +|`batchNum` | uint64 | Batch number + +### getRollupPendingStateTransitions +```solidity + function getRollupPendingStateTransitions( + uint32 rollupID, + uint64 batchNum + ) public returns (struct LegacyZKEVMStateVariables.PendingState) +``` +Get rollup sequence pending state struct given a batch number + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`rollupID` | uint32 | Rollup identifier +|`batchNum` | uint64 | Batch number + +## Events +### AddNewRollupType +```solidity + event AddNewRollupType( + ) +``` + +Emitted when a new rollup type is added + +### ObsoleteRollupType +```solidity + event ObsoleteRollupType( + ) +``` + +Emitted when a a rolup type is obsoleted + +### CreateNewRollup +```solidity + event CreateNewRollup( + ) +``` + +Emitted when a new rollup is created based on a rollupType + +### AddExistingRollup +```solidity + event AddExistingRollup( + ) +``` + +Emitted when an existing rollup is added + +### UpdateRollup +```solidity + event UpdateRollup( + ) +``` + +Emitted when a rollup is udpated + +### OnSequenceBatches +```solidity + event OnSequenceBatches( + ) +``` + +Emitted when a new verifier is added + +### VerifyBatches +```solidity + event VerifyBatches( + ) +``` + +Emitted when an aggregator verifies batches + +### VerifyBatchesTrustedAggregator +```solidity + event VerifyBatchesTrustedAggregator( + ) +``` + +Emitted when the trusted aggregator verifies batches + +### ConsolidatePendingState +```solidity + event ConsolidatePendingState( + ) +``` + +Emitted when pending state is consolidated + +### ProveNonDeterministicPendingState +```solidity + event ProveNonDeterministicPendingState( + ) +``` + +Emitted when is proved a different state given the same batches + +### OverridePendingState +```solidity + event OverridePendingState( + ) +``` + +Emitted when the trusted aggregator overrides pending state + +### SetTrustedAggregatorTimeout +```solidity + event SetTrustedAggregatorTimeout( + ) +``` + +Emitted when is updated the trusted aggregator timeout + +### SetPendingStateTimeout +```solidity + event SetPendingStateTimeout( + ) +``` + +Emitted when is updated the pending state timeout + +### SetMultiplierBatchFee +```solidity + event SetMultiplierBatchFee( + ) +``` + +Emitted when is updated the multiplier batch fee + +### SetVerifyBatchTimeTarget +```solidity + event SetVerifyBatchTimeTarget( + ) +``` + +Emitted when is updated the verify batch timeout + +### SetTrustedAggregator +```solidity + event SetTrustedAggregator( + ) +``` + +Emitted when is updated the trusted aggregator address + +### SetBatchFee +```solidity + event SetBatchFee( + ) +``` + +Emitted when is updated the batch fee + diff --git a/docs/v2/sovereignChains/BridgeL2SovereignChain.md b/docs/v2/sovereignChains/BridgeL2SovereignChain.md new file mode 100644 index 000000000..a9d4bda92 --- /dev/null +++ b/docs/v2/sovereignChains/BridgeL2SovereignChain.md @@ -0,0 +1,338 @@ +Sovereign chains bridge that will be deployed on all Sovereign chains +Contract responsible to manage the token interactions with other networks +This contract is not meant to replace the current zkEVM bridge contract, but deployed on sovereign networks + + +## Functions +### constructor +```solidity + function constructor( + ) public +``` +Disable initializers on the implementation following the best practices + + + +### initialize +```solidity + function initialize( + uint32 _networkID, + address _gasTokenAddress, + uint32 _gasTokenNetwork, + contract IBasePolygonZkEVMGlobalExitRoot _globalExitRootManager, + address _polygonRollupManager, + bytes _gasTokenMetadata, + address _bridgeManager, + address _sovereignWETHAddress, + bool _sovereignWETHAddressIsNotMintable + ) public +``` +The value of `_polygonRollupManager` on the L2 deployment of the contract will be address(0), so +emergency state is not possible for the L2 deployment of the bridge, intentionally + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`_networkID` | uint32 | networkID +|`_gasTokenAddress` | address | gas token address +|`_gasTokenNetwork` | uint32 | gas token network +|`_globalExitRootManager` | contract IBasePolygonZkEVMGlobalExitRoot | global exit root manager address +|`_polygonRollupManager` | address | Rollup manager address +|`_gasTokenMetadata` | bytes | Abi encoded gas token metadata +|`_bridgeManager` | address | bridge manager address +|`_sovereignWETHAddress` | address | sovereign WETH address +|`_sovereignWETHAddressIsNotMintable` | bool | Flag to indicate if the wrapped ETH is not mintable + +### initialize +```solidity + function initialize( + ) external +``` +Override the function to prevent the contract from being initialized with this initializer + + + +### setMultipleSovereignTokenAddress +```solidity + function setMultipleSovereignTokenAddress( + uint32[] originNetworks, + address[] originTokenAddresses, + address[] sovereignTokenAddresses, + bool[] isNotMintable + ) external +``` +Remap multiple wrapped tokens to a new sovereign token address + +This function is a "multi/batch call" to `setSovereignTokenAddress` + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`originNetworks` | uint32[] | Array of Origin networks +|`originTokenAddresses` | address[] | Array od Origin token addresses, 0 address is reserved for ether +|`sovereignTokenAddresses` | address[] | Array of Addresses of the sovereign wrapped token +|`isNotMintable` | bool[] | Array of Flags to indicate if the wrapped token is not mintable + +### _setSovereignTokenAddress +```solidity + function _setSovereignTokenAddress( + uint32 originNetwork, + address originTokenAddress, + address sovereignTokenAddress, + bool isNotMintable + ) internal +``` +Remap a wrapped token to a new sovereign token address +If this function is called multiple times for the same existingTokenAddress, +this will override the previous calls and only keep the last sovereignTokenAddress. +The tokenInfoToWrappedToken mapping value is replaced by the new sovereign address but it's not the case for the wrappedTokenToTokenInfo map where the value is added, this way user will always be able to withdraw their tokens +The number of decimals between sovereign token and origin token is not checked, it doesn't affect the bridge functionality but the UI. + +This function is used to allow any existing token to be mapped with + origin token. + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`originNetwork` | uint32 | Origin network +|`originTokenAddress` | address | Origin token address, 0 address is reserved for gas token address. If WETH address is zero, means this gas token is ether, else means is a custom erc20 gas token +|`sovereignTokenAddress` | address | Address of the sovereign wrapped token +|`isNotMintable` | bool | Flag to indicate if the wrapped token is not mintable + +### removeLegacySovereignTokenAddress +```solidity + function removeLegacySovereignTokenAddress( + address legacySovereignTokenAddress + ) external +``` +Remove the address of a remapped token from the mapping. Used to stop supporting legacy sovereign tokens +It also removes the token from the isNotMintable mapping +Although the token is removed from the mapping, the user will still be able to withdraw their tokens using tokenInfoToWrappedToken mapping + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`legacySovereignTokenAddress` | address | Address of the sovereign wrapped token + +### setSovereignWETHAddress +```solidity + function setSovereignWETHAddress( + address sovereignWETHTokenAddress, + bool isNotMintable + ) external +``` +Set the custom wrapper for weth +If this function is called multiple times this will override the previous calls and only keep the last WETHToken. +WETH will not maintain legacy versions.Users easily should be able to unwrapp the legacy WETH and unwrapp it with the new one. + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`sovereignWETHTokenAddress` | address | Address of the sovereign weth token +|`isNotMintable` | bool | Flag to indicate if the wrapped token is not mintable + +### migrateLegacyToken +```solidity + function migrateLegacyToken( + address legacyTokenAddress, + uint256 amount + ) external +``` +Moves old native or remapped token (legacy) to the new mapped token. If the token is mintable, it will be burnt and minted, otherwise it will be transferred + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`legacyTokenAddress` | address | Address of legacy token to migrate +|`amount` | uint256 | Legacy token balance to migrate + +### unsetMultipleClaimedBitmap +```solidity + function unsetMultipleClaimedBitmap( + uint32[] leafIndexes, + uint32[] sourceBridgeNetworks + ) external +``` +unset multiple claims from the claimedBitmap + +This function is a "multi/batch call" to `unsetClaimedBitmap` + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`leafIndexes` | uint32[] | Array of Index +|`sourceBridgeNetworks` | uint32[] | Array of Origin networks + +### setBridgeManager +```solidity + function setBridgeManager( + address _bridgeManager + ) external +``` +Updated bridge manager address, recommended to set a timelock at this address after bootstrapping phase + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`_bridgeManager` | address | Bridge manager address + +### _bridgeWrappedAsset +```solidity + function _bridgeWrappedAsset( + contract TokenWrapped tokenWrapped, + uint256 amount + ) internal +``` +Burn tokens from wrapped token to execute the bridge, if the token is not mintable it will be transferred +note This function has been extracted to be able to override it by other contracts like Bridge2SovereignChain + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`tokenWrapped` | contract TokenWrapped | Wrapped token to burnt +|`amount` | uint256 | Amount of tokens + +### _claimWrappedAsset +```solidity + function _claimWrappedAsset( + contract TokenWrapped tokenWrapped, + address destinationAddress, + uint256 amount + ) internal +``` +Mints tokens from wrapped token to proceed with the claim, if the token is not mintable it will be transferred +note This function has been extracted to be able to override it by other contracts like BridgeL2SovereignChain + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`tokenWrapped` | contract TokenWrapped | Wrapped token to mint +|`destinationAddress` | address | Minted token receiver +|`amount` | uint256 | Amount of tokens + +### isClaimed +```solidity + function isClaimed( + uint32 leafIndex, + uint32 sourceBridgeNetwork + ) external returns (bool) +``` +Function to check if an index is claimed or not + +function overridden to improve a bit the performance and bytecode not checking unnecessary conditions for sovereign chains context + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`leafIndex` | uint32 | Index +|`sourceBridgeNetwork` | uint32 | Origin network + +### _setAndCheckClaimed +```solidity + function _setAndCheckClaimed( + uint32 leafIndex, + uint32 sourceBridgeNetwork + ) internal +``` +Function to check that an index is not claimed and set it as claimed + +function overridden to improve a bit the performance and bytecode not checking unnecessary conditions for sovereign chains context + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`leafIndex` | uint32 | Index +|`sourceBridgeNetwork` | uint32 | Origin network + +### _permit +```solidity + function _permit( + address amount, + uint256 permitData + ) internal +``` +Function to call token permit method of extended ERC20 + +function overridden from PolygonZkEVMBridgeV2 to improve a bit the performance and bytecode not checking unnecessary conditions for sovereign chains context + + @param token ERC20 token address + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`amount` | address | Quantity that is expected to be allowed +|`permitData` | uint256 | Raw data of the call `permit` of the token + +### activateEmergencyState +```solidity + function activateEmergencyState( + ) external +``` + + + + +### deactivateEmergencyState +```solidity + function deactivateEmergencyState( + ) external +``` + + + + +## Events +### SetBridgeManager +```solidity + event SetBridgeManager( + ) +``` + +Emitted when a bridge manager is updated + +### UnsetClaim +```solidity + event UnsetClaim( + ) +``` + +Emitted when a claim is unset + +### SetSovereignTokenAddress +```solidity + event SetSovereignTokenAddress( + ) +``` + +Emitted when a token address is remapped by a sovereign token address + +### MigrateLegacyToken +```solidity + event MigrateLegacyToken( + ) +``` + +Emitted when a legacy token is migrated to a new token + +### RemoveLegacySovereignTokenAddress +```solidity + event RemoveLegacySovereignTokenAddress( + ) +``` + +Emitted when a remapped token is removed from mapping + +### SetSovereignWETHAddress +```solidity + event SetSovereignWETHAddress( + ) +``` + +Emitted when a WETH address is remapped by a sovereign WETH address + diff --git a/docs/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.md b/docs/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.md new file mode 100644 index 000000000..7e94fc54b --- /dev/null +++ b/docs/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.md @@ -0,0 +1,122 @@ +Contract responsible for managing the exit roots for the Sovereign chains and global exit roots + + +## Functions +### constructor +```solidity + function constructor( + address _bridgeAddress + ) public +``` + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`_bridgeAddress` | address | PolygonZkEVMBridge contract address + +### initialize +```solidity + function initialize( + address _globalExitRootUpdater, + address _globalExitRootRemover + ) external +``` +Initialize contract + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`_globalExitRootUpdater` | address | setting the globalExitRootUpdater. +|`_globalExitRootRemover` | address | In case of initializing a chain with Full execution proofs, this address should be set to zero, otherwise, some malicious sequencer could insert invalid global exit roots, claim and go back and the execution would be correctly proved. + +### insertGlobalExitRoot +```solidity + function insertGlobalExitRoot( + bytes32 _newRoot + ) external +``` +Insert a new global exit root + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`_newRoot` | bytes32 | new global exit root to insert + +### removeLastGlobalExitRoots +```solidity + function removeLastGlobalExitRoots( + bytes32[] gersToRemove + ) external +``` +Remove last global exit roots + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`gersToRemove` | bytes32[] | Array of gers to remove in inserted order where first element of the array is the last inserted + +### setGlobalExitRootUpdater +```solidity + function setGlobalExitRootUpdater( + address _globalExitRootUpdater + ) external +``` +Set the globalExitRootUpdater + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`_globalExitRootUpdater` | address | new globalExitRootUpdater address + +### setGlobalExitRootRemover +```solidity + function setGlobalExitRootRemover( + address _globalExitRootRemover + ) external +``` +Set the globalExitRootRemover + + +#### Parameters: +| Name | Type | Description | +| :--- | :--- | :------------------------------------------------------------------- | +|`_globalExitRootRemover` | address | new globalExitRootRemover address + +## Events +### InsertGlobalExitRoot +```solidity + event InsertGlobalExitRoot( + ) +``` + +Emitted when a new global exit root is inserted + +### RemoveLastGlobalExitRoot +```solidity + event RemoveLastGlobalExitRoot( + ) +``` + +Emitted when the last global exit root is removed + +### SetGlobalExitRootUpdater +```solidity + event SetGlobalExitRootUpdater( + ) +``` + +Emitted when the globalExitRootUpdater is set + +### SetGlobalExitRootRemover +```solidity + event SetGlobalExitRootRemover( + ) +``` + +Emitted when the globalExitRootRemover is set + diff --git a/foundry.toml b/foundry.toml new file mode 100644 index 000000000..f2af5126c --- /dev/null +++ b/foundry.toml @@ -0,0 +1,5 @@ +[profile.default] +src = 'contracts' +# *.ignore files are added to the .gitignore file +out = 'folder.ignore' +libs = ['node_modules'] diff --git a/hardhat.config.ts b/hardhat.config.ts index 3cf06de28..0d104c532 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -2,6 +2,7 @@ import "dotenv/config"; import "@nomicfoundation/hardhat-toolbox"; import "@openzeppelin/hardhat-upgrades"; import "hardhat-dependency-compiler"; +import "hardhat-switch-network"; import {HardhatUserConfig} from "hardhat/config"; @@ -75,12 +76,22 @@ const config: HardhatUserConfig = { }, ], overrides: { + "contracts/v2/sovereignChains/BridgeL2SovereignChain.sol": { + version: "0.8.20", + settings: { + optimizer: { + enabled: true, + runs: 20, + }, + evmVersion: "shanghai", + }, // try yul optimizer + }, "contracts/v2/PolygonRollupManager.sol": { version: "0.8.20", settings: { optimizer: { enabled: true, - runs: 500, + runs: 500, // Should have the same optimizations as PolygonTransparentProxy }, evmVersion: "shanghai", }, // try yul optimizer @@ -100,7 +111,7 @@ const config: HardhatUserConfig = { settings: { optimizer: { enabled: true, - runs: 200, + runs: 500, // Should have the same optimizations as PolygonTransparentProxy }, evmVersion: "shanghai", }, // try yul optimizer @@ -110,7 +121,7 @@ const config: HardhatUserConfig = { settings: { optimizer: { enabled: true, - runs: 10, + runs: 500, // Should have the same optimizations as PolygonTransparentProxy }, evmVersion: "shanghai", }, // try yul optimizer diff --git a/package-lock.json b/package-lock.json index 3ff960cb4..89c183ade 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,12 +9,12 @@ "version": "3.0.0", "license": "pending", "devDependencies": { - "@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#main", + "@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#v8.0.0-fork.12", "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@openzeppelin/contracts": "4.8.2", "@openzeppelin/contracts-upgradeable": "4.8.2", - "@openzeppelin/contracts5": "npm:@openzeppelin/contracts@^5.0.0", - "@openzeppelin/hardhat-upgrades": "2.5.0", + "@openzeppelin/contracts5": "npm:@openzeppelin/contracts@5.0.0", + "@openzeppelin/hardhat-upgrades": "^2.5.1", "@types/yargs": "^17.0.28", "circomlibjs": "0.1.1", "dotenv": "^8.6.0", @@ -25,10 +25,15 @@ "ffjavascript": "^0.2.60", "hardhat": "^2.22.3", "hardhat-dependency-compiler": "^1.1.3", + "hardhat-switch-network": "^1.2.0", + "lodash": "^4.17.21", "prettier": "^2.8.8", - "prettier-plugin-solidity": "^1.1.3", + "prettier-plugin-solidity": "^1.4.1", + "shelljs": "^0.8.5", "solc-0.8": "npm:solc@0.8.20", - "solidity-docgen": "^0.5.17" + "solc-0.8.17": "npm:solc@0.8.17", + "solidity-docgen": "^0.5.17", + "winston": "^3.17.0" } }, "node_modules/@0xpolygonhermez/zkevm-commonjs": { @@ -126,12 +131,12 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.654.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.654.0.tgz", - "integrity": "sha512-VWvbED3SV+10QJIcmU/PKjsKilsTV16d1I7/on4bvD/jo1qGeMXqLDBSen3ks/tuvXZF/mFc7ZW/W2DiLVtO7A==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.679.0.tgz", + "integrity": "sha512-NwVq8YvInxQdJ47+zz4fH3BRRLC6lL+WLkvr242PVBbUOLRyK/lkwHlfiKUoeVIMyK5NF+up6TRg71t/8Bny6Q==", "dev": true, "dependencies": { - "@smithy/types": "^3.4.2", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -139,9 +144,9 @@ } }, "node_modules/@aws-sdk/types/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@aws-sdk/util-utf8-browser": { @@ -154,11 +159,20 @@ } }, "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -171,6 +185,17 @@ "node": ">=12" } }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dev": true, + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "node_modules/@ensdomains/ens": { "version": "0.4.5", "resolved": "https://registry.npmjs.org/@ensdomains/ens/-/ens-0.4.5.tgz", @@ -395,24 +420,27 @@ "dev": true }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", - "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -1981,81 +2009,81 @@ } }, "node_modules/@nomicfoundation/edr": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.6.2.tgz", - "integrity": "sha512-yPUegN3sTWiAkRatCmGRkuvMgD9HSSpivl2ebAqq0aU2xgC7qmIO+YQPxQ3Z46MUoi7MrTf4e6GpbT4S/8x0ew==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.6.4.tgz", + "integrity": "sha512-YgrSuT3yo5ZQkbvBGqQ7hG+RDvz3YygSkddg4tb1Z0Y6pLXFzwrcEwWaJCFAVeeZxdxGfCgGMUYgRVneK+WXkw==", "dev": true, "dependencies": { - "@nomicfoundation/edr-darwin-arm64": "0.6.2", - "@nomicfoundation/edr-darwin-x64": "0.6.2", - "@nomicfoundation/edr-linux-arm64-gnu": "0.6.2", - "@nomicfoundation/edr-linux-arm64-musl": "0.6.2", - "@nomicfoundation/edr-linux-x64-gnu": "0.6.2", - "@nomicfoundation/edr-linux-x64-musl": "0.6.2", - "@nomicfoundation/edr-win32-x64-msvc": "0.6.2" + "@nomicfoundation/edr-darwin-arm64": "0.6.4", + "@nomicfoundation/edr-darwin-x64": "0.6.4", + "@nomicfoundation/edr-linux-arm64-gnu": "0.6.4", + "@nomicfoundation/edr-linux-arm64-musl": "0.6.4", + "@nomicfoundation/edr-linux-x64-gnu": "0.6.4", + "@nomicfoundation/edr-linux-x64-musl": "0.6.4", + "@nomicfoundation/edr-win32-x64-msvc": "0.6.4" }, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-arm64": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.2.tgz", - "integrity": "sha512-o4A9SaPlxJ1MS6u8Ozqq7Y0ri2XO0jASw+qkytQyBYowNFNReoGqVSs7SCwenYCDiN+1il8+M0VAUq7wOovnCQ==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.4.tgz", + "integrity": "sha512-QNQErISLgssV9+qia8sIjRANqtbW8snSDvjspixT/kSQ5ZSGxxctTg7x72wPSrcu8+EBEveIe5uqENIp5GH8HQ==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-x64": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.2.tgz", - "integrity": "sha512-WG8BeG2eR3rFC+2/9V1hoPGW7tmNRUcuztdHUijO1h2flRsf2YWv+kEHO+EEnhGkEbgBUiwOrwlwlSMxhe2cGA==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.4.tgz", + "integrity": "sha512-cjVmREiwByyc9+oGfvAh49IAw+oVJHF9WWYRD+Tm/ZlSpnEVWxrGNBak2bd/JSYjn+mZE7gmWS4SMRi4nKaLUg==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.2.tgz", - "integrity": "sha512-wvHaTmOwuPjRIOqBB+paI3RBdNlG8f3e1F2zWj75EdeWwefimPzzFUs05JxOYuPO0JhDQIn2tbYUgdZbBQ+mqg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.4.tgz", + "integrity": "sha512-96o9kRIVD6W5VkgKvUOGpWyUGInVQ5BRlME2Fa36YoNsRQMaKtmYJEU0ACosYES6ZTpYC8U5sjMulvPtVoEfOA==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-musl": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.2.tgz", - "integrity": "sha512-UrOAxnsywUcEngQM2ZxIuucci0VX29hYxX7jcpwZU50HICCjxNsxnuXYPxv+IM+6gbhBY1FYvYJGW4PJcP1Nyw==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.4.tgz", + "integrity": "sha512-+JVEW9e5plHrUfQlSgkEj/UONrIU6rADTEk+Yp9pbe+mzNkJdfJYhs5JYiLQRP4OjxH4QOrXI97bKU6FcEbt5Q==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-gnu": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.2.tgz", - "integrity": "sha512-gYxlPLi7fkNcmDmCwZWQa5eOfNcTDundE+TWjpyafxLAjodQuKBD4I0p4XbnuocHjoBEeNzLWdE5RShbZEXEJA==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.4.tgz", + "integrity": "sha512-nzYWW+fO3EZItOeP4CrdMgDXfaGBIBkKg0Y/7ySpUxLqzut40O4Mb0/+quqLAFkacUSWMlFp8nsmypJfOH5zoA==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-musl": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.2.tgz", - "integrity": "sha512-ev5hy9wmiHZi1GKQ1l6PJ2+UpsUh+DvK9AwiCZVEdaicuhmTfO6fdL4szgE4An8RU+Ou9DeiI1tZcq6iw++Wuw==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.4.tgz", + "integrity": "sha512-QFRoE9qSQ2boRrVeQ1HdzU+XN7NUgwZ1SIy5DQt4d7jCP+5qTNsq8LBNcqhRBOATgO63nsweNUhxX/Suj5r1Sw==", "dev": true, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-win32-x64-msvc": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.2.tgz", - "integrity": "sha512-2ZXVVcmdmEeX0Hb3IAurHUjgU3H1GIk9h7Okosdjgl3tl+BaNHxi84Us+DblynO1LRj8nL/ATeVtSfBuW3Z1vw==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.4.tgz", + "integrity": "sha512-2yopjelNkkCvIjUgBGhrn153IBPLwnsDeNiq6oA0WkeM8tGmQi4td+PGi9jAriUDAkc59Yoi2q9hYA6efiY7Zw==", "dev": true, "engines": { "node": ">= 18" @@ -2489,9 +2517,9 @@ } }, "node_modules/@oclif/config/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@oclif/core": { @@ -2710,9 +2738,9 @@ } }, "node_modules/@oclif/core/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@oclif/errors": { @@ -2930,9 +2958,9 @@ } }, "node_modules/@oclif/help/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@oclif/help/node_modules/wrap-ansi": { @@ -3042,9 +3070,9 @@ } }, "node_modules/@oclif/parser/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@oclif/plugin-help": { @@ -3073,9 +3101,9 @@ }, "node_modules/@openzeppelin/contracts5": { "name": "@openzeppelin/contracts", - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.0.2.tgz", - "integrity": "sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.0.0.tgz", + "integrity": "sha512-bv2sdS6LKqVVMLI5+zqnNrNU/CA+6z6CmwFXm/MzmOPBRSO5reEJN7z0Gbzvs0/bv/MZZXNklubpwy3v2+azsw==", "dev": true }, "node_modules/@openzeppelin/defender-admin-client": { @@ -3155,9 +3183,9 @@ } }, "node_modules/@openzeppelin/defender-sdk-base-client": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.14.4.tgz", - "integrity": "sha512-tOePVQLKpqfGQ1GMzHvSBNd2psPYd86LDNpvdl5gjD0Y2kW/zNh5qBXy29RraGtk/qc8zs9hzS5pAOh0vhGkGQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.15.0.tgz", + "integrity": "sha512-nuf/xegMIuKCO0hMrxI1KQKTzQw1iCl/9kew2nJM9MrFIohhfEXItc5rbJRoV/jehmK/Jhi9ATF9OHH09StEsQ==", "dev": true, "dependencies": { "amazon-cognito-identity-js": "^6.3.6", @@ -3165,26 +3193,26 @@ } }, "node_modules/@openzeppelin/defender-sdk-deploy-client": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.14.4.tgz", - "integrity": "sha512-+diSoz1zid37LMsY2RDxI+uAsYx9Eryg8Vz+yfvuyd56fXrzjQEln7BBtYQw+2zp9yvyAByOL5XSQdrQga9OBQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.15.0.tgz", + "integrity": "sha512-2ODMN4j5pPYWyIOvA/zRQmJ0tJyqi6NV3S/PyvufBXa3oj/MDnVO5bMGSQFH0M2VE3bg+i/rcUb0hdbX9Rtm5Q==", "dev": true, "dependencies": { - "@openzeppelin/defender-sdk-base-client": "^1.14.4", + "@openzeppelin/defender-sdk-base-client": "^1.15.0", "axios": "^1.7.2", "lodash": "^4.17.21" } }, "node_modules/@openzeppelin/hardhat-upgrades": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-2.5.0.tgz", - "integrity": "sha512-pRsqyRbp8LX9sTSMbL7jx4NjqjN/4PlKngmuAyRQIheYTGbRIs3FW3WyLuiCjkDlTETfmOsmzrnZxJmxDmxZIA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-2.5.1.tgz", + "integrity": "sha512-wRwq9f2PqlfIdNGFApsqRpqptqy98exSFp8SESb6Brgw4L07sExySInNJhscM/tWVSnR1Qnuws9Ck6Fs5zIxvg==", "dev": true, "dependencies": { "@openzeppelin/defender-admin-client": "^1.52.0", "@openzeppelin/defender-base-client": "^1.52.0", - "@openzeppelin/defender-sdk-base-client": "^1.5.0", - "@openzeppelin/defender-sdk-deploy-client": "^1.5.0", + "@openzeppelin/defender-sdk-base-client": "^1.8.0", + "@openzeppelin/defender-sdk-deploy-client": "^1.8.0", "@openzeppelin/upgrades-core": "^1.31.2", "chalk": "^4.1.0", "debug": "^4.1.1", @@ -3278,9 +3306,9 @@ } }, "node_modules/@openzeppelin/upgrades-core": { - "version": "1.38.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.38.0.tgz", - "integrity": "sha512-0kbc6Wd6S8/Kmhg7oqRIn+GBpAL+EccYQh+SjgVBEktpkzTDN56KHuuxYHXnpXclWaO6l7u/TRMe6LsHCHqJHw==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.40.0.tgz", + "integrity": "sha512-4bPSXdEqHsNRL5T1ybPLneWGYjzGl6XWGWkv7aUoFFgz8mOdarstRBX1Wi4XJFw6IeHPUI7mMSQr2jdz8Y2ypQ==", "dev": true, "dependencies": { "@nomicfoundation/slang": "^0.17.0", @@ -3813,9 +3841,9 @@ } }, "node_modules/@smithy/types": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.4.2.tgz", - "integrity": "sha512-tHiFcfcVedVBHpmHUEUHOCCih8iZbIAYn9NvPsNzaPm/237I3imdDdZoOC8c87H5HBAVEa06tTgb+OcSWV9g5w==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.6.0.tgz", + "integrity": "sha512-8VXK/KzOHefoC65yRgCn5vG1cysPJjHnOVt9d0ybFQSmJgQj152vMn4EkYhGuaOmnnZvCPav/KnYyE6/KsNZ2w==", "dev": true, "dependencies": { "tslib": "^2.6.2" @@ -3825,9 +3853,9 @@ } }, "node_modules/@smithy/types/node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "dev": true }, "node_modules/@solidity-parser/parser": { @@ -4015,19 +4043,19 @@ } }, "node_modules/@types/mocha": { - "version": "10.0.8", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.8.tgz", - "integrity": "sha512-HfMcUmy9hTMJh66VNcmeC9iVErIZJli2bszuXc6julh5YGuRb/W5OnkHjwLNYdFlMis0sY3If5SEAp+PktdJjw==", + "version": "10.0.9", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.9.tgz", + "integrity": "sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q==", "dev": true, "peer": true }, "node_modules/@types/node": { - "version": "22.7.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", - "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", + "version": "22.8.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.2.tgz", + "integrity": "sha512-NzaRNFV+FZkvK/KLCsNdTvID0SThyrs5SHB6tsD/lajr22FGC73N2QeDPM2wHtVde8mgcXuSsHQkH5cX1pbPLw==", "dev": true, "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.19.8" } }, "node_modules/@types/node-fetch": { @@ -4080,6 +4108,12 @@ "@types/node": "*" } }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "dev": true + }, "node_modules/@types/yargs": { "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", @@ -4155,9 +4189,9 @@ } }, "node_modules/acorn": { - "version": "8.12.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", - "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -5325,6 +5359,16 @@ "node": ">=0.10.0" } }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -5340,6 +5384,16 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -5350,6 +5404,16 @@ "node": ">=0.1.90" } }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dev": true, + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -5931,6 +5995,12 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "dev": true + }, "node_modules/encoding-down": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/encoding-down/-/encoding-down-6.3.0.tgz", @@ -6236,6 +6306,7 @@ "version": "8.57.1", "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", @@ -6357,9 +6428,9 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.30.0.tgz", - "integrity": "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==", + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", "dev": true, "peer": true, "dependencies": { @@ -6371,7 +6442,7 @@ "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.9.0", + "eslint-module-utils": "^2.12.0", "hasown": "^2.0.2", "is-core-module": "^2.15.1", "is-glob": "^4.0.3", @@ -6380,13 +6451,14 @@ "object.groupby": "^1.0.3", "object.values": "^1.2.0", "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "node_modules/eslint-plugin-import/node_modules/brace-expansion": { @@ -7008,9 +7080,9 @@ } }, "node_modules/ethers": { - "version": "6.13.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.2.tgz", - "integrity": "sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg==", + "version": "6.13.4", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.4.tgz", + "integrity": "sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA==", "dev": true, "funding": [ { @@ -7027,9 +7099,9 @@ "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", - "@types/node": "18.15.13", + "@types/node": "22.7.5", "aes-js": "4.0.0-beta.5", - "tslib": "2.4.0", + "tslib": "2.7.0", "ws": "8.17.1" }, "engines": { @@ -7037,16 +7109,19 @@ } }, "node_modules/ethers/node_modules/@types/node": { - "version": "18.15.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", "dev": true, - "peer": true + "peer": true, + "dependencies": { + "undici-types": "~6.19.2" + } }, "node_modules/ethers/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "dev": true, "peer": true }, @@ -7162,9 +7237,9 @@ "dev": true }, "node_modules/fast-uri": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.2.tgz", - "integrity": "sha512-GR6f0hD7XXyNJa25Tb9BuIdN0tdr+0BMi6/CJPH3wJO1JjNG3n/VsSw38AwRdKZABm8lGbPfakLRkYzx2V9row==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", "dev": true, "peer": true }, @@ -7177,6 +7252,12 @@ "reusify": "^1.0.4" } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "dev": true + }, "node_modules/ffjavascript": { "version": "0.2.63", "resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.2.63.tgz", @@ -7300,6 +7381,12 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", + "dev": true + }, "node_modules/follow-redirects": { "version": "1.15.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", @@ -7340,9 +7427,9 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "dev": true, "dependencies": { "asynckit": "^0.4.0", @@ -7387,20 +7474,6 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -16957,14 +17030,14 @@ } }, "node_modules/hardhat": { - "version": "2.22.12", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.12.tgz", - "integrity": "sha512-yok65M+LsOeTBHQsjg//QreGCyrsaNmeLVzhTFqlOvZ4ZE5y69N0wRxH1b2BC9dGK8S8OPUJMNiL9X0RAvbm8w==", + "version": "2.22.15", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.15.tgz", + "integrity": "sha512-BpTGa9PE/sKAaHi4s/S1e9WGv63DR1m7Lzfd60C8gSEchDPfAJssVRSq0MZ2v2k76ig9m0kHAwVLf5teYwu/Mw==", "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/edr": "^0.6.1", + "@nomicfoundation/edr": "^0.6.4", "@nomicfoundation/ethereumjs-common": "4.0.4", "@nomicfoundation/ethereumjs-tx": "5.0.4", "@nomicfoundation/ethereumjs-util": "9.0.4", @@ -17050,6 +17123,18 @@ "hardhat": "^2.0.2" } }, + "node_modules/hardhat-switch-network": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hardhat-switch-network/-/hardhat-switch-network-1.2.0.tgz", + "integrity": "sha512-z7YubwwQCBiZ+zwx6cnSQ+KryFxzOjOhRhBVFP8KEfEcJh8dhCcM8zuUb05j4m3GGSCSIpQSH98gAqoFlts+og==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "hardhat": "^2.0.0" + } + }, "node_modules/hardhat/node_modules/@noble/hashes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", @@ -17389,7 +17474,8 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", - "dev": true + "dev": true, + "peer": true }, "node_modules/hmac-drbg": { "version": "1.0.1", @@ -17637,7 +17723,6 @@ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true, - "peer": true, "engines": { "node": ">= 0.10" } @@ -17941,6 +18026,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -18243,9 +18340,9 @@ "dev": true }, "node_modules/json-stream-stringify": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/json-stream-stringify/-/json-stream-stringify-3.1.5.tgz", - "integrity": "sha512-wurRuTiw27mck9MWaUIGAunfwqhPDxnXQVN/+Rzi+IEQUUALU10AZs1nWkSdtjH7PAVuAUcqQjH11S/JHOWeaA==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz", + "integrity": "sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==", "dev": true, "engines": { "node": ">=7.10.1" @@ -18364,6 +18461,12 @@ "graceful-fs": "^4.1.11" } }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "dev": true + }, "node_modules/lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", @@ -18712,6 +18815,23 @@ "node": ">=8" } }, + "node_modules/logform": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", + "dev": true, + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/loupe": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", @@ -19453,6 +19573,15 @@ "wrappy": "1" } }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dev": true, + "dependencies": { + "fn.name": "1.x.x" + } + }, "node_modules/open": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", @@ -19869,9 +19998,9 @@ "dev": true }, "node_modules/pg": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.0.tgz", - "integrity": "sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw==", + "version": "8.13.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.13.1.tgz", + "integrity": "sha512-OUir1A0rPNZlX//c7ksiu7crsGZTKSOXJPgtNiHGIlC9H0lO+NC6ZDYksSgBYY/thSWhnSRBv8w1lieNNGATNQ==", "dev": true, "dependencies": { "pg-connection-string": "^2.7.0", @@ -20327,9 +20456,9 @@ } }, "node_modules/readdirp": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.1.tgz", - "integrity": "sha512-GkMg9uOTpIWWKbSsgwb5fA4EavTR+SG/PMPoAY8hkhHfEEY0/vqljY+XHqtDf2cr2IJtoNRDbrrEpZUiZCkYRw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", + "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", "dev": true, "engines": { "node": ">= 14.16.0" @@ -20344,7 +20473,6 @@ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", "dev": true, - "peer": true, "dependencies": { "resolve": "^1.1.6" }, @@ -20422,16 +20550,16 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", - "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", "dev": true, "peer": true, "dependencies": { - "call-bind": "^1.0.6", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-errors": "^1.3.0", - "set-function-name": "^2.0.1" + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -20732,6 +20860,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -20901,24 +21038,45 @@ "dev": true }, "node_modules/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", "dev": true, "hasInstallScript": true, "dependencies": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", "node-gyp-build": "^4.2.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=18.0.0" + } + }, + "node_modules/secp256k1/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/secp256k1/node_modules/elliptic": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", + "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" } }, "node_modules/secp256k1/node_modules/node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", "dev": true }, "node_modules/semaphore-async-await": { @@ -21052,7 +21210,6 @@ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", "dev": true, - "peer": true, "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", @@ -21089,6 +21246,21 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + }, "node_modules/slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -21192,6 +21364,49 @@ "node": ">=10.0.0" } }, + "node_modules/solc-0.8.17": { + "name": "solc", + "version": "0.8.17", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.17.tgz", + "integrity": "sha512-Dtidk2XtTTmkB3IKdyeg6wLYopJnBVxdoykN8oP8VY3PQjN16BScYoUJTXFm2OP7P0hXNAqWiJNmmfuELtLf8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "command-exists": "^1.2.8", + "commander": "^8.1.0", + "follow-redirects": "^1.12.1", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solc.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/solc-0.8.17/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/solc-0.8.17/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/solc-0.8/node_modules/commander": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", @@ -21536,6 +21751,15 @@ "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", "dev": true }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/stacktrace-parser": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", @@ -21893,6 +22117,12 @@ "deprecated": "testrpc has been renamed to ganache-cli, please use this package from now on.", "dev": true }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "dev": true + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -21930,15 +22160,16 @@ "peer": true }, "node_modules/then-request/node_modules/form-data": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", - "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.2.tgz", + "integrity": "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==", "dev": true, "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" + "mime-types": "^2.1.12", + "safe-buffer": "^5.2.1" }, "engines": { "node": ">= 0.12" @@ -22005,6 +22236,15 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "dev": true }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "dev": true, + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ts-command-line-args": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", @@ -22485,9 +22725,9 @@ "peer": true }, "node_modules/typescript": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz", - "integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "peer": true, "bin": { @@ -22847,6 +23087,48 @@ "node": ">= 0.10.0" } }, + "node_modules/winston": { + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.17.0.tgz", + "integrity": "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==", + "dev": true, + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.7.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.9.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", + "dev": true, + "dependencies": { + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston/node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/package.json b/package.json index 48a40a561..c55ac26b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@0xpolygonhermez/zkevm-contracts", - "description": "Core contracts for the Polygon Hermez zkEVM", + "description": "Core contracts for the Polygon Hermez zkEVM.", "version": "3.0.0", "repository": { "type": "git", @@ -30,12 +30,13 @@ "homepage": "https://github.com/0xPolygonHermez/contracts-zkEVM#readme", "license": "pending", "devDependencies": { - "@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#main", + "@0xpolygonhermez/zkevm-commonjs": "github:0xPolygonHermez/zkevm-commonjs#v8.0.0-fork.12", "@nomicfoundation/hardhat-toolbox": "^3.0.0", "@openzeppelin/contracts": "4.8.2", + "shelljs": "^0.8.5", "@openzeppelin/contracts-upgradeable": "4.8.2", - "@openzeppelin/contracts5": "npm:@openzeppelin/contracts@^5.0.0", - "@openzeppelin/hardhat-upgrades": "2.5.0", + "@openzeppelin/contracts5": "npm:@openzeppelin/contracts@5.0.0", + "@openzeppelin/hardhat-upgrades": "^2.5.1", "@types/yargs": "^17.0.28", "circomlibjs": "0.1.1", "dotenv": "^8.6.0", @@ -46,16 +47,21 @@ "ffjavascript": "^0.2.60", "hardhat": "^2.22.3", "hardhat-dependency-compiler": "^1.1.3", + "hardhat-switch-network": "^1.2.0", + "lodash": "^4.17.21", "prettier": "^2.8.8", - "prettier-plugin-solidity": "^1.1.3", + "prettier-plugin-solidity": "^1.4.1", "solc-0.8": "npm:solc@0.8.20", - "solidity-docgen": "^0.5.17" + "solc-0.8.17": "npm:solc@0.8.17", + "solidity-docgen": "^0.5.17", + "winston": "^3.17.0" }, "scripts": { "saveDeployment:goerli": "mkdir -p deployments/goerli_$(date +%s) && cp -r deployment/v2/deploy_*.json deployments/goerli_$(date +%s) && cp .openzeppelin/goerli.json deployments/goerli_$(date +%s) && cp deployment/v2/genesis.json deployments/goerli_$(date +%s) && cp deployment/v2/create_rollup_output.json deployments/goerli_$(date +%s)", "saveDeployment:mainnet": "mkdir -p deployments/mainnet_$(date +%s) && cp -r deployment/v2/deploy_*.json deployments/mainnet_$(date +%s) && cp .openzeppelin/mainnet.json deployments/mainnet_$(date +%s) && cp deployment/v2/genesis.json deployments/mainnet_$(date +%s) && cp deployment/v2/create_rollup_output.json deployments/mainnet_$(date +%s)", - "test": "npx hardhat test test/contractsv2/*ts", - "docgen": "npx solidity-docgen --solc-module solc-0.8 -t ./docs/templates -e ./contracts/verifiers,./contracts/mocks", + "test": "npx hardhat test test/contractsv2/*ts test/contractsv2/real-prover-sp1/*.ts test/src/*.ts", + "docgen": "npx solidity-docgen --solc-module solc-0.8 -t ./docs/templates -e ./contracts/verifiers,./contracts/mocks,./contracts/token-wrapped-bridge-compiled", + "docgen:0.8.17": "npx solidity-docgen --solc-module solc-0.8.17 -t ./docs/templates -i ./contracts/token-wrapped-bridge-compiled -o ./docs/token-wrapped-bridge", "prepare:testnet:ZkEVM:localhost": "npx hardhat run deployment/testnet/prepareTestnet.ts --network localhost", "deploy:ZkEVM:localhost": "rm -f .openzeppelin/unknown-*.json && node deployment/1_createGenesis.js && npx hardhat run deployment/2_deployPolygonZKEVMDeployer.js --network localhost && npx hardhat run deployment/3_deployContracts.js --network localhost", "deploy:testnet:ZkEVM:localhost": "npm run prepare:testnet:ZkEVM:localhost && npm run deploy:ZkEVM:localhost", @@ -112,4 +118,4 @@ "verify:upgradeV2:mainnet": "npx hardhat run upgrade/upgradeToV2/verifyContracts.ts --network mainnet", "saveUpgradeV2:mainnet": "mkdir -p upgrade/upgradeToV2/mainnet_$(date +%s) && cp -r upgrade/upgradeToV2/upgrade_*.json upgrade/upgradeToV2/mainnet_$(date +%s) && cp -r upgrade/upgradeToV2/deploy_*.json upgrade/upgradeToV2/mainnet_$(date +%s) && cp .openzeppelin/mainnet.json upgrade/upgradeToV2/mainnet_$(date +%s)" } -} +} \ No newline at end of file diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 000000000..941fbbe64 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,43 @@ +const ethers = require('ethers'); + +/// ///////////////////////////////// +/// TIMELOCK CONSTANTS ///////// +/// ///////////////////////////////// +const TIMELOCK = {}; +module.exports.TIMELOCK = TIMELOCK; +/* + * Since roles are used, most storage is written in pseudoRandom storage slots + * bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256("TIMELOCK_ADMIN_ROLE"); + * bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE"); + * bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); + * bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE"); + * note: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.2/contracts/governance/TimelockController.sol#L27 + */ +TIMELOCK.ROLES = { + TIMELOCK_ADMIN_ROLE: ethers.id('TIMELOCK_ADMIN_ROLE'), + PROPOSER_ROLE: ethers.id('PROPOSER_ROLE'), + EXECUTOR_ROLE: ethers.id('EXECUTOR_ROLE'), + CANCELLER_ROLE: ethers.id('CANCELLER_ROLE'), +}; + +TIMELOCK.ROLES_HASH = [ + ethers.id('TIMELOCK_ADMIN_ROLE'), + ethers.id('PROPOSER_ROLE'), + ethers.id('EXECUTOR_ROLE'), + ethers.id('CANCELLER_ROLE'), +]; + +/* + * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.2/contracts/governance/TimelockController.sol#L27 + * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.2/contracts/access/AccessControl.sol#L55 + */ +TIMELOCK.ROLES_MAPPING_STORAGE_POS = 0; + +// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.2/contracts/governance/TimelockController.sol#L34 +TIMELOCK.MINDELAY_STORAGE_POS = 2; + +/// ///////////////////////////////// +/// STORAGE CONSTANTS ////////// +/// ///////////////////////////////// +module.exports.STORAGE_ONE_VALUE = '0x0000000000000000000000000000000000000000000000000000000000000001'; +module.exports.STORAGE_ZERO_VALUE = '0x0000000000000000000000000000000000000000000000000000000000000000'; diff --git a/src/create-genesis.js b/src/create-genesis-old.js similarity index 100% rename from src/create-genesis.js rename to src/create-genesis-old.js diff --git a/src/genesis/genesis-helpers.js b/src/genesis/genesis-helpers.js new file mode 100644 index 000000000..b3500e7ec --- /dev/null +++ b/src/genesis/genesis-helpers.js @@ -0,0 +1,65 @@ +const ethers = require('ethers'); + +const { TIMELOCK, STORAGE_ONE_VALUE } = require('../constants'); +const { valueToStorageBytes } = require('../utils'); + +function setupRole(storage, address, roleHash) { + const storagePosition = ethers.solidityPackedKeccak256( + ['uint256', 'uint256'], + [roleHash, TIMELOCK.ROLES_MAPPING_STORAGE_POS], + ); + + const storagePositionRole = ethers.solidityPackedKeccak256( + ['uint256', 'uint256'], + [address, storagePosition], + ); + + storage[storagePositionRole] = STORAGE_ONE_VALUE; +} + +/** + * This function aims to compute te storage when the timelock is deployed + * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.2/contracts/governance/TimelockController.sol#L77 + * @param {number} minDelay - Minimum delay for the timelock + * @param {string} adminAddress - Grant admin, proposer, executor and canceller roles to this address + * @param {string} timelockAddress - Grant admin to this address + * @returns {Object} - Timelock storage slots + */ +function initializeTimelockStorage(minDelay, adminAddress, timelockAddress) { + const storage = {}; + + // set TIMELOCK_ADMIN_ROLE as an adminRole to all timelock roles + for (let i = 0; i < TIMELOCK.ROLES_HASH.length; i++) { + const storagePosition = ethers.solidityPackedKeccak256( + ['uint256', 'uint256'], + [TIMELOCK.ROLES_HASH[i], TIMELOCK.ROLES_MAPPING_STORAGE_POS], + ); + + // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.8.2/contracts/access/AccessControl.sol#L52 + const roleAdminSlot = ethers.zeroPadValue(ethers.toQuantity(ethers.toBigInt(storagePosition) + BigInt(1)), 32); + + storage[roleAdminSlot] = TIMELOCK.ROLES.TIMELOCK_ADMIN_ROLE; + } + + // Self administration + setupRole(storage, timelockAddress, TIMELOCK.ROLES.TIMELOCK_ADMIN_ROLE); + + // admin tole + setupRole(storage, adminAddress, TIMELOCK.ROLES.TIMELOCK_ADMIN_ROLE); + + // register proposers and cancellers + setupRole(storage, adminAddress, TIMELOCK.ROLES.PROPOSER_ROLE); + setupRole(storage, adminAddress, TIMELOCK.ROLES.CANCELLER_ROLE); + + // register executors + setupRole(storage, adminAddress, TIMELOCK.ROLES.EXECUTOR_ROLE); + + // set minDelay + storage[valueToStorageBytes(TIMELOCK.MINDELAY_STORAGE_POS)] = valueToStorageBytes(minDelay); + + return storage; +} + +module.exports = { + initializeTimelockStorage, +}; diff --git a/src/logger.js b/src/logger.js new file mode 100644 index 000000000..cc70244fb --- /dev/null +++ b/src/logger.js @@ -0,0 +1,16 @@ +const winston = require('winston'); + +// Create Winston logger with console transport only +const logger = winston.createLogger({ + level: 'debug', // Set log level (error, warn, info, debug) + format: winston.format.combine( + winston.format.colorize(), // Adds color to console logs + winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), // Adds timestamp + winston.format.printf(({ timestamp, level, message }) => `${timestamp} [${level}]: ${message}`), // Custom format + ), + transports: [ + new winston.transports.Console(), // Logs only to the terminal + ], +}); + +module.exports.logger = logger; diff --git a/src/pessimistic-utils.js b/src/pessimistic-utils.js new file mode 100644 index 000000000..a1c0bdac3 --- /dev/null +++ b/src/pessimistic-utils.js @@ -0,0 +1,70 @@ +const ethers = require('ethers'); + +const VerifierType = { + StateTransition: 0, + Pessimistic: 1, +}; + +const ConsensusTypes = { + Ecdsa: 0, +}; + +const ConsensusContracts = { + PolygonZkEVMEtrog: 'PolygonZkEVMEtrog', + PolygonValidiumEtrog: 'PolygonValidiumEtrog', + PolygonPessimisticConsensus: 'PolygonPessimisticConsensus', + +}; +/** + * Compute input for SNARK circuit: sha256( + * initStateRoot, initBlobStateRoot, initBlobAccInputHash, initNumBlob, chainId, forkID + * finalStateRoot, finalBlobStateRoot, finalBlobAccInputHash, finalNumBlob, finalLocalExitRoot + * aggregatorAddress + * ) % FrSNARK + * @param {String} lastLocalExitRoot - old LER + * @param {String} lastPessimisticRoot - old pessimistic root. pessRoor = Poseidon(LBR # nullifierRoot) + * @param {String} l1InfoTreeRoot - L1 info tree root + * @param {Number} rollupID - rollup identifier (networkID = rollupID - 1) + * @param {String} consensusHash - consensus hash. consensusHash = Sha(consensusType # consensusPayload) + * @param {String} newLocalExitRoot - new LER + * @param {String} newPessimisticRoot - new pessimistic root + */ +function computeInputPessimisticBytes( + lastLocalExitRoot, + lastPessimisticRoot, + l1InfoTreeRoot, + rollupID, + consensusHash, + newLocalExitRoot, + newPessimisticRoot, +) { + return ethers.solidityPacked( + ['bytes32', 'bytes32', 'bytes32', 'uint32', 'bytes32', 'bytes32', 'bytes32'], + [ + lastLocalExitRoot, + lastPessimisticRoot, + l1InfoTreeRoot, + rollupID, + consensusHash, + newLocalExitRoot, + newPessimisticRoot, + ], + ); +} + +/** + * Computes consensus hash + * @param address - Signer of the message in the pessimsistic proof + * @returns consensus hash + */ +function computeConsensusHashEcdsa(address) { + return ethers.solidityPackedKeccak256(['uint32', 'address'], [ConsensusTypes.Ecdsa, address]); +} + +module.exports = { + VerifierType, + ConsensusTypes, + computeInputPessimisticBytes, + computeConsensusHashEcdsa, + ConsensusContracts, +}; diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 000000000..44185218a --- /dev/null +++ b/src/utils.js @@ -0,0 +1,99 @@ +const { Scalar } = require('ffjavascript'); + +/** + * Check if all params are present in the expectedParams + * @param {Object} objParams - object with parameters + * @param {Array} expectedParams - array of expected parameters in string + */ +function checkParams(objParams, expectedParams) { + // eslint-disable-next-line no-restricted-syntax + for (const parameterName of expectedParams) { + if (objParams[parameterName] === undefined || objParams[parameterName] === '') { + throw new Error(`Missing parameter: ${parameterName}`); + } + } +} + +/** + * Convert a value into in its hexadecimal string representation + * @param {Number | BigInt} _value - value to encode + * @param {Boolean} prefix - attach '0x' at the beginning of the string + * @returns {String} encoded value in hexadecimal string + */ +function valueToHexStr(_value, prefix = false) { + if (!(typeof _value === 'number' || typeof _value === 'bigint')) { + throw new Error('valueToHexStr: _value is not a number or BigInt type'); + } + + if (prefix !== false && typeof prefix !== 'boolean') { + throw new Error('valueToHexStr: _prefix is not a boolean'); + } + + let valueHex = Scalar.e(_value).toString(16); + valueHex = valueHex.length % 2 ? `0${valueHex}` : valueHex; + + return prefix ? `0x${valueHex}` : valueHex; +} + +/** + * Pad a string hex number with 0 + * @param {String} str - String input + * @param {Number} length - Length of the resulting string + * @returns {String} Resulting string + */ +function padZeros(str, length) { + if (length > str.length) { + str = '0'.repeat(length - str.length) + str; + } + + return str; +} + +/** + * Convert a value into in its hexadecimal string representation with 32 bytes padding + * @param {Number | BigInt} _value - value to encode + * @returns {String} encoded value in hexadecimal string + */ +function valueToStorageBytes(_value) { + const valueHex = valueToHexStr(_value, false); + return `0x${padZeros(valueHex, 64)}`; +} + +/** + * Scan all SSTORE opcodes in a trace + * Does not take into account revert operations neither depth + * @param {Object} trace + * @returns {Object} - storage writes: {"key": "value"} + */ +function getStorageWrites(trace) { + const writes = trace.structLogs + .filter((log) => log.op === 'SSTORE') + .map((log) => { + const [newValue, slot] = log.stack.slice(-2); + return { newValue, slot }; + }); + + // print all storage writes in an object fashion style + const writeObject = {}; + writes.forEach((write) => { + writeObject[`0x${write.slot}`] = `0x${write.newValue}`; + }); + + return writeObject; +} + +/** + * Get all SLOAD and SSTORE in a trace + * @param {Object} trace + * @returns {Object} - storage read and writes: {"key": "value"} + */ +function getStorageReadWrites(trace) { + return trace.structLogs[trace.structLogs.length - 1].storage; +} + +module.exports = { + getStorageWrites, + getStorageReadWrites, + valueToStorageBytes, + checkParams, +}; diff --git a/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts b/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts new file mode 100644 index 000000000..5ad44a2ea --- /dev/null +++ b/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts @@ -0,0 +1,1562 @@ +import {expect} from "chai"; +import {ethers, upgrades} from "hardhat"; +import { + ERC20PermitMock, + GlobalExitRootManagerL2SovereignChain, + BridgeL2SovereignChain, + TokenWrapped, +} from "../../typechain-types"; +import {takeSnapshot, time} from "@nomicfoundation/hardhat-network-helpers"; +import {processorUtils, contractUtils, MTBridge, mtBridgeUtils} from "@0xpolygonhermez/zkevm-commonjs"; +const {calculateSnarkInput, calculateAccInputHash, calculateBatchHashData} = contractUtils; +const MerkleTreeBridge = MTBridge; +const {verifyMerkleProof, getLeafValue} = mtBridgeUtils; +import {setBalance} from "@nomicfoundation/hardhat-network-helpers"; + +function calculateGlobalExitRoot(mainnetExitRoot: any, rollupExitRoot: any) { + return ethers.solidityPackedKeccak256(["bytes32", "bytes32"], [mainnetExitRoot, rollupExitRoot]); +} +const _GLOBAL_INDEX_MAINNET_FLAG = 2n ** 64n; + +function computeGlobalIndex(indexLocal: any, indexRollup: any, isMainnet: Boolean) { + if (isMainnet === true) { + return BigInt(indexLocal) + _GLOBAL_INDEX_MAINNET_FLAG; + } else { + return BigInt(indexLocal) + BigInt(indexRollup) * 2n ** 32n; + } +} + +describe("SovereignChainBridge Gas tokens tests", () => { + upgrades.silenceWarnings(); + + let sovereignChainBridgeContract: BridgeL2SovereignChain; + let polTokenContract: ERC20PermitMock; + let sovereignChainGlobalExitRoot: GlobalExitRootManagerL2SovereignChain; + + let deployer: any; + let rollupManager: any; + let acc1: any; + let bridgeManager: any; + + const tokenName = "Matic Token"; + const tokenSymbol = "MATIC"; + const decimals = 18; + const tokenInitialBalance = ethers.parseEther("20000000"); + const metadataToken = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [tokenName, tokenSymbol, decimals] + ); + const networkIDMainnet = 0; + const networkIDRollup = 1; + const networkIDRollup2 = 2; + + const LEAF_TYPE_ASSET = 0; + const LEAF_TYPE_MESSAGE = 1; + + let gasTokenAddress: any; + let gasTokenNetwork: any; + let gasTokenMetadata: any; + let WETHToken: TokenWrapped; + + beforeEach("Deploy contracts", async () => { + // load signers + [deployer, rollupManager, acc1, bridgeManager] = await ethers.getSigners(); + + // Set trusted sequencer as coinbase for sovereign chains + await ethers.provider.send("hardhat_setCoinbase", [deployer.address]); + // deploy PolygonZkEVMBridge + const BridgeL2SovereignChainFactory = await ethers.getContractFactory("BridgeL2SovereignChain"); + sovereignChainBridgeContract = (await upgrades.deployProxy(BridgeL2SovereignChainFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + })) as unknown as BridgeL2SovereignChain; + + // deploy global exit root manager + const SovereignChainGlobalExitRootFactory = await ethers.getContractFactory( + "GlobalExitRootManagerL2SovereignChain" + ); + sovereignChainGlobalExitRoot = await SovereignChainGlobalExitRootFactory.deploy( + sovereignChainBridgeContract.target + ); + + // deploy weth token by bridge + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + polTokenContract = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + WETHToken = await tokenWrappedFactory + .connect(bridgeMock) + .deploy(tokenName, tokenSymbol, decimals, {gasPrice: 0}); + + gasTokenAddress = polTokenContract.target; + gasTokenNetwork = 0; + gasTokenMetadata = metadataToken; + + await sovereignChainBridgeContract.initialize( + networkIDRollup2, + polTokenContract.target, // zero for ether + 0, // zero for ether + sovereignChainGlobalExitRoot.target, + rollupManager.address, + metadataToken, + ethers.Typed.address(bridgeManager.address), + WETHToken.target, + false, + ); + expect(await sovereignChainBridgeContract.WETHToken()).to.be.equal(WETHToken.target); + }); + + it("should claim message from not mintable remapped gas (WETH) token", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDRollup; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x176923791298713271763697869132"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + // deploy sovereign + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + const sovereignToken = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRoot.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + // Remap weth token + await expect( + sovereignChainBridgeContract.connect(bridgeManager).setSovereignWETHAddress(sovereignToken.target, true) + ) + .to.emit(sovereignChainBridgeContract, "SetSovereignWETHAddress") + .withArgs(sovereignToken.target, true); + // try claim without balance to transfer (from bridge) + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.revertedWith("ERC20: transfer amount exceeds balance"); + // Transfer tokens to bridge + await sovereignToken.transfer(sovereignChainBridgeContract.target, amount); + const balanceBridge = await sovereignToken.balanceOf(sovereignChainBridgeContract.target); + + // Check balances before claim + expect(balanceBridge).to.be.equal(amount); + // Claim message + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, sovereignToken.target, destinationAddress, amount); + + // Check balances after claim + expect(await sovereignToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(ethers.parseEther("0")); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should check the constructor parameters", async () => { + expect(await sovereignChainBridgeContract.globalExitRootManager()).to.be.equal( + sovereignChainGlobalExitRoot.target + ); + expect(await sovereignChainBridgeContract.networkID()).to.be.equal(networkIDRollup2); + expect(await sovereignChainBridgeContract.polygonRollupManager()).to.be.equal(rollupManager.address); + + expect(await sovereignChainBridgeContract.gasTokenAddress()).to.be.equal(gasTokenAddress); + expect(await sovereignChainBridgeContract.gasTokenNetwork()).to.be.equal(gasTokenNetwork); + expect(await sovereignChainBridgeContract.gasTokenMetadata()).to.be.equal(gasTokenMetadata); + }); + + it("should SovereignChain bridge asset and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const mainnetExitRoot = ethers.ZeroHash; + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSSovereignRollup = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: 1} + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "MsgValueNotZero"); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSSovereignRollup); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet) + ).to.be.equal(true); + }); + + it("should PolygonZkEVMBridge message and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const originAddress = deployer.address; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + const mainnetExitRoot = ethers.ZeroHash; + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSSovereignChain = merkleTree.getRoot(); + + // using gas TOkens cannot use bridge message with etther + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, true, metadata, { + value: amount, + }) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NoValueInMessagesOnGasTokenNetworks"); + + // Use bridgeMessageWETH instead! + + // cannot use value + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + true, + metadata, + { + value: amount, + } + ) + ).to.be.reverted; + + // Use bridgeMessageWETH instead! + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + true, + metadata + ) + ).to.be.revertedWith("ERC20: burn amount exceeds balance"); + + // Mock mint weth + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + + await WETHToken.connect(bridgeMock).mint(deployer.address, amount, {gasPrice: 0}); + + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + true, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + // check merkle root with SC + const rootSCSovereignChain = await sovereignChainBridgeContract.getRoot(); + expect(rootSCSovereignChain).to.be.equal(rootJSSovereignChain); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCSovereignChain)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCSovereignChain) + ).to.be.equal(true); + + // bridge message without value is fine + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, true, metadata, {}) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + 0, + metadata, + depositCount + 1n + ); + }); + + it("should SovereignChain bridge asset and message to check global exit root updates", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const mainnetExitRoot = ethers.ZeroHash; + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSSovereignChain = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + false, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(0); + expect(mainnetExitRoot).to.be.equal(ethers.ZeroHash); + + // check merkle root with SC + const rootSCSovereignChain = await sovereignChainBridgeContract.getRoot(); + expect(rootSCSovereignChain).to.be.equal(rootJSSovereignChain); + + // Update global exit root + await expect(sovereignChainBridgeContract.updateGlobalExitRoot()); + + // no state changes since there are not any deposit pending to be updated + await sovereignChainBridgeContract.updateGlobalExitRoot(); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + expect(mainnetExitRoot).to.be.equal(mainnetExitRoot); + + // bridge message + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, false, metadata, { + value: amount, + }) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NoValueInMessagesOnGasTokenNetworks"); + + // Mock mint weth + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await WETHToken.connect(bridgeMock).mint(deployer.address, amount, {gasPrice: 0}); + + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + false, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + deployer.address, + destinationNetwork, + destinationAddress, + amount, + metadata, + 1 + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + expect(mainnetExitRoot).to.be.equal(mainnetExitRoot); + + // Update global exit root + await sovereignChainBridgeContract.updateGlobalExitRoot(); + + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(2); + expect(mainnetExitRoot).to.not.be.equal(rootJSSovereignChain); + + // Just to have the metric of a low cost bridge Asset + const tokenAddress2 = WETHToken.target; // Ether + const amount2 = ethers.parseEther("10"); + await WETHToken.connect(bridgeMock).mint(deployer.address, amount2, {gasPrice: 0}); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount2, + tokenAddress2, + false, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + 0, // weth bridge + ethers.ZeroAddress, + destinationNetwork, + destinationAddress, + amount2, + "0x", + 2 + ) + .to.emit(WETHToken, "Transfer") + .withArgs(deployer.address, ethers.ZeroAddress, amount2); + }); + + it("should claim Gas tokens from SovereignChain to SovereignChain", async () => { + const originNetwork = networkIDMainnet; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = acc1.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + const indexRollup = 5; + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + if (i == indexRollup) { + merkleTreeRollup.add(rootLocalRollup); + } else { + merkleTreeRollup.add(ethers.toBeHex(ethers.toQuantity(ethers.randomBytes(32)), 32)); + } + } + const rootRollup = merkleTreeRollup.getRoot(); + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRoot.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRoot, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const sovereignChainExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(sovereignChainExitRootSC).to.be.equal(rootRollup); + const mainnetExitRootSC = ethers.ZeroHash; + expect(mainnetExitRootSC).to.be.equal(mainnetExitRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rootRollup); + + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + // check merkle proof + + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof rollup + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, indexLocal, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + + /* + * claim + * Can't claim without native (ether) + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + rootLocalRollup, + sovereignChainExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.reverted; + + await setBalance(sovereignChainBridgeContract.target as any, amount); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + const initialBalance = await ethers.provider.getBalance(sovereignChainBridgeContract.target); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + sovereignChainExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + { + gasPrice: 0, + } + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + sovereignChainExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + expect(initialBalance - amount).to.be.equal( + await ethers.provider.getBalance(sovereignChainBridgeContract.target) + ); + }); + + it("should claim tokens from SovereignChain to SovereignChain2", async () => { + const originNetwork = networkIDRollup; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + merkleTreeRollup.add(rootLocalRollup); + } + + const rootRollup = merkleTreeRollup.getRoot(); + + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRoot.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRoot, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rootRollup); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + // check merkle proof + + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof local + const indexRollup = 5; + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, indexLocal, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup) + ).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + // claim + const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); + // create2 parameters + const salt = ethers.solidityPackedKeccak256(["uint32", "address"], [networkIDRollup, tokenAddress]); + const minimalBytecodeProxy = await sovereignChainBridgeContract.BASE_INIT_BYTECODE_WRAPPED_TOKEN(); + const hashInitCode = ethers.solidityPackedKeccak256(["bytes", "bytes"], [minimalBytecodeProxy, metadataToken]); + const precalculateWrappedErc20 = await ethers.getCreate2Address( + sovereignChainBridgeContract.target as string, + salt, + hashInitCode + ); + const newWrappedToken = tokenWrappedFactory.attach(precalculateWrappedErc20) as TokenWrapped; + + // Use precalculatedWrapperAddress and check if matches + expect( + await sovereignChainBridgeContract.precalculatedWrapperAddress( + networkIDRollup, + tokenAddress, + tokenName, + tokenSymbol, + decimals + ) + ).to.be.equal(precalculateWrappedErc20); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(sovereignChainBridgeContract, "NewWrappedToken") + .withArgs(originNetwork, tokenAddress, precalculateWrappedErc20, metadata) + .to.emit(newWrappedToken, "Transfer") + .withArgs(ethers.ZeroAddress, destinationAddress, amount); + + const newTokenInfo = await sovereignChainBridgeContract.wrappedTokenToTokenInfo(precalculateWrappedErc20); + + expect(newTokenInfo.originNetwork).to.be.equal(networkIDRollup); + expect(newTokenInfo.originTokenAddress).to.be.equal(tokenAddress); + expect(await sovereignChainBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( + precalculateWrappedErc20 + ); + expect(await sovereignChainBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( + precalculateWrappedErc20 + ); + + expect(await sovereignChainBridgeContract.tokenInfoToWrappedToken(salt)).to.be.equal(precalculateWrappedErc20); + + // Check the wrapper info + expect(await newWrappedToken.name()).to.be.equal(tokenName); + expect(await newWrappedToken.symbol()).to.be.equal(tokenSymbol); + expect(await newWrappedToken.decimals()).to.be.equal(decimals); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + expect(await newWrappedToken.totalSupply()).to.be.equal(amount); + + // Claim again the other leaf to mint tokens + const index2 = 1; + const proof2 = merkleTreeLocal.getProofTreeByIndex(index2); + + expect(verifyMerkleProof(leafValue, proof2, index2, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rollupExitRootSC)).to.be.equal(true); + + const globalIndex2 = computeGlobalIndex(index2, indexRollup, false); + await expect( + sovereignChainBridgeContract.claimAsset( + proof2, + proofRollup, + globalIndex2, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex2, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(newWrappedToken, "Transfer") + .withArgs(ethers.ZeroAddress, destinationAddress, amount); + + // Burn Tokens + const depositCount = await sovereignChainBridgeContract.depositCount(); + const wrappedTokenAddress = newWrappedToken.target; + const newDestinationNetwork = networkIDRollup; + + const rollupExitRoot = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + + // create a new deposit + await expect(newWrappedToken.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(newWrappedToken, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + /* + * pre compute root merkle tree in Js + * const height = 32; + */ + const merkleTreeMainnet = new MerkleTreeBridge(height); + // Imporant calcualte leaf with origin token address no wrapped token address + const originTokenAddress = tokenAddress; + const metadataMainnet = metadata; // since the token does not belong to this network + const metadataHashMainnet = ethers.solidityPackedKeccak256(["bytes"], [metadataMainnet]); + + const leafValueMainnet = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataHashMainnet + ); + const leafValueMainnetSC = await sovereignChainBridgeContract.getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataHashMainnet + ); + + expect(leafValueMainnet).to.be.equal(leafValueMainnetSC); + merkleTreeMainnet.add(leafValueMainnet); + const rootJSMainnet = ethers.ZeroHash; + + // Tokens are burnt + expect(await newWrappedToken.totalSupply()).to.be.equal(amount * 2n); + expect(await newWrappedToken.balanceOf(destinationAddress)).to.be.equal(amount * 2n); + await expect( + sovereignChainBridgeContract.bridgeAsset( + newDestinationNetwork, + destinationAddress, + amount, + wrappedTokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataMainnet, + depositCount + ) + .to.emit(newWrappedToken, "Transfer") + .withArgs(deployer.address, ethers.ZeroAddress, amount); + + expect(await newWrappedToken.totalSupply()).to.be.equal(amount); + expect(await newWrappedToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await newWrappedToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(0); + + // check merkle root with SC + const rootSCSovereignChain = await sovereignChainBridgeContract.getRoot(); + + // check merkle proof + const proofMainnet = merkleTreeMainnet.getProofTreeByIndex(0); + const indexMainnet = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValueMainnet, proofMainnet, indexMainnet, rootSCSovereignChain)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof( + leafValueMainnet, + proofMainnet, + indexMainnet, + rootSCSovereignChain + ) + ).to.be.equal(true); + }); + + it("should PolygonZkEVMBridge and sync the current root with events", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // gasToken + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + // create 3 new deposit + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + gasTokenAddress, + destinationNetwork, + destinationAddress, + amount, + gasTokenMetadata, + depositCount + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + gasTokenAddress, + destinationNetwork, + destinationAddress, + amount, + gasTokenMetadata, + depositCount + 1n + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + gasTokenAddress, + destinationNetwork, + destinationAddress, + amount, + gasTokenMetadata, + depositCount + 2n + ); + + // Prepare merkle tree + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + + // Get the deposit's events + const filter = sovereignChainBridgeContract.filters.BridgeEvent( + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined + ); + const events = await sovereignChainBridgeContract.queryFilter(filter, 0, "latest"); + events.forEach((e) => { + const {args} = e; + const leafValue = getLeafValue( + args.leafType, + args.originNetwork, + args.originAddress, + args.destinationNetwork, + args.destinationAddress, + args.amount, + ethers.solidityPackedKeccak256(["bytes"], [args.metadata]) + ); + merkleTree.add(leafValue); + }); + + // Check merkle root with SC + const rootSC = await sovereignChainBridgeContract.getRoot(); + const rootJS = merkleTree.getRoot(); + + expect(rootSC).to.be.equal(rootJS); + }); + + it("should claim testing all the asserts", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + const globalIndex = computeGlobalIndex(index, index, false); + // Can't claim without tokens + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.reverted; + + await setBalance(sovereignChainBridgeContract.target as any, amount); + + // Check GlobalExitRoot invalid assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + mainnetExitRoot, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "GlobalExitRootInvalid"); + + // Check Invalid smt proof assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex + 1n, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount); + + // Check Already claimed_claim + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim ether", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + // claim weth + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(WETHToken, "Transfer") + .withArgs(ethers.ZeroAddress, deployer.address, amount); + + // Check balances after claim + expect(await WETHToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await WETHToken.totalSupply()).to.be.equal(amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim message", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x176923791298713271763697869132"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRoot.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRoot.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + + // Insert global exit root + expect(await sovereignChainGlobalExitRoot.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRoot, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + /* + * claim + * Can't claim a message as an assets + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + const balanceDeployer = await ethers.provider.getBalance(deployer.address); + + // Check mainnet destination assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(WETHToken, "Transfer") + .withArgs(ethers.ZeroAddress, deployer.address, amount); + + // Check balances after claim + expect(await WETHToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await WETHToken.totalSupply()).to.be.equal(amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); +}); diff --git a/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts b/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts new file mode 100644 index 000000000..a8189f324 --- /dev/null +++ b/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts @@ -0,0 +1,1603 @@ +import {expect} from "chai"; +import {ethers, upgrades} from "hardhat"; +import { + ERC20PermitMock, + GlobalExitRootManagerL2SovereignChain, + BridgeL2SovereignChain, + TokenWrapped, +} from "../../typechain-types"; +import {takeSnapshot, time} from "@nomicfoundation/hardhat-network-helpers"; +import {processorUtils, contractUtils, MTBridge, mtBridgeUtils} from "@0xpolygonhermez/zkevm-commonjs"; +const {calculateSnarkInput, calculateAccInputHash, calculateBatchHashData} = contractUtils; +const MerkleTreeBridge = MTBridge; +const {verifyMerkleProof, getLeafValue} = mtBridgeUtils; +import {setBalance} from "@nomicfoundation/hardhat-network-helpers"; + +function calculateGlobalExitRoot(mainnetExitRoot: any, rollupExitRoot: any) { + return ethers.solidityPackedKeccak256(["bytes32", "bytes32"], [mainnetExitRoot, rollupExitRoot]); +} +const _GLOBAL_INDEX_MAINNET_FLAG = 2n ** 64n; + +function computeGlobalIndex(indexLocal: any, indexRollup: any, isMainnet: Boolean) { + if (isMainnet === true) { + return BigInt(indexLocal) + _GLOBAL_INDEX_MAINNET_FLAG; + } else { + return BigInt(indexLocal) + BigInt(indexRollup) * 2n ** 32n; + } +} + +describe("SovereignChainBridge Gas tokens tests", () => { + upgrades.silenceWarnings(); + + let sovereignChainBridgeContract: BridgeL2SovereignChain; + let polTokenContract: ERC20PermitMock; + let sovereignChainGlobalExitRootContract: GlobalExitRootManagerL2SovereignChain; + + let deployer: any; + let rollupManager: any; + let acc1: any; + let bridgeManager: any; + + const tokenName = "Matic Token"; + const tokenSymbol = "MATIC"; + const decimals = 18; + const tokenInitialBalance = ethers.parseEther("20000000"); + const metadataToken = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [tokenName, tokenSymbol, decimals] + ); + const networkIDMainnet = 0; + const networkIDRollup = 1; + const networkIDRollup2 = 2; + + const LEAF_TYPE_ASSET = 0; + const LEAF_TYPE_MESSAGE = 1; + + let gasTokenAddress: any; + let gasTokenNetwork: any; + let gasTokenMetadata: any; + let WETHToken: TokenWrapped; + + beforeEach("Deploy contracts", async () => { + // load signers + [deployer, rollupManager, acc1, bridgeManager] = await ethers.getSigners(); + + // Set trusted sequencer as coinbase for sovereign chains + await ethers.provider.send("hardhat_setCoinbase", [deployer.address]); + // deploy PolygonZkEVMBridge + const BridgeL2SovereignChainFactory = await ethers.getContractFactory("BridgeL2SovereignChain"); + sovereignChainBridgeContract = (await upgrades.deployProxy(BridgeL2SovereignChainFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + })) as unknown as BridgeL2SovereignChain; + + // deploy global exit root manager + const GlobalExitRootManagerL2SovereignChainFactory = await ethers.getContractFactory( + "GlobalExitRootManagerL2SovereignChain" + ); + sovereignChainGlobalExitRootContract = (await upgrades.deployProxy( + GlobalExitRootManagerL2SovereignChainFactory, + [deployer.address, deployer.address], // Initializer params + { + initializer: "initialize", // initializer function name + constructorArgs: [sovereignChainBridgeContract.target], // Constructor arguments + unsafeAllow: ["constructor", "state-variable-immutable"], + } + )) as unknown as GlobalExitRootManagerL2SovereignChain; + + // deploy token + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + polTokenContract = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + + gasTokenAddress = polTokenContract.target; + gasTokenNetwork = 0; + gasTokenMetadata = metadataToken; + + await expect( + sovereignChainBridgeContract.initialize( + networkIDRollup2, + polTokenContract.target, + 0, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + metadataToken, + ethers.Typed.address(bridgeManager.address), + ethers.ZeroAddress, + true, // Not false, revert + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSovereignWETHAddressParams"); + + await sovereignChainBridgeContract.initialize( + networkIDRollup2, + polTokenContract.target, // zero for ether + 0, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + metadataToken, + ethers.Typed.address(bridgeManager.address), + ethers.ZeroAddress, + false, + ); + + // calculate the weth address: + const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); + // create2 parameters + const minimalBytecodeProxy = await sovereignChainBridgeContract.BASE_INIT_BYTECODE_WRAPPED_TOKEN(); + const WETHName = "Wrapped Ether"; + const WETHSymbol = "WETH"; + const WETHDecimals = 18; + const metadataWETH = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [WETHName, WETHSymbol, WETHDecimals] + ); + + const hashInitCode = ethers.solidityPackedKeccak256(["bytes", "bytes"], [minimalBytecodeProxy, metadataWETH]); + const precalculatedWeth = await ethers.getCreate2Address( + sovereignChainBridgeContract.target as string, + ethers.ZeroHash, // salt is zero + hashInitCode + ); + WETHToken = tokenWrappedFactory.attach(precalculatedWeth) as TokenWrapped; + + expect(await sovereignChainBridgeContract.WETHToken()).to.be.equal(WETHToken.target); + }); + + it("should claim message from not mintable remapped gas (WETH) token", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDRollup; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x176923791298713271763697869132"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + // deploy sovereign + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + const sovereignToken = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + + // Try to insert global exit root with non coinbase + await expect( + sovereignChainGlobalExitRootContract.connect(acc1).insertGlobalExitRoot(computedGlobalExitRoot) + ).to.be.revertedWithCustomError(sovereignChainGlobalExitRootContract, "OnlyGlobalExitRootUpdater"); + + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + // Remap weth token + await expect(sovereignChainBridgeContract.connect(bridgeManager).setSovereignWETHAddress(sovereignToken.target, true)) + .to.emit(sovereignChainBridgeContract, "SetSovereignWETHAddress") + .withArgs(sovereignToken.target, true); + // try claim without balance to transfer (from bridge) + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.revertedWith("ERC20: transfer amount exceeds balance"); + // Transfer tokens to bridge + await sovereignToken.transfer(sovereignChainBridgeContract.target, amount); + const balanceBridge = await sovereignToken.balanceOf(sovereignChainBridgeContract.target); + + // Check balances before claim + expect(balanceBridge).to.be.equal(amount); + // Claim message + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, sovereignToken.target, destinationAddress, amount); + + // Check balances after claim + expect(await sovereignToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(ethers.parseEther("0")); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sovereignToken.target, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should check the constructor parameters", async () => { + expect(await sovereignChainBridgeContract.globalExitRootManager()).to.be.equal( + sovereignChainGlobalExitRootContract.target + ); + expect(await sovereignChainBridgeContract.networkID()).to.be.equal(networkIDRollup2); + expect(await sovereignChainBridgeContract.polygonRollupManager()).to.be.equal(rollupManager.address); + + expect(await sovereignChainBridgeContract.gasTokenAddress()).to.be.equal(gasTokenAddress); + expect(await sovereignChainBridgeContract.gasTokenNetwork()).to.be.equal(gasTokenNetwork); + expect(await sovereignChainBridgeContract.gasTokenMetadata()).to.be.equal(gasTokenMetadata); + }); + + it("should SovereignChain bridge asset and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const mainnetExitRoot = ethers.ZeroHash; + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSSovereignRollup = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: 1} + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "MsgValueNotZero"); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSSovereignRollup); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet) + ).to.be.equal(true); + }); + + it("should PolygonZkEVMBridge message and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const originAddress = deployer.address; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + const mainnetExitRoot = ethers.ZeroHash; + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSSovereignChain = merkleTree.getRoot(); + + // using gas TOkens cannot use bridge message with etther + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, true, metadata, { + value: amount, + }) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NoValueInMessagesOnGasTokenNetworks"); + + // Use bridgeMessageWETH instead! + + // cannot use value + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + true, + metadata, + { + value: amount, + } + ) + ).to.be.reverted; + + // Use bridgeMessageWETH instead! + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + true, + metadata + ) + ).to.be.revertedWith("ERC20: burn amount exceeds balance"); + + // Mock mint weth + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + + await WETHToken.connect(bridgeMock).mint(deployer.address, amount, {gasPrice: 0}); + + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + true, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + // check merkle root with SC + const rootSCSovereignChain = await sovereignChainBridgeContract.getRoot(); + expect(rootSCSovereignChain).to.be.equal(rootJSSovereignChain); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCSovereignChain)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCSovereignChain) + ).to.be.equal(true); + + // bridge message without value is fine + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, true, metadata, {}) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + 0, + metadata, + depositCount + 1n + ); + }); + + it("should SovereignChain bridge asset and message to check global exit root updates", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const mainnetExitRoot = ethers.ZeroHash; + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSSovereignChain = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + false, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(0); + expect(mainnetExitRoot).to.be.equal(ethers.ZeroHash); + + // check merkle root with SC + const rootSCSovereignChain = await sovereignChainBridgeContract.getRoot(); + expect(rootSCSovereignChain).to.be.equal(rootJSSovereignChain); + + // Update global exit root + await expect(sovereignChainBridgeContract.updateGlobalExitRoot()); + + // no state changes since there are not any deposit pending to be updated + await sovereignChainBridgeContract.updateGlobalExitRoot(); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + expect(mainnetExitRoot).to.be.equal(mainnetExitRoot); + + // bridge message + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, false, metadata, { + value: amount, + }) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NoValueInMessagesOnGasTokenNetworks"); + + // Mock mint weth + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await WETHToken.connect(bridgeMock).mint(deployer.address, amount, {gasPrice: 0}); + + await expect( + sovereignChainBridgeContract.bridgeMessageWETH( + destinationNetwork, + destinationAddress, + amount, + false, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + deployer.address, + destinationNetwork, + destinationAddress, + amount, + metadata, + 1 + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + expect(mainnetExitRoot).to.be.equal(mainnetExitRoot); + + // Update global exit root + await sovereignChainBridgeContract.updateGlobalExitRoot(); + + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(2); + expect(mainnetExitRoot).to.not.be.equal(rootJSSovereignChain); + + // Just to have the metric of a low cost bridge Asset + const tokenAddress2 = WETHToken.target; // Ether + const amount2 = ethers.parseEther("10"); + await WETHToken.connect(bridgeMock).mint(deployer.address, amount2, {gasPrice: 0}); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount2, + tokenAddress2, + false, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + 0, // weth bridge + ethers.ZeroAddress, + destinationNetwork, + destinationAddress, + amount2, + "0x", + 2 + ) + .to.emit(WETHToken, "Transfer") + .withArgs(deployer.address, ethers.ZeroAddress, amount2); + }); + + it("should claim Gas tokens from SovereignChain to SovereignChain", async () => { + const originNetwork = networkIDMainnet; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = acc1.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + const indexRollup = 5; + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + if (i == indexRollup) { + merkleTreeRollup.add(rootLocalRollup); + } else { + merkleTreeRollup.add(ethers.toBeHex(ethers.toQuantity(ethers.randomBytes(32)), 32)); + } + } + const rootRollup = merkleTreeRollup.getRoot(); + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRootContract.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRootContract, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const sovereignChainExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(sovereignChainExitRootSC).to.be.equal(rootRollup); + const mainnetExitRootSC = ethers.ZeroHash; + expect(mainnetExitRootSC).to.be.equal(mainnetExitRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rootRollup); + + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + // check merkle proof + + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof rollup + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, indexLocal, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + + /* + * claim + * Can't claim without native (ether) + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + rootLocalRollup, + sovereignChainExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.reverted; + + await setBalance(sovereignChainBridgeContract.target as any, amount); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + const initialBalance = await ethers.provider.getBalance(sovereignChainBridgeContract.target); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + sovereignChainExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + { + gasPrice: 0, + } + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + sovereignChainExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + expect(initialBalance - amount).to.be.equal( + await ethers.provider.getBalance(sovereignChainBridgeContract.target) + ); + }); + + it("should claim tokens from SovereignChain to SovereignChain2", async () => { + const originNetwork = networkIDRollup; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + merkleTreeRollup.add(rootLocalRollup); + } + + const rootRollup = merkleTreeRollup.getRoot(); + + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRootContract.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRootContract, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rootRollup); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + // check merkle proof + + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof local + const indexRollup = 5; + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, indexLocal, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup) + ).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + // claim + const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); + // create2 parameters + const salt = ethers.solidityPackedKeccak256(["uint32", "address"], [networkIDRollup, tokenAddress]); + const minimalBytecodeProxy = await sovereignChainBridgeContract.BASE_INIT_BYTECODE_WRAPPED_TOKEN(); + const hashInitCode = ethers.solidityPackedKeccak256(["bytes", "bytes"], [minimalBytecodeProxy, metadataToken]); + const precalculateWrappedErc20 = await ethers.getCreate2Address( + sovereignChainBridgeContract.target as string, + salt, + hashInitCode + ); + const newWrappedToken = tokenWrappedFactory.attach(precalculateWrappedErc20) as TokenWrapped; + + // Use precalculatedWrapperAddress and check if matches + expect( + await sovereignChainBridgeContract.precalculatedWrapperAddress( + networkIDRollup, + tokenAddress, + tokenName, + tokenSymbol, + decimals + ) + ).to.be.equal(precalculateWrappedErc20); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(sovereignChainBridgeContract, "NewWrappedToken") + .withArgs(originNetwork, tokenAddress, precalculateWrappedErc20, metadata) + .to.emit(newWrappedToken, "Transfer") + .withArgs(ethers.ZeroAddress, destinationAddress, amount); + + const newTokenInfo = await sovereignChainBridgeContract.wrappedTokenToTokenInfo(precalculateWrappedErc20); + + expect(newTokenInfo.originNetwork).to.be.equal(networkIDRollup); + expect(newTokenInfo.originTokenAddress).to.be.equal(tokenAddress); + expect(await sovereignChainBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( + precalculateWrappedErc20 + ); + expect(await sovereignChainBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( + precalculateWrappedErc20 + ); + + expect(await sovereignChainBridgeContract.tokenInfoToWrappedToken(salt)).to.be.equal(precalculateWrappedErc20); + + // Check the wrapper info + expect(await newWrappedToken.name()).to.be.equal(tokenName); + expect(await newWrappedToken.symbol()).to.be.equal(tokenSymbol); + expect(await newWrappedToken.decimals()).to.be.equal(decimals); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + expect(await newWrappedToken.totalSupply()).to.be.equal(amount); + + // Claim again the other leaf to mint tokens + const index2 = 1; + const proof2 = merkleTreeLocal.getProofTreeByIndex(index2); + + expect(verifyMerkleProof(leafValue, proof2, index2, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rollupExitRootSC)).to.be.equal(true); + + const globalIndex2 = computeGlobalIndex(index2, indexRollup, false); + await expect( + sovereignChainBridgeContract.claimAsset( + proof2, + proofRollup, + globalIndex2, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex2, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(newWrappedToken, "Transfer") + .withArgs(ethers.ZeroAddress, destinationAddress, amount); + + // Burn Tokens + const depositCount = await sovereignChainBridgeContract.depositCount(); + const wrappedTokenAddress = newWrappedToken.target; + const newDestinationNetwork = networkIDRollup; + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // create a new deposit + await expect(newWrappedToken.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(newWrappedToken, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + /* + * pre compute root merkle tree in Js + * const height = 32; + */ + const merkleTreeMainnet = new MerkleTreeBridge(height); + // Imporant calcualte leaf with origin token address no wrapped token address + const originTokenAddress = tokenAddress; + const metadataMainnet = metadata; // since the token does not belong to this network + const metadataHashMainnet = ethers.solidityPackedKeccak256(["bytes"], [metadataMainnet]); + + const leafValueMainnet = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataHashMainnet + ); + const leafValueMainnetSC = await sovereignChainBridgeContract.getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataHashMainnet + ); + + expect(leafValueMainnet).to.be.equal(leafValueMainnetSC); + merkleTreeMainnet.add(leafValueMainnet); + const rootJSMainnet = ethers.ZeroHash; + + // Tokens are burnt + expect(await newWrappedToken.totalSupply()).to.be.equal(amount * 2n); + expect(await newWrappedToken.balanceOf(destinationAddress)).to.be.equal(amount * 2n); + await expect( + sovereignChainBridgeContract.bridgeAsset( + newDestinationNetwork, + destinationAddress, + amount, + wrappedTokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataMainnet, + depositCount + ) + .to.emit(newWrappedToken, "Transfer") + .withArgs(deployer.address, ethers.ZeroAddress, amount); + + expect(await newWrappedToken.totalSupply()).to.be.equal(amount); + expect(await newWrappedToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await newWrappedToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(0); + + // check merkle root with SC + const rootSCSovereignChain = await sovereignChainBridgeContract.getRoot(); + + // check merkle proof + const proofMainnet = merkleTreeMainnet.getProofTreeByIndex(0); + const indexMainnet = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValueMainnet, proofMainnet, indexMainnet, rootSCSovereignChain)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof( + leafValueMainnet, + proofMainnet, + indexMainnet, + rootSCSovereignChain + ) + ).to.be.equal(true); + }); + + it("should PolygonZkEVMBridge and sync the current root with events", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // gasToken + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + // create 3 new deposit + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + gasTokenAddress, + destinationNetwork, + destinationAddress, + amount, + gasTokenMetadata, + depositCount + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + gasTokenAddress, + destinationNetwork, + destinationAddress, + amount, + gasTokenMetadata, + depositCount + 1n + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + gasTokenAddress, + destinationNetwork, + destinationAddress, + amount, + gasTokenMetadata, + depositCount + 2n + ); + + // Prepare merkle tree + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + + // Get the deposit's events + const filter = sovereignChainBridgeContract.filters.BridgeEvent( + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined + ); + const events = await sovereignChainBridgeContract.queryFilter(filter, 0, "latest"); + events.forEach((e) => { + const {args} = e; + const leafValue = getLeafValue( + args.leafType, + args.originNetwork, + args.originAddress, + args.destinationNetwork, + args.destinationAddress, + args.amount, + ethers.solidityPackedKeccak256(["bytes"], [args.metadata]) + ); + merkleTree.add(leafValue); + }); + + // Check merkle root with SC + const rootSC = await sovereignChainBridgeContract.getRoot(); + const rootJS = merkleTree.getRoot(); + + expect(rootSC).to.be.equal(rootJS); + }); + + it("should claim testing all the asserts", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + const globalIndex = computeGlobalIndex(index, index, false); + // Can't claim without tokens + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.reverted; + + await setBalance(sovereignChainBridgeContract.target as any, amount); + + // Check GlobalExitRoot invalid assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + mainnetExitRoot, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "GlobalExitRootInvalid"); + + // Check Invalid smt proof assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex + 1n, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount); + + // Check Already claimed_claim + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim ether", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + // claim weth + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(WETHToken, "Transfer") + .withArgs(ethers.ZeroAddress, deployer.address, amount); + + // Check balances after claim + expect(await WETHToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await WETHToken.totalSupply()).to.be.equal(amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim message", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x176923791298713271763697869132"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + /* + * claim + * Can't claim a message as an assets + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + const balanceDeployer = await ethers.provider.getBalance(deployer.address); + + // Check mainnet destination assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(WETHToken, "Transfer") + .withArgs(ethers.ZeroAddress, deployer.address, amount); + + // Check balances after claim + expect(await WETHToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await WETHToken.totalSupply()).to.be.equal(amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); +}); diff --git a/test/contractsv2/BridgeL2SovereignChain.test.ts b/test/contractsv2/BridgeL2SovereignChain.test.ts new file mode 100644 index 000000000..79dfedd5d --- /dev/null +++ b/test/contractsv2/BridgeL2SovereignChain.test.ts @@ -0,0 +1,2370 @@ +import {expect} from "chai"; +import {ethers, upgrades} from "hardhat"; +import { + ERC20PermitMock, + GlobalExitRootManagerL2SovereignChain, + BridgeL2SovereignChain, + TokenWrapped, + ERC20Decimals, +} from "../../typechain-types"; +import {MTBridge, mtBridgeUtils} from "@0xpolygonhermez/zkevm-commonjs"; +const MerkleTreeBridge = MTBridge; +const {verifyMerkleProof, getLeafValue} = mtBridgeUtils; + +function calculateGlobalExitRoot(mainnetExitRoot: any, rollupExitRoot: any) { + return ethers.solidityPackedKeccak256(["bytes32", "bytes32"], [mainnetExitRoot, rollupExitRoot]); +} +const _GLOBAL_INDEX_MAINNET_FLAG = 2n ** 64n; + +function computeGlobalIndex(indexLocal: any, indexRollup: any, isMainnet: Boolean) { + if (isMainnet === true) { + return BigInt(indexLocal) + _GLOBAL_INDEX_MAINNET_FLAG; + } else { + return BigInt(indexLocal) + BigInt(indexRollup) * 2n ** 32n; + } +} + +describe("BridgeL2SovereignChain Contract", () => { + upgrades.silenceWarnings(); + + let sovereignChainBridgeContract: BridgeL2SovereignChain; + let polTokenContract: ERC20PermitMock; + let sovereignChainGlobalExitRootContract: GlobalExitRootManagerL2SovereignChain; + + let deployer: any; + let rollupManager: any; + let bridgeManager: any; + let acc1: any; + + const tokenName = "Matic Token"; + const tokenSymbol = "MATIC"; + const decimals = 18; + const tokenInitialBalance = ethers.parseEther("20000000"); + const metadataToken = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [tokenName, tokenSymbol, decimals] + ); + const networkIDMainnet = 0; + const networkIDRollup = 1; + const networkIDRollup2 = 2; + + const LEAF_TYPE_ASSET = 0; + const LEAF_TYPE_MESSAGE = 1; + + beforeEach("Deploy contracts", async () => { + // load signers + [deployer, rollupManager, acc1, bridgeManager] = await ethers.getSigners(); + // Set trusted sequencer as coinbase for sovereign chains + await ethers.provider.send("hardhat_setCoinbase", [deployer.address]); + // deploy BridgeL2SovereignChain + const BridgeL2SovereignChainFactory = await ethers.getContractFactory("BridgeL2SovereignChain"); + sovereignChainBridgeContract = (await upgrades.deployProxy(BridgeL2SovereignChainFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + })) as unknown as BridgeL2SovereignChain; + + // deploy global exit root manager + const GlobalExitRootManagerL2SovereignChainFactory = await ethers.getContractFactory( + "GlobalExitRootManagerL2SovereignChain" + ); + sovereignChainGlobalExitRootContract = (await upgrades.deployProxy( + GlobalExitRootManagerL2SovereignChainFactory, + [ethers.ZeroAddress, deployer.address], // Initializer params + { + initializer: "initialize", // initializer function name + constructorArgs: [sovereignChainBridgeContract.target], // Constructor arguments + unsafeAllow: ["constructor", "state-variable-immutable"], + } + )) as unknown as GlobalExitRootManagerL2SovereignChain; + + // cannot initialize bridgeV2 initializer from Sovereign bridge + await expect( + sovereignChainBridgeContract.initialize( + networkIDMainnet, + ethers.ZeroAddress, // zero for ether + ethers.ZeroAddress, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + "0x" + ) + ).to.revertedWithCustomError(sovereignChainBridgeContract, "InvalidInitializeFunction"); + + await sovereignChainBridgeContract.initialize( + networkIDRollup2, + ethers.ZeroAddress, // zero for ether + ethers.ZeroAddress, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + "0x", + ethers.Typed.address(bridgeManager), + ethers.ZeroAddress, + false + ); + + // deploy token + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + polTokenContract = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + }); + + it("Should remap source 6 decimal token to 18 sovereign wrapped token and bridge", async () => { + const originNetwork = networkIDMainnet; + const destinationNetwork = networkIDRollup2; + const destinationAddress = acc1.address; + const sixDecimal = 6; + const eighteenDecimal = 18; + const amountSIXBridged = 1; + // Deploy 6 decimals token + const sixDecimalsTokenFactory = await ethers.getContractFactory("ERC20Decimals"); + const sixDecimalsTokenContract = await sixDecimalsTokenFactory.deploy( + "6DEC", + "SIX", + deployer.address, + ethers.parseUnits("10", sixDecimal), // 10 SIX + sixDecimal + ); + const sovereignTokenContract = await sixDecimalsTokenFactory.deploy( + "18DEC", + "EIGHTEEN", + deployer.address, + ethers.parseUnits("20", eighteenDecimal), // 20 EIGHTEEN + eighteenDecimal + ); + // Remap token + await expect( + sovereignChainBridgeContract + .connect(bridgeManager) + .setMultipleSovereignTokenAddress( + [networkIDMainnet], + [sixDecimalsTokenContract.target], + [sovereignTokenContract.target], + [false] + ) + ) + .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") + .withArgs(networkIDMainnet, sixDecimalsTokenContract.target, sovereignTokenContract.target, false); + + // Add allowance + await sixDecimalsTokenContract.approve( + sovereignChainBridgeContract.target, + ethers.parseUnits("10", sixDecimal) + ); + + // bridge asset + await sovereignChainBridgeContract.bridgeAsset( + originNetwork, + destinationAddress, + ethers.parseUnits(String(amountSIXBridged), sixDecimal), // 1 SIX + sixDecimalsTokenContract.target, + true, + "0x" + ); + + // Check burnt balance is 1 SIX + const balanceOfSIX = await sixDecimalsTokenContract.balanceOf(deployer.address); + const balanceOfEIGHTEEN = await sovereignTokenContract.balanceOf(deployer.address); + expect(balanceOfSIX).to.be.equal(ethers.parseUnits(String(10 - amountSIXBridged), 6)); + const metadata = "0x"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + // Claim Asset + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + sixDecimalsTokenContract.target, + destinationNetwork, + destinationAddress, + ethers.parseUnits(String(amountSIXBridged), sixDecimal), // 1 SIX + metadataHash + ); + merkleTree.add(leafValue); + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const mainnetExitRoot = ethers.ZeroHash; + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + sixDecimalsTokenContract.target, + destinationNetwork, + destinationAddress, + ethers.parseUnits(String(amountSIXBridged), sixDecimal), // 1 SIX + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs( + index, + originNetwork, + sixDecimalsTokenContract.target, + destinationAddress, + ethers.parseUnits(String(amountSIXBridged), sixDecimal) + ); + // Check balance is with 6 decimals and check is from sovereign token + const sovereignTokenAmount = await sovereignTokenContract.balanceOf(destinationAddress); + const sixDecimalsTokenAmount = await sixDecimalsTokenContract.balanceOf(destinationAddress); + expect(String(sovereignTokenAmount)).to.be.equal(ethers.parseUnits(String(amountSIXBridged), sixDecimal)); + }); + + it("should check the initialize function", async () => { + // deploy PolygonZkEVMBridge + const sovereignChainBridgeContract = await ethers.getContractFactory("BridgeL2SovereignChain"); + const bridge = await upgrades.deployProxy(sovereignChainBridgeContract, [], { + initializer: false, + unsafeAllow: ["constructor"], + }); + + // Gas token network should be zero if gas token address is zero + await expect( + bridge.initialize( + networkIDRollup2, + ethers.ZeroAddress, // zero for ether + 1, // not zero, revert + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + metadataToken, + ethers.Typed.address(bridgeManager.address), + ethers.ZeroAddress, + false + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "GasTokenNetworkMustBeZeroOnEther"); + + // _sovereignWETHAddress should be zero and _sovereignWETHAddressIsNotMintable should be false for native wethGasTokenNetworks + await expect( + bridge.initialize( + networkIDRollup2, + ethers.ZeroAddress, // zero for ether + 0, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + metadataToken, + ethers.Typed.address(bridgeManager.address), + bridge.target, // Not zero, revert + false + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSovereignWETHAddressParams"); + + await expect( + bridge.initialize( + networkIDRollup2, + ethers.ZeroAddress, // zero for ether + 0, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + metadataToken, + ethers.Typed.address(bridgeManager.address), + ethers.ZeroAddress, + true // Not false, revert, + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSovereignWETHAddressParams"); + }); + + it("Migrate non mintable tokens", async () => { + // Deploy token1 + const tokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + const iBalance = ethers.parseEther("20000000"); + const migrationAmount = ethers.parseEther("10"); + const networkIDRollup1 = 1; + const legacyToken = await tokenFactory.deploy(tokenName, tokenSymbol, deployer.address, iBalance); + // Send legacy tokens to user + await legacyToken.transfer(acc1.address, migrationAmount); + expect(await legacyToken.balanceOf(acc1.address)).to.be.equal(migrationAmount); + // Approve token transfer to bridge + await legacyToken.connect(acc1).approve(sovereignChainBridgeContract.target, migrationAmount); + + // Try migrate token that is not mapped + await expect( + sovereignChainBridgeContract.connect(acc1).migrateLegacyToken(legacyToken.target, migrationAmount) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "TokenNotMapped"); + + // Make first remapping + await sovereignChainBridgeContract + .connect(bridgeManager) + .setMultipleSovereignTokenAddress( + [networkIDRollup1], + [polTokenContract.target], + [legacyToken.target], + [true] + ); + await expect( + sovereignChainBridgeContract + .connect(bridgeManager) + .setMultipleSovereignTokenAddress( + [networkIDRollup1], + [polTokenContract.target], + [legacyToken.target], + [true] + ) + ).to.revertedWithCustomError(sovereignChainBridgeContract, "TokenAlreadyMapped"); + // Deploy token 2 + const updatedToken = await tokenFactory.deploy(tokenName, tokenSymbol, deployer.address, iBalance); + // Send legacy tokens to bridge + await updatedToken.transfer(sovereignChainBridgeContract.target, migrationAmount); + expect(await updatedToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(migrationAmount); + // Make second remapping + await sovereignChainBridgeContract + .connect(bridgeManager) + .setMultipleSovereignTokenAddress( + [networkIDRollup1], + [polTokenContract.target], + [updatedToken.target], + [true] + ); + + // Try migrate a token already updated + await expect( + sovereignChainBridgeContract.connect(acc1).migrateLegacyToken(updatedToken.target, migrationAmount) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "TokenAlreadyUpdated"); + + // Migrate tokens + await sovereignChainBridgeContract.connect(acc1).migrateLegacyToken(legacyToken.target, migrationAmount); + expect(await legacyToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(migrationAmount); + expect(await legacyToken.balanceOf(acc1.address)).to.be.equal(0n); + expect(await updatedToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(0n); + expect(await updatedToken.balanceOf(acc1.address)).to.be.equal(migrationAmount); + }); + + it("should Sovereign Chain bridge a remapped asset not mintable and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // deploy sovereign + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + const sovereignToken = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + const sovereignToken2 = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + const sovereignToken3 = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + const sovereignToken4 = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + const tokenAddress2 = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + const balanceDeployer = await sovereignToken.balanceOf(deployer.address); + const balanceBridge = await sovereignToken.balanceOf(sovereignChainBridgeContract.target); + // Remap asset + // Remap not mintable token + await expect( + sovereignChainBridgeContract + .connect(bridgeManager) + .setMultipleSovereignTokenAddress([networkIDRollup], [tokenAddress], [sovereignToken.target], [true]) + ) + .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") + .withArgs(networkIDRollup, tokenAddress, sovereignToken.target, true); + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + // Check insufficient allowance + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + sovereignToken.target, + true, + "0x" + ) + ).to.be.revertedWith("ERC20: insufficient allowance"); + // create a new deposit + await expect(sovereignToken.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(sovereignToken, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + sovereignToken.target, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + networkIDRollup, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + // Check updated exit root + expect(await sovereignChainGlobalExitRootContract.lastRollupExitRoot()).to.be.equal(rootJSMainnet); + expect(await sovereignToken.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await sovereignToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(balanceBridge + amount); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet) + ).to.be.equal(true); + + const computedGlobalExitRoot = calculateGlobalExitRoot(rootJSMainnet, rollupExitRoot); + + // Try to insert global exit root with non coinbase + await expect( + sovereignChainGlobalExitRootContract.connect(acc1).insertGlobalExitRoot(computedGlobalExitRoot) + ).to.be.revertedWithCustomError(sovereignChainGlobalExitRootContract, "OnlyGlobalExitRootUpdater"); + + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.be.eq(1); + + expect(await sovereignChainGlobalExitRootContract.insertedGERCount()).to.be.eq(1); + + // Trigger NotEnoughGlobalExitRootsInserted + await expect( + sovereignChainGlobalExitRootContract.removeLastGlobalExitRoots([ + computedGlobalExitRoot, + computedGlobalExitRoot, + ]) + ).to.revertedWithCustomError(sovereignChainGlobalExitRootContract, "NotEnoughGlobalExitRootsInserted"); + + // Trigger NotLastInsertedGlobalExitRoot + await expect( + sovereignChainGlobalExitRootContract.removeLastGlobalExitRoots([metadataHash]) + ).to.revertedWithCustomError(sovereignChainGlobalExitRootContract, "NotLastInsertedGlobalExitRoot"); + + // Trigger OnlyGlobalExitRootRemover + await expect( + sovereignChainGlobalExitRootContract.connect(rollupManager).removeLastGlobalExitRoots([metadataHash]) + ).to.revertedWithCustomError(sovereignChainGlobalExitRootContract, "OnlyGlobalExitRootRemover"); + + // Update globalExitRootRemover + await sovereignChainGlobalExitRootContract.setGlobalExitRootRemover(deployer.address); + // Update globalExitRootUpdater + await sovereignChainGlobalExitRootContract.setGlobalExitRootUpdater(deployer.address); + + // Remove global exit root + expect(await sovereignChainGlobalExitRootContract.removeLastGlobalExitRoots([computedGlobalExitRoot])) + .to.emit(sovereignChainGlobalExitRootContract, "RemoveGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Test to remove more than one global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + const computedGlobalExitRoot2 = "0x5946741ff5ff7732e1c7614ae327543a1d9f5870fcb8afbf146bd5ea75d6d519"; // Random 32 bytes + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot2)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot2); + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot2)).to.be.eq(2); + + expect( + await sovereignChainGlobalExitRootContract.removeLastGlobalExitRoots([ + computedGlobalExitRoot2, + computedGlobalExitRoot, + ]) + ) + .to.emit(sovereignChainGlobalExitRootContract, "RemoveGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.be.eq(0); + + expect(await sovereignChainGlobalExitRootContract.insertedGERCount()).to.be.eq(0); + + // Insert global exit root again + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + + // Remove unmapped sovereign token address, should revert + await expect( + sovereignChainBridgeContract.connect(bridgeManager).removeLegacySovereignTokenAddress(tokenAddress) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "TokenNotRemapped"); + // Remove not updated sovereign token address, should revert + await expect( + sovereignChainBridgeContract.connect(bridgeManager).removeLegacySovereignTokenAddress(sovereignToken.target) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "TokenNotRemapped"); + + // Remove updated sovereign token address + // Remap token a second time to support removal function + await expect( + sovereignChainBridgeContract + .connect(bridgeManager) + .setMultipleSovereignTokenAddress([networkIDRollup], [tokenAddress], [sovereignToken2.target], [true]) + ) + .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") + .withArgs(networkIDRollup, tokenAddress, sovereignToken2.target, true); + await expect( + sovereignChainBridgeContract.connect(bridgeManager).removeLegacySovereignTokenAddress(sovereignToken.target) + ) + .to.emit(sovereignChainBridgeContract, "RemoveLegacySovereignTokenAddress") + .withArgs(sovereignToken.target); + // Remap sovereign address with multiCall + const originNetworksArray = [networkIDRollup, networkIDRollup]; + const originTokenAddressesArray = [tokenAddress, tokenAddress2.target]; + const sovereignTokenAddressesArray = [sovereignToken3.target, sovereignToken4.target]; + const isNotMintableArray = [true, false]; + await expect( + sovereignChainBridgeContract + .connect(bridgeManager) + .setMultipleSovereignTokenAddress( + originNetworksArray, + originTokenAddressesArray, + sovereignTokenAddressesArray, + isNotMintableArray + ) + ) + .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") + .withArgs(networkIDRollup, tokenAddress, sovereignToken3.target, true) + .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") + .withArgs(networkIDRollup, tokenAddress2.target, sovereignToken4.target, false); + + await expect( + sovereignChainBridgeContract.connect(bridgeManager).setMultipleSovereignTokenAddress( + originNetworksArray, + [], // Different length + sovereignTokenAddressesArray, + isNotMintableArray + ) + ).to.revertedWithCustomError(sovereignChainBridgeContract, "InputArraysLengthMismatch"); + }); + + it("should Sovereign Chain bridge a remapped asset mintable and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // deploy sovereign + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + const sovereignToken = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + + // Remap asset + // Trigger requires + // only bridge manager + await expect( + sovereignChainBridgeContract + .connect(rollupManager) + .setMultipleSovereignTokenAddress([networkIDMainnet], [tokenAddress], [sovereignToken.target], [false]) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OnlyBridgeManager"); + // Set rollupManager as bridge manager + await expect(sovereignChainBridgeContract.connect(bridgeManager).setBridgeManager(rollupManager.address)) + .to.emit(sovereignChainBridgeContract, "SetBridgeManager") + .withArgs(rollupManager.address); + + // invalid token address + await expect( + sovereignChainBridgeContract + .connect(rollupManager) + .setMultipleSovereignTokenAddress( + [networkIDMainnet], + [ethers.ZeroAddress], + [sovereignToken.target], + [false] + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidZeroAddress"); + // Invalid origin network + await expect( + sovereignChainBridgeContract + .connect(rollupManager) + .setMultipleSovereignTokenAddress([networkIDRollup2], [tokenAddress], [sovereignToken.target], [false]) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "OriginNetworkInvalid"); + await expect( + sovereignChainBridgeContract + .connect(rollupManager) + .setMultipleSovereignTokenAddress([networkIDRollup], [tokenAddress], [sovereignToken.target], [false]) + ) + .to.emit(sovereignChainBridgeContract, "SetSovereignTokenAddress") + .withArgs(networkIDRollup, tokenAddress, sovereignToken.target, false); + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + // Check updated exit root + expect(await sovereignChainGlobalExitRootContract.lastRollupExitRoot()).to.be.equal(rootJSMainnet); + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet) + ).to.be.equal(true); + + const computedGlobalExitRoot = calculateGlobalExitRoot(rootJSMainnet, rollupExitRoot); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + }); + + it("should check the initialize parameters", async () => { + expect(await sovereignChainBridgeContract.globalExitRootManager()).to.be.equal( + sovereignChainGlobalExitRootContract.target + ); + expect(await sovereignChainBridgeContract.networkID()).to.be.equal(networkIDRollup2); + expect(await sovereignChainBridgeContract.polygonRollupManager()).to.be.equal(rollupManager.address); + + // cannot initialize again + await expect( + sovereignChainBridgeContract.initialize( + networkIDMainnet, + ethers.ZeroAddress, // zero for ether + ethers.ZeroAddress, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + "0x", + ethers.Typed.address(bridgeManager), + ethers.ZeroAddress, + false + ) + ).to.be.revertedWith("Initializable: contract is already initialized"); + + await expect( + sovereignChainGlobalExitRootContract.initialize(ethers.ZeroAddress, ethers.ZeroAddress) + ).to.be.revertedWith("Initializable: contract is already initialized"); + }); + + it("should check bridgeMessageWETH reverts", async () => { + await expect( + sovereignChainBridgeContract.bridgeMessageWETH(networkIDMainnet, deployer.address, 0, true, "0x") + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NativeTokenIsEther"); + + await expect( + sovereignChainBridgeContract.connect(bridgeManager).setSovereignWETHAddress(deployer.address, true) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "WETHRemappingNotSupportedOnGasTokenNetworks"); + }); + + it("should Sovereign Chain bridge asset and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: 1} + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "MsgValueNotZero"); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + // Check updated exit root + expect(await sovereignChainGlobalExitRootContract.lastRollupExitRoot()).to.be.equal(rootJSMainnet); + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet) + ).to.be.equal(true); + + const computedGlobalExitRoot = calculateGlobalExitRoot(rootJSMainnet, rollupExitRoot); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + }); + + it("should message at Sovereign chain and verify merkle proof", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const originAddress = deployer.address; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeMessage(networkIDRollup2, destinationAddress, true, "0x") + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "DestinationNetworkInvalid"); + + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, true, metadata, { + value: amount, + }) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + originAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet) + ).to.be.equal(true); + + const computedGlobalExitRoot = calculateGlobalExitRoot(rootJSMainnet, rollupExitRoot); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + }); + + it("should bridge asset and message to sovereign chain to check global exit root updates", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // create a new deposit + await expect(polTokenContract.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + false, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal( + balanceBridge + amount + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(0); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // Update global exit root + await sovereignChainBridgeContract.updateGlobalExitRoot(); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + const computedGlobalExitRoot = calculateGlobalExitRoot(rootJSMainnet, rollupExitRoot); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + + // bridge message + await expect( + sovereignChainBridgeContract.bridgeMessage(destinationNetwork, destinationAddress, false, metadata, { + value: amount, + }) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_MESSAGE, + originNetwork, + deployer.address, + destinationNetwork, + destinationAddress, + amount, + metadata, + 1 + ); + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(1); + + // Update global exit root + await sovereignChainBridgeContract.updateGlobalExitRoot(); + + expect(await sovereignChainBridgeContract.lastUpdatedDepositCount()).to.be.equal(2); + expect(await sovereignChainGlobalExitRootContract.lastRollupExitRoot()).to.not.be.equal(rootJSMainnet); + + // Just to have the metric of a low cost bridge Asset + const tokenAddress2 = ethers.ZeroAddress; // Ether + const amount2 = ethers.parseEther("10"); + await sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount2, + tokenAddress2, + false, + "0x", + {value: amount2} + ); + }); + + it("should claim tokens from Mainnet to Mainnet", async () => { + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = acc1.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + const indexRollup = 5; + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + if (i == indexRollup) { + merkleTreeRollup.add(rootLocalRollup); + } else { + merkleTreeRollup.add(ethers.toBeHex(ethers.toQuantity(ethers.randomBytes(32)), 32)); + } + } + + const rootRollup = merkleTreeRollup.getRoot(); + + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRootContract.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRootContract, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rootRollup); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + + // check merkle proof + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof rollup + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup) + ).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + /* + * claim + * Can't claim without tokens + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + Number(globalIndex), + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWith("ERC20: transfer amount exceeds balance"); + + // transfer tokens, then claim + await expect(polTokenContract.transfer(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Transfer") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(polTokenContract, "Transfer") + .withArgs(sovereignChainBridgeContract.target, acc1.address, amount); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim tokens from Rollup to Mainnet", async () => { + const originNetwork = networkIDRollup; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + merkleTreeRollup.add(rootLocalRollup); + } + + const rootRollup = merkleTreeRollup.getRoot(); + + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRootContract.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRootContract, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rootRollup); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + // check merkle proof + + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof local + const indexRollup = 5; + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, indexLocal, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup) + ).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + // claim + const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); + // create2 parameters + const salt = ethers.solidityPackedKeccak256(["uint32", "address"], [networkIDRollup, tokenAddress]); + const minimalBytecodeProxy = await sovereignChainBridgeContract.BASE_INIT_BYTECODE_WRAPPED_TOKEN(); + const hashInitCode = ethers.solidityPackedKeccak256(["bytes", "bytes"], [minimalBytecodeProxy, metadataToken]); + const precalculateWrappedErc20 = await ethers.getCreate2Address( + sovereignChainBridgeContract.target as string, + salt, + hashInitCode + ); + const newWrappedToken = tokenWrappedFactory.attach(precalculateWrappedErc20) as TokenWrapped; + + // Use precalculatedWrapperAddress and check if matches + expect( + await sovereignChainBridgeContract.precalculatedWrapperAddress( + networkIDRollup, + tokenAddress, + tokenName, + tokenSymbol, + decimals + ) + ).to.be.equal(precalculateWrappedErc20); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(sovereignChainBridgeContract, "NewWrappedToken") + .withArgs(originNetwork, tokenAddress, precalculateWrappedErc20, metadata) + .to.emit(newWrappedToken, "Transfer") + .withArgs(ethers.ZeroAddress, destinationAddress, amount); + + const newTokenInfo = await sovereignChainBridgeContract.wrappedTokenToTokenInfo(precalculateWrappedErc20); + + // Use precalculatedWrapperAddress and check if matches + expect( + await sovereignChainBridgeContract.calculateTokenWrapperAddress( + networkIDRollup, + tokenAddress, + precalculateWrappedErc20 + ) + ).to.be.equal(precalculateWrappedErc20); + + expect(newTokenInfo.originNetwork).to.be.equal(networkIDRollup); + expect(newTokenInfo.originTokenAddress).to.be.equal(tokenAddress); + expect(await sovereignChainBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( + precalculateWrappedErc20 + ); + expect(await sovereignChainBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( + precalculateWrappedErc20 + ); + + expect(await sovereignChainBridgeContract.tokenInfoToWrappedToken(salt)).to.be.equal(precalculateWrappedErc20); + + // Check the wrapper info + expect(await newWrappedToken.name()).to.be.equal(tokenName); + expect(await newWrappedToken.symbol()).to.be.equal(tokenSymbol); + expect(await newWrappedToken.decimals()).to.be.equal(decimals); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + expect(await newWrappedToken.totalSupply()).to.be.equal(amount); + + // Claim again the other leaf to mint tokens + const index2 = 1; + const proof2 = merkleTreeLocal.getProofTreeByIndex(index2); + + expect(verifyMerkleProof(leafValue, proof2, index2, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rollupExitRootSC)).to.be.equal(true); + + const globalIndex2 = computeGlobalIndex(index2, indexRollup, false); + await expect( + sovereignChainBridgeContract.claimAsset( + proof2, + proofRollup, + globalIndex2, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(globalIndex2, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(newWrappedToken, "Transfer") + .withArgs(ethers.ZeroAddress, destinationAddress, amount); + + // Burn Tokens + const depositCount = await sovereignChainBridgeContract.depositCount(); + const wrappedTokenAddress = newWrappedToken.target; + const newDestinationNetwork = networkIDRollup; + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // create a new deposit + await expect(newWrappedToken.approve(sovereignChainBridgeContract.target, amount)) + .to.emit(newWrappedToken, "Approval") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + /* + * pre compute root merkle tree in Js + * const height = 32; + */ + const merkleTreeMainnet = new MerkleTreeBridge(height); + // Imporant calcualte leaf with origin token address no wrapped token address + const originTokenAddress = tokenAddress; + const metadataMainnet = metadata; // since the token does not belong to this network + const metadataHashMainnet = ethers.solidityPackedKeccak256(["bytes"], [metadataMainnet]); + + const leafValueMainnet = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataHashMainnet + ); + const leafValueMainnetSC = await sovereignChainBridgeContract.getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataHashMainnet + ); + + expect(leafValueMainnet).to.be.equal(leafValueMainnetSC); + merkleTreeMainnet.add(leafValueMainnet); + const rootJSMainnet = merkleTreeMainnet.getRoot(); + + // Tokens are burnt + expect(await newWrappedToken.totalSupply()).to.be.equal(amount * 2n); + expect(await newWrappedToken.balanceOf(destinationAddress)).to.be.equal(amount * 2n); + await expect( + sovereignChainBridgeContract.bridgeAsset( + newDestinationNetwork, + destinationAddress, + amount, + wrappedTokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + originTokenAddress, + newDestinationNetwork, + destinationAddress, + amount, + metadataMainnet, + depositCount + ) + .to.emit(newWrappedToken, "Transfer") + .withArgs(deployer.address, ethers.ZeroAddress, amount); + + expect(await newWrappedToken.totalSupply()).to.be.equal(amount); + expect(await newWrappedToken.balanceOf(deployer.address)).to.be.equal(amount); + expect(await newWrappedToken.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(0); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proofMainnet = merkleTreeMainnet.getProofTreeByIndex(0); + const indexMainnet = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValueMainnet, proofMainnet, indexMainnet, rootSCMainnet)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof( + leafValueMainnet, + proofMainnet, + indexMainnet, + rootSCMainnet + ) + ).to.be.equal(true); + + const computedGlobalExitRoot2 = calculateGlobalExitRoot(rootJSMainnet, rollupExitRoot); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot2)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot2)).to.not.be.eq(0); + + // Insert an already inserted GER + await expect( + sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot2) + ).to.be.revertedWithCustomError(sovereignChainGlobalExitRootContract, "GlobalExitRootAlreadySet"); + + // Unset claims in bulk + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + expect(true).to.be.equal(await sovereignChainBridgeContract.isClaimed(index2, indexRollup + 1)); + + await expect( + sovereignChainBridgeContract + .connect(bridgeManager) + .unsetMultipleClaimedBitmap([indexLocal, index2], [indexRollup + 1]) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InputArraysLengthMismatch"); + + await sovereignChainBridgeContract + .connect(bridgeManager) + .unsetMultipleClaimedBitmap([indexLocal, index2], [indexRollup + 1, indexRollup + 1]); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(index2, indexRollup + 1)); + + // Try to unset again + await expect( + sovereignChainBridgeContract + .connect(bridgeManager) + .unsetMultipleClaimedBitmap([indexLocal, index2], [indexRollup + 1, indexRollup + 1]) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "ClaimNotSet"); + }); + + it("should claim tokens from Rollup to Mainnet, failing deploy wrapped", async () => { + const originNetwork = networkIDRollup; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = ethers.hexlify(ethers.randomBytes(40)); + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTreeLocal = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTreeLocal.add(leafValue); + merkleTreeLocal.add(leafValue); + + const rootLocalRollup = merkleTreeLocal.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + for (let i = 0; i < 10; i++) { + merkleTreeRollup.add(rootLocalRollup); + } + + const rootRollup = merkleTreeRollup.getRoot(); + + // check only rollup account with update rollup exit root + await expect(sovereignChainGlobalExitRootContract.updateExitRoot(rootRollup)).to.be.revertedWithCustomError( + sovereignChainGlobalExitRootContract, + "OnlyAllowedContracts" + ); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rootRollup, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rootRollup); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + // check merkle proof + // Merkle proof local + const indexLocal = 0; + const proofLocal = merkleTreeLocal.getProofTreeByIndex(indexLocal); + + // Merkle proof local + const indexRollup = 5; + const proofRollup = merkleTreeRollup.getProofTreeByIndex(indexRollup); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, indexLocal, rootLocalRollup)).to.be.equal(true); + expect(verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(rootLocalRollup, proofRollup, indexRollup, rootRollup) + ).to.be.equal(true); + const globalIndex = computeGlobalIndex(indexLocal, indexRollup, false); + + expect(false).to.be.equal(await sovereignChainBridgeContract.isClaimed(indexLocal, indexRollup + 1)); + + // claim + const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); + // create2 parameters + const salt = ethers.solidityPackedKeccak256(["uint32", "address"], [networkIDRollup, tokenAddress]); + const minimalBytecodeProxy = await sovereignChainBridgeContract.BASE_INIT_BYTECODE_WRAPPED_TOKEN(); + const hashInitCode = ethers.solidityPackedKeccak256(["bytes", "bytes"], [minimalBytecodeProxy, metadataToken]); + const precalculateWrappedErc20 = await ethers.getCreate2Address( + sovereignChainBridgeContract.target as string, + salt, + hashInitCode + ); + + // Use precalculatedWrapperAddress and check if matches + expect( + await sovereignChainBridgeContract.precalculatedWrapperAddress( + networkIDRollup, + tokenAddress, + tokenName, + tokenSymbol, + decimals + ) + ).to.be.equal(precalculateWrappedErc20); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "FailedTokenWrappedDeployment"); + }); + it("should sovereignChainBridge and sync the current root with events", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // Ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = "0x"; // since is ether does not have metadata + + // create 3 new deposit + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + 1n + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + 2n + ); + + // Prepare merkle tree + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + + // Get the deposit's events + const filter = sovereignChainBridgeContract.filters.BridgeEvent( + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined + ); + const events = await sovereignChainBridgeContract.queryFilter(filter, 0, "latest"); + events.forEach((e) => { + const {args} = e; + const leafValue = getLeafValue( + args.leafType, + args.originNetwork, + args.originAddress, + args.destinationNetwork, + args.destinationAddress, + args.amount, + ethers.solidityPackedKeccak256(["bytes"], [args.metadata]) + ); + merkleTree.add(leafValue); + }); + + // Check merkle root with SC + const rootSC = await sovereignChainBridgeContract.getRoot(); + const rootJS = merkleTree.getRoot(); + + expect(rootSC).to.be.equal(rootJS); + }); + + it("should claim testing all the asserts", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDRollup2; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + + // Try claim with 10 rollup leafs + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + const globalIndex = computeGlobalIndex(index, index, false); + // Can't claim without tokens + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWith("ERC20: transfer amount exceeds balance"); + + // transfer tokens, then claim + await expect(polTokenContract.transfer(sovereignChainBridgeContract.target, amount)) + .to.emit(polTokenContract, "Transfer") + .withArgs(deployer.address, sovereignChainBridgeContract.target, amount); + + // Check GlobalExitRoot invalid assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + mainnetExitRoot, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "GlobalExitRootInvalid"); + + // Check Invalid smt proof assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex + 1n, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount) + .to.emit(polTokenContract, "Transfer") + .withArgs(sovereignChainBridgeContract.target, deployer.address, amount); + + // Check Already claimed_claim + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim ether", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + /* + * claim + * Can't claim without ether + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "EtherTransferFailed"); + + const balanceDeployer = await ethers.provider.getBalance(deployer.address); + // Check mainnet destination assert + await expect( + sovereignChainBridgeContract.bridgeAsset( + networkIDRollup2, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "DestinationNetworkInvalid"); + + // This is used just to pay ether to the SovereignChain smart contract and be able to claim it afterwards. + expect( + await sovereignChainBridgeContract.bridgeAsset( + networkIDRollup, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ); + + // Check balances before claim + expect(await ethers.provider.getBalance(sovereignChainBridgeContract.target)).to.be.equal(amount); + expect(await ethers.provider.getBalance(deployer.address)).to.be.lte(balanceDeployer - amount); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount); + + // Check balances after claim + expect(await ethers.provider.getBalance(sovereignChainBridgeContract.target)).to.be.equal( + ethers.parseEther("0") + ); + expect(await ethers.provider.getBalance(deployer.address)).to.be.lte(balanceDeployer); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should claim message", async () => { + // Add a claim leaf to rollup exit tree + const originNetwork = networkIDMainnet; + const tokenAddress = ethers.ZeroAddress; // ether + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup2; + const destinationAddress = deployer.address; + + const metadata = "0x176923791298713271763697869132"; // since is ether does not have metadata + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const mainnetExitRoot = ethers.ZeroHash; + + // compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_MESSAGE, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + + // check merkle root with SC + const rootJSRollup = merkleTree.getRoot(); + const merkleTreeRollup = new MerkleTreeBridge(height); + merkleTreeRollup.add(rootJSRollup); + const rollupRoot = merkleTreeRollup.getRoot(); + + // add rollup Merkle root + await ethers.provider.send("hardhat_impersonateAccount", [sovereignChainBridgeContract.target]); + const bridgeMock = await ethers.getSigner(sovereignChainBridgeContract.target as any); + await sovereignChainGlobalExitRootContract.connect(bridgeMock).updateExitRoot(rollupRoot, {gasPrice: 0}); + + // check roots + const rollupExitRootSC = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + expect(rollupExitRootSC).to.be.equal(rollupRoot); + + const computedGlobalExitRoot = calculateGlobalExitRoot(mainnetExitRoot, rollupExitRootSC); + // Insert global exit root + expect(await sovereignChainGlobalExitRootContract.insertGlobalExitRoot(computedGlobalExitRoot)) + .to.emit(sovereignChainGlobalExitRootContract, "InsertGlobalExitRoot") + .withArgs(computedGlobalExitRoot); + + // Check GER has value in mapping + expect(await sovereignChainGlobalExitRootContract.globalExitRootMap(computedGlobalExitRoot)).to.not.be.eq(0); + // check merkle proof + const index = 0; + const proofLocal = merkleTree.getProofTreeByIndex(0); + const proofRollup = merkleTreeRollup.getProofTreeByIndex(0); + const globalIndex = computeGlobalIndex(index, index, false); + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup)).to.be.equal(true); + expect( + await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proofLocal, index, rootJSRollup) + ).to.be.equal(true); + + /* + * claim + * Can't claim a message as an assets + */ + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + /* + * claim + * Can't claim invalid destination network + */ + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + networkIDRollup, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "DestinationNetworkInvalid"); + + /* + * claim + * Can't claim without ether + */ + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "MessageFailed"); + + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + networkIDRollup, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "DestinationNetworkInvalid"); + + const balanceDeployer = await ethers.provider.getBalance(deployer.address); + /* + * Create a deposit to add ether to the SovereignChainBridge + * Check deposit amount ether asserts + */ + await expect( + sovereignChainBridgeContract.bridgeAsset( + networkIDRollup, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: ethers.parseEther("100")} + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AmountDoesNotMatchMsgValue"); + + // Check mainnet destination assert + await expect( + sovereignChainBridgeContract.bridgeAsset( + networkIDRollup2, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "DestinationNetworkInvalid"); + + // This is used just to pay ether to the SovereignChainBridge smart contract and be able to claim it afterwards. + expect( + await sovereignChainBridgeContract.bridgeAsset( + networkIDRollup, + destinationAddress, + amount, + tokenAddress, + true, + "0x", + {value: amount} + ) + ); + + // Check balances before claim + expect(await ethers.provider.getBalance(sovereignChainBridgeContract.target)).to.be.equal(amount); + expect(await ethers.provider.getBalance(deployer.address)).to.be.lte(balanceDeployer - amount); + + // Check mainnet destination assert + await expect( + sovereignChainBridgeContract.claimAsset( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "InvalidSmtProof"); + + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ) + .to.emit(sovereignChainBridgeContract, "ClaimEvent") + .withArgs(index, originNetwork, tokenAddress, destinationAddress, amount); + + // Check balances after claim + expect(await ethers.provider.getBalance(sovereignChainBridgeContract.target)).to.be.equal( + ethers.parseEther("0") + ); + expect(await ethers.provider.getBalance(deployer.address)).to.be.lte(balanceDeployer); + + // Can't claim because nullifier + await expect( + sovereignChainBridgeContract.claimMessage( + proofLocal, + proofRollup, + globalIndex, + mainnetExitRoot, + rollupExitRootSC, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "AlreadyClaimed"); + }); + + it("should test emergency state", async () => { + await expect(sovereignChainBridgeContract.activateEmergencyState()).to.be.revertedWithCustomError( + sovereignChainBridgeContract, + "EmergencyStateNotAllowed" + ); + + await expect(sovereignChainBridgeContract.deactivateEmergencyState()).to.be.revertedWithCustomError( + sovereignChainBridgeContract, + "EmergencyStateNotAllowed" + ); + }); +}); diff --git a/test/contractsv2/BridgeV2MetadataSovereignChains.test.ts b/test/contractsv2/BridgeV2MetadataSovereignChains.test.ts new file mode 100644 index 000000000..86a30b725 --- /dev/null +++ b/test/contractsv2/BridgeV2MetadataSovereignChains.test.ts @@ -0,0 +1,787 @@ +import {expect} from "chai"; +import {ethers, upgrades} from "hardhat"; +import { + ERC20PermitMock, + GlobalExitRootManagerL2SovereignChain, + BridgeL2SovereignChain, +} from "../../typechain-types"; +import { MTBridge, mtBridgeUtils} from "@0xpolygonhermez/zkevm-commonjs"; +const MerkleTreeBridge = MTBridge; +const {verifyMerkleProof, getLeafValue} = mtBridgeUtils; +const { + createPermitSignature, + ifacePermit, + createPermitSignatureDaiType, + ifacePermitDAI, + createPermitSignatureUniType, +} = require("../../src/permit-helper"); + +function calculateGlobalExitRoot(mainnetExitRoot: any, rollupExitRoot: any) { + return ethers.solidityPackedKeccak256(["bytes32", "bytes32"], [mainnetExitRoot, rollupExitRoot]); +} + +describe("SovereignBridge Contract", () => { + upgrades.silenceWarnings(); + + let sovereignChainBridgeContract: BridgeL2SovereignChain; + let polTokenContract: ERC20PermitMock; + let sovereignChainGlobalExitRootContract: GlobalExitRootManagerL2SovereignChain; + + let deployer: any; + let rollupManager: any; + let acc1: any; + + const tokenName = "Matic Token"; + const tokenSymbol = "MATIC"; + const decimals = 18; + const tokenInitialBalance = ethers.parseEther("20000000"); + const metadataToken = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [tokenName, tokenSymbol, decimals] + ); + const networkIDMainnet = 0; + const networkIDRollup = 1; + + const LEAF_TYPE_ASSET = 0; + + + beforeEach("Deploy contracts", async () => { + // load signers + [deployer, rollupManager, acc1] = await ethers.getSigners(); + + // deploy PolygonZkEVMBridge + const BridgeL2SovereignChainFactory = await ethers.getContractFactory("BridgeL2SovereignChain"); + sovereignChainBridgeContract = (await upgrades.deployProxy(BridgeL2SovereignChainFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + })) as unknown as BridgeL2SovereignChain; + + // deploy global exit root manager + const GlobalExitRootManagerL2SovereignChainFactory = await ethers.getContractFactory("GlobalExitRootManagerL2SovereignChain"); + sovereignChainGlobalExitRootContract = await GlobalExitRootManagerL2SovereignChainFactory.deploy( + sovereignChainBridgeContract.target + ); + + await sovereignChainBridgeContract.initialize( + networkIDMainnet, + ethers.ZeroAddress, // zero for ether + ethers.ZeroAddress, // zero for ether + sovereignChainGlobalExitRootContract.target, + rollupManager.address, + "0x", + ethers.Typed.address(deployer.address), + ethers.ZeroAddress, + false, + ); + + // deploy token + const maticTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + polTokenContract = await maticTokenFactory.deploy( + tokenName, + tokenSymbol, + deployer.address, + tokenInitialBalance + ); + }); + + it("should PolygonZkEVMBridge with weird token metadata", async () => { + const weirdErc20Metadata = await ethers.getContractFactory("ERC20WeirdMetadata"); + + const nameWeird = "nameToken"; + const symbolWeird = "NTK"; + + const nameWeirdBytes32 = ethers.encodeBytes32String(nameWeird); + const symbolWeirdBytes = ethers.toUtf8Bytes(symbolWeird); + const decimalsWeird = 14; + + const weirdTokenContract = await weirdErc20Metadata.deploy( + nameWeirdBytes32, // bytes32 + symbolWeirdBytes, // bytes + decimalsWeird + ); + await weirdTokenContract.waitForDeployment(); + + // mint and approve tokens + await weirdTokenContract.mint(deployer.address, tokenInitialBalance); + await weirdTokenContract.approve(sovereignChainBridgeContract.target, tokenInitialBalance); + + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = weirdTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [nameWeird, symbolWeird, decimalsWeird] + ); + + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await sovereignChainBridgeContract.getRoot()).to.be.equal(rootJSMainnet); + }); + + it("should PolygonZkEVMBridge with weird token metadata with reverts", async () => { + const weirdErc20Metadata = await ethers.getContractFactory("ERC20WeirdMetadata"); + + const nameWeird = "nameToken"; + const symbolWeird = "NTK"; + + const nameWeirdBytes32 = ethers.encodeBytes32String(nameWeird); + const symbolWeirdBytes = ethers.toUtf8Bytes(symbolWeird); + const decimalsWeird = ethers.MaxUint256; + + const weirdTokenContract = await weirdErc20Metadata.deploy( + nameWeirdBytes32, // bytes32 + symbolWeirdBytes, // bytes + decimalsWeird + ); + await weirdTokenContract.waitForDeployment(); + + // mint and approve tokens + await weirdTokenContract.mint(deployer.address, tokenInitialBalance); + await weirdTokenContract.approve(sovereignChainBridgeContract.target, tokenInitialBalance); + + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = weirdTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + // Since cannot decode decimals + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ).to.be.reverted; + + // toogle revert + await weirdTokenContract.toggleIsRevert(); + // Use revert strings + const nameRevert = "NO_NAME"; + const symbolRevert = "NO_SYMBOL"; + const decimalsTooRevert = 18; + const metadata = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [nameRevert, symbolRevert, decimalsTooRevert] + ); + + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await sovereignChainBridgeContract.getRoot()).to.be.equal(rootJSMainnet); + }); + + it("should PolygonZkEVMBridge with weird token metadata with empty data", async () => { + const weirdErc20Metadata = await ethers.getContractFactory("ERC20WeirdMetadata"); + + const nameWeird = ""; + const symbolWeird = ""; + + const nameWeirdBytes32 = ethers.encodeBytes32String(nameWeird); + const symbolWeirdBytes = ethers.toUtf8Bytes(symbolWeird); + const decimalsWeird = 255; + + const weirdTokenContract = await weirdErc20Metadata.deploy( + nameWeirdBytes32, // bytes32 + symbolWeirdBytes, // bytes + decimalsWeird + ); + await weirdTokenContract.waitForDeployment(); + + // mint and approve tokens + await weirdTokenContract.mint(deployer.address, tokenInitialBalance); + await weirdTokenContract.approve(sovereignChainBridgeContract.target, tokenInitialBalance); + + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = weirdTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + // Empty bytes32 is a not valid encoding + const nameEmpty = "NOT_VALID_ENCODING"; // bytes32 empty + const symbolEmpty = ""; + + const metadata = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [nameEmpty, symbolEmpty, decimalsWeird] + ); + + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await sovereignChainBridgeContract.getRoot()).to.be.equal(rootJSMainnet); + }); + + it("should PolygonZkEVMBridge with weird token metadata with invalid data", async () => { + const weirdErc20Metadata = await ethers.getContractFactory("ERC20InvalidMetadata"); + + const nameWeird = ""; + const symbolWeird = ""; + + const nameWeirdBytes32 = ethers.encodeBytes32String(nameWeird); + const symbolWeirdBytes = ethers.toUtf8Bytes(symbolWeird); + const decimalsWeird = 255; + + const weirdTokenContract = (await weirdErc20Metadata.deploy( + nameWeirdBytes32, // bytes32 + symbolWeirdBytes, // bytes + decimalsWeird + )) as any; + await weirdTokenContract.waitForDeployment(); + + // mint and approve tokens + await weirdTokenContract.mint(deployer.address, tokenInitialBalance); + await weirdTokenContract.approve(sovereignChainBridgeContract.target, tokenInitialBalance); + + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = weirdTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + // Empty bytes32 is a not valid encoding + const nameEmpty = "NOT_VALID_ENCODING"; // bytes32 empty + const symbolEmpty = "NOT_VALID_ENCODING"; + + const metadata = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [nameEmpty, symbolEmpty, decimalsWeird] + ); + + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ); + + expect(await sovereignChainBridgeContract.getRoot()).to.be.equal(rootJSMainnet); + }); + + it("should PolygonZkEVMBridge and with permit eip-2612 compilant", async () => { + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = polTokenContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = metadataToken; + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await polTokenContract.balanceOf(deployer.address); + const balanceBridge = await polTokenContract.balanceOf(sovereignChainBridgeContract.target); + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ).to.be.revertedWith("ERC20: insufficient allowance"); + + // user permit + const nonce = await polTokenContract.nonces(deployer.address); + const deadline = ethers.MaxUint256; + const {chainId} = await ethers.provider.getNetwork(); + + const {v, r, s} = await createPermitSignature( + polTokenContract, + deployer, + sovereignChainBridgeContract.target, + amount, + nonce, + deadline, + chainId + ); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + ifacePermit.encodeFunctionData("permit", [ + deployer.address, + sovereignChainBridgeContract.target, + amount + 1n, + deadline, + v, + r, + s, + ]) + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NotValidAmount"); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + ethers.ZeroHash + ) + ).to.be.revertedWithCustomError(sovereignChainBridgeContract, "NotValidSignature"); + + const dataPermit = ifacePermit.encodeFunctionData("permit", [ + deployer.address, + sovereignChainBridgeContract.target, + amount, + deadline, + v, + r, + s, + ]); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + dataPermit + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ) + + expect(await polTokenContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await polTokenContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(balanceBridge + amount); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect(await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal( + true + ); + + }); + + it("should PolygonZkEVMBridge with permit DAI type contracts", async () => { + const {chainId} = await ethers.provider.getNetwork(); + const daiTokenFactory = await ethers.getContractFactory("DaiMock"); + const daiContract = (await daiTokenFactory.deploy(chainId)) as any; + await daiContract.waitForDeployment(); + await daiContract.mint(deployer.address, ethers.parseEther("100")); + + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = daiContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [await daiContract.name(), await daiContract.symbol(), await daiContract.decimals()] + ); + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await daiContract.balanceOf(deployer.address); + const balanceBridge = await daiContract.balanceOf(sovereignChainBridgeContract.target); + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ).to.be.revertedWith("Dai/insufficient-allowance"); + + // user permit + const nonce = await daiContract.nonces(deployer.address); + const deadline = ethers.MaxUint256; + + const {v, r, s} = await createPermitSignatureDaiType( + daiContract, + deployer, + sovereignChainBridgeContract.target, + nonce, + deadline, + chainId + ); + + const dataPermit = ifacePermitDAI.encodeFunctionData("permit", [ + deployer.address, + sovereignChainBridgeContract.target, + nonce, + deadline, + true, + v, + r, + s, + ]); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + dataPermit + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ) + + expect(await daiContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await daiContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(balanceBridge + amount); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect(await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal( + true + ); + + }); + + it("should PolygonZkEVMBridge with permit UNI type contracts", async () => { + const uniTokenFactory = await ethers.getContractFactory("Uni"); + const lastBlock = (await ethers.provider.getBlock("latest")) as any; + const uniContract = (await uniTokenFactory.deploy( + deployer.address, + deployer.address, + lastBlock.timestamp + 1 + )) as any; + await uniContract.waitForDeployment(); + await uniContract.mint(deployer.address, ethers.parseEther("100")); + + const depositCount = await sovereignChainBridgeContract.depositCount(); + const originNetwork = networkIDMainnet; + const tokenAddress = uniContract.target; + const amount = ethers.parseEther("10"); + const destinationNetwork = networkIDRollup; + const destinationAddress = deployer.address; + + const metadata = ethers.AbiCoder.defaultAbiCoder().encode( + ["string", "string", "uint8"], + [await uniContract.name(), await uniContract.symbol(), await uniContract.decimals()] + ); + const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); + + const balanceDeployer = await uniContract.balanceOf(deployer.address); + const balanceBridge = await uniContract.balanceOf(sovereignChainBridgeContract.target); + + const rollupExitRoot = await sovereignChainGlobalExitRootContract.lastRollupExitRoot(); + + // pre compute root merkle tree in Js + const height = 32; + const merkleTree = new MerkleTreeBridge(height); + const leafValue = getLeafValue( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadataHash + ); + merkleTree.add(leafValue); + const rootJSMainnet = merkleTree.getRoot(); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + "0x" + ) + ).to.be.revertedWith("Uni::transferFrom: transfer amount exceeds spender allowance"); + + // user permit + const nonce = await uniContract.nonces(deployer.address); + const deadline = ethers.MaxUint256; + const {chainId} = await ethers.provider.getNetwork(); + + const {v, r, s} = await createPermitSignatureUniType( + uniContract, + deployer, + sovereignChainBridgeContract.target, + amount, + nonce, + deadline, + chainId + ); + + const dataPermit = ifacePermit.encodeFunctionData("permit", [ + deployer.address, + sovereignChainBridgeContract.target, + amount, + deadline, + v, + r, + s, + ]); + + await expect( + sovereignChainBridgeContract.bridgeAsset( + destinationNetwork, + destinationAddress, + amount, + tokenAddress, + true, + dataPermit + ) + ) + .to.emit(sovereignChainBridgeContract, "BridgeEvent") + .withArgs( + LEAF_TYPE_ASSET, + originNetwork, + tokenAddress, + destinationNetwork, + destinationAddress, + amount, + metadata, + depositCount + ) + + expect(await uniContract.balanceOf(deployer.address)).to.be.equal(balanceDeployer - amount); + expect(await uniContract.balanceOf(sovereignChainBridgeContract.target)).to.be.equal(balanceBridge + amount); + + // check merkle root with SC + const rootSCMainnet = await sovereignChainBridgeContract.getRoot(); + expect(rootSCMainnet).to.be.equal(rootJSMainnet); + + // check merkle proof + const proof = merkleTree.getProofTreeByIndex(0); + const index = 0; + + // verify merkle proof + expect(verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal(true); + expect(await sovereignChainBridgeContract.verifyMerkleProof(leafValue, proof, index, rootSCMainnet)).to.be.equal( + true + ); + + }); +}); diff --git a/test/contractsv2/PolygonGlobalExitRootV2.test.ts b/test/contractsv2/PolygonGlobalExitRootV2.test.ts index 102fc32a7..e03740c1b 100644 --- a/test/contractsv2/PolygonGlobalExitRootV2.test.ts +++ b/test/contractsv2/PolygonGlobalExitRootV2.test.ts @@ -99,6 +99,7 @@ describe("Polygon Global exit root v2", () => { const currentL1InfoRoot = await polygonZkEVMGlobalExitRootV2.getRoot(); // Retrieve depositCount const depositCount = await polygonZkEVMGlobalExitRootV2.depositCount(); + // Retrieve parentHash and timestamp const blockInfo = await ethers.provider.getBlock(updateExitRoot?.blockHash as any); diff --git a/test/contractsv2/PolygonPessimisticConsensus.test.ts b/test/contractsv2/PolygonPessimisticConsensus.test.ts new file mode 100644 index 000000000..4da607412 --- /dev/null +++ b/test/contractsv2/PolygonPessimisticConsensus.test.ts @@ -0,0 +1,163 @@ +/* eslint-disable no-plusplus, no-await-in-loop */ +import {expect} from "chai"; +import {ethers, upgrades} from "hardhat"; +import {Address, PolygonPessimisticConsensus} from "../../typechain-types"; + +describe("PolygonPessimisticConsensus", () => { + let deployer: any; + let trustedSequencer: any; + let admin: any; + + let PolygonPPConsensusContract: PolygonPessimisticConsensus; + + const gerManagerAddress = "0xA00000000000000000000000000000000000000A" as unknown as Address; + const polTokenAddress = "0xB00000000000000000000000000000000000000B" as unknown as Address; + const rollupManagerAddress = "0xC00000000000000000000000000000000000000C" as unknown as Address; + const bridgeAddress = "0xD00000000000000000000000000000000000000D" as unknown as Address; + + const urlSequencer = "http://zkevm-json-rpc:8123"; + const networkName = "zkevm"; + const networkID = 1; + + // Native token will be ether + const gasTokenAddress = ethers.ZeroAddress; + + beforeEach("Deploy contract", async () => { + upgrades.silenceWarnings(); + + // load signers + [deployer, trustedSequencer, admin] = await ethers.getSigners(); + + // deploy consensus + // create polygonPessimisticConsensus implementation + const ppConsensusFactory = await ethers.getContractFactory("PolygonPessimisticConsensus"); + PolygonPPConsensusContract = await upgrades.deployProxy(ppConsensusFactory, [], { + initializer: false, + constructorArgs: [gerManagerAddress, polTokenAddress, bridgeAddress, rollupManagerAddress], + unsafeAllow: ["constructor", "state-variable-immutable"], + }); + + await PolygonPPConsensusContract.waitForDeployment(); + }); + + it("should check the initalized parameters", async () => { + // initialize zkEVM using non admin address + await expect( + PolygonPPConsensusContract.initialize( + admin.address, + trustedSequencer.address, + networkID, + gasTokenAddress, + urlSequencer, + networkName + ) + ).to.be.revertedWithCustomError(PolygonPPConsensusContract, "OnlyRollupManager"); + + // initialize using rollup manager + await ethers.provider.send("hardhat_impersonateAccount", [rollupManagerAddress]); + const rolllupManagerSigner = await ethers.getSigner(rollupManagerAddress as any); + await PolygonPPConsensusContract.connect(rolllupManagerSigner).initialize( + admin.address, + trustedSequencer.address, + networkID, + gasTokenAddress, + urlSequencer, + networkName, + {gasPrice: 0} + ); + + expect(await PolygonPPConsensusContract.admin()).to.be.equal(admin.address); + expect(await PolygonPPConsensusContract.trustedSequencer()).to.be.equal(trustedSequencer.address); + expect(await PolygonPPConsensusContract.trustedSequencerURL()).to.be.equal(urlSequencer); + expect(await PolygonPPConsensusContract.networkName()).to.be.equal(networkName); + expect(await PolygonPPConsensusContract.gasTokenAddress()).to.be.equal(gasTokenAddress); + + // initialize again + await expect( + PolygonPPConsensusContract.connect(rolllupManagerSigner).initialize( + admin.address, + trustedSequencer.address, + networkID, + gasTokenAddress, + urlSequencer, + networkName, + {gasPrice: 0} + ) + ).to.be.revertedWith("Initializable: contract is already initialized"); + }); + + it("should check admin functions", async () => { + // initialize using rollup manager + await ethers.provider.send("hardhat_impersonateAccount", [rollupManagerAddress]); + const rolllupManagerSigner = await ethers.getSigner(rollupManagerAddress as any); + await PolygonPPConsensusContract.connect(rolllupManagerSigner).initialize( + admin.address, + trustedSequencer.address, + networkID, + gasTokenAddress, + urlSequencer, + networkName, + {gasPrice: 0} + ); + + // setTrustedSequencer + await expect(PolygonPPConsensusContract.setTrustedSequencer(deployer.address)).to.be.revertedWithCustomError( + PolygonPPConsensusContract, + "OnlyAdmin" + ); + + await expect(PolygonPPConsensusContract.connect(admin).setTrustedSequencer(deployer.address)) + .to.emit(PolygonPPConsensusContract, "SetTrustedSequencer") + .withArgs(deployer.address); + + // setTrustedSequencerURL + await expect(PolygonPPConsensusContract.setTrustedSequencerURL("0x1253")).to.be.revertedWithCustomError( + PolygonPPConsensusContract, + "OnlyAdmin" + ); + await expect(PolygonPPConsensusContract.connect(admin).setTrustedSequencerURL("0x1253")) + .to.emit(PolygonPPConsensusContract, "SetTrustedSequencerURL") + .withArgs("0x1253"); + + // transferAdminRole & acceptAdminRole + await expect(PolygonPPConsensusContract.connect(admin).transferAdminRole(deployer.address)) + .to.emit(PolygonPPConsensusContract, "TransferAdminRole") + .withArgs(deployer.address); + + await expect(PolygonPPConsensusContract.connect(admin).acceptAdminRole()).to.be.revertedWithCustomError( + PolygonPPConsensusContract, + "OnlyPendingAdmin" + ); + + await expect(PolygonPPConsensusContract.connect(deployer).acceptAdminRole()) + .to.emit(PolygonPPConsensusContract, "AcceptAdminRole") + .withArgs(deployer.address); + }); + + it("should check getConsensusHash", async () => { + // initialize using rollup manager + await ethers.provider.send("hardhat_impersonateAccount", [rollupManagerAddress]); + const rolllupManagerSigner = await ethers.getSigner(rollupManagerAddress as any); + await PolygonPPConsensusContract.connect(rolllupManagerSigner).initialize( + admin.address, + trustedSequencer.address, + networkID, + gasTokenAddress, + urlSequencer, + networkName, + {gasPrice: 0} + ); + + // pessimistic constant CONSENSUS_TYPE = 0; + const CONSENSUS_TYPE = 0; + const consensusHashJs = ethers.solidityPackedKeccak256( + ["uint32", "address"], + [CONSENSUS_TYPE, trustedSequencer.address] + ); + + // getConsensusHash + const resGetConsensusHash = await PolygonPPConsensusContract.getConsensusHash(); + + expect(resGetConsensusHash).to.be.equal(consensusHashJs); + }); +}); diff --git a/test/contractsv2/PolygonRollupManager-Pessimistic.test.ts b/test/contractsv2/PolygonRollupManager-Pessimistic.test.ts new file mode 100644 index 000000000..500870b55 --- /dev/null +++ b/test/contractsv2/PolygonRollupManager-Pessimistic.test.ts @@ -0,0 +1,1039 @@ +/* eslint-disable no-plusplus, no-await-in-loop */ +import {expect} from "chai"; +import {ethers, upgrades} from "hardhat"; +import { + VerifierRollupHelperMock, + ERC20PermitMock, + PolygonRollupManagerMock, + PolygonZkEVMGlobalExitRootV2, + PolygonZkEVMBridgeV2, + PolygonZkEVMEtrog, + PolygonRollupBaseEtrog, + TokenWrapped, + Address, + PolygonDataCommittee, + PolygonPessimisticConsensus, +} from "../../typechain-types"; +import {takeSnapshot, time} from "@nomicfoundation/hardhat-network-helpers"; +const {VerifierType, computeInputPessimisticBytes, computeConsensusHashEcdsa} = require("../../src/pessimistic-utils"); + +describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { + let deployer: any; + let timelock: any; + let emergencyCouncil: any; + let trustedAggregator: any; + let trustedSequencer: any; + let admin: any; + let beneficiary: any; + + let verifierContract: VerifierRollupHelperMock; + let polygonZkEVMBridgeContract: PolygonZkEVMBridgeV2; + let polTokenContract: ERC20PermitMock; + let polygonZkEVMGlobalExitRoot: PolygonZkEVMGlobalExitRootV2; + let rollupManagerContract: PolygonRollupManagerMock; + let PolygonPPConsensusContract: PolygonPessimisticConsensus; + + const polTokenName = "POL Token"; + const polTokenSymbol = "POL"; + const polTokenInitialBalance = ethers.parseEther("20000000"); + + const pendingStateTimeoutDefault = 100; + const trustedAggregatorTimeout = 100; + const FORCE_BATCH_TIMEOUT = 60 * 60 * 24 * 5; // 5 days + + // BRidge constants + const networkIDMainnet = 0; + const networkIDRollup = 1; + + const LEAF_TYPE_ASSET = 0; + const LEAF_TYPE_MESSAGE = 1; + + const globalExitRootL2Address = "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa" as unknown as Address; + + let firstDeployment = true; + + //roles + const DEFAULT_ADMIN_ROLE = ethers.ZeroHash; + const ADD_ROLLUP_TYPE_ROLE = ethers.id("ADD_ROLLUP_TYPE_ROLE"); + const OBSOLETE_ROLLUP_TYPE_ROLE = ethers.id("OBSOLETE_ROLLUP_TYPE_ROLE"); + const CREATE_ROLLUP_ROLE = ethers.id("CREATE_ROLLUP_ROLE"); + const ADD_EXISTING_ROLLUP_ROLE = ethers.id("ADD_EXISTING_ROLLUP_ROLE"); + const UPDATE_ROLLUP_ROLE = ethers.id("UPDATE_ROLLUP_ROLE"); + const TRUSTED_AGGREGATOR_ROLE = ethers.id("TRUSTED_AGGREGATOR_ROLE"); + const TRUSTED_AGGREGATOR_ROLE_ADMIN = ethers.id("TRUSTED_AGGREGATOR_ROLE_ADMIN"); + const TWEAK_PARAMETERS_ROLE = ethers.id("TWEAK_PARAMETERS_ROLE"); + const SET_FEE_ROLE = ethers.id("SET_FEE_ROLE"); + const STOP_EMERGENCY_ROLE = ethers.id("STOP_EMERGENCY_ROLE"); + const EMERGENCY_COUNCIL_ROLE = ethers.id("EMERGENCY_COUNCIL_ROLE"); + const EMERGENCY_COUNCIL_ADMIN = ethers.id("EMERGENCY_COUNCIL_ADMIN"); + + const SIGNATURE_BYTES = 32 + 32 + 1; + const EFFECTIVE_PERCENTAGE_BYTES = 1; + + beforeEach("Deploy contract", async () => { + upgrades.silenceWarnings(); + + // load signers + [deployer, trustedAggregator, trustedSequencer, admin, timelock, emergencyCouncil, beneficiary] = + await ethers.getSigners(); + + // deploy mock verifier + const VerifierRollupHelperFactory = await ethers.getContractFactory("VerifierRollupHelperMock"); + verifierContract = await VerifierRollupHelperFactory.deploy(); + + // deploy pol + const polTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + polTokenContract = await polTokenFactory.deploy( + polTokenName, + polTokenSymbol, + deployer.address, + polTokenInitialBalance + ); + + /* + * deploy global exit root manager + * In order to not have trouble with nonce deploy first proxy admin + */ + await upgrades.deployProxyAdmin(); + + if ((await upgrades.admin.getInstance()).target !== "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0") { + firstDeployment = false; + } + const nonceProxyBridge = + Number(await ethers.provider.getTransactionCount(deployer.address)) + (firstDeployment ? 3 : 2); + + const nonceProxyZkevm = nonceProxyBridge + 2; // Always have to redeploy impl since the polygonZkEVMGlobalExitRoot address changes + + const precalculateBridgeAddress = ethers.getCreateAddress({ + from: deployer.address, + nonce: nonceProxyBridge, + }); + const precalculateRollupManagerAddress = ethers.getCreateAddress({ + from: deployer.address, + nonce: nonceProxyZkevm, + }); + firstDeployment = false; + + // deploy globalExitRoot + const PolygonZkEVMGlobalExitRootFactory = await ethers.getContractFactory("PolygonZkEVMGlobalExitRootV2"); + polygonZkEVMGlobalExitRoot = await upgrades.deployProxy(PolygonZkEVMGlobalExitRootFactory, [], { + constructorArgs: [precalculateRollupManagerAddress, precalculateBridgeAddress], + unsafeAllow: ["constructor", "state-variable-immutable"], + }); + + // deploy PolygonZkEVMBridge + const polygonZkEVMBridgeFactory = await ethers.getContractFactory("PolygonZkEVMBridgeV2"); + polygonZkEVMBridgeContract = await upgrades.deployProxy(polygonZkEVMBridgeFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + }); + + // deploy polygon rollup manager mock + const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManagerMock"); + + rollupManagerContract = (await upgrades.deployProxy(PolygonRollupManagerFactory, [], { + initializer: false, + constructorArgs: [ + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + ], + unsafeAllow: ["constructor", "state-variable-immutable"], + })) as unknown as PolygonRollupManagerMock; + + await rollupManagerContract.waitForDeployment(); + + // check precalculated address + expect(precalculateBridgeAddress).to.be.equal(polygonZkEVMBridgeContract.target); + expect(precalculateRollupManagerAddress).to.be.equal(rollupManagerContract.target); + + await polygonZkEVMBridgeContract.initialize( + networkIDMainnet, + ethers.ZeroAddress, // zero for ether + ethers.ZeroAddress, // zero for ether + polygonZkEVMGlobalExitRoot.target, + rollupManagerContract.target, + "0x" + ); + + // Initialize Mock + await rollupManagerContract.initializeMock( + trustedAggregator.address, + pendingStateTimeoutDefault, + trustedAggregatorTimeout, + admin.address, + timelock.address, + emergencyCouncil.address + ); + + await expect(rollupManagerContract.initialize()).to.emit(rollupManagerContract, "UpdateRollupManagerVersion") + + // fund sequencer address with Matic tokens + await polTokenContract.transfer(trustedSequencer.address, ethers.parseEther("1000")); + }); + + it("should check the initalized parameters", async () => { + expect(await rollupManagerContract.globalExitRootManager()).to.be.equal(polygonZkEVMGlobalExitRoot.target); + expect(await rollupManagerContract.pol()).to.be.equal(polTokenContract.target); + expect(await rollupManagerContract.bridgeAddress()).to.be.equal(polygonZkEVMBridgeContract.target); + + expect(await rollupManagerContract.getBatchFee()).to.be.equal(ethers.parseEther("0.1")); + expect(await rollupManagerContract.getForcedBatchFee()).to.be.equal(ethers.parseEther("10")); + expect(await rollupManagerContract.calculateRewardPerBatch()).to.be.equal(0); + + // Check roles + expect(await rollupManagerContract.hasRole(DEFAULT_ADMIN_ROLE, timelock.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(ADD_ROLLUP_TYPE_ROLE, timelock.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(UPDATE_ROLLUP_ROLE, timelock.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(ADD_EXISTING_ROLLUP_ROLE, timelock.address)).to.be.equal(true); + + expect(await rollupManagerContract.hasRole(TRUSTED_AGGREGATOR_ROLE, trustedAggregator.address)).to.be.equal( + true + ); + + expect(await rollupManagerContract.hasRole(OBSOLETE_ROLLUP_TYPE_ROLE, admin.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(CREATE_ROLLUP_ROLE, admin.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(TRUSTED_AGGREGATOR_ROLE_ADMIN, admin.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(TWEAK_PARAMETERS_ROLE, admin.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(SET_FEE_ROLE, admin.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(STOP_EMERGENCY_ROLE, admin.address)).to.be.equal(true); + + expect(await rollupManagerContract.hasRole(EMERGENCY_COUNCIL_ROLE, emergencyCouncil.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(EMERGENCY_COUNCIL_ADMIN, emergencyCouncil.address)).to.be.equal( + true + ); + }); + + it("should add a new rollup type: PolygonConsensusPessimistic", async () => { + // deploy consensus + // create polygonPessimisticConsensus implementation + const ppConsensusFactory = await ethers.getContractFactory("PolygonPessimisticConsensus"); + PolygonPPConsensusContract = await ppConsensusFactory.deploy( + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + rollupManagerContract.target + ); + await PolygonPPConsensusContract.waitForDeployment(); + + // Try to add a new rollup type + const forkID = 11; // just metadata for pessimistic consensus + const genesis = ethers.ZeroHash; + const description = "new pessimistic consensus"; + const programVKey = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + const newRollupTypeID = 1; + const nonZeroGenesis = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + + // sender does not have _ADD_ROLLUP_TYPE_ROLE role + await expect( + rollupManagerContract.addNewRollupType( + PolygonPPConsensusContract.target, + verifierContract.target, + forkID, + VerifierType.Pessimistic, + genesis, + description, + programVKey + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); + + // genesis != 0 on Pessimistic Verifier type + await expect( + rollupManagerContract + .connect(timelock) + .addNewRollupType( + PolygonPPConsensusContract.target, + verifierContract.target, + forkID, + VerifierType.Pessimistic, + nonZeroGenesis, + description, + programVKey + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "InvalidRollupType"); + + // correct add new rollup via timelock + await expect( + rollupManagerContract + .connect(timelock) + .addNewRollupType( + PolygonPPConsensusContract.target, + verifierContract.target, + forkID, + VerifierType.Pessimistic, + genesis, + description, + programVKey + ) + ) + .to.emit(rollupManagerContract, "AddNewRollupType") + .withArgs( + newRollupTypeID, + PolygonPPConsensusContract.target, + verifierContract.target, + forkID, + VerifierType.Pessimistic, + genesis, + description, + programVKey + ); + + // assert new rollup type + const createdRollupType = await rollupManagerContract.rollupTypeMap(newRollupTypeID); + + const expectedRollupType = [ + PolygonPPConsensusContract.target, + verifierContract.target, + forkID, + VerifierType.Pessimistic, + false, + genesis, + programVKey, + ]; + + expect(createdRollupType).to.be.deep.equal(expectedRollupType); + + // do obsoleteRollupType + await expect(rollupManagerContract.obsoleteRollupType(newRollupTypeID)).to.be.revertedWithCustomError( + rollupManagerContract, + "AddressDoNotHaveRequiredRole" + ); + + await expect(rollupManagerContract.connect(admin).obsoleteRollupType(newRollupTypeID)) + .to.emit(rollupManagerContract, "ObsoleteRollupType") + .withArgs(newRollupTypeID); + }); + + it("should create a new rollup: PolygonConsensusPessimistic", async () => { + // deploy consensus + // create polygonPessimisticConsensus implementation + const ppConsensusFactory = await ethers.getContractFactory("PolygonPessimisticConsensus"); + PolygonPPConsensusContract = await ppConsensusFactory.deploy( + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + rollupManagerContract.target + ); + await PolygonPPConsensusContract.waitForDeployment(); + + // Try to add a new rollup type + const forkID = 11; // just metadata for pessimistic consensus + const genesis = ethers.ZeroHash; + const description = "new pessimistic consensus"; + const programVKey = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + const newRollupTypeID = 1; + + // correct add new rollup via timelock + await expect( + rollupManagerContract + .connect(timelock) + .addNewRollupType( + PolygonPPConsensusContract.target, + verifierContract.target, + forkID, + VerifierType.Pessimistic, + genesis, + description, + programVKey + ) + ) + .to.emit(rollupManagerContract, "AddNewRollupType") + .withArgs( + newRollupTypeID, + PolygonPPConsensusContract.target, + verifierContract.target, + forkID, + VerifierType.Pessimistic, + genesis, + description, + programVKey + ); + + // create new pessimsitic: only admin + const chainID = 1; + const gasTokenAddress = ethers.ZeroAddress; + const urlSequencer = "https://pessimistic:8545"; + const networkName = "testPessimistic"; + const newCreatedRollupID = 1; + const nonExistentRollupID = 4; + + // Only admin can create new zkEVMs + await expect( + rollupManagerContract.createNewRollup( + newRollupTypeID, + chainID, + admin.address, + trustedSequencer.address, + gasTokenAddress, + urlSequencer, + networkName + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); + + // rollupTypeID does not exist + await expect( + rollupManagerContract + .connect(admin) + .createNewRollup( + nonExistentRollupID, + chainID, + admin.address, + trustedSequencer.address, + gasTokenAddress, + urlSequencer, + networkName + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeDoesNotExist"); + + // create new pessimistic + const newZKEVMAddress = ethers.getCreateAddress({ + from: rollupManagerContract.target as string, + nonce: 1, + }); + const newZkEVMContract = ppConsensusFactory.attach(newZKEVMAddress) as PolygonPessimisticConsensus; + + await expect( + rollupManagerContract + .connect(admin) + .createNewRollup( + newRollupTypeID, + chainID, + admin.address, + trustedSequencer.address, + gasTokenAddress, + urlSequencer, + networkName + ) + ) + .to.emit(rollupManagerContract, "CreateNewRollup") + .withArgs(newCreatedRollupID, newRollupTypeID, newZKEVMAddress, chainID, gasTokenAddress); + + // assert new rollup created + expect(await newZkEVMContract.admin()).to.be.equal(admin.address); + expect(await newZkEVMContract.trustedSequencer()).to.be.equal(trustedSequencer.address); + expect(await newZkEVMContract.trustedSequencerURL()).to.be.equal(urlSequencer); + expect(await newZkEVMContract.networkName()).to.be.equal(networkName); + + // assert new rollup + const resRollupData = await rollupManagerContract.rollupIDToRollupDataV2(newCreatedRollupID); + + const expectedRollupData = [ + newZKEVMAddress, + chainID, + verifierContract.target, + forkID, + ethers.ZeroHash, + 0, + 0, + 0, + newRollupTypeID, + VerifierType.Pessimistic, + ethers.ZeroHash, + programVKey, + ]; + + expect(expectedRollupData).to.be.deep.equal(resRollupData); + }); + + it("should add an existing rollup: PolygonConsensusPessimistic", async () => { + // add existing rollup + const rollupAddress = "0xAa000000000000000000000000000000000000Bb"; + const forkID = 1; + const chainID = 1; + const initLER = "0xff000000000000000000000000000000000000000000000000000000000000ff"; + const programVKey = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + + // add existing rollup: pessimistic type + const newCreatedRollupID = 1; + + await expect( + rollupManagerContract + .connect(timelock) + .addExistingRollup( + rollupAddress, + verifierContract.target, + forkID, + chainID, + initLER, + VerifierType.Pessimistic, + programVKey + ) + ) + .to.emit(rollupManagerContract, "AddExistingRollup") + .withArgs(newCreatedRollupID, forkID, rollupAddress, chainID, VerifierType.Pessimistic, 0, programVKey); + }); + + it("should prevent to update rollup with different VerifierTypes", async () => { + // deploy consensus + // create polygonPessimisticConsensus implementation + const ppConsensusFactory = await ethers.getContractFactory("PolygonPessimisticConsensus"); + PolygonPPConsensusContract = await ppConsensusFactory.deploy( + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + rollupManagerContract.target + ); + await PolygonPPConsensusContract.waitForDeployment(); + + // Try to add a new rollup type + const forkID = 11; // just metadata for pessimistic consensus + const genesis = ethers.ZeroHash; + const description = "new pessimistic consensus"; + const programVKey = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + const newRollupTypeID = 1; + + // correct add new rollup via timelock + await rollupManagerContract + .connect(timelock) + .addNewRollupType( + PolygonPPConsensusContract.target, + verifierContract.target, + forkID, + VerifierType.Pessimistic, + genesis, + description, + programVKey + ); + + // create new pessimsitic: only admin + const chainID = 1; + const gasTokenAddress = ethers.ZeroAddress; + const urlSequencer = "https://pessimistic:8545"; + const networkName = "testPessimistic"; + const pessimisticRollupID = 1; + + // create new pessimistic + await rollupManagerContract + .connect(admin) + .createNewRollup( + newRollupTypeID, + chainID, + admin.address, + trustedSequencer.address, + gasTokenAddress, + urlSequencer, + networkName + ); + + // Create zkEVM implementation + const PolygonZKEVMV2Factory = await ethers.getContractFactory("PolygonZkEVMEtrog"); + const PolygonZKEVMV2Contract = await PolygonZKEVMV2Factory.deploy( + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + rollupManagerContract.target + ); + await PolygonZKEVMV2Contract.waitForDeployment(); + + // Add a new rollup type with timelock + const genesisRandom = "0x0000000000000000000000000000000000000000000000000000000000000001"; + const description2 = "description"; + const chainID2 = 2; + const stateTransistionRollupID = 2; + + // add new rollup type StateTransistion with programVKey != 0 + await expect( + rollupManagerContract + .connect(timelock) + .addNewRollupType( + PolygonZKEVMV2Contract.target, + verifierContract.target, + forkID, + VerifierType.StateTransition, + genesisRandom, + description2, + programVKey + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "InvalidRollupType"); + + // add new rollup type stateTranstion correctly + const newRollupTypeID2 = 2; + + await rollupManagerContract + .connect(timelock) + .addNewRollupType( + PolygonZKEVMV2Contract.target, + verifierContract.target, + forkID, + VerifierType.StateTransition, + genesisRandom, + description2, + ethers.ZeroHash + ); + + // create new rollup + await rollupManagerContract + .connect(admin) + .createNewRollup( + newRollupTypeID2, + chainID2, + admin.address, + trustedSequencer.address, + gasTokenAddress, + urlSequencer, + networkName + ); + + // get rollup data + const rollupPessimistic = await rollupManagerContract.rollupIDToRollupDataV2(pessimisticRollupID); + const rollupStateTransition = await rollupManagerContract.rollupIDToRollupData(stateTransistionRollupID); + + // try to update rollup from Pessimistic to stateTransition + await expect( + rollupManagerContract.connect(timelock).updateRollup(rollupPessimistic[0] as unknown as Address, 2, "0x") + ).to.be.revertedWithCustomError(rollupManagerContract, "UpdateNotCompatible"); + + // try to update rollup from StateTransition to Pessimistic + await expect( + rollupManagerContract + .connect(timelock) + .updateRollup(rollupStateTransition[0] as unknown as Address, 1, "0x") + ).to.be.revertedWithCustomError(rollupManagerContract, "UpdateNotCompatible"); + + // try to update rollup with rollupType = 0 + await expect( + rollupManagerContract + .connect(timelock) + .updateRollup(rollupStateTransition[0] as unknown as Address, 0, "0x") + ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeDoesNotExist"); + + // try to update rollup with a greater rollupType that the last created + await expect( + rollupManagerContract + .connect(timelock) + .updateRollup(rollupStateTransition[0] as unknown as Address, 4, "0x") + ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeDoesNotExist"); + }); + + it("should update rollup: pessismsitic type", async () => { + // deploy consensus + // create polygonPessimisticConsensus implementation + const ppConsensusFactory = await ethers.getContractFactory("PolygonPessimisticConsensus"); + PolygonPPConsensusContract = await ppConsensusFactory.deploy( + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + rollupManagerContract.target + ); + await PolygonPPConsensusContract.waitForDeployment(); + + // Try to add a new rollup type + const forkID = 11; // just metadata for pessimistic consensus + const genesis = ethers.ZeroHash; + const description = "new pessimistic consensus"; + const programVKey = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + const rollupTypeID = 1; + + // correct add new rollup via timelock + await rollupManagerContract + .connect(timelock) + .addNewRollupType( + PolygonPPConsensusContract.target, + verifierContract.target, + forkID, + VerifierType.Pessimistic, + genesis, + description, + programVKey + ); + + // create new pessimsitic: only admin + const chainID = 1; + const gasTokenAddress = ethers.ZeroAddress; + const urlSequencer = "https://pessimistic:8545"; + const networkName = "testPessimistic"; + const pessimisticRollupID = 1; + + // create new pessimistic + const newZKEVMAddress = ethers.getCreateAddress({ + from: rollupManagerContract.target as string, + nonce: 1, + }); + + await rollupManagerContract + .connect(admin) + .createNewRollup( + rollupTypeID, + chainID, + admin.address, + trustedSequencer.address, + gasTokenAddress, + urlSequencer, + networkName + ); + + // Try to add a new rollup type + const newForkID = 11; // just metadata for pessimistic consensus + const newProgramVKey = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + const newRollupTypeID = 2; + const newVerifier = "0xaa000000000000000000000000000000000000bb" as unknown as Address; + + // correct add new rollup via timelock + await rollupManagerContract + .connect(timelock) + .addNewRollupType( + PolygonPPConsensusContract.target, + newVerifier, + newForkID, + VerifierType.Pessimistic, + genesis, + description, + newProgramVKey + ); + + // get rollup data + const rollupPessimistic = await rollupManagerContract.rollupIDToRollupDataV2(pessimisticRollupID); + + // try to update rollup from StateTransition to Pessimistic + await rollupManagerContract + .connect(timelock) + .updateRollup(rollupPessimistic[0] as unknown as Address, newRollupTypeID, "0x"); + + // assert new rollup + const resRollupData = await rollupManagerContract.rollupIDToRollupDataV2(pessimisticRollupID); + + const expectedRollupData = [ + newZKEVMAddress, + chainID, + newVerifier, + newForkID, + ethers.ZeroHash, + 0, + 0, + 0, + newRollupTypeID, + VerifierType.Pessimistic, + ethers.ZeroHash, + newProgramVKey, + ]; + + expect(expectedRollupData).to.be.deep.equal(resRollupData); + }); + + it("should not allow rollback sequences: pessismsitic type", async () => { + // deploy consensus + // create polygonPessimisticConsensus implementation + const ppConsensusFactory = await ethers.getContractFactory("PolygonPessimisticConsensus"); + PolygonPPConsensusContract = await ppConsensusFactory.deploy( + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + rollupManagerContract.target + ); + await PolygonPPConsensusContract.waitForDeployment(); + + // Try to add a new rollup type + const forkID = 11; // just metadata for pessimistic consensus + const genesis = ethers.ZeroHash; + const description = "new pessimistic consensus"; + const programVKey = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + const rollupTypeID = 1; + + // correct add new rollup via timelock + await rollupManagerContract + .connect(timelock) + .addNewRollupType( + PolygonPPConsensusContract.target, + verifierContract.target, + forkID, + VerifierType.Pessimistic, + genesis, + description, + programVKey + ); + + // create new pessimsitic: only admin + const chainID = 1; + const gasTokenAddress = ethers.ZeroAddress; + const urlSequencer = "https://pessimistic:8545"; + const networkName = "testPessimistic"; + const pessimisticRollupID = 1; + + // create new pessimistic + await rollupManagerContract + .connect(admin) + .createNewRollup( + rollupTypeID, + chainID, + admin.address, + trustedSequencer.address, + gasTokenAddress, + urlSequencer, + networkName + ); + + // get rollup data + const rollupPessimistic = await rollupManagerContract.rollupIDToRollupDataV2(pessimisticRollupID); + + // try to rollback sequences + await expect( + rollupManagerContract.connect(admin).rollbackBatches(rollupPessimistic[0] as unknown as Address, 2) + ).to.be.revertedWithCustomError(rollupManagerContract, "OnlyStateTransitionChains"); + }); + + it("should verify pessimistic proof: pessimistic type", async () => { + // deploy consensus + // create polygonPessimisticConsensus implementation + const ppConsensusFactory = await ethers.getContractFactory("PolygonPessimisticConsensus"); + PolygonPPConsensusContract = await ppConsensusFactory.deploy( + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + rollupManagerContract.target + ); + await PolygonPPConsensusContract.waitForDeployment(); + + // Try to add a new rollup type + const forkID = 11; // just metadata for pessimistic consensus + const genesis = ethers.ZeroHash; + const description = "new pessimistic consensus"; + const programVKey = "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; + const rollupTypeID = 1; + + // correct add new rollup via timelock + await rollupManagerContract + .connect(timelock) + .addNewRollupType( + PolygonPPConsensusContract.target, + verifierContract.target, + forkID, + VerifierType.Pessimistic, + genesis, + description, + programVKey + ); + + // create new pessimsitic: only admin + const chainID = 1; + const gasTokenAddress = ethers.ZeroAddress; + const urlSequencer = "https://pessimistic:8545"; + const networkName = "testPessimistic"; + const pessimisticRollupID = 1; + + // create new pessimistic + const newZKEVMAddress = ethers.getCreateAddress({ + from: rollupManagerContract.target as string, + nonce: 1, + }); + + await rollupManagerContract + .connect(admin) + .createNewRollup( + rollupTypeID, + chainID, + admin.address, + trustedSequencer.address, + gasTokenAddress, + urlSequencer, + networkName + ); + + // select unexistent global exit root + const unexistentL1InfoTreeCount = 2; + const newLER = "0x0000000000000000000000000000000000000000000000000000000000000001"; + const newPPRoot = "0x0000000000000000000000000000000000000000000000000000000000000002"; + const proofPP = "0x00"; + + // not trusted aggregator + await expect( + rollupManagerContract.verifyPessimisticTrustedAggregator( + pessimisticRollupID, + unexistentL1InfoTreeCount, + newLER, + newPPRoot, + proofPP + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); + + // global exit root does not exist + await expect( + rollupManagerContract + .connect(trustedAggregator) + .verifyPessimisticTrustedAggregator( + pessimisticRollupID, + unexistentL1InfoTreeCount, + newLER, + newPPRoot, + proofPP + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "L1InfoTreeLeafCountInvalid"); + + // create a bridge to generate a new GER and add another value in the l1IfoRootMap + const tokenAddress = ethers.ZeroAddress; + const amount = ethers.parseEther("1"); + await polygonZkEVMBridgeContract.bridgeAsset( + pessimisticRollupID, + polTokenContract.target, + amount, + tokenAddress, + true, + "0x", + { + value: amount, + } + ); + + // get last L1InfoTreeLeafCount + const lastL1InfoTreeLeafCount = await polygonZkEVMGlobalExitRoot.depositCount(); + const lastL1InfoTreeRoot = await polygonZkEVMGlobalExitRoot.l1InfoRootMap(0); + + // check JS function computeInputPessimisticBytes + const inputPessimisticBytes = await rollupManagerContract.getInputPessimisticBytes( + pessimisticRollupID, + lastL1InfoTreeRoot, + newLER, + newPPRoot + ); + + const infoRollup = await rollupManagerContract.rollupIDToRollupDataV2(pessimisticRollupID); + + const consensusHash = computeConsensusHashEcdsa(trustedSequencer.address); + + const expectedInputPessimsiticBytes = computeInputPessimisticBytes( + infoRollup[4], + infoRollup[10], + lastL1InfoTreeRoot, + pessimisticRollupID, + consensusHash, + newLER, + newPPRoot + ); + + expect(inputPessimisticBytes).to.be.equal(expectedInputPessimsiticBytes); + + // verify pessimistic + await expect( + rollupManagerContract + .connect(trustedAggregator) + .verifyPessimisticTrustedAggregator( + pessimisticRollupID, + lastL1InfoTreeLeafCount, + newLER, + newPPRoot, + proofPP + ) + ) + .to.emit(rollupManagerContract, "VerifyBatchesTrustedAggregator") + .withArgs(pessimisticRollupID, 0, ethers.ZeroHash, newLER, trustedAggregator.address); + + // assert rollup data + const resRollupData = await rollupManagerContract.rollupIDToRollupDataV2(pessimisticRollupID); + + const expectedRollupData = [ + newZKEVMAddress, + chainID, + verifierContract.target, + forkID, + newLER, + 0, + 0, + 0, + rollupTypeID, + VerifierType.Pessimistic, + newPPRoot, + programVKey, + ]; + + expect(expectedRollupData).to.be.deep.equal(resRollupData); + + // not allow verifyBatchesTrustedAggregator from a Pessimistic chain + await expect( + rollupManagerContract + .connect(trustedAggregator) + .verifyBatchesTrustedAggregator( + pessimisticRollupID, + 0, + 0, + 0, + newLER, + newPPRoot, + beneficiary.address, + new Array(24).fill(ethers.ZeroHash) + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "OnlyStateTransitionChains"); + + // pendingstate != 0 + await expect( + rollupManagerContract + .connect(trustedAggregator) + .verifyBatchesTrustedAggregator( + pessimisticRollupID, + 42, + 0, + 0, + newLER, + newPPRoot, + beneficiary.address, + new Array(24).fill(ethers.ZeroHash) + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "PendingStateNumExist"); + }); + + it("should not verify pessimistic proof from stateTransistion chain", async () => { + // Create zkEVM implementation + const PolygonZKEVMV2Factory = await ethers.getContractFactory("PolygonZkEVMEtrog"); + const PolygonZKEVMV2Contract = await PolygonZKEVMV2Factory.deploy( + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + rollupManagerContract.target + ); + await PolygonZKEVMV2Contract.waitForDeployment(); + + // Add a new rollup type with timelock + const gasTokenAddress = ethers.ZeroAddress; + const urlSequencer = "https://pessimistic:8545"; + const networkName = "testPessimistic"; + const genesisRandom = "0x0000000000000000000000000000000000000000000000000000000000000001"; + const description = "description"; + const forkID = 1; + const chainID = 1; + const stateTransistionRollupID = 1; + + // add new rollup type stateTranstion correctly + const newRollupTypeID = 1; + + await rollupManagerContract + .connect(timelock) + .addNewRollupType( + PolygonZKEVMV2Contract.target, + verifierContract.target, + forkID, + VerifierType.StateTransition, + genesisRandom, + description, + ethers.ZeroHash + ); + + // create new rollup + await rollupManagerContract + .connect(admin) + .createNewRollup( + newRollupTypeID, + chainID, + admin.address, + trustedSequencer.address, + gasTokenAddress, + urlSequencer, + networkName + ); + + // try to verify + const unexistentL1InfoTreeLeafcount = 2; + const newLER = "0x0000000000000000000000000000000000000000000000000000000000000001"; + const newPPRoot = "0x0000000000000000000000000000000000000000000000000000000000000002"; + const proofPP = "0x00"; + + await expect( + rollupManagerContract + .connect(trustedAggregator) + .verifyPessimisticTrustedAggregator( + stateTransistionRollupID, + unexistentL1InfoTreeLeafcount, + newLER, + newPPRoot, + proofPP + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "OnlyChainsWithPessimisticProofs"); + }); +}); diff --git a/test/contractsv2/PolygonRollupManager.test.ts b/test/contractsv2/PolygonRollupManager.test.ts index 18272eae2..b12bbf44d 100644 --- a/test/contractsv2/PolygonRollupManager.test.ts +++ b/test/contractsv2/PolygonRollupManager.test.ts @@ -14,7 +14,7 @@ import { PolygonDataCommittee, } from "../../typechain-types"; import {takeSnapshot, time} from "@nomicfoundation/hardhat-network-helpers"; -import {processorUtils, contractUtils, MTBridge, mtBridgeUtils} from "@0xpolygonhermez/zkevm-commonjs"; +import {processorUtils, contractUtils, MTBridge, mtBridgeUtils, utils} from "@0xpolygonhermez/zkevm-commonjs"; const {calculateSnarkInput, calculateAccInputHash, calculateBatchHashData} = contractUtils; type BatchDataStructEtrog = PolygonRollupBaseEtrog.BatchDataStruct; @@ -48,6 +48,7 @@ describe("Polygon Rollup Manager", () => { const pendingStateTimeoutDefault = 100; const trustedAggregatorTimeout = 100; const FORCE_BATCH_TIMEOUT = 60 * 60 * 24 * 5; // 5 days + const HALT_AGGREGATION_TIMEOUT = 60 * 60 * 24 * 7; // 7 days // BRidge constants const networkIDMainnet = 0; @@ -183,9 +184,6 @@ describe("Polygon Rollup Manager", () => { expect(await rollupManagerContract.pol()).to.be.equal(polTokenContract.target); expect(await rollupManagerContract.bridgeAddress()).to.be.equal(polygonZkEVMBridgeContract.target); - expect(await rollupManagerContract.pendingStateTimeout()).to.be.equal(pendingStateTimeoutDefault); - expect(await rollupManagerContract.trustedAggregatorTimeout()).to.be.equal(trustedAggregatorTimeout); - expect(await rollupManagerContract.getBatchFee()).to.be.equal(ethers.parseEther("0.1")); expect(await rollupManagerContract.getForcedBatchFee()).to.be.equal(ethers.parseEther("10")); expect(await rollupManagerContract.calculateRewardPerBatch()).to.be.equal(0); @@ -246,14 +244,49 @@ describe("Polygon Rollup Manager", () => { expect(await polygonZkEVMBridgeContract.isEmergencyState()).to.be.equal(false); }); + it("should check _checkStateRootInsidePrime", async () => { + let stateRoot = "0x0000000000000000000000000000000000000000000000000000000000000000"; + expect(await rollupManagerContract.exposed_checkStateRootInsidePrime(stateRoot)).to.be.equal(true); + + // goldilocks - 1 + stateRoot = "0x000000000000000000000000000000000000000000000000ffffffff00000000"; + expect(await rollupManagerContract.exposed_checkStateRootInsidePrime(stateRoot)).to.be.equal(true); + + // goldilocks + stateRoot = "0x000000000000000000000000000000000000000000000000ffffffff00000001"; + expect(await rollupManagerContract.exposed_checkStateRootInsidePrime(stateRoot)).to.be.equal(false); + + // goldilocks + 1 + stateRoot = "0x000000000000000000000000000000000000000000000000ffffffff00000002"; + expect(await rollupManagerContract.exposed_checkStateRootInsidePrime(stateRoot)).to.be.equal(false); + + // goldilocks 2nd element + stateRoot = "0x00000000000000000000000000000000ffffffff00000001ffffffff00000000"; + expect(await rollupManagerContract.exposed_checkStateRootInsidePrime(stateRoot)).to.be.equal(false); + + // goldilocks 3rd element + stateRoot = "0x0000000000000000ffffffff00000001ffffffff00000000ffffffff00000000"; + expect(await rollupManagerContract.exposed_checkStateRootInsidePrime(stateRoot)).to.be.equal(false); + + // goldilocks 4rt element + stateRoot = "0xffffffff00000001ffffffff00000000ffffffff00000000ffffffff00000000"; + expect(await rollupManagerContract.exposed_checkStateRootInsidePrime(stateRoot)).to.be.equal(false); + + // all goldilocks - 1 + stateRoot = "0xffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000"; + expect(await rollupManagerContract.exposed_checkStateRootInsidePrime(stateRoot)).to.be.equal(true); + }); + it("should check full flow etrog", async () => { const urlSequencer = "http://zkevm-json-rpc:8123"; const chainID = 1000; const networkName = "zkevm"; const forkID = 0; const genesisRandom = "0x0000000000000000000000000000000000000000000000000000000000000001"; - const rollupCompatibilityID = 0; - const descirption = "zkevm test"; + const rollupVerifierType = 0; + const description = "zkevm test"; + const programVKey = "0x0000000000000000000000000000000000000000000000000000000000000000"; + // Native token will be ether const gasTokenAddress = ethers.ZeroAddress; const gasTokenNetwork = 0; @@ -276,9 +309,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ) ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); @@ -291,9 +325,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ) ) .to.emit(rollupManagerContract, "AddNewRollupType") @@ -302,9 +337,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ); // assert new rollup type @@ -314,9 +350,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, false, genesisRandom, + programVKey, ]; expect(createdRollupType).to.be.deep.equal(expectedRollupType); @@ -336,9 +373,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, true, genesisRandom, + programVKey, ]).to.be.deep.equal(await rollupManagerContract.rollupTypeMap(newRollupTypeID)); await snapshot.restore(); @@ -444,6 +482,10 @@ describe("Polygon Rollup Manager", () => { expect(await newZkEVMContract.networkName()).to.be.equal(networkName); expect(await newZkEVMContract.forceBatchTimeout()).to.be.equal(FORCE_BATCH_TIMEOUT); + // Retrieve rollup batch info + const genesisStateRoot = await rollupManagerContract.getRollupBatchNumToStateRoot(newCreatedRollupID, 0); + expect(genesisStateRoot).to.be.equal(genesisRandom); + // Cannot create 2 chains with the same chainID await expect( rollupManagerContract @@ -512,11 +554,11 @@ describe("Polygon Rollup Manager", () => { expect(rollupData.lastLocalExitRoot).to.be.equal(ethers.ZeroHash); expect(rollupData.lastBatchSequenced).to.be.equal(newSequencedBatch); expect(rollupData.lastVerifiedBatch).to.be.equal(0); - expect(rollupData.lastPendingState).to.be.equal(0); - expect(rollupData.lastPendingStateConsolidated).to.be.equal(0); + expect(rollupData._legacyLastPendingState).to.be.equal(0); + expect(rollupData._legacyLastPendingStateConsolidated).to.be.equal(0); expect(rollupData.lastVerifiedBatchBeforeUpgrade).to.be.equal(0); expect(rollupData.rollupTypeID).to.be.equal(1); - expect(rollupData.rollupCompatibilityID).to.be.equal(0); + expect(rollupData.rollupVerifierType).to.be.equal(0); const sequencedBatchData = await rollupManagerContract.getRollupSequencedBatches( newCreatedRollupID, @@ -575,6 +617,25 @@ describe("Polygon Rollup Manager", () => { ethers.ZeroHash ); + // try to sequence in an emergency state + // snapshot emergency + const snapshotEmergencyStateSequence = await takeSnapshot(); + await rollupManagerContract.connect(emergencyCouncil).activateEmergencyState(); + + await expect( + newZkEVMContract + .connect(trustedSequencer) + .sequenceBatches( + [sequence], + l1InfoTreeLeafCount, + currentTime, + expectedAccInputHash2, + trustedSequencer.address + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "OnlyNotEmergencyState"); + + await snapshotEmergencyStateSequence.restore(); + await expect( newZkEVMContract .connect(trustedSequencer) @@ -654,6 +715,21 @@ describe("Polygon Rollup Manager", () => { ) ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); + await expect( + rollupManagerContract + .connect(trustedAggregator) + .verifyBatchesTrustedAggregator( + newCreatedRollupID, + pendingState, + 1, + currentVerifiedBatch, + newLocalExitRoot, + newStateRoot, + beneficiary.address, + zkProofFFlonk + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "OldStateRootDoesNotExist"); + await expect( rollupManagerContract .connect(trustedAggregator) @@ -689,6 +765,55 @@ describe("Polygon Rollup Manager", () => { merkleTreeRollups.add(newLocalExitRoot); const rootRollups = merkleTreeRollups.getRoot(); + // get input snark bytes + const oldSeqData = await rollupManagerContract.getRollupSequencedBatches( + newCreatedRollupID, + currentVerifiedBatch + ); + const oldStateRoot = await rollupManagerContract.getRollupBatchNumToStateRoot( + newCreatedRollupID, + currentVerifiedBatch + ); + const newSeqData = await rollupManagerContract.getRollupSequencedBatches(newCreatedRollupID, newVerifiedBatch); + + const expectedHashInputSnarkBytes = await contractUtils.calculateSnarkInput( + oldStateRoot, + newStateRoot, + newLocalExitRoot, + oldSeqData[0], + newSeqData[0], + currentVerifiedBatch, + newVerifiedBatch, + chainID, + deployer.address, + forkID + ); + + // check newStateroot inside golilocks + const failNewSR = "0x000000000000000000000000000000000000000000000000ffffffff00000001"; + await expect( + rollupManagerContract.getInputSnarkBytes( + newCreatedRollupID, + currentVerifiedBatch, + newVerifiedBatch, + newLocalExitRoot, + oldStateRoot, + failNewSR + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "NewStateRootNotInsidePrime"); + + const inputSnark = await rollupManagerContract.getInputSnarkBytes( + newCreatedRollupID, + currentVerifiedBatch, + newVerifiedBatch, + newLocalExitRoot, + oldStateRoot, + newStateRoot + ); + + const hashInputSnark = utils.sha256Snark(inputSnark.substring(2)); + expect(hashInputSnark).to.be.equal(expectedHashInputSnarkBytes); + // Verify batch const verifyBatchesTrustedAggregator = await rollupManagerContract .connect(trustedAggregator) @@ -718,6 +843,49 @@ describe("Polygon Rollup Manager", () => { .to.emit(polygonZkEVMGlobalExitRoot, "UpdateL1InfoTreeV2") .withArgs(currentL1InfoRoot, depositCount, blockInfo?.parentHash, blockInfo?.timestamp); + // try to set emergency state + await expect(rollupManagerContract.activateEmergencyState()).to.be.revertedWithCustomError( + rollupManagerContract, + "HaltTimeoutNotExpired" + ); + + // enter emergency state when timeout has passed + const enterEmergencyState = await takeSnapshot(); + // Increment timestamp + const blockTime = (await ethers.provider.getBlock("latest"))?.timestamp as any; + await ethers.provider.send("evm_setNextBlockTimestamp", [blockTime + HALT_AGGREGATION_TIMEOUT + 1]); + // activate + await rollupManagerContract.connect(trustedAggregator).activateEmergencyState(); + await enterEmergencyState.restore(); + + // try to enter emergency state when: timeout has passed but it has been an deactivated emergency state + const snapshotEmergencyTimeout = await takeSnapshot(); + // Increment timestamp + const currentTimestamp = (await ethers.provider.getBlock("latest"))?.timestamp as any; + await ethers.provider.send("evm_setNextBlockTimestamp", [currentTimestamp + HALT_AGGREGATION_TIMEOUT / 2 - 1]); + // activate + await rollupManagerContract.connect(emergencyCouncil).activateEmergencyState(); + // deactivate + await rollupManagerContract.connect(admin).deactivateEmergencyState(); + // Increment timestamp + const currentTimestampA = (await ethers.provider.getBlock("latest"))?.timestamp as any; + await ethers.provider.send("evm_setNextBlockTimestamp", [currentTimestampA + HALT_AGGREGATION_TIMEOUT / 2 + 2]); + + // try to set emergency state + await expect(rollupManagerContract.activateEmergencyState()).to.be.revertedWithCustomError( + rollupManagerContract, + "HaltTimeoutNotExpired" + ); + + await snapshotEmergencyTimeout.restore(); + + // Retrieve rollup batch info + const batchStateRoot = await rollupManagerContract.getRollupBatchNumToStateRoot( + newCreatedRollupID, + newVerifiedBatch + ); + expect(batchStateRoot).to.be.equal(newStateRoot); + const finalAggregatorMatic = await polTokenContract.balanceOf(beneficiary.address); expect(finalAggregatorMatic).to.equal(initialAggregatorMatic + maticAmount); @@ -857,9 +1025,10 @@ describe("Polygon Rollup Manager", () => { newZkEVMContract.connect(admin).setForceBatchAddress(deployer.address) ).to.be.revertedWithCustomError(newZkEVMContract, "ForceBatchesDecentralized"); - //snapshot emergency + // snapshot emergency const snapshotEmergencyState = await takeSnapshot(); await rollupManagerContract.connect(emergencyCouncil).activateEmergencyState(); + await expect(newZkEVMContract.forceBatch("0x", 0)).to.be.revertedWithCustomError( newZkEVMContract, "ForceBatchesNotAllowedOnEmergencyState" @@ -999,6 +1168,11 @@ describe("Polygon Rollup Manager", () => { "NotAllowedAddress" ); + await expect( + rollupManagerContract.connect(timelock).rollbackBatches(admin.address, 0) + ).to.be.revertedWithCustomError(rollupManagerContract, "RollupMustExist"); + + // doe snot implement admin() method await expect(rollupManagerContract.connect(admin).rollbackBatches(admin.address, 0)).to.be.reverted; await expect( @@ -1021,16 +1195,73 @@ describe("Polygon Rollup Manager", () => { // compare accINputHash expect(await newZkEVMContract.lastAccInputHash()).not.to.be.equal(expectedAccInputHash2); + const snapshotRollback = await takeSnapshot(); + await expect(rollupManagerContract.connect(admin).rollbackBatches(newZkEVMContract.target, 2)) .to.emit(rollupManagerContract, "RollbackBatches") .withArgs(newCreatedRollupID, 2, expectedAccInputHash2); // compare accINputHash expect(await newZkEVMContract.lastAccInputHash()).to.be.equal(expectedAccInputHash2); + await snapshotRollback.restore(); await expect(newZkEVMContract.connect(deployer).acceptAdminRole()) .to.emit(newZkEVMContract, "AcceptAdminRole") .withArgs(deployer.address); + + // get last accInputHash + const rollupDataRes = await rollupManagerContract.rollupIDToRollupData(networkIDRollup); + const lastAccInputHash = await rollupManagerContract.getRollupSequencedBatches( + networkIDRollup, + rollupDataRes[5] + ); + + // Sequence two batches + // fund deployer with Matic tokens + await polTokenContract.transfer(deployer.address, ethers.parseEther("1000")); + // Approve tokens + await expect(polTokenContract.approve(newZkEVMContract.target, ethers.parseEther("1000"))).to.emit( + polTokenContract, + "Approval" + ); + + const currentTime2 = Number((await ethers.provider.getBlock("latest"))?.timestamp); + const indexL1InfoRoot = 0; + const l1InfoTreeRootSelected = await polygonZkEVMGlobalExitRoot.l1InfoRootMap(indexL1InfoRoot); + + const accInputHash4 = calculateAccInputHashetrog( + lastAccInputHash[0], + ethers.keccak256(l2txData), + l1InfoTreeRootSelected, + currentTime2, + trustedSequencer.address, + ethers.ZeroHash + ); + + const accInputHash5 = calculateAccInputHashetrog( + accInputHash4, + ethers.keccak256(l2txData), + l1InfoTreeRootSelected, + currentTime2, + trustedSequencer.address, + ethers.ZeroHash + ); + + await expect( + newZkEVMContract.sequenceBatches( + [sequence, sequence], + indexL1InfoRoot, + currentTime2, + accInputHash5, + trustedSequencer.address + ) + ).to.emit(newZkEVMContract, "SequenceBatches"); + + // try to rollback batches to a non finish sequence + await expect(rollupManagerContract.rollbackBatches(newZkEVMContract.target, 4)).to.be.revertedWithCustomError( + rollupManagerContract, + "RollbackBatchIsNotEndOfSequence" + ); }); it("should check full flow with gas Token etrog", async () => { @@ -1039,8 +1270,11 @@ describe("Polygon Rollup Manager", () => { const networkName = "zkevm"; const forkID = 0; const genesisRandom = "0x0000000000000000000000000000000000000000000000000000000000000001"; - const rollupCompatibilityID = 0; - const descirption = "zkevm test"; + const rollupVerifierType = 0; + const description = "zkevm test"; + const programVKey = "0x0000000000000000000000000000000000000000000000000000000000000000"; + const lastPessimisticRoot = "0x0000000000000000000000000000000000000000000000000000000000000000"; + // Native token will be ether // deploy pol @@ -1083,9 +1317,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ) ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); @@ -1098,9 +1333,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ) ) .to.emit(rollupManagerContract, "AddNewRollupType") @@ -1109,9 +1345,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ); // assert new rollup type @@ -1121,9 +1358,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, false, genesisRandom, + programVKey, ]; expect(createdRollupType).to.be.deep.equal(expectedRollupType); @@ -1143,9 +1381,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, true, genesisRandom, + programVKey, ]).to.be.deep.equal(await rollupManagerContract.rollupTypeMap(newRollupTypeID)); await snapshot.restore(); @@ -1319,11 +1558,11 @@ describe("Polygon Rollup Manager", () => { expect(rollupData.lastLocalExitRoot).to.be.equal(ethers.ZeroHash); expect(rollupData.lastBatchSequenced).to.be.equal(newSequencedBatch); expect(rollupData.lastVerifiedBatch).to.be.equal(0); - expect(rollupData.lastPendingState).to.be.equal(0); - expect(rollupData.lastPendingStateConsolidated).to.be.equal(0); + expect(rollupData._legacyLastPendingState).to.be.equal(0); + expect(rollupData._legacyLastPendingStateConsolidated).to.be.equal(0); expect(rollupData.lastVerifiedBatchBeforeUpgrade).to.be.equal(0); expect(rollupData.rollupTypeID).to.be.equal(1); - expect(rollupData.rollupCompatibilityID).to.be.equal(0); + expect(rollupData.rollupVerifierType).to.be.equal(0); const sequencedBatchData = await rollupManagerContract.getRollupSequencedBatches( newCreatedRollupID, @@ -1661,8 +1900,11 @@ describe("Polygon Rollup Manager", () => { const networkName = "zkevm"; const forkID = 0; const genesisRandom = "0x0000000000000000000000000000000000000000000000000000000000000001"; - const rollupCompatibilityID = 0; - const descirption = "zkevm test"; + const rollupVerifierType = 0; + const description = "zkevm test"; + const programVKey = "0x0000000000000000000000000000000000000000000000000000000000000000"; + const lastPessimisticRoot = "0x0000000000000000000000000000000000000000000000000000000000000000"; + // Native token will be ether // deploy pol @@ -1705,9 +1947,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ) ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); @@ -1720,9 +1963,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ) ) .to.emit(rollupManagerContract, "AddNewRollupType") @@ -1731,9 +1975,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ); // assert new rollup type @@ -1743,9 +1988,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, false, genesisRandom, + programVKey, ]; expect(createdRollupType).to.be.deep.equal(expectedRollupType); @@ -1765,9 +2011,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, true, genesisRandom, + programVKey, ]).to.be.deep.equal(await rollupManagerContract.rollupTypeMap(newRollupTypeID)); await snapshot.restore(); @@ -1942,11 +2189,11 @@ describe("Polygon Rollup Manager", () => { expect(rollupData.lastLocalExitRoot).to.be.equal(ethers.ZeroHash); expect(rollupData.lastBatchSequenced).to.be.equal(newSequencedBatch); expect(rollupData.lastVerifiedBatch).to.be.equal(0); - expect(rollupData.lastPendingState).to.be.equal(0); - expect(rollupData.lastPendingStateConsolidated).to.be.equal(0); + expect(rollupData._legacyLastPendingState).to.be.equal(0); + expect(rollupData._legacyLastPendingStateConsolidated).to.be.equal(0); expect(rollupData.lastVerifiedBatchBeforeUpgrade).to.be.equal(0); expect(rollupData.rollupTypeID).to.be.equal(1); - expect(rollupData.rollupCompatibilityID).to.be.equal(0); + expect(rollupData.rollupVerifierType).to.be.equal(0); const sequencedBatchData = await rollupManagerContract.getRollupSequencedBatches( newCreatedRollupID, @@ -2286,9 +2533,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMEtrogContract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ) ) .to.emit(rollupManagerContract, "AddNewRollupType") @@ -2297,13 +2545,15 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMEtrogContract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ); - // Add a new rollup type with timelock - const randomType = 3; + // Add a new rollup type (pessimistic) with timelock + const newRandomTypeID = 3; + const rollupVerifierTypeNew = 1; await expect( rollupManagerContract .connect(timelock) @@ -2311,31 +2561,34 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMEtrogContract.target, verifierContract.target, forkID, - randomType, - genesisRandom, - descirption + rollupVerifierTypeNew, + programVKey, + description, + genesisRandom ) ) .to.emit(rollupManagerContract, "AddNewRollupType") .withArgs( - randomType, + newRandomTypeID, PolygonZKEVMEtrogContract.target, verifierContract.target, forkID, - randomType, - genesisRandom, - descirption + rollupVerifierTypeNew, + programVKey, + description, + genesisRandom ); // assert new rollup type - const createdEtrogRollupType = await rollupManagerContract.rollupTypeMap(etrogRollupType); + const createdEtrogRollupType = await rollupManagerContract.rollupTypeMap(newRandomTypeID); const expectedEtrogRollupType = [ PolygonZKEVMEtrogContract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierTypeNew, false, + programVKey, genesisRandom, ]; expect(createdEtrogRollupType).to.be.deep.equal(expectedEtrogRollupType); @@ -2383,11 +2636,6 @@ describe("Polygon Rollup Manager", () => { rollupManagerContract.connect(timelock).updateRollup(newZKEVMAddress, 4, "0x") ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeDoesNotExist"); - // Try update to not comaptible type - await expect( - rollupManagerContract.connect(timelock).updateRollup(newZKEVMAddress, randomType, "0x") - ).to.be.revertedWithCustomError(rollupManagerContract, "UpdateNotCompatible"); - // obsoleteRollupType, take snapshot for it const snapshotUpdateRollup = await takeSnapshot(); @@ -2422,15 +2670,32 @@ describe("Polygon Rollup Manager", () => { expect(rollupDataFinal.lastLocalExitRoot).to.be.equal(newLocalExitRoot); expect(rollupDataFinal.lastBatchSequenced).to.be.equal(newVerifiedBatch); expect(rollupDataFinal.lastVerifiedBatch).to.be.equal(newVerifiedBatch); - expect(rollupDataFinal.lastPendingState).to.be.equal(0); - expect(rollupDataFinal.lastPendingStateConsolidated).to.be.equal(0); + expect(rollupData._legacyLastPendingState).to.be.equal(0); + expect(rollupData._legacyLastPendingStateConsolidated).to.be.equal(0); expect(rollupDataFinal.lastVerifiedBatchBeforeUpgrade).to.be.equal(newVerifiedBatch); expect(rollupDataFinal.rollupTypeID).to.be.equal(etrogRollupType); - expect(rollupDataFinal.rollupCompatibilityID).to.be.equal(0); + expect(rollupDataFinal.rollupVerifierType).to.be.equal(0); expect(await upgrades.erc1967.getImplementationAddress(newZKEVMAddress as string)).to.be.equal( PolygonZKEVMEtrogContract.target ); + + // try to verify a batch smaller than the lastVerifiedBatchBeforeUpgrade + // Verify batch + await expect( + rollupManagerContract + .connect(trustedAggregator) + .verifyBatchesTrustedAggregator( + newCreatedRollupID, + pendingState, + currentVerifiedBatch, + newVerifiedBatch, + newLocalExitRoot, + newStateRoot, + beneficiary.address, + zkProofFFlonk + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "InitBatchMustMatchCurrentForkID"); }); it("should check full flow upgrading validium storage migration", async () => { @@ -2439,8 +2704,11 @@ describe("Polygon Rollup Manager", () => { const networkName = "zkevm"; const forkID = 0; const genesisRandom = "0x0000000000000000000000000000000000000000000000000000000000000001"; - const rollupCompatibilityID = 0; - const descirption = "zkevm test"; + const rollupVerifierType = 0; + const description = "zkevm test"; + const programVKey = "0x0000000000000000000000000000000000000000000000000000000000000000"; + const lastPessimisticRoot = "0x0000000000000000000000000000000000000000000000000000000000000000"; + // Native token will be ether // deploy pol @@ -2486,9 +2754,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ) ) .to.emit(rollupManagerContract, "AddNewRollupType") @@ -2497,9 +2766,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ); // assert new rollup type @@ -2509,9 +2779,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, false, genesisRandom, + programVKey, ]; expect(createdRollupType).to.be.deep.equal(expectedRollupType); @@ -2608,11 +2879,11 @@ describe("Polygon Rollup Manager", () => { expect(rollupData.lastLocalExitRoot).to.be.equal(ethers.ZeroHash); expect(rollupData.lastBatchSequenced).to.be.equal(newSequencedBatch); expect(rollupData.lastVerifiedBatch).to.be.equal(0); - expect(rollupData.lastPendingState).to.be.equal(0); - expect(rollupData.lastPendingStateConsolidated).to.be.equal(0); + expect(rollupData._legacyLastPendingState).to.be.equal(0); + expect(rollupData._legacyLastPendingStateConsolidated).to.be.equal(0); expect(rollupData.lastVerifiedBatchBeforeUpgrade).to.be.equal(0); expect(rollupData.rollupTypeID).to.be.equal(1); - expect(rollupData.rollupCompatibilityID).to.be.equal(0); + expect(rollupData.rollupVerifierType).to.be.equal(0); const sequencedBatchData = await rollupManagerContract.getRollupSequencedBatches( newCreatedRollupID, @@ -2760,8 +3031,11 @@ describe("Polygon Rollup Manager", () => { const networkName = "zkevm"; const forkID = 0; const genesisRandom = "0x0000000000000000000000000000000000000000000000000000000000000001"; - const rollupCompatibilityID = 0; - const descirption = "zkevm test"; + const rollupVerifierType = 0; + const description = "zkevm test"; + const programVKey = "0x0000000000000000000000000000000000000000000000000000000000000000"; + const lastPessimisticRoot = "0x0000000000000000000000000000000000000000000000000000000000000000"; + // Native token will be ether const gasTokenAddress = ethers.ZeroAddress; const gasTokenNetwork = 0; @@ -2770,12 +3044,17 @@ describe("Polygon Rollup Manager", () => { // Create zkEVM implementation const PolygonZKEVMV2Factory = await ethers.getContractFactory("PolygonZkEVMExistentEtrog"); - const PolygonZKEVMV2Contract = await PolygonZKEVMV2Factory.deploy( - polygonZkEVMGlobalExitRoot.target, - polTokenContract.target, - polygonZkEVMBridgeContract.target, - rollupManagerContract.target - ); + const PolygonZKEVMV2Contract = await upgrades.deployProxy(PolygonZKEVMV2Factory, [], { + initializer: false, + constructorArgs: [ + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + rollupManagerContract.target, + ], + unsafeAllow: ["constructor", "state-variable-immutable"], + }); + await PolygonZKEVMV2Contract.waitForDeployment(); // Add a new rollup type with timelock @@ -2819,7 +3098,8 @@ describe("Polygon Rollup Manager", () => { forkID, chainID, genesisRandom, - rollupCompatibilityID + rollupVerifierType, + programVKey ) ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); @@ -2831,7 +3111,8 @@ describe("Polygon Rollup Manager", () => { forkID, 4294967296, // 2**32 genesisRandom, - rollupCompatibilityID + rollupVerifierType, + programVKey ) ).to.be.revertedWithCustomError(rollupManagerContract, "ChainIDOutOfRange"); @@ -2844,11 +3125,16 @@ describe("Polygon Rollup Manager", () => { forkID, chainID, genesisRandom, - rollupCompatibilityID + rollupVerifierType, + programVKey ) ) .to.emit(rollupManagerContract, "AddExistingRollup") - .withArgs(RollupID, forkID, PolygonZKEVMV2Contract.target, chainID, rollupCompatibilityID, 0); + .withArgs(RollupID, forkID, PolygonZKEVMV2Contract.target, chainID, rollupVerifierType, 0, programVKey); + + // Retrieve rollup batch info + const genesisStateRoot = await rollupManagerContract.getRollupBatchNumToStateRoot(RollupID, 0); + expect(genesisStateRoot).to.be.equal(genesisRandom); await expect( rollupManagerContract @@ -2859,7 +3145,8 @@ describe("Polygon Rollup Manager", () => { forkID, chainID, genesisRandom, - rollupCompatibilityID + rollupVerifierType, + programVKey ) ).to.be.revertedWithCustomError(rollupManagerContract, "ChainIDAlreadyExist"); @@ -2872,7 +3159,8 @@ describe("Polygon Rollup Manager", () => { forkID, chainID + 1, genesisRandom, - rollupCompatibilityID + rollupVerifierType, + programVKey ) ).to.be.revertedWithCustomError(rollupManagerContract, "RollupAddressAlreadyExist"); @@ -3218,8 +3506,10 @@ describe("Polygon Rollup Manager", () => { it("Should test obsolete rollup", async () => { const forkID = 0; const genesisRandom = "0x0000000000000000000000000000000000000000000000000000000000000001"; - const rollupCompatibilityID = 0; - const descirption = "zkevm test"; + const rollupVerifierType = 0; + const description = "zkevm test"; + const programVKey = "0x0000000000000000000000000000000000000000000000000000000000000000"; + const lastPessimisticRoot = "0x0000000000000000000000000000000000000000000000000000000000000000"; // In order to create a new rollup type, create an implementation of the contract @@ -3242,9 +3532,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ) ) .to.emit(rollupManagerContract, "AddNewRollupType") @@ -3253,9 +3544,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ); // assert new rollup type @@ -3265,9 +3557,10 @@ describe("Polygon Rollup Manager", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, false, genesisRandom, + programVKey, ]; expect(createdRollupType).to.be.deep.equal(expectedRollupType); @@ -3328,7 +3621,7 @@ describe("Polygon Rollup Manager", () => { }); /** - * Compute accumulateInputHash = Keccak256(oldAccInputHash, batchHashData, globalExitRoot, timestamp, seqAddress) + * Compute accumulateInputHash = Keccak256(oldAccInputHash, batchHashData, l1InfoTreeRoot, timestamp, seqAddress) * @param {String} oldAccInputHash - old accumulateInputHash * @param {String} batchHashData - Batch hash data * @param {String} globalExitRoot - Global Exit Root @@ -3339,14 +3632,14 @@ describe("Polygon Rollup Manager", () => { function calculateAccInputHashetrog( oldAccInputHash: any, batchHashData: any, - globalExitRoot: any, + l1InfoTreeRoot: any, timestamp: any, sequencerAddress: any, forcedBlockHash: any ) { const hashKeccak = ethers.solidityPackedKeccak256( ["bytes32", "bytes32", "bytes32", "uint64", "address", "bytes32"], - [oldAccInputHash, batchHashData, globalExitRoot, timestamp, sequencerAddress, forcedBlockHash] + [oldAccInputHash, batchHashData, l1InfoTreeRoot, timestamp, sequencerAddress, forcedBlockHash] ); return hashKeccak; diff --git a/test/contractsv2/PolygonRollupManagerUpgrade.test.ts b/test/contractsv2/PolygonRollupManagerUpgrade.test.ts index b4ce4a56d..64e530418 100644 --- a/test/contractsv2/PolygonRollupManagerUpgrade.test.ts +++ b/test/contractsv2/PolygonRollupManagerUpgrade.test.ts @@ -57,6 +57,7 @@ describe("Polygon Rollup manager upgraded", () => { let polygonZkEVMGlobalExitRoot: PolygonZkEVMGlobalExitRootV2; let rollupManagerContract: PolygonRollupManagerMock; + const latestVersionRollupManager = "pessimistic"; const polTokenName = "POL Token"; const polTokenSymbol = "POL"; const polTokenInitialBalance = ethers.parseEther("20000000"); @@ -174,10 +175,12 @@ describe("Polygon Rollup manager upgraded", () => { expect(precalculateBridgeAddress).to.be.equal(polygonZkEVMBridgeContract.target); expect(precalculatezkEVM).to.be.equal(polygonZkEVMContract.target); - const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManagerPrevious"); + // get previous versions + const PolygonRollupManagerFactoryV1toV2 = await ethers.getContractFactory("PolygonRollupManagerPreviousV1toV2"); + const PolygonRollupManagerFactoryPrevious = await ethers.getContractFactory("PolygonRollupManagerPrevious"); const PolygonRollupManagerFactoryCurrent = await ethers.getContractFactory("PolygonRollupManagerMock"); - rollupManagerContract = PolygonRollupManagerFactoryCurrent.attach(polygonZkEVMContract.target) as any; + rollupManagerContract = PolygonRollupManagerFactoryCurrent.attach(polygonZkEVMContract.target) as any; await polygonZkEVMContract.initialize( { admin: admin.address, @@ -218,15 +221,15 @@ describe("Polygon Rollup manager upgraded", () => { unsafeAllow: ["constructor", "state-variable-immutable"], })) as any as PolygonZkEVMExistentEtrog; - //const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager"); - const txRollupManager = await upgrades.upgradeProxy(polygonZkEVMContract.target, PolygonRollupManagerFactory, { + // upgrade from V1 to V2 + const txRollupManager = await upgrades.upgradeProxy(polygonZkEVMContract.target, PolygonRollupManagerFactoryV1toV2, { constructorArgs: [ polygonZkEVMGlobalExitRoot.target, polTokenContract.target, polygonZkEVMBridgeContract.target, ], unsafeAllow: ["constructor", "state-variable-immutable"], - unsafeAllowRenames: false, + unsafeAllowRenames: true, call: { fn: "initialize", args: [ @@ -244,7 +247,25 @@ describe("Polygon Rollup manager upgraded", () => { }, }); + // upgrade from V2 to Banana const txRollupManager2 = await upgrades.upgradeProxy( + polygonZkEVMContract.target, + PolygonRollupManagerFactoryPrevious, + { + constructorArgs: [ + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + ], + unsafeAllow: ["constructor", "state-variable-immutable", "enum-definition", "struct-definition"], + unsafeAllowRenames: true, + unsafeAllowCustomTypes: true, + unsafeSkipStorageCheck: true, + } + ); + + // upgrade Banana to pessimsitic + const txRollupManager3 = await upgrades.upgradeProxy( polygonZkEVMContract.target, PolygonRollupManagerFactoryCurrent, { @@ -253,8 +274,13 @@ describe("Polygon Rollup manager upgraded", () => { polTokenContract.target, polygonZkEVMBridgeContract.target, ], - unsafeAllow: ["constructor", "state-variable-immutable"], - unsafeAllowRenames: false, + unsafeAllow: ["constructor", "state-variable-immutable", "enum-definition", "struct-definition"], + unsafeAllowRenames: true, + unsafeAllowCustomTypes: true, + unsafeSkipStorageCheck: true, + call: { + fn: "initialize" + } } ); }); @@ -264,9 +290,6 @@ describe("Polygon Rollup manager upgraded", () => { expect(await rollupManagerContract.pol()).to.be.equal(polTokenContract.target); expect(await rollupManagerContract.bridgeAddress()).to.be.equal(polygonZkEVMBridgeContract.target); - expect(await rollupManagerContract.pendingStateTimeout()).to.be.equal(pendingStateTimeoutDefault); - expect(await rollupManagerContract.trustedAggregatorTimeout()).to.be.equal(trustedAggregatorTimeout); - expect(await rollupManagerContract.getBatchFee()).to.be.equal(ethers.parseEther("0.1")); expect(await rollupManagerContract.getForcedBatchFee()).to.be.equal(ethers.parseEther("10")); @@ -291,41 +314,11 @@ describe("Polygon Rollup manager upgraded", () => { expect(await rollupManagerContract.hasRole(EMERGENCY_COUNCIL_ADMIN, emergencyCouncil.address)).to.be.equal( true ); + + expect(await rollupManagerContract.ROLLUP_MANAGER_VERSION()).to.be.equal(latestVersionRollupManager); }); it("Check admin parameters", async () => { - expect(await rollupManagerContract.multiplierBatchFee()).to.be.equal(1002); - await expect(rollupManagerContract.setMultiplierBatchFee(1023)).to.be.revertedWithCustomError( - rollupManagerContract, - "AddressDoNotHaveRequiredRole" - ); - await expect(rollupManagerContract.connect(admin).setMultiplierBatchFee(0)).to.be.revertedWithCustomError( - rollupManagerContract, - "InvalidRangeMultiplierBatchFee" - ); - - await expect(rollupManagerContract.connect(admin).setMultiplierBatchFee(1020)) - .to.emit(rollupManagerContract, "SetMultiplierBatchFee") - .withArgs(1020); - - expect(await rollupManagerContract.multiplierBatchFee()).to.be.equal(1020); - - // verifyBatchTImetarget - expect(await rollupManagerContract.verifyBatchTimeTarget()).to.be.equal(60 * 30); - - await expect(rollupManagerContract.setVerifyBatchTimeTarget(0)).to.be.revertedWithCustomError( - rollupManagerContract, - "AddressDoNotHaveRequiredRole" - ); - await expect( - rollupManagerContract.connect(admin).setVerifyBatchTimeTarget(60 * 60 * 24 + 1) - ).to.be.revertedWithCustomError(rollupManagerContract, "InvalidRangeBatchTimeTarget"); - - await expect(rollupManagerContract.connect(admin).setVerifyBatchTimeTarget(60)) - .to.emit(rollupManagerContract, "SetVerifyBatchTimeTarget") - .withArgs(60); - expect(await rollupManagerContract.verifyBatchTimeTarget()).to.be.equal(60); - // batch Fee // verifyBatchTImetarget expect(await rollupManagerContract.getBatchFee()).to.be.equal(ethers.parseEther("0.1")); @@ -334,11 +327,16 @@ describe("Polygon Rollup manager upgraded", () => { rollupManagerContract, "AddressDoNotHaveRequiredRole" ); + await expect(rollupManagerContract.connect(admin).setBatchFee(0)).to.be.revertedWithCustomError( rollupManagerContract, "BatchFeeOutOfRange" ); + await expect( + rollupManagerContract.connect(admin).setBatchFee(ethers.parseEther("1001")) + ).to.be.revertedWithCustomError(rollupManagerContract, "BatchFeeOutOfRange"); + await expect(rollupManagerContract.connect(admin).setBatchFee(ethers.parseEther("10"))) .to.emit(rollupManagerContract, "SetBatchFee") .withArgs(ethers.parseEther("10")); @@ -351,9 +349,11 @@ describe("Polygon Rollup manager upgraded", () => { const chainID2 = chainID + 1; const networkName = "zkevm"; const forkID = 0; + const rollupVerifierType = 0; const genesisRandom = "0x0000000000000000000000000000000000000000000000000000000000000001"; - const rollupCompatibilityID = 0; - const descirption = "zkevm test"; + const description = "zkevm test"; + const programVKey = "0x0000000000000000000000000000000000000000000000000000000000000000"; + // Native token will be ether const gasTokenAddress = ethers.ZeroAddress; const gasTokenNetwork = 0; @@ -375,9 +375,10 @@ describe("Polygon Rollup manager upgraded", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ) ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); @@ -390,9 +391,10 @@ describe("Polygon Rollup manager upgraded", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ) ) .to.emit(rollupManagerContract, "AddNewRollupType") @@ -401,9 +403,10 @@ describe("Polygon Rollup manager upgraded", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ); // assert new rollup type @@ -413,9 +416,10 @@ describe("Polygon Rollup manager upgraded", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, false, genesisRandom, + programVKey, ]; expect(createdRollupType).to.be.deep.equal(expectedRollupType); @@ -435,9 +439,10 @@ describe("Polygon Rollup manager upgraded", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, true, genesisRandom, + programVKey, ]).to.be.deep.equal(await rollupManagerContract.rollupTypeMap(newRollupTypeID)); await snapshot.restore(); @@ -598,11 +603,11 @@ describe("Polygon Rollup manager upgraded", () => { expect(rollupData.lastLocalExitRoot).to.be.equal(ethers.ZeroHash); expect(rollupData.lastBatchSequenced).to.be.equal(newSequencedBatch); expect(rollupData.lastVerifiedBatch).to.be.equal(0); - expect(rollupData.lastPendingState).to.be.equal(0); - expect(rollupData.lastPendingStateConsolidated).to.be.equal(0); + expect(rollupData._legacyLastPendingState).to.be.equal(0); + expect(rollupData._legacyLastPendingStateConsolidated).to.be.equal(0); expect(rollupData.lastVerifiedBatchBeforeUpgrade).to.be.equal(0); expect(rollupData.rollupTypeID).to.be.equal(1); - expect(rollupData.rollupCompatibilityID).to.be.equal(0); + expect(rollupData.rollupVerifierType).to.be.equal(0); const sequencedBatchData = await rollupManagerContract.getRollupSequencedBatches( newCreatedRollupID, @@ -1066,959 +1071,12 @@ describe("Polygon Rollup manager upgraded", () => { .withArgs(deployer.address); }); - it("should check full flow no trusted aggreagtor", async () => { - const urlSequencer = "http://zkevm-json-rpc:8123"; - const chainID2 = chainID + 1; - const networkName = "zkevm"; - const forkID = 0; - const genesisRandom = "0x0000000000000000000000000000000000000000000000000000000000000001"; - const rollupCompatibilityID = 0; - const descirption = "zkevm test"; - // Native token will be ether - const gasTokenAddress = ethers.ZeroAddress; - const gasTokenNetwork = 0; - - // In order to create a new rollup type, create an implementation of the contract - - // Create zkEVM implementation - const PolygonZKEVMV2Factory = await ethers.getContractFactory("PolygonZkEVMEtrog"); - const PolygonZKEVMV2Contract = await PolygonZKEVMV2Factory.deploy( - polygonZkEVMGlobalExitRoot.target, - polTokenContract.target, - polygonZkEVMBridgeContract.target, - rollupManagerContract.target - ); - await PolygonZKEVMV2Contract.waitForDeployment(); - - // Try to add a new rollup type - await expect( - rollupManagerContract.addNewRollupType( - PolygonZKEVMV2Contract.target, - verifierContract.target, - forkID, - rollupCompatibilityID, - genesisRandom, - descirption - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); - - // Add a new rollup type with timelock - const newRollupTypeID = 1; - await expect( - rollupManagerContract - .connect(timelock) - .addNewRollupType( - PolygonZKEVMV2Contract.target, - verifierContract.target, - forkID, - rollupCompatibilityID, - genesisRandom, - descirption - ) - ) - .to.emit(rollupManagerContract, "AddNewRollupType") - .withArgs( - newRollupTypeID, - PolygonZKEVMV2Contract.target, - verifierContract.target, - forkID, - rollupCompatibilityID, - genesisRandom, - descirption - ); - - // assert new rollup type - const createdRollupType = await rollupManagerContract.rollupTypeMap(newRollupTypeID); - - const expectedRollupType = [ - PolygonZKEVMV2Contract.target, - verifierContract.target, - forkID, - rollupCompatibilityID, - false, - genesisRandom, - ]; - expect(createdRollupType).to.be.deep.equal(expectedRollupType); - - // obsoleteRollupType, take snapshot for it - const snapshot = await takeSnapshot(); - - await expect(rollupManagerContract.obsoleteRollupType(newRollupTypeID)).to.be.revertedWithCustomError( - rollupManagerContract, - "AddressDoNotHaveRequiredRole" - ); - - await expect(rollupManagerContract.connect(admin).obsoleteRollupType(newRollupTypeID)) - .to.emit(rollupManagerContract, "ObsoleteRollupType") - .withArgs(newRollupTypeID); - - expect([ - PolygonZKEVMV2Contract.target, - verifierContract.target, - forkID, - rollupCompatibilityID, - true, - genesisRandom, - ]).to.be.deep.equal(await rollupManagerContract.rollupTypeMap(newRollupTypeID)); - await snapshot.restore(); - - expect(expectedRollupType).to.be.deep.equal(await rollupManagerContract.rollupTypeMap(newRollupTypeID)); - // Create a - - // Only admin can create new zkEVMs - await expect( - rollupManagerContract.createNewRollup( - newRollupTypeID, - chainID2, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); - - // UNexisting rollupType - await expect( - rollupManagerContract - .connect(admin) - .createNewRollup( - 0, - chainID2, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeDoesNotExist"); - - // Obsolete rollup type and test that fails - const snapshot2 = await takeSnapshot(); - await expect(rollupManagerContract.connect(admin).obsoleteRollupType(newRollupTypeID)) - .to.emit(rollupManagerContract, "ObsoleteRollupType") - .withArgs(newRollupTypeID); - - await expect( - rollupManagerContract - .connect(admin) - .createNewRollup( - newRollupTypeID, - chainID2, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeObsolete"); - await snapshot2.restore(); - - const newCreatedRollupID = 2; // 1 is zkEVM - const newZKEVMAddress = ethers.getCreateAddress({ - from: rollupManagerContract.target as string, - nonce: 1, - }); - - const newZkEVMContract = PolygonZKEVMV2Factory.attach(newZKEVMAddress) as PolygonZkEVMEtrog; - const newSequencedBatch = 1; - - await expect( - rollupManagerContract - .connect(admin) - .createNewRollup( - newRollupTypeID, - chainID2, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName - ) - ) - .to.emit(rollupManagerContract, "CreateNewRollup") - .withArgs(newCreatedRollupID, newRollupTypeID, newZKEVMAddress, chainID2, gasTokenAddress) - .to.emit(newZkEVMContract, "InitialSequenceBatches") - .to.emit(rollupManagerContract, "OnSequenceBatches") - .withArgs(newCreatedRollupID, newSequencedBatch); - - const blockCreatedRollup = await ethers.provider.getBlock("latest"); - - // Assert new rollup created - const timestampCreatedRollup = blockCreatedRollup?.timestamp; - expect(await newZkEVMContract.admin()).to.be.equal(admin.address); - expect(await newZkEVMContract.trustedSequencer()).to.be.equal(trustedSequencer.address); - expect(await newZkEVMContract.trustedSequencerURL()).to.be.equal(urlSequencer); - expect(await newZkEVMContract.networkName()).to.be.equal(networkName); - expect(await newZkEVMContract.forceBatchTimeout()).to.be.equal(FORCE_BATCH_TIMEOUT); - - // Cannot create 2 chains with the same chainID2 - await expect( - rollupManagerContract - .connect(admin) - .createNewRollup( - newRollupTypeID, - chainID2, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "ChainIDAlreadyExist"); - - const transaction = await newZkEVMContract.generateInitializeTransaction( - newCreatedRollupID, - gasTokenAddress, - gasTokenNetwork, - "0x" // empty metadata - ); - - // Check transaction - const bridgeL2Factory = await ethers.getContractFactory("PolygonZkEVMBridgeV2"); - const encodedData = bridgeL2Factory.interface.encodeFunctionData("initialize", [ - newCreatedRollupID, - gasTokenAddress, - gasTokenNetwork, - globalExitRootL2Address, - ethers.ZeroAddress, - "0x", - ]); - - const rawTx = processorUtils.customRawTxToRawTx(transaction); - const tx = ethers.Transaction.from(rawTx); - const rlpSignData = transaction.slice(0, -(SIGNATURE_BYTES * 2 + EFFECTIVE_PERCENTAGE_BYTES * 2)); - expect(rlpSignData).to.be.equal(tx.unsignedSerialized); - - expect(tx.to).to.be.equal(polygonZkEVMBridgeContract.target); - expect(tx.value).to.be.equal(0); - expect(tx.data).to.be.equal(encodedData); - expect(tx.gasPrice).to.be.equal(0); - expect(tx.gasLimit).to.be.equal(30000000); - expect(tx.nonce).to.be.equal(0); - expect(tx.chainId).to.be.equal(0); - - const expectedAccInputHash = calculateAccInputHashetrog( - ethers.ZeroHash, - ethers.keccak256(transaction), - await polygonZkEVMGlobalExitRoot.getLastGlobalExitRoot(), - timestampCreatedRollup, - trustedSequencer.address, - blockCreatedRollup?.parentHash - ); - // calcualte accINputHash - expect(await newZkEVMContract.lastAccInputHash()).to.be.equal(expectedAccInputHash); - - // Check mapping on rollup Manager - const rollupData = await rollupManagerContract.rollupIDToRollupData(newCreatedRollupID); - expect(rollupData.rollupContract).to.be.equal(newZKEVMAddress); - expect(rollupData.chainID).to.be.equal(chainID2); - expect(rollupData.verifier).to.be.equal(verifierContract.target); - expect(rollupData.forkID).to.be.equal(forkID); - expect(rollupData.lastLocalExitRoot).to.be.equal(ethers.ZeroHash); - expect(rollupData.lastBatchSequenced).to.be.equal(newSequencedBatch); - expect(rollupData.lastVerifiedBatch).to.be.equal(0); - expect(rollupData.lastPendingState).to.be.equal(0); - expect(rollupData.lastPendingStateConsolidated).to.be.equal(0); - expect(rollupData.lastVerifiedBatchBeforeUpgrade).to.be.equal(0); - expect(rollupData.rollupTypeID).to.be.equal(1); - expect(rollupData.rollupCompatibilityID).to.be.equal(0); - - const sequencedBatchData = await rollupManagerContract.getRollupSequencedBatches( - newCreatedRollupID, - newSequencedBatch - ); - - expect(sequencedBatchData.accInputHash).to.be.equal(expectedAccInputHash); - expect(sequencedBatchData.sequencedTimestamp).to.be.equal(timestampCreatedRollup); - expect(sequencedBatchData.previousLastBatchSequenced).to.be.equal(0); - - // try verify batches - const l2txData = "0x123456"; - const maticAmount = await rollupManagerContract.getBatchFee(); - const currentTimestamp = (await ethers.provider.getBlock("latest"))?.timestamp; - - const sequence = { - transactions: l2txData, - forcedGlobalExitRoot: ethers.ZeroHash, - forcedTimestamp: 0, - forcedBlockHashL1: ethers.ZeroHash, - } as BatchDataStructEtrog; - - // Approve tokens - await expect(polTokenContract.connect(trustedSequencer).approve(newZkEVMContract.target, maticAmount)).to.emit( - polTokenContract, - "Approval" - ); - - // Sequence Batches - const currentTime = Number((await ethers.provider.getBlock("latest"))?.timestamp); - const currentLastBatchSequenced = 1; - - const height = 32; - const merkleTreeGLobalExitRoot = new MerkleTreeBridge(height); - - const rootSC = await polygonZkEVMGlobalExitRoot.getRoot(); - const rootJS = merkleTreeGLobalExitRoot.getRoot(); - const l1InfoTreeLeafCount = 0; - - expect(rootSC).to.be.equal(rootJS); - - const expectedAccInputHash2 = calculateAccInputHashetrog( - expectedAccInputHash, - ethers.keccak256(l2txData), - rootSC, - currentTime, - trustedSequencer.address, - ethers.ZeroHash - ); - - await expect( - newZkEVMContract - .connect(trustedSequencer) - .sequenceBatches( - [sequence], - l1InfoTreeLeafCount, - currentTime, - expectedAccInputHash2, - trustedSequencer.address - ) - ).to.emit(newZkEVMContract, "SequenceBatches"); - - const currnetRollup = await rollupManagerContract.rollupIDToRollupData(newCreatedRollupID); - expect(currnetRollup.lastBatchSequenced).to.be.equal(2); - - // calcualte accINputHash - expect(await newZkEVMContract.lastAccInputHash()).to.be.equal(expectedAccInputHash2); - - // Create a new local exit root mocking some bridge - const tokenName = "Matic Token"; - const tokenSymbol = "MATIC"; - const decimals = 18; - const metadataToken = ethers.AbiCoder.defaultAbiCoder().encode( - ["string", "string", "uint8"], - [tokenName, tokenSymbol, decimals] - ); - - const originNetwork = networkIDRollup; - const tokenAddress = ethers.getAddress(ethers.hexlify(ethers.randomBytes(20))); - const amount = ethers.parseEther("10"); - const destinationNetwork = networkIDMainnet; - const destinationAddress = beneficiary.address; - const metadata = metadataToken; // since we are inserting in the exit root can be anything - const metadataHash = ethers.solidityPackedKeccak256(["bytes"], [metadata]); - - // compute root merkle tree in Js - const merkleTreezkEVM = new MerkleTreeBridge(height); - const leafValue = getLeafValue( - LEAF_TYPE_ASSET, - originNetwork, - tokenAddress, - destinationNetwork, - destinationAddress, - amount, - metadataHash - ); - - // Add 2 leafs - merkleTreezkEVM.add(leafValue); - merkleTreezkEVM.add(leafValue); - - // check merkle root with SC - const rootzkEVM = merkleTreezkEVM.getRoot(); - - // trustedAggregator forge the batch - const pendingState = 0; - const newLocalExitRoot = rootzkEVM; - const newStateRoot = "0x0000000000000000000000000000000000000000000000000000000000000123"; - const newVerifiedBatch = newSequencedBatch; - const zkProofFFlonk = new Array(24).fill(ethers.ZeroHash); - const currentVerifiedBatch = 0; - - const initialAggregatorMatic = await polTokenContract.balanceOf(beneficiary.address); - - await expect( - rollupManagerContract.getInputSnarkBytes( - newCreatedRollupID, - 3, - 4, - newLocalExitRoot, - ethers.ZeroHash, - newStateRoot - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "OldAccInputHashDoesNotExist"); - - await expect( - rollupManagerContract.getInputSnarkBytes( - newCreatedRollupID, - 2, - 3, - newLocalExitRoot, - ethers.ZeroHash, - newStateRoot - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "NewAccInputHashDoesNotExist"); - - await expect( - rollupManagerContract - .connect(trustedAggregator) - .verifyBatches( - newCreatedRollupID, - pendingState, - currentVerifiedBatch, - newVerifiedBatch, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "TrustedAggregatorTimeoutNotExpired"); - - await rollupManagerContract.connect(admin).setTrustedAggregatorTimeout(0); - - await expect( - rollupManagerContract - .connect(trustedAggregator) - .verifyBatches( - newCreatedRollupID, - pendingState, - currentVerifiedBatch, - currentVerifiedBatch + _MAX_VERIFY_BATCHES + 1, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "ExceedMaxVerifyBatches"); - - await expect( - rollupManagerContract - .connect(trustedAggregator) - .verifyBatches( - newCreatedRollupID, - pendingState, - currentVerifiedBatch, - currentVerifiedBatch, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "FinalNumBatchBelowLastVerifiedBatch"); - - await expect( - rollupManagerContract.verifyBatches( - newCreatedRollupID, - pendingState, - currentVerifiedBatch, - 3, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "NewAccInputHashDoesNotExist"); - - // Calcualte new globalExitroot - const merkleTreeRollups = new MerkleTreeBridge(height); - merkleTreeRollups.add(ethers.ZeroHash); - merkleTreeRollups.add(newLocalExitRoot); - const rootRollups = merkleTreeRollups.getRoot(); - - // Verify batch - await expect( - rollupManagerContract.verifyBatches( - newCreatedRollupID, - pendingState, - currentVerifiedBatch, - newVerifiedBatch, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ) - .to.emit(rollupManagerContract, "VerifyBatches") - .withArgs(newCreatedRollupID, newVerifiedBatch, newStateRoot, newLocalExitRoot, deployer.address); - - const timestampVerifyBatches = (await ethers.provider.getBlock("latest"))?.timestamp; - const finalAggregatorMatic = await polTokenContract.balanceOf(beneficiary.address); - expect(finalAggregatorMatic).to.equal(((initialAggregatorMatic + maticAmount) * 1n) / 3n); - const createdPendingState = 1; - - const snapshotVerify = await takeSnapshot(); - await rollupManagerContract.connect(admin).setPendingStateTimeout(0); - - await expect( - rollupManagerContract.verifyBatches( - newCreatedRollupID, - 0, - 5, - 6, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "OldStateRootDoesNotExist"); - - await expect( - rollupManagerContract.verifyBatches( - newCreatedRollupID, - 0, - newVerifiedBatch, - 0, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ).to.be.reverted; - - await expect( - rollupManagerContract.verifyBatches( - newCreatedRollupID, - createdPendingState + 1, - currentVerifiedBatch, - newVerifiedBatch + 1, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "PendingStateDoesNotExist"); - - await expect( - rollupManagerContract.verifyBatches( - newCreatedRollupID, - createdPendingState, - currentVerifiedBatch, - newVerifiedBatch + 1, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "InitNumBatchDoesNotMatchPendingState"); - - await expect( - rollupManagerContract.verifyBatches( - newCreatedRollupID, - createdPendingState, - newVerifiedBatch, - newVerifiedBatch + 1, - newLocalExitRoot, - ethers.toQuantity(ethers.MaxUint256), - beneficiary.address, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "NewStateRootNotInsidePrime"); - - await expect( - rollupManagerContract.verifyBatches( - newCreatedRollupID, - createdPendingState, - newVerifiedBatch, - newVerifiedBatch + 1, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ) - .to.emit(rollupManagerContract, "VerifyBatches") - .withArgs(newCreatedRollupID, newVerifiedBatch + 1, newStateRoot, newLocalExitRoot, deployer.address); - - let rollupDataV = await rollupManagerContract.rollupIDToRollupData(newCreatedRollupID); - expect(rollupDataV.lastPendingState).to.be.equal(0); - expect(rollupDataV.lastLocalExitRoot).to.be.equal(newLocalExitRoot); - expect(rollupDataV.lastBatchSequenced).to.be.equal(2); - expect(rollupDataV.lastVerifiedBatch).to.be.equal(newVerifiedBatch + 1); - expect(rollupDataV.lastPendingState).to.be.equal(0); - expect(rollupDataV.lastPendingStateConsolidated).to.be.equal(0); - expect(rollupDataV.lastVerifiedBatchBeforeUpgrade).to.be.equal(0); - - await expect( - rollupManagerContract - .connect(trustedAggregator) - .verifyBatchesTrustedAggregator( - newCreatedRollupID, - 0, - 0, - newVerifiedBatch, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "FinalNumBatchBelowLastVerifiedBatch"); - - await snapshotVerify.restore(); - await rollupManagerContract.connect(admin).setPendingStateTimeout(1); - - await expect( - rollupManagerContract.verifyBatches( - newCreatedRollupID, - createdPendingState, - newVerifiedBatch, - newVerifiedBatch + 1, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ) - .to.emit(rollupManagerContract, "VerifyBatches") - .withArgs(newCreatedRollupID, newVerifiedBatch + 1, newStateRoot, newLocalExitRoot, deployer.address); - - rollupDataV = await rollupManagerContract.rollupIDToRollupData(newCreatedRollupID); - expect(rollupDataV.lastPendingState).to.be.equal(2); - expect(rollupDataV.lastLocalExitRoot).to.be.equal(newLocalExitRoot); - expect(rollupDataV.lastBatchSequenced).to.be.equal(2); - expect(rollupDataV.lastVerifiedBatch).to.be.equal(newVerifiedBatch); - expect(rollupDataV.lastPendingStateConsolidated).to.be.equal(1); - expect(rollupDataV.lastVerifiedBatchBeforeUpgrade).to.be.equal(0); - - await snapshotVerify.restore(); - - await expect( - rollupManagerContract - .connect(trustedAggregator) - .verifyBatchesTrustedAggregator( - newCreatedRollupID, - pendingState, - currentVerifiedBatch, - newVerifiedBatch + 1, - newLocalExitRoot, - newStateRoot, - beneficiary.address, - zkProofFFlonk - ) - ) - .to.emit(rollupManagerContract, "VerifyBatchesTrustedAggregator") - .withArgs( - newCreatedRollupID, - newVerifiedBatch + 1, - newStateRoot, - newLocalExitRoot, - trustedAggregator.address - ); - - rollupDataV = await rollupManagerContract.rollupIDToRollupData(newCreatedRollupID); - expect(rollupDataV.lastPendingState).to.be.equal(0); - expect(rollupDataV.lastLocalExitRoot).to.be.equal(newLocalExitRoot); - expect(rollupDataV.lastBatchSequenced).to.be.equal(2); - expect(rollupDataV.lastVerifiedBatch).to.be.equal(newVerifiedBatch + 1); - expect(rollupDataV.lastPendingState).to.be.equal(0); - expect(rollupDataV.lastPendingStateConsolidated).to.be.equal(0); - expect(rollupDataV.lastVerifiedBatchBeforeUpgrade).to.be.equal(0); - - await snapshotVerify.restore(); - await expect( - rollupManagerContract.proveNonDeterministicPendingState( - newCreatedRollupID, - 0, - createdPendingState, - 0, - newVerifiedBatch, - newLocalExitRoot, - newStateRoot, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "StoredRootMustBeDifferentThanNewRoot"); - - await expect( - rollupManagerContract.proveNonDeterministicPendingState( - newCreatedRollupID, - 0, - createdPendingState, - 5, - newVerifiedBatch, - newLocalExitRoot, - newStateRoot, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "OldStateRootDoesNotExist"); - - await expect( - rollupManagerContract.proveNonDeterministicPendingState( - newCreatedRollupID, - 3, // init pending state - 2, - 0, - newVerifiedBatch, - newLocalExitRoot, - newStateRoot, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "PendingStateDoesNotExist"); - - await expect( - rollupManagerContract.proveNonDeterministicPendingState( - newCreatedRollupID, - createdPendingState, - createdPendingState, - 0, - newVerifiedBatch, - newLocalExitRoot, - newStateRoot, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "InitNumBatchDoesNotMatchPendingState"); - - await expect( - rollupManagerContract.proveNonDeterministicPendingState( - newCreatedRollupID, - createdPendingState, - createdPendingState, - newVerifiedBatch, - newVerifiedBatch, - newLocalExitRoot, - newStateRoot, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "FinalPendingStateNumInvalid"); - - await expect( - rollupManagerContract.proveNonDeterministicPendingState( - newCreatedRollupID, - 0, - createdPendingState, - 0, - newVerifiedBatch + 1, - newLocalExitRoot, - ethers.ZeroHash, - zkProofFFlonk - ) - ).to.be.revertedWithCustomError(rollupManagerContract, "FinalNumBatchDoesNotMatchPendingState"); - - await expect( - rollupManagerContract.proveNonDeterministicPendingState( - newCreatedRollupID, - 0, - createdPendingState, - 0, - newVerifiedBatch, - newLocalExitRoot, - ethers.ZeroHash, - zkProofFFlonk - ) - ) - .to.emit(rollupManagerContract, "ProveNonDeterministicPendingState") - .withArgs(newStateRoot, ethers.ZeroHash); - - expect(await rollupManagerContract.isEmergencyState()).to.be.equal(true); - - await snapshotVerify.restore(); - - const randomSTateRoot = ethers.hexlify(ethers.randomBytes(32)); - const randomlocalRoot = ethers.hexlify(ethers.randomBytes(32)); - - await expect( - rollupManagerContract.connect(trustedAggregator).overridePendingState( - newCreatedRollupID, - 0, - createdPendingState, - 0, - newVerifiedBatch, - randomlocalRoot, // local exit root - randomSTateRoot, // state root - zkProofFFlonk - ) - ) - .to.emit(rollupManagerContract, "OverridePendingState") - .withArgs( - newCreatedRollupID, - newVerifiedBatch, - randomSTateRoot, - randomlocalRoot, - trustedAggregator.address - ); - - expect( - await rollupManagerContract.getRollupBatchNumToStateRoot(newCreatedRollupID, newVerifiedBatch) - ).to.be.equal(randomSTateRoot); - - rollupDataV = await rollupManagerContract.rollupIDToRollupData(newCreatedRollupID); - expect(rollupDataV.lastPendingState).to.be.equal(0); - expect(rollupDataV.lastLocalExitRoot).to.be.equal(randomlocalRoot); - expect(rollupDataV.lastBatchSequenced).to.be.equal(2); - expect(rollupDataV.lastVerifiedBatch).to.be.equal(newVerifiedBatch); - expect(rollupDataV.lastPendingState).to.be.equal(0); - expect(rollupDataV.lastPendingStateConsolidated).to.be.equal(0); - - expect(await rollupManagerContract.isEmergencyState()).to.be.equal(false); - expect(await rollupManagerContract.trustedAggregatorTimeout()).to.be.equal(_HALT_AGGREGATION_TIMEOUT); - - await snapshotVerify.restore(); - - const pendingStateNum = 1; - // check revert reasons: - - expect( - await rollupManagerContract.isPendingStateConsolidable(newCreatedRollupID, createdPendingState) - ).to.be.equal(false); - - const currentPendingStateTransition = await rollupManagerContract.getRollupPendingStateTransitions( - newCreatedRollupID, - createdPendingState - ); - - expect(currentPendingStateTransition.timestamp).to.be.equal(timestampVerifyBatches); - expect(currentPendingStateTransition.lastVerifiedBatch).to.be.equal(newVerifiedBatch); - expect(currentPendingStateTransition.exitRoot).to.be.equal(newLocalExitRoot); - expect(currentPendingStateTransition.stateRoot).to.be.equal(newStateRoot); - - await expect( - rollupManagerContract.consolidatePendingState(newCreatedRollupID, pendingStateNum) - ).to.be.revertedWithCustomError(rollupManagerContract, "PendingStateNotConsolidable"); - - // try emergency - await rollupManagerContract.connect(emergencyCouncil).activateEmergencyState(); - await rollupManagerContract.connect(admin).setPendingStateTimeout(0); - - await expect( - rollupManagerContract.consolidatePendingState(newCreatedRollupID, pendingStateNum) - ).to.be.revertedWithCustomError(rollupManagerContract, "OnlyNotEmergencyState"); - await snapshotVerify.restore(); - - await expect( - rollupManagerContract - .connect(trustedAggregator) - .consolidatePendingState(newCreatedRollupID, pendingStateNum + 1) - ).to.be.revertedWithCustomError(rollupManagerContract, "PendingStateInvalid"); - - await expect( - rollupManagerContract - .connect(trustedAggregator) - .consolidatePendingState(newCreatedRollupID, pendingStateNum) - ) - .to.emit(rollupManagerContract, "ConsolidatePendingState") - .withArgs(newCreatedRollupID, newVerifiedBatch, newStateRoot, newLocalExitRoot, pendingStateNum); - - // Assert new root - expect( - await rollupManagerContract.getRollupBatchNumToStateRoot(newCreatedRollupID, newVerifiedBatch) - ).to.be.equal(newStateRoot); - - // Assert global exit root - expect(await polygonZkEVMGlobalExitRoot.lastRollupExitRoot()).to.be.equal(rootRollups); - expect(await polygonZkEVMGlobalExitRoot.lastMainnetExitRoot()).to.be.equal(ethers.ZeroHash); - - expect(await polygonZkEVMGlobalExitRoot.getLastGlobalExitRoot()).to.be.equal( - calculateGlobalExitRoot(ethers.ZeroHash, rootRollups) - ); - - const indexLeaf = 0; - const indexRollup = 1; - const proofZkEVM = merkleTreezkEVM.getProofTreeByIndex(indexLeaf); - const proofRollups = merkleTreeRollups.getProofTreeByIndex(indexRollup); - - // verify merkle proof - expect(verifyMerkleProof(leafValue, proofZkEVM, indexLeaf, rootzkEVM)).to.be.equal(true); - expect(verifyMerkleProof(rootzkEVM, proofRollups, indexRollup, rootRollups)).to.be.equal(true); - - expect( - await polygonZkEVMBridgeContract.verifyMerkleProof(leafValue, proofZkEVM, indexLeaf, rootzkEVM) - ).to.be.equal(true); - - expect( - await polygonZkEVMBridgeContract.verifyMerkleProof(newLocalExitRoot, proofRollups, indexRollup, rootRollups) - ).to.be.equal(true); - - // claim - const tokenWrappedFactory = await ethers.getContractFactory("TokenWrapped"); - // create2 parameters - const salt = ethers.solidityPackedKeccak256(["uint32", "address"], [networkIDRollup, tokenAddress]); - const minimalBytecodeProxy = await polygonZkEVMBridgeContract.BASE_INIT_BYTECODE_WRAPPED_TOKEN(); - const hashInitCode = ethers.solidityPackedKeccak256(["bytes", "bytes"], [minimalBytecodeProxy, metadataToken]); - const precalculateWrappedErc20 = await ethers.getCreate2Address( - polygonZkEVMBridgeContract.target as string, - salt, - hashInitCode - ); - const newWrappedToken = tokenWrappedFactory.attach(precalculateWrappedErc20) as TokenWrapped; - - // Use precalculatedWrapperAddress and check if matches - expect( - await polygonZkEVMBridgeContract.precalculatedWrapperAddress( - networkIDRollup, - tokenAddress, - tokenName, - tokenSymbol, - decimals - ) - ).to.be.equal(precalculateWrappedErc20); - - // index leaf is 0 bc, does not have mainnet flag, and it's rollup 0 on leaf 0 - const globalIndex = computeGlobalIndex(indexLeaf, indexRollup, false); - await expect( - polygonZkEVMBridgeContract.claimAsset( - proofZkEVM, - proofRollups, - globalIndex, - ethers.ZeroHash, - rootRollups, - originNetwork, - tokenAddress, - destinationNetwork, - destinationAddress, - amount, - metadata - ) - ) - .to.emit(polygonZkEVMBridgeContract, "ClaimEvent") - .withArgs(globalIndex, originNetwork, tokenAddress, destinationAddress, amount) - .to.emit(polygonZkEVMBridgeContract, "NewWrappedToken") - .withArgs(originNetwork, tokenAddress, precalculateWrappedErc20, metadata) - .to.emit(newWrappedToken, "Transfer") - .withArgs(ethers.ZeroAddress, beneficiary.address, amount); - - // Assert maps created - const newTokenInfo = await polygonZkEVMBridgeContract.wrappedTokenToTokenInfo(precalculateWrappedErc20); - - expect(newTokenInfo.originNetwork).to.be.equal(networkIDRollup); - expect(newTokenInfo.originTokenAddress).to.be.equal(tokenAddress); - expect(await polygonZkEVMBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( - precalculateWrappedErc20 - ); - expect(await polygonZkEVMBridgeContract.getTokenWrappedAddress(networkIDRollup, tokenAddress)).to.be.equal( - precalculateWrappedErc20 - ); - - expect(await polygonZkEVMBridgeContract.tokenInfoToWrappedToken(salt)).to.be.equal(precalculateWrappedErc20); - - // Check the wrapper info - expect(await newWrappedToken.name()).to.be.equal(tokenName); - expect(await newWrappedToken.symbol()).to.be.equal(tokenSymbol); - expect(await newWrappedToken.decimals()).to.be.equal(decimals); - - // Can't claim because nullifier - await expect( - polygonZkEVMBridgeContract.claimAsset( - proofZkEVM, - proofRollups, - globalIndex, - ethers.ZeroHash, - rootRollups, - originNetwork, - tokenAddress, - destinationNetwork, - destinationAddress, - amount, - metadata - ) - ).to.be.revertedWithCustomError(polygonZkEVMBridgeContract, "AlreadyClaimed"); - - // Check new token - expect(await newWrappedToken.totalSupply()).to.be.equal(amount); - }); - it("Should test obsolete rollup", async () => { const forkID = 0; const genesisRandom = "0x0000000000000000000000000000000000000000000000000000000000000001"; - const rollupCompatibilityID = 0; - const descirption = "zkevm test"; + const rollupVerifierType = 0; + const description = "zkevm test"; + const programVKey = "0x0000000000000000000000000000000000000000000000000000000000000000"; // In order to create a new rollup type, create an implementation of the contract @@ -2041,9 +1099,10 @@ describe("Polygon Rollup manager upgraded", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ) ) .to.emit(rollupManagerContract, "AddNewRollupType") @@ -2052,9 +1111,10 @@ describe("Polygon Rollup manager upgraded", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, genesisRandom, - descirption + description, + programVKey ); // assert new rollup type @@ -2064,9 +1124,10 @@ describe("Polygon Rollup manager upgraded", () => { PolygonZKEVMV2Contract.target, verifierContract.target, forkID, - rollupCompatibilityID, + rollupVerifierType, false, genesisRandom, + programVKey, ]; expect(createdRollupType).to.be.deep.equal(expectedRollupType); diff --git a/test/contractsv2/PolygonValidiumEtrog.test.ts b/test/contractsv2/PolygonValidiumEtrog.test.ts index cb9199f82..ca1c8816b 100644 --- a/test/contractsv2/PolygonValidiumEtrog.test.ts +++ b/test/contractsv2/PolygonValidiumEtrog.test.ts @@ -29,7 +29,7 @@ function calculateGlobalExitRoot(mainnetExitRoot: any, rollupExitRoot: any) { return ethers.solidityPackedKeccak256(["bytes32", "bytes32"], [mainnetExitRoot, rollupExitRoot]); } -describe("PolygonZkEVMEtrog", () => { +describe("PolygonValidiumEtrog", () => { let deployer: any; let timelock: any; let emergencyCouncil: any; @@ -166,12 +166,17 @@ describe("PolygonZkEVMEtrog", () => { // deploy consensus // Create zkEVM implementation const PolygonZKEVMV2Factory = await ethers.getContractFactory("PolygonValidiumEtrog"); - PolygonZKEVMV2Contract = await PolygonZKEVMV2Factory.deploy( - polygonZkEVMGlobalExitRoot.target, - polTokenContract.target, - polygonZkEVMBridgeContract.target, - rollupManagerContract.target - ); + PolygonZKEVMV2Contract = await upgrades.deployProxy(PolygonZKEVMV2Factory, [], { + initializer: false, + constructorArgs: [ + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + rollupManagerContract.target, + ], + unsafeAllow: ["constructor", "state-variable-immutable"], + }); + await PolygonZKEVMV2Contract.waitForDeployment(); // Create CdkCommitee diff --git a/test/contractsv2/PolygonZkEVMEtrog.test.ts b/test/contractsv2/PolygonZkEVMEtrog.test.ts index fa85c094a..1de6965e7 100644 --- a/test/contractsv2/PolygonZkEVMEtrog.test.ts +++ b/test/contractsv2/PolygonZkEVMEtrog.test.ts @@ -163,12 +163,17 @@ describe("PolygonZkEVMEtrog", () => { // deploy consensus // Create zkEVM implementation const PolygonZKEVMV2Factory = await ethers.getContractFactory("PolygonZkEVMEtrog"); - PolygonZKEVMV2Contract = await PolygonZKEVMV2Factory.deploy( - polygonZkEVMGlobalExitRoot.target, - polTokenContract.target, - polygonZkEVMBridgeContract.target, - rollupManagerContract.target - ); + PolygonZKEVMV2Contract = await upgrades.deployProxy(PolygonZKEVMV2Factory, [], { + initializer: false, + constructorArgs: [ + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + rollupManagerContract.target, + ], + unsafeAllow: ["constructor", "state-variable-immutable"], + }); + await PolygonZKEVMV2Contract.waitForDeployment(); }); diff --git a/test/contractsv2/real-prover-sp1/e2e-verify-proof.test.ts b/test/contractsv2/real-prover-sp1/e2e-verify-proof.test.ts new file mode 100644 index 000000000..076b47243 --- /dev/null +++ b/test/contractsv2/real-prover-sp1/e2e-verify-proof.test.ts @@ -0,0 +1,351 @@ +/* eslint-disable no-plusplus, no-await-in-loop */ +import {expect} from "chai"; +import {ethers, upgrades} from "hardhat"; +import { + SP1VerifierPlonk, + ERC20PermitMock, + PolygonRollupManagerMock, + PolygonZkEVMGlobalExitRootV2Mock, + PolygonZkEVMBridgeV2, + PolygonPessimisticConsensus, +} from "../../../typechain-types"; +const { + VerifierType, + computeInputPessimisticBytes, + computeConsensusHashEcdsa, +} = require("../../../src/pessimistic-utils"); +const inputProof = require("./test-inputs/input.json"); + +describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { + let deployer: any; + let timelock: any; + let emergencyCouncil: any; + let trustedAggregator: any; + let trustedSequencer: any; + let admin: any; + let beneficiary: any; + + let verifierContract: SP1VerifierPlonk; + let polygonZkEVMBridgeContract: PolygonZkEVMBridgeV2; + let polTokenContract: ERC20PermitMock; + let polygonZkEVMGlobalExitRoot: PolygonZkEVMGlobalExitRootV2Mock; + let rollupManagerContract: PolygonRollupManagerMock; + let PolygonPPConsensusContract: PolygonPessimisticConsensus; + + const polTokenName = "POL Token"; + const polTokenSymbol = "POL"; + const polTokenInitialBalance = ethers.parseEther("20000000"); + + const pendingStateTimeoutDefault = 100; + const trustedAggregatorTimeout = 100; + + // BRidge constants + const networkIDMainnet = 0; + const networkIDRollup = 1; + + const LEAF_TYPE_ASSET = 0; + const LEAF_TYPE_MESSAGE = 1; + + let firstDeployment = true; + + //roles + const DEFAULT_ADMIN_ROLE = ethers.ZeroHash; + const ADD_ROLLUP_TYPE_ROLE = ethers.id("ADD_ROLLUP_TYPE_ROLE"); + const OBSOLETE_ROLLUP_TYPE_ROLE = ethers.id("OBSOLETE_ROLLUP_TYPE_ROLE"); + const CREATE_ROLLUP_ROLE = ethers.id("CREATE_ROLLUP_ROLE"); + const ADD_EXISTING_ROLLUP_ROLE = ethers.id("ADD_EXISTING_ROLLUP_ROLE"); + const UPDATE_ROLLUP_ROLE = ethers.id("UPDATE_ROLLUP_ROLE"); + const TRUSTED_AGGREGATOR_ROLE = ethers.id("TRUSTED_AGGREGATOR_ROLE"); + const TRUSTED_AGGREGATOR_ROLE_ADMIN = ethers.id("TRUSTED_AGGREGATOR_ROLE_ADMIN"); + const TWEAK_PARAMETERS_ROLE = ethers.id("TWEAK_PARAMETERS_ROLE"); + const SET_FEE_ROLE = ethers.id("SET_FEE_ROLE"); + const STOP_EMERGENCY_ROLE = ethers.id("STOP_EMERGENCY_ROLE"); + const EMERGENCY_COUNCIL_ROLE = ethers.id("EMERGENCY_COUNCIL_ROLE"); + const EMERGENCY_COUNCIL_ADMIN = ethers.id("EMERGENCY_COUNCIL_ADMIN"); + + const SIGNATURE_BYTES = 32 + 32 + 1; + const EFFECTIVE_PERCENTAGE_BYTES = 1; + + beforeEach("Deploy contract", async () => { + upgrades.silenceWarnings(); + + // load signers + [deployer, trustedAggregator, admin, timelock, emergencyCouncil, beneficiary] = await ethers.getSigners(); + trustedSequencer = inputProof.signer; + // deploy mock verifier + const VerifierRollupHelperFactory = await ethers.getContractFactory("SP1VerifierPlonk"); + verifierContract = await VerifierRollupHelperFactory.deploy(); + + // deploy pol + const polTokenFactory = await ethers.getContractFactory("ERC20PermitMock"); + polTokenContract = await polTokenFactory.deploy( + polTokenName, + polTokenSymbol, + deployer.address, + polTokenInitialBalance + ); + + /* + * deploy global exit root manager + * In order to not have trouble with nonce deploy first proxy admin + */ + await upgrades.deployProxyAdmin(); + + if ((await upgrades.admin.getInstance()).target !== "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0") { + firstDeployment = false; + } + const nonceProxyBridge = + Number(await ethers.provider.getTransactionCount(deployer.address)) + (firstDeployment ? 3 : 2); + + const nonceProxyZkevm = nonceProxyBridge + 2; // Always have to redeploy impl since the polygonZkEVMGlobalExitRoot address changes + + const precalculateBridgeAddress = ethers.getCreateAddress({ + from: deployer.address, + nonce: nonceProxyBridge, + }); + const precalculateRollupManagerAddress = ethers.getCreateAddress({ + from: deployer.address, + nonce: nonceProxyZkevm, + }); + firstDeployment = false; + + // deploy globalExitRoot + const PolygonZkEVMGlobalExitRootFactory = await ethers.getContractFactory("PolygonZkEVMGlobalExitRootV2Mock"); + polygonZkEVMGlobalExitRoot = await upgrades.deployProxy(PolygonZkEVMGlobalExitRootFactory, [], { + constructorArgs: [precalculateRollupManagerAddress, precalculateBridgeAddress], + unsafeAllow: ["constructor", "state-variable-immutable"], + }); + + // deploy PolygonZkEVMBridge + const polygonZkEVMBridgeFactory = await ethers.getContractFactory("PolygonZkEVMBridgeV2"); + polygonZkEVMBridgeContract = await upgrades.deployProxy(polygonZkEVMBridgeFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + }); + + // deploy polygon rollup manager mock + const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManagerMock"); + + rollupManagerContract = (await upgrades.deployProxy(PolygonRollupManagerFactory, [], { + initializer: false, + constructorArgs: [ + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + ], + unsafeAllow: ["constructor", "state-variable-immutable"], + })) as unknown as PolygonRollupManagerMock; + + await rollupManagerContract.waitForDeployment(); + + // check precalculated address + expect(precalculateBridgeAddress).to.be.equal(polygonZkEVMBridgeContract.target); + expect(precalculateRollupManagerAddress).to.be.equal(rollupManagerContract.target); + + await polygonZkEVMBridgeContract.initialize( + networkIDMainnet, + ethers.ZeroAddress, // zero for ether + ethers.ZeroAddress, // zero for ether + polygonZkEVMGlobalExitRoot.target, + rollupManagerContract.target, + "0x" + ); + + // Initialize Mock + await rollupManagerContract.initializeMock( + trustedAggregator.address, + pendingStateTimeoutDefault, + trustedAggregatorTimeout, + admin.address, + timelock.address, + emergencyCouncil.address + ); + + await expect(rollupManagerContract.initialize()).to.emit(rollupManagerContract, "UpdateRollupManagerVersion"); + + // fund sequencer address with Matic tokens + await polTokenContract.transfer(trustedSequencer, ethers.parseEther("1000")); + }); + + it("should check the initalized parameters", async () => { + expect(await rollupManagerContract.globalExitRootManager()).to.be.equal(polygonZkEVMGlobalExitRoot.target); + expect(await rollupManagerContract.pol()).to.be.equal(polTokenContract.target); + expect(await rollupManagerContract.bridgeAddress()).to.be.equal(polygonZkEVMBridgeContract.target); + + expect(await rollupManagerContract.getBatchFee()).to.be.equal(ethers.parseEther("0.1")); + expect(await rollupManagerContract.getForcedBatchFee()).to.be.equal(ethers.parseEther("10")); + expect(await rollupManagerContract.calculateRewardPerBatch()).to.be.equal(0); + + // Check roles + expect(await rollupManagerContract.hasRole(DEFAULT_ADMIN_ROLE, timelock.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(ADD_ROLLUP_TYPE_ROLE, timelock.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(UPDATE_ROLLUP_ROLE, timelock.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(ADD_EXISTING_ROLLUP_ROLE, timelock.address)).to.be.equal(true); + + expect(await rollupManagerContract.hasRole(TRUSTED_AGGREGATOR_ROLE, trustedAggregator.address)).to.be.equal( + true + ); + + expect(await rollupManagerContract.hasRole(OBSOLETE_ROLLUP_TYPE_ROLE, admin.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(CREATE_ROLLUP_ROLE, admin.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(TRUSTED_AGGREGATOR_ROLE_ADMIN, admin.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(TWEAK_PARAMETERS_ROLE, admin.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(SET_FEE_ROLE, admin.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(STOP_EMERGENCY_ROLE, admin.address)).to.be.equal(true); + + expect(await rollupManagerContract.hasRole(EMERGENCY_COUNCIL_ROLE, emergencyCouncil.address)).to.be.equal(true); + expect(await rollupManagerContract.hasRole(EMERGENCY_COUNCIL_ADMIN, emergencyCouncil.address)).to.be.equal( + true + ); + }); + + it("should verify pessimistic proof: pessimistic type, with a real verifier (not mock)", async () => { + // deploy consensus + // create polygonPessimisticConsensus implementation + const ppConsensusFactory = await ethers.getContractFactory("PolygonPessimisticConsensus"); + PolygonPPConsensusContract = await ppConsensusFactory.deploy( + polygonZkEVMGlobalExitRoot.target, + polTokenContract.target, + polygonZkEVMBridgeContract.target, + rollupManagerContract.target + ); + await PolygonPPConsensusContract.waitForDeployment(); + + // Try to add a new rollup type + const forkID = 11; // just metadata for pessimistic consensus + const genesis = ethers.ZeroHash; + const description = "new pessimistic consensus"; + const programVKey = inputProof.vkey; + const rollupTypeID = 1; + + // correct add new rollup via timelock + await rollupManagerContract + .connect(timelock) + .addNewRollupType( + PolygonPPConsensusContract.target, + verifierContract.target, + forkID, + VerifierType.Pessimistic, + genesis, + description, + programVKey + ); + + // create new pessimistic: only admin + const chainID = 1; + const gasTokenAddress = ethers.ZeroAddress; + const urlSequencer = "https://pessimistic:8545"; + const networkName = "testPessimistic"; + const pessimisticRollupID = inputProof["pp-inputs"]["origin-network"]; + + // create new pessimistic + const newZKEVMAddress = ethers.getCreateAddress({ + from: rollupManagerContract.target as string, + nonce: 1, + }); + + await rollupManagerContract + .connect(admin) + .createNewRollup( + rollupTypeID, + chainID, + admin.address, + trustedSequencer, + gasTokenAddress, + urlSequencer, + networkName + ); + + // select unexistent global exit root + const l1InfoTreeLeafCount = 2; + const newLER = inputProof["pp-inputs"]["new-local-exit-root"]; + const newPPRoot = inputProof["pp-inputs"]["new-pessimistic-root"]; + const proofPP = inputProof.proof; + + // not trusted aggregator + await expect( + rollupManagerContract.verifyPessimisticTrustedAggregator( + pessimisticRollupID, + l1InfoTreeLeafCount, + newLER, + newPPRoot, + proofPP + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); + + // global exit root does not exist + await expect( + rollupManagerContract + .connect(trustedAggregator) + .verifyPessimisticTrustedAggregator( + pessimisticRollupID, + l1InfoTreeLeafCount, + newLER, + newPPRoot, + proofPP + ) + ).to.be.revertedWithCustomError(rollupManagerContract, "L1InfoTreeLeafCountInvalid"); + + const l1InfoRoot = inputProof["pp-inputs"]["l1-info-root"]; + // check JS function computeInputPessimisticBytes + const inputPessimisticBytes = await rollupManagerContract.getInputPessimisticBytes( + pessimisticRollupID, + l1InfoRoot, + inputProof["pp-inputs"]["new-local-exit-root"], + inputProof["pp-inputs"]["new-pessimistic-root"] + ); + + const infoRollup = await rollupManagerContract.rollupIDToRollupDataV2(pessimisticRollupID); + + const consensusHash = computeConsensusHashEcdsa(trustedSequencer); + + const expectedInputPessimisticBytes = computeInputPessimisticBytes( + infoRollup[4], + infoRollup[10], + l1InfoRoot, + pessimisticRollupID, + consensusHash, + newLER, + newPPRoot + ); + + expect(inputPessimisticBytes).to.be.equal(expectedInputPessimisticBytes); + // Mock selected GER + await polygonZkEVMGlobalExitRoot.injectGER(l1InfoRoot, l1InfoTreeLeafCount); + + // verify pessimistic + await expect( + rollupManagerContract + .connect(trustedAggregator) + .verifyPessimisticTrustedAggregator( + pessimisticRollupID, + l1InfoTreeLeafCount, + newLER, + newPPRoot, + proofPP + ) + ) + .to.emit(rollupManagerContract, "VerifyBatchesTrustedAggregator") + .withArgs(pessimisticRollupID, 0, ethers.ZeroHash, newLER, trustedAggregator.address); + + // assert rollup data + const resRollupData = await rollupManagerContract.rollupIDToRollupDataV2(pessimisticRollupID); + + const expectedRollupData = [ + newZKEVMAddress, + chainID, + verifierContract.target, + forkID, + newLER, + 0, + 0, + 0, + rollupTypeID, + VerifierType.Pessimistic, + newPPRoot, + programVKey, + ]; + + expect(expectedRollupData).to.be.deep.equal(resRollupData); + }); +}); diff --git a/test/contractsv2/real-prover-sp1/real-prover-test-inputs.test.ts b/test/contractsv2/real-prover-sp1/real-prover-test-inputs.test.ts new file mode 100644 index 000000000..5bbf5845d --- /dev/null +++ b/test/contractsv2/real-prover-sp1/real-prover-test-inputs.test.ts @@ -0,0 +1,24 @@ +const { ethers } = require('hardhat'); + +const input = require('./test-inputs/input.json'); + +describe('Real prover inputs test', () => { + let verifierContract; + + beforeEach('Deploy contract', async () => { + // deploy mock verifier + const VerifierFactory = await ethers.getContractFactory( + 'SP1VerifierPlonk', + ); + verifierContract = await VerifierFactory.deploy(); + }); + + it('Test real prover', async () => { + // If the verification fails, it reverts and throws error, else it returns nothing + await verifierContract.verifyProof( + input.vkey, + input['public-values'], + input.proof, + ); + }); +}); diff --git a/test/contractsv2/real-prover-sp1/test-inputs/input.json b/test/contractsv2/real-prover-sp1/test-inputs/input.json new file mode 100644 index 000000000..7926fa674 --- /dev/null +++ b/test/contractsv2/real-prover-sp1/test-inputs/input.json @@ -0,0 +1,15 @@ +{ + "pp-inputs": { + "prev-local-exit-root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "prev-pessimistic-root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "l1-info-root": "0x9f1d0c7713a6a5f1e79222623c0687242c3feed74ebecb6f9d0e87e7572cdeca", + "origin-network": 1, + "consensus-hash": "0x999e4fef8b9af84b9cb960e8ec82f8e22265fad3dd91f243151f329b2be822d8", + "new-local-exit-root": "0xdc8303b7d6a0efe97628c90caa9b8bd30a451c72b16af6b65c618d33f8d94c9e", + "new-pessimistic-root": "0x1178d1e1a7a864774831e9d047573600731bdfc28aaccd663a3a221447e60fb0" + }, + "signer": "0x67f761cd7f8e3fdb3c7bdf7c0bbf76ab3f4fbd2a", + "vkey": "0x0062c685702e0582d900f3a19521270c92a58e2588230c4a5cf3b45103f4a512", + "public-values": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009f1d0c7713a6a5f1e79222623c0687242c3feed74ebecb6f9d0e87e7572cdeca00000001999e4fef8b9af84b9cb960e8ec82f8e22265fad3dd91f243151f329b2be822d8dc8303b7d6a0efe97628c90caa9b8bd30a451c72b16af6b65c618d33f8d94c9e1178d1e1a7a864774831e9d047573600731bdfc28aaccd663a3a221447e60fb0", + "proof": "0x1b34fe112a4ada9058510af95e7f5319263677e3551158d405afe37843808235d89b38370199b493d80d5f02dbd607af9f16e387a1065bd689815cb8b66052a1d8fa6e5f0fd906e6dd73ad9ec2841dc10efaaa09da41d38fa9c3d6d48aabea2c27371b730550c7175a3a00d940b6ba0f4d0b7a9b7fa8f04b4b44e26cb5d664e5831cf50f2e25bfa80dd3a6b27093849e5691922180c0d2df9eeae0ffd6c7f9330f36ea2a2c7b1b97e3f839a7b5ceafeb92960d0714ca2bbe2c951d9e91052cb02eb16a7613672b22de3898850d0658a08e7fd33fa63124f173fb5623a019c39eed66f5df17a85d1f7ed35495b2bcdacc560608ff944f410d73adbdf567472678a933ac460c55f17dedbcf2de75ac964fb58f052222d902f8f4a55b79471e9e566ea53ec82d6a005251a8264b3270b6370697293652efcb05e25b703432852400a8b1d4ca1ed512d016e6371c57ac51c6ebba9c629802698b0e4487dec044acd9e08fc3660d5ef2fc130f8facfbe26a97e1bde0f58876d45fce622f228211557488cd3a701fbb03ff74b85e4b6ba9ab76e059d5e17f0e27aada7737f9ad16ed7d880b037424e9df26b900b7f0c7b3c55495e1cb88d1b80e04bd4f8f49fbb6c3edd159da89303068cf1b319332e020be6d7c173e55a3064d38b180174ee3504fdc6be8882612e76b5d0e3037ef856bd81006844250042a8b441ed25ff6a513fd636ec805fb12fdda1b11fed516b00719d9f1c881797e17feca48723fad06ea0e66212e19df139217b56c8e48e83277a0e0a664bbaea9ec02cac9d447536d247c53aa2def050c0996b93060ac0b09b8377784df4f877534ec601352645ad3d206bc5044878f149865264c19f864ccf40c58f94a63996d878baf246ba109d9695afeffefe4c9024d66443ea45c4d1a493e7b4bcaf86e8652513a417ac47c939623a24e6e55e927e14a3ec539c929e288568bb2966627a53de0f0fc480150d7637b8c99d9e42609c9b4dcf66a091c833e436ee61bc6c11d0189016e5790e805c75e710122b15903464a856b27ebe483cdf87d1cd1c9538f90741f9fbe7fc51999b05f6b8d56e229da7125024a6bf51d67eaefa8fc0633394fca33162b611428294bbb7eb00967270c425b9b1ce22b13f298451720424695e902f72383a7f15e0d36181b7db709252307f8da504522eb0854ce89edcb87939539db1e84fea0cba0ef7b903f3972" +} \ No newline at end of file diff --git a/test/src/timelock-storage.test.ts b/test/src/timelock-storage.test.ts new file mode 100644 index 000000000..7fe6c3f47 --- /dev/null +++ b/test/src/timelock-storage.test.ts @@ -0,0 +1,35 @@ +import { expect } from 'chai'; +import { ethers } from 'hardhat'; +import lodash from 'lodash'; +const { initializeTimelockStorage } = require('../../src/genesis/genesis-helpers'); +const { getStorageWrites } = require('../../src/utils'); + +describe('Timelock storage util', () => { + it('Verify genesis util: initializeTimelockStorage', async () => { + const minDelay = 3600; + const timelockAdminAddress = '0x1234567890123456789012345678901234567890'; + + const timelockContractFactory = await ethers.getContractFactory('PolygonZkEVMTimelock'); + const timelockContract = await timelockContractFactory.deploy( + minDelay, + [timelockAdminAddress], + [timelockAdminAddress], + timelockAdminAddress, + ethers.ZeroAddress + ); + const tx = await timelockContract.deploymentTransaction(); + + const trace = await ethers.provider.send("debug_traceTransaction", [tx.hash, { + enableMemory: false, + disableStack: false, + disableStorage: false, + enableReturnData: false, + }]); + + // Get utils storage and compare with the one computed + const computedTimelockStorage = getStorageWrites(trace); + const utilsTimelockStorage = initializeTimelockStorage(minDelay, timelockAdminAddress, timelockContract.target); + + expect(lodash.isEqual(computedTimelockStorage, utilsTimelockStorage)).to.be.equal(true); + }); +}); diff --git a/tools/addRollupType/.gitignore b/tools/addRollupType/.gitignore index a7ca529c6..8d94ceb78 100644 --- a/tools/addRollupType/.gitignore +++ b/tools/addRollupType/.gitignore @@ -1,3 +1,3 @@ -add_rollup_type_output-*.json +add_rollup_type_output*.json add_rollup_type.json genesis.json \ No newline at end of file diff --git a/tools/addRollupType/README.md b/tools/addRollupType/README.md index ff9a2c115..4bd295630 100644 --- a/tools/addRollupType/README.md +++ b/tools/addRollupType/README.md @@ -1,5 +1,5 @@ # Add Rollup Type -Script to call `addNewRollupType` function with no timelock involved +Script to call `addNewRollupType` function ## Install ``` @@ -7,23 +7,25 @@ npm i ``` ## Setup -- Config file - - `consensusContract`: select between consensus contract. Supprted: `["PolygonZkEVMEtrog", "PolygonValidiumEtrog"]` - - `polygonRollupManagerAddress`: polygonRollupManager smart contract address - - `verifierAddress`: verifier to be used +- Config file `add_rollup_type.json`: + - `consensusContract`: select between consensus contract. Supported: `["PolygonZkEVMEtrog", "PolygonValidiumEtrog", "PolygonPessimisticConsensus"]` + - `consensusContractAddress`: gets this address instead of deploying a new consensus implementation + - `polygonRollupManagerAddress`: `PolygonRollupManager.sol` smart contract address + - `verifierAddress`: verifier address to be used - `description`: string to describe rollup type added. Example: "Type: Validium, Version: etrog, genesis: /ipfs/QmUXnRoPbUmZuEZCGyiHjEsoNcFVu3hLtSvhpnfBS2mAYU" - `forkID`: forkID to be used - - `rollupCompatibilityID`: rollup compatibility ID + - `programVKey`: program key for pessimistic consensus + - `genesisRoot`: initial genesis root. Must match the `genesis.json` generated. - `timelockDelay`: timelock delay - `timelockSalt(optional)`: timelock salt - `predecessor(optional)`: timelock predecessor - `deployerPvtKey(optional)`: private key deployer - First option will load `deployerPvtKey`. Otherwise, `process.env.MNEMONIC` will be loaded from the `.env` file - - `maxFeePerGas(optional)`: string, Set `maxFeePerGas`, must define aswell `maxPriorityFeePerGas` to use it - - `maxPriorityFeePerGas(optional)`: string, Set `maxPriorityFeePerGas`, must define aswell `maxFeePerGas` to use it + - `maxFeePerGas(optional)`: string, Set `maxFeePerGas`, must define as well `maxPriorityFeePerGas` to use it + - `maxPriorityFeePerGas(optional)`: string, Set `maxPriorityFeePerGas`, must define as well `maxFeePerGas` to use it - `multiplierGas(optional)`: number, Gas multiplier with 3 decimals. If `maxFeePerGas` and `maxPriorityFeePerGas` are set, this will not take effect - A network should be selected when running the script - - examples: `-- sepolia` or `--mainnet` + - examples: `--sepolia` or `--mainnet` - This uses variables set in `hardhat.config.ts` - Which uses some environment variables that should be set in `.env` > All paths are from root repository @@ -45,7 +47,7 @@ cp ./tools/addRollupType/genesis.json.example ./tools/addRollupType/genesis.json - Set your parameters - Run tool: ``` -npx hardhat run ./tools/addRollupType/addRollupType.ts --network sepolia +npx hardhat run ./tools/addRollupType/addRollupType.ts --network ``` ### Generate 'addNewRollupType' to the Timelock SC @@ -58,12 +60,12 @@ cp ./tools/addRollupType/add_rollup_type.json.example ./tools/addRollupType/add_ - Set your parameters - Run tool: ``` -npx hardhat run ./tools/addRollupType/addRollupType.ts --network sepolia +npx hardhat run ./tools/addRollupType/addRollupTypeTimelock.ts --network ``` - Output: - scheduleData - executeData > send data to the timelock contract address: -> - use your favourite browser extension +> - use your favorite browser extension > - send tx to timelock address with hex data as `scheduleData` > - wait timelockDelay and then send `executeData` to timelock address \ No newline at end of file diff --git a/tools/addRollupType/addRollupMainnet9/add_rollup_type_9.json b/tools/addRollupType/addRollupMainnet9/add_rollup_type_9.json new file mode 100644 index 000000000..f1ef85c87 --- /dev/null +++ b/tools/addRollupType/addRollupMainnet9/add_rollup_type_9.json @@ -0,0 +1,16 @@ +{ + "consensusContract": "PolygonPessimisticConsensus", + "consensusContractAddress": "", + "polygonRollupManagerAddress": "0x5132A183E9F3CB7C848b0AAC5Ae0c4f0491B7aB2", + "verifierAddress": "0xE00a3cBFC45241b33c0A44C78e26168CBc55EC63", + "description": "Type: Pessimistic, Version: v0.2.1, genesis: /ipfs/QmUXnRoPbUmZuEZCGyiHjEsoNcFVu3hLtSvhpnfBS2mAYU", + "forkID": 12, + "timelockDelay": 864000, + "timelockSalt": "", + "deployerPvtKey": "", + "maxFeePerGas":"", + "maxPriorityFeePerGas":"", + "multiplierGas": "", + "genesisRoot": "0xe3a7d8bae497945ba8ddc51c69564f60ad4c1a990b9c7bdbd27f7929bfa8f272", + "programVKey": "0x0062c685702e0582d900f3a19521270c92a58e2588230c4a5cf3b45103f4a512" +} \ No newline at end of file diff --git a/tools/addRollupType/addRollupMainnet9/add_rollup_type_9_output-2025-01-17T16:15:52.866Z.json b/tools/addRollupType/addRollupMainnet9/add_rollup_type_9_output-2025-01-17T16:15:52.866Z.json new file mode 100644 index 000000000..519b1eaa0 --- /dev/null +++ b/tools/addRollupType/addRollupMainnet9/add_rollup_type_9_output-2025-01-17T16:15:52.866Z.json @@ -0,0 +1,25 @@ +{ + "genesis": "0xe3a7d8bae497945ba8ddc51c69564f60ad4c1a990b9c7bdbd27f7929bfa8f272", + "verifierAddress": "0xE00a3cBFC45241b33c0A44C78e26168CBc55EC63", + "consensusContract": "PolygonPessimisticConsensus", + "scheduleData": "0x01d5062a0000000000000000000000005132a183e9f3cb7c848b0aac5ae0c4f0491b7ab2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d2f000000000000000000000000000000000000000000000000000000000000000184abcb519800000000000000000000000018c45dd422f6587357a6d3b23307e75d42b2bc5b000000000000000000000000e00a3cbfc45241b33c0a44c78e26168cbc55ec63000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00062c685702e0582d900f3a19521270c92a58e2588230c4a5cf3b45103f4a5120000000000000000000000000000000000000000000000000000000000000061547970653a2050657373696d69737469632c2056657273696f6e3a2076302e322e312c2067656e657369733a202f697066732f516d55586e526f5062556d5a75455a43477969486a45736f4e6346567533684c74537668706e664253326d4159550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "executeData": "0x134008d30000000000000000000000005132a183e9f3cb7c848b0aac5ae0c4f0491b7ab2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000184abcb519800000000000000000000000018c45dd422f6587357a6d3b23307e75d42b2bc5b000000000000000000000000e00a3cbfc45241b33c0a44c78e26168cbc55ec63000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00062c685702e0582d900f3a19521270c92a58e2588230c4a5cf3b45103f4a5120000000000000000000000000000000000000000000000000000000000000061547970653a2050657373696d69737469632c2056657273696f6e3a2076302e322e312c2067656e657369733a202f697066732f516d55586e526f5062556d5a75455a43477969486a45736f4e6346567533684c74537668706e664253326d4159550000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "id": "0x56a65b79e3976426b41227c5c6b0b468436873d7d88df553b9e6637811af1d4a", + "decodedScheduleData": { + "target": "0x5132A183E9F3CB7C848b0AAC5Ae0c4f0491B7aB2", + "value": "0", + "data": "0xabcb519800000000000000000000000018c45dd422f6587357a6d3b23307e75d42b2bc5b000000000000000000000000e00a3cbfc45241b33c0a44c78e26168cbc55ec63000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e00062c685702e0582d900f3a19521270c92a58e2588230c4a5cf3b45103f4a5120000000000000000000000000000000000000000000000000000000000000061547970653a2050657373696d69737469632c2056657273696f6e3a2076302e322e312c2067656e657369733a202f697066732f516d55586e526f5062556d5a75455a43477969486a45736f4e6346567533684c74537668706e664253326d41595500000000000000000000000000000000000000000000000000000000000000", + "decodedData": { + "consensusImplementation": "0x18C45DD422f6587357a6d3b23307E75D42b2bc5B", + "verifier": "0xE00a3cBFC45241b33c0A44C78e26168CBc55EC63", + "forkID": "12", + "rollupVerifierType": "1", + "genesis": "0x0000000000000000000000000000000000000000000000000000000000000000", + "description": "Type: Pessimistic, Version: v0.2.1, genesis: /ipfs/QmUXnRoPbUmZuEZCGyiHjEsoNcFVu3hLtSvhpnfBS2mAYU", + "programVKey": "0x0062c685702e0582d900f3a19521270c92a58e2588230c4a5cf3b45103f4a512" + }, + "predecessor": "0x0000000000000000000000000000000000000000000000000000000000000000", + "salt": "0x0000000000000000000000000000000000000000000000000000000000000000", + "delay": "864000" + } +} \ No newline at end of file diff --git a/tools/addRollupType/addRollupMainnet9/genesis-rollup-type-9.json b/tools/addRollupType/addRollupMainnet9/genesis-rollup-type-9.json new file mode 100644 index 000000000..afa6204b2 --- /dev/null +++ b/tools/addRollupType/addRollupMainnet9/genesis-rollup-type-9.json @@ -0,0 +1,92 @@ +{ + "root": "0xe3a7d8bae497945ba8ddc51c69564f60ad4c1a990b9c7bdbd27f7929bfa8f272", + "genesis": [ + { + "contractName": "PolygonZkEVMDeployer", + "balance": "0", + "nonce": "4", + "address": "0xCB19eDdE626906eB1EE52357a27F62dd519608C2", + "bytecode": "0x60806040526004361061006e575f3560e01c8063715018a61161004c578063715018a6146100e25780638da5cb5b146100f6578063e11ae6cb1461011f578063f2fde38b14610132575f80fd5b80632b79805a146100725780634a94d487146100875780636d07dbf81461009a575b5f80fd5b610085610080366004610908565b610151565b005b6100856100953660046109a2565b6101c2565b3480156100a5575f80fd5b506100b96100b43660046109f5565b610203565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ed575f80fd5b50610085610215565b348015610101575f80fd5b505f5473ffffffffffffffffffffffffffffffffffffffff166100b9565b61008561012d366004610a15565b610228565b34801561013d575f80fd5b5061008561014c366004610a61565b61028e565b61015961034a565b5f6101658585856103ca565b90506101718183610527565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a15050505050565b6101ca61034a565b6101d583838361056a565b506040517f25adb19089b6a549831a273acdf7908cff8b7ee5f551f8d1d37996cf01c5df5b905f90a1505050565b5f61020e8383610598565b9392505050565b61021d61034a565b6102265f6105a4565b565b61023061034a565b5f61023c8484846103ca565b60405173ffffffffffffffffffffffffffffffffffffffff821681529091507fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a150505050565b61029661034a565b73ffffffffffffffffffffffffffffffffffffffff811661033e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610347816105a4565b50565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610226576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610335565b5f83471015610435576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401610335565b81515f0361049f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401610335565b8282516020840186f5905073ffffffffffffffffffffffffffffffffffffffff811661020e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401610335565b606061020e83835f6040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250610618565b6060610590848484604051806060016040528060298152602001610b0860299139610618565b949350505050565b5f61020e83833061072d565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060824710156106aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610335565b5f808673ffffffffffffffffffffffffffffffffffffffff1685876040516106d29190610a9c565b5f6040518083038185875af1925050503d805f811461070c576040519150601f19603f3d011682016040523d82523d5f602084013e610711565b606091505b509150915061072287838387610756565b979650505050505050565b5f604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b606083156107eb5782515f036107e45773ffffffffffffffffffffffffffffffffffffffff85163b6107e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610335565b5081610590565b61059083838151156108005781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103359190610ab7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f830112610870575f80fd5b813567ffffffffffffffff8082111561088b5761088b610834565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156108d1576108d1610834565b816040528381528660208588010111156108e9575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f806080858703121561091b575f80fd5b8435935060208501359250604085013567ffffffffffffffff80821115610940575f80fd5b61094c88838901610861565b93506060870135915080821115610961575f80fd5b5061096e87828801610861565b91505092959194509250565b803573ffffffffffffffffffffffffffffffffffffffff8116811461099d575f80fd5b919050565b5f805f606084860312156109b4575f80fd5b6109bd8461097a565b9250602084013567ffffffffffffffff8111156109d8575f80fd5b6109e486828701610861565b925050604084013590509250925092565b5f8060408385031215610a06575f80fd5b50508035926020909101359150565b5f805f60608486031215610a27575f80fd5b8335925060208401359150604084013567ffffffffffffffff811115610a4b575f80fd5b610a5786828701610861565b9150509250925092565b5f60208284031215610a71575f80fd5b61020e8261097a565b5f5b83811015610a94578181015183820152602001610a7c565b50505f910152565b5f8251610aad818460208701610a7a565b9190910192915050565b602081525f8251806020840152610ad5816040850160208701610a7a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220330b94dc698c4d290bf55c23f13b473cde6a6bae0030cb902de18af54e35839f64736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000004c1665d6651ecefa59b9b3041951608468b18891" + } + }, + { + "contractName": "ProxyAdmin", + "balance": "0", + "nonce": "1", + "address": "0x0F99738B2Fc14D77308337f3e2596b63aE7BCC4A", + "bytecode": "0x608060405260043610610079575f3560e01c80639623609d1161004c5780639623609d1461012357806399a88ec414610136578063f2fde38b14610155578063f3b7dead14610174575f80fd5b8063204e1c7a1461007d578063715018a6146100c55780637eff275e146100db5780638da5cb5b146100fa575b5f80fd5b348015610088575f80fd5b5061009c6100973660046105e8565b610193565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d0575f80fd5b506100d9610244565b005b3480156100e6575f80fd5b506100d96100f536600461060a565b610257565b348015610105575f80fd5b505f5473ffffffffffffffffffffffffffffffffffffffff1661009c565b6100d961013136600461066e565b6102e0565b348015610141575f80fd5b506100d961015036600461060a565b610371565b348015610160575f80fd5b506100d961016f3660046105e8565b6103cd565b34801561017f575f80fd5b5061009c61018e3660046105e8565b610489565b5f805f8373ffffffffffffffffffffffffffffffffffffffff166040516101dd907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b5f60405180830381855afa9150503d805f8114610215576040519150601f19603f3d011682016040523d82523d5f602084013e61021a565b606091505b509150915081610228575f80fd5b8080602001905181019061023c919061075b565b949350505050565b61024c6104d3565b6102555f610553565b565b61025f6104d3565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b5f604051808303815f87803b1580156102c6575f80fd5b505af11580156102d8573d5f803e3d5ffd5b505050505050565b6102e86104d3565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef28690349061033e9086908690600401610776565b5f604051808303818588803b158015610355575f80fd5b505af1158015610367573d5f803e3d5ffd5b5050505050505050565b6103796104d3565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016102af565b6103d56104d3565b73ffffffffffffffffffffffffffffffffffffffff811661047d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61048681610553565b50565b5f805f8373ffffffffffffffffffffffffffffffffffffffff166040516101dd907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610255576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610474565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610486575f80fd5b5f602082840312156105f8575f80fd5b8135610603816105c7565b9392505050565b5f806040838503121561061b575f80fd5b8235610626816105c7565b91506020830135610636816105c7565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f805f60608486031215610680575f80fd5b833561068b816105c7565b9250602084013561069b816105c7565b9150604084013567ffffffffffffffff808211156106b7575f80fd5b818601915086601f8301126106ca575f80fd5b8135818111156106dc576106dc610641565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561072257610722610641565b8160405282815289602084870101111561073a575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f6020828403121561076b575f80fd5b8151610603816105c7565b73ffffffffffffffffffffffffffffffffffffffff831681525f602060408184015283518060408501525f5b818110156107be578581018301518582016060015282016107a2565b505f6060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010192505050939250505056fea26469706673582212203083a4ccc2e42eed60bd19037f2efa77ed086dc7a5403f75bebb995dcba2221c64736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000bba0935fa93eb23de7990b47f0d96a8f75766d13" + } + }, + { + "contractName": "PolygonZkEVMBridge implementation", + "balance": "0", + "nonce": "1", + "address": "0x5ac4182A1dd41AeEf465E40B82fd326BF66AB82C", + "bytecode": "0x6080604052600436106101db575f3560e01c806383f24403116100fd578063ccaa2d1111610092578063ee25560b11610062578063ee25560b146105a9578063f5efcd79146105d4578063f811bff7146105f3578063fb57083414610612575f80fd5b8063ccaa2d111461053b578063cd5865791461055a578063d02103ca1461056d578063dbc1697614610595575f80fd5b8063bab161bf116100cd578063bab161bf146104b9578063be5831c7146104da578063c00f14ab146104fd578063cc4616321461051c575f80fd5b806383f244031461043d5780638ed7e3f21461045c578063aaa13cc21461047b578063b8b284d01461049a575f80fd5b80633cbc795b116101735780637843298b116101435780637843298b146103c257806379e2cf97146103e157806381b1c174146103f557806383c43a5514610429575f80fd5b80633cbc795b146103385780633e197043146103705780634b2f336d1461038f5780635ca1e165146103ae575f80fd5b806327aef4e8116101ae57806327aef4e81461026d5780632dfdf0b51461028e578063318aee3d146102b15780633c351e1014610319575f80fd5b806315064c96146101df5780632072f6c51461020d57806322e95f2c14610223578063240ff3781461025a575b5f80fd5b3480156101ea575f80fd5b506068546101f89060ff1681565b60405190151581526020015b60405180910390f35b348015610218575f80fd5b50610221610631565b005b34801561022e575f80fd5b5061024261023d366004612fb9565b610666565b6040516001600160a01b039091168152602001610204565b610221610268366004613040565b6106d0565b348015610278575f80fd5b50610281610759565b6040516102049190613102565b348015610299575f80fd5b506102a360535481565b604051908152602001610204565b3480156102bc575f80fd5b506102f56102cb36600461311b565b606b6020525f908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201610204565b348015610324575f80fd5b50606d54610242906001600160a01b031681565b348015610343575f80fd5b50606d5461035b90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610204565b34801561037b575f80fd5b506102a361038a366004613144565b6107e5565b34801561039a575f80fd5b50606f54610242906001600160a01b031681565b3480156103b9575f80fd5b506102a361088e565b3480156103cd575f80fd5b506102426103dc3660046131be565b61096a565b3480156103ec575f80fd5b50610221610993565b348015610400575f80fd5b5061024261040f366004613204565b606a6020525f90815260409020546001600160a01b031681565b348015610434575f80fd5b506102816109b4565b348015610448575f80fd5b506102a361045736600461322c565b6109d3565b348015610467575f80fd5b50606c54610242906001600160a01b031681565b348015610486575f80fd5b5061024261049536600461332d565b610aa8565b3480156104a5575f80fd5b506102216104b43660046133c3565b610be7565b3480156104c4575f80fd5b5060685461035b90610100900463ffffffff1681565b3480156104e5575f80fd5b5060685461035b90600160c81b900463ffffffff1681565b348015610508575f80fd5b5061028161051736600461311b565b610cc2565b348015610527575f80fd5b506101f8610536366004613441565b610d07565b348015610546575f80fd5b50610221610555366004613472565b610d8f565b610221610568366004613556565b6112c0565b348015610578575f80fd5b50606854610242906501000000000090046001600160a01b031681565b3480156105a0575f80fd5b5061022161172c565b3480156105b4575f80fd5b506102a36105c3366004613204565b60696020525f908152604090205481565b3480156105df575f80fd5b506102216105ee366004613472565b61175f565b3480156105fe575f80fd5b5061022161060d3660046135e6565b611a25565b34801561061d575f80fd5b506101f861062c366004613689565b611d40565b606c546001600160a01b0316331461065c57604051631736745960e31b815260040160405180910390fd5b610664611d57565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091205f908152606a90915220546001600160a01b03165b92915050565b60685460ff16156106f457604051630bc011ff60e21b815260040160405180910390fd5b341580159061070d5750606f546001600160a01b031615155b15610744576040517f6f625c4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610752858534868686611db2565b5050505050565b606e8054610766906136ce565b80601f0160208091040260200160405190810160405280929190818152602001828054610792906136ce565b80156107dd5780601f106107b4576101008083540402835291602001916107dd565b820191905f5260205f20905b8154815290600101906020018083116107c057829003601f168201915b505050505081565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b6053545f90819081805b6020811015610961578083901c6001166001036108f557603381602081106108c2576108c2613706565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610922565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806109599061372e565b915050610898565b50919392505050565b5f61098b848461097985611e7c565b61098286611f66565b61049587612047565b949350505050565b605354606854600160c81b900463ffffffff16101561066457610664612114565b60405180611ba00160405280611b668152602001613d80611b66913981565b5f83815b6020811015610a9f57600163ffffffff8516821c81169003610a4257848160208110610a0557610a05613706565b602002013582604051602001610a25929190918252602082015260400190565b604051602081830303815290604052805190602001209150610a8d565b81858260208110610a5557610a55613706565b6020020135604051602001610a74929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80610a978161372e565b9150506109d7565b50949350505050565b6040516001600160e01b031960e087901b1660208201526bffffffffffffffffffffffff19606086901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180611ba00160405280611b668152602001613d80611b669139898989604051602001610b3093929190613746565b60408051601f1981840301815290829052610b4e929160200161377e565b60405160208183030381529060405280519060200120604051602001610bc394939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60685460ff1615610c0b57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b0316610c4d576040517fdde3cda700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f54604051632770a7eb60e21b8152336004820152602481018690526001600160a01b0390911690639dc29fac906044015f604051808303815f87803b158015610c96575f80fd5b505af1158015610ca8573d5f803e3d5ffd5b50505050610cba868686868686611db2565b505050505050565b6060610ccd82611e7c565b610cd683611f66565b610cdf84612047565b604051602001610cf193929190613746565b6040516020818303038152906040529050919050565b6068545f908190610100900463ffffffff16158015610d2c575063ffffffff83166001145b15610d3e575063ffffffff8316610d66565b610d5364010000000063ffffffff85166137ac565b610d639063ffffffff86166137c3565b90505b600881901c5f90815260696020526040902054600160ff9092169190911b908116149392505050565b60685460ff1615610db357604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614610de3576040516302caf51760e11b815260040160405180910390fd5b610e168c8c8c8c8c610e115f8e8e8e8e8e8e8e604051610e049291906137d6565b60405180910390206107e5565b6121c2565b6001600160a01b038616610f6057606f546001600160a01b0316610efa575f6001600160a01b03851684825b6040519080825280601f01601f191660200182016040528015610e6c576020820181803683370190505b50604051610e7a91906137e5565b5f6040518083038185875af1925050503d805f8114610eb4576040519150601f19603f3d011682016040523d82523d5f602084013e610eb9565b606091505b5050905080610ef4576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611256565b606f546040516340c10f1960e01b81526001600160a01b03868116600483015260248201869052909116906340c10f19906044015f604051808303815f87803b158015610f45575f80fd5b505af1158015610f57573d5f803e3d5ffd5b50505050611256565b606d546001600160a01b038781169116148015610f8e5750606d5463ffffffff888116600160a01b90920416145b15610fa5575f6001600160a01b0385168482610e42565b60685463ffffffff610100909104811690881603610fd657610fd16001600160a01b0387168585612354565b611256565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201525f9060380160408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b0316806111f5575f6110808386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506123d592505050565b6040516340c10f1960e01b81526001600160a01b03898116600483015260248201899052919250908216906340c10f19906044015f604051808303815f87803b1580156110cb575f80fd5b505af11580156110dd573d5f803e3d5ffd5b5050505080606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a8388886040516111e7959493929190613828565b60405180910390a150611253565b6040516340c10f1960e01b81526001600160a01b038781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801561123c575f80fd5b505af115801561124e573d5f803e3d5ffd5b505050505b50505b604080518b815263ffffffff891660208201526001600160a01b0388811682840152861660608201526080810185905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a1505050505050505050505050565b60685460ff16156112e457604051630bc011ff60e21b815260040160405180910390fd5b6112ec612468565b60685463ffffffff61010090910481169088160361131d576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b03881661141957883414611369576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff16945090611396906136ce565b80601f01602080910402602001604051908101604052809291908181526020018280546113c2906136ce565b801561140d5780601f106113e45761010080835404028352916020019161140d565b820191905f5260205f20905b8154815290600101906020018083116113f057829003601f168201915b505050505091506116a3565b3415611451576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546001600160a01b03908116908916036114c757604051632770a7eb60e21b8152336004820152602481018a90526001600160a01b03891690639dc29fac906044015f604051808303815f87803b1580156114ac575f80fd5b505af11580156114be573d5f803e3d5ffd5b505050506116a3565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901561157957604051632770a7eb60e21b8152336004820152602481018b90526001600160a01b038a1690639dc29fac906044015f604051808303815f87803b158015611551575f80fd5b505af1158015611563573d5f803e3d5ffd5b5050505080602001519450805f01519350611696565b851561158b5761158b898b89896124c1565b6040516370a0823160e01b81523060048201525f906001600160a01b038b16906370a0823190602401602060405180830381865afa1580156115cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f39190613860565b905061160a6001600160a01b038b1633308e612860565b6040516370a0823160e01b81523060048201525f906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561164e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116729190613860565b905061167e8282613877565b6068548c9850610100900463ffffffff169650935050505b61169f89610cc2565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e86886053546040516116e298979695949392919061388a565b60405180910390a16117086117035f85878f8f8789805190602001206107e5565b6128b1565b861561171657611716612114565b5050505061172360018055565b50505050505050565b606c546001600160a01b0316331461175757604051631736745960e31b815260040160405180910390fd5b6106646129b2565b60685460ff161561178357604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff86811661010090920416146117b3576040516302caf51760e11b815260040160405180910390fd5b6117d58c8c8c8c8c610e1160018e8e8e8e8e8e8e604051610e049291906137d6565b606f545f906001600160a01b031661188857846001600160a01b031684888a868660405160240161180994939291906138f3565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161183e91906137e5565b5f6040518083038185875af1925050503d805f8114611878576040519150601f19603f3d011682016040523d82523d5f602084013e61187d565b606091505b505080915050611983565b606f546040516340c10f1960e01b81526001600160a01b03878116600483015260248201879052909116906340c10f19906044015f604051808303815f87803b1580156118d3575f80fd5b505af11580156118e5573d5f803e3d5ffd5b50505050846001600160a01b03168789858560405160240161190a94939291906138f3565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161193f91906137e5565b5f604051808303815f865af19150503d805f8114611978576040519150601f19603f3d011682016040523d82523d5f602084013e61197d565b606091505b50909150505b806119ba576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518c815263ffffffff8a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a150505050505050505050505050565b5f54610100900460ff1615808015611a4357505f54600160ff909116105b80611a5c5750303b158015611a5c57505f5460ff166001145b611ad35760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805460ff191660011790558015611af4575f805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8a16027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038781169190910291909117909155606c805473ffffffffffffffffffffffffffffffffffffffff19168583161790558616611bcf5763ffffffff851615611bca576040517f1a874c1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ceb565b606d805463ffffffff8716600160a01b027fffffffffffffffff0000000000000000000000000000000000000000000000009091166001600160a01b03891617179055606e611c1e8382613970565b50611cbd5f801b6012604051602001611ca991906060808252600d908201527f5772617070656420457468657200000000000000000000000000000000000000608082015260a0602082018190526004908201527f574554480000000000000000000000000000000000000000000000000000000060c082015260ff91909116604082015260e00190565b6040516020818303038152906040526123d5565b606f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03929092169190911790555b611cf3612a22565b8015611723575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b5f81611d4d8686866109d3565b1495945050505050565b60685460ff1615611d7b57604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b60685463ffffffff610100909104811690871603611de3576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338989898888605354604051611e3799989796959493929190613a2c565b60405180910390a1611e6e6117036001606860019054906101000a900463ffffffff16338a8a8a8989604051610e049291906137d6565b8215610cba57610cba612114565b60408051600481526024810182526020810180516001600160e01b03167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611edb91906137e5565b5f60405180830381855afa9150503d805f8114611f13576040519150601f19603f3d011682016040523d82523d5f602084013e611f18565b606091505b509150915081611f5d576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525061098b565b61098b81612a94565b60408051600481526024810182526020810180516001600160e01b03167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611fc591906137e5565b5f60405180830381855afa9150503d805f8114611ffd576040519150601f19603f3d011682016040523d82523d5f602084013e612002565b606091505b509150915081611f5d576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525061098b565b60408051600481526024810182526020810180516001600160e01b03167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f91829182916001600160a01b038616916120a591906137e5565b5f60405180830381855afa9150503d805f81146120dd576040519150601f19603f3d011682016040523d82523d5f602084013e6120e2565b606091505b50915091508180156120f5575080516020145b61210057601261098b565b8080602001905181019061098b9190613a97565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d61217561088e565b6040518263ffffffff1660e01b815260040161219391815260200190565b5f604051808303815f87803b1580156121aa575f80fd5b505af11580156121bc573d5f803e3d5ffd5b50505050565b606854604080516020808201879052818301869052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f916501000000000090046001600160a01b03169063257b3632906084016020604051808303815f875af1158015612253573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122779190613860565b9050805f036122b1576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80680100000000000000008716156122f5578691506122d3848a8489611d40565b6122f0576040516338105f3b60e21b815260040160405180910390fd5b61233f565b602087901c612305816001613ab2565b9150879250612320612318868c866109d3565b8a8389611d40565b61233d576040516338105f3b60e21b815260040160405180910390fd5b505b6123498282612c64565b505050505050505050565b6040516001600160a01b0383166024820152604481018290526123d09084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612d24565b505050565b5f8060405180611ba00160405280611b668152602001613d80611b6691398360405160200161240592919061377e565b6040516020818303038152906040529050838151602083015ff591506001600160a01b038216612461576040517fbefb092000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092915050565b6002600154036124ba5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611aca565b6002600155565b5f6124cf6004828486613acf565b6124d891613af6565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b03198216016126b2575f80808080808061251f896004818d613acf565b81019061252c9190613b26565b9650965096509650965096509650336001600160a01b0316876001600160a01b03161461256c5760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03861630146125955760405163750643af60e01b815260040160405180910390fd5b8a85146125ce576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169161266591906137e5565b5f604051808303815f865af19150503d805f811461269e576040519150601f19603f3d011682016040523d82523d5f602084013e6126a3565b606091505b50505050505050505050610752565b6001600160e01b031981166323f2ebc360e21b146126fc576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806127118a6004818e613acf565b81019061271e9190613b75565b97509750975097509750975097509750336001600160a01b0316886001600160a01b0316146127605760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03871630146127895760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f169161281091906137e5565b5f604051808303815f865af19150503d805f8114612849576040519150601f19603f3d011682016040523d82523d5f602084013e61284e565b606091505b50505050505050505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526121bc9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612399565b8060016128c060206002613cd3565b6128ca9190613877565b60535410612904576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f81546129139061372e565b918290555090505f5b60208110156129a3578082901c60011660010361294f57826033826020811061294757612947613706565b015550505050565b6033816020811061296257612962613706565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808061299b9061372e565b91505061291c565b506123d0613cde565b60018055565b60685460ff166129ee576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f54610100900460ff16612a8c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611aca565b610664612e08565b60606040825110612ab357818060200190518101906106ca9190613cf2565b8151602003612c26575f5b602081108015612b055750828181518110612adb57612adb613706565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15612b1c5780612b148161372e565b915050612abe565b805f03612b5e57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115612b7857612b78613268565b6040519080825280601f01601f191660200182016040528015612ba2576020820181803683370190505b5090505f5b82811015612c1e57848181518110612bc157612bc1613706565b602001015160f81c60f81b828281518110612bde57612bde613706565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080612c168161372e565b915050612ba7565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b6068545f90610100900463ffffffff16158015612c87575063ffffffff82166001145b15612c99575063ffffffff8216612cc1565b612cae64010000000063ffffffff84166137ac565b612cbe9063ffffffff85166137c3565b90505b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003611723576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612d78826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612e729092919063ffffffff16565b8051909150156123d05780806020019051810190612d969190613d64565b6123d05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611aca565b5f54610100900460ff166129ac5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611aca565b606061098b84845f85855f80866001600160a01b03168587604051612e9791906137e5565b5f6040518083038185875af1925050503d805f8114612ed1576040519150601f19603f3d011682016040523d82523d5f602084013e612ed6565b606091505b5091509150612ee787838387612ef2565b979650505050505050565b60608315612f605782515f03612f59576001600160a01b0385163b612f595760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611aca565b508161098b565b61098b8383815115612f755781518083602001fd5b8060405162461bcd60e51b8152600401611aca9190613102565b803563ffffffff81168114612c5f575f80fd5b6001600160a01b0381168114612fb6575f80fd5b50565b5f8060408385031215612fca575f80fd5b612fd383612f8f565b91506020830135612fe381612fa2565b809150509250929050565b8015158114612fb6575f80fd5b5f8083601f84011261300b575f80fd5b50813567ffffffffffffffff811115613022575f80fd5b602083019150836020828501011115613039575f80fd5b9250929050565b5f805f805f60808688031215613054575f80fd5b61305d86612f8f565b9450602086013561306d81612fa2565b9350604086013561307d81612fee565b9250606086013567ffffffffffffffff811115613098575f80fd5b6130a488828901612ffb565b969995985093965092949392505050565b5f5b838110156130cf5781810151838201526020016130b7565b50505f910152565b5f81518084526130ee8160208601602086016130b5565b601f01601f19169290920160200192915050565b602081525f61311460208301846130d7565b9392505050565b5f6020828403121561312b575f80fd5b813561311481612fa2565b60ff81168114612fb6575f80fd5b5f805f805f805f60e0888a03121561315a575f80fd5b873561316581613136565b965061317360208901612f8f565b9550604088013561318381612fa2565b945061319160608901612f8f565b935060808801356131a181612fa2565b9699959850939692959460a0840135945060c09093013592915050565b5f805f606084860312156131d0575f80fd5b6131d984612f8f565b925060208401356131e981612fa2565b915060408401356131f981612fa2565b809150509250925092565b5f60208284031215613214575f80fd5b5035919050565b8061040081018310156106ca575f80fd5b5f805f610440848603121561323f575f80fd5b83359250613250856020860161321b565b915061325f6104208501612f8f565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156132a5576132a5613268565b604052919050565b5f67ffffffffffffffff8211156132c6576132c6613268565b50601f01601f191660200190565b5f6132e66132e1846132ad565b61327c565b90508281528383830111156132f9575f80fd5b828260208301375f602084830101529392505050565b5f82601f83011261331e575f80fd5b613114838335602085016132d4565b5f805f805f60a08688031215613341575f80fd5b61334a86612f8f565b9450602086013561335a81612fa2565b9350604086013567ffffffffffffffff80821115613376575f80fd5b61338289838a0161330f565b94506060880135915080821115613397575f80fd5b506133a48882890161330f565b92505060808601356133b581613136565b809150509295509295909350565b5f805f805f8060a087890312156133d8575f80fd5b6133e187612f8f565b955060208701356133f181612fa2565b945060408701359350606087013561340881612fee565b9250608087013567ffffffffffffffff811115613423575f80fd5b61342f89828a01612ffb565b979a9699509497509295939492505050565b5f8060408385031215613452575f80fd5b61345b83612f8f565b915061346960208401612f8f565b90509250929050565b5f805f805f805f805f805f806109208d8f03121561348e575f80fd5b6134988e8e61321b565b9b506134a88e6104008f0161321b565b9a506108008d013599506108208d013598506108408d013597506134cf6108608e01612f8f565b96506134df6108808e0135612fa2565b6108808d013595506134f46108a08e01612f8f565b94506135046108c08e0135612fa2565b6108c08d013593506108e08d0135925067ffffffffffffffff6109008e0135111561352d575f80fd5b61353e8e6109008f01358f01612ffb565b81935080925050509295989b509295989b509295989b565b5f805f805f805f60c0888a03121561356c575f80fd5b61357588612f8f565b9650602088013561358581612fa2565b955060408801359450606088013561359c81612fa2565b935060808801356135ac81612fee565b925060a088013567ffffffffffffffff8111156135c7575f80fd5b6135d38a828b01612ffb565b989b979a50959850939692959293505050565b5f805f805f8060c087890312156135fb575f80fd5b61360487612f8f565b9550602087013561361481612fa2565b945061362260408801612f8f565b9350606087013561363281612fa2565b9250608087013561364281612fa2565b915060a087013567ffffffffffffffff81111561365d575f80fd5b8701601f8101891361366d575f80fd5b61367c898235602084016132d4565b9150509295509295509295565b5f805f80610460858703121561369d575f80fd5b843593506136ae866020870161321b565b92506136bd6104208601612f8f565b939692955092936104400135925050565b600181811c908216806136e257607f821691505b60208210810361370057634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f6001820161373f5761373f61371a565b5060010190565b606081525f61375860608301866130d7565b828103602084015261376a81866130d7565b91505060ff83166040830152949350505050565b5f835161378f8184602088016130b5565b8351908301906137a38183602088016130b5565b01949350505050565b80820281158282048414176106ca576106ca61371a565b808201808211156106ca576106ca61371a565b818382375f9101908152919050565b5f82516137f68184602087016130b5565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681525f6001600160a01b03808716602084015280861660408401525060806060830152612ee7608083018486613800565b5f60208284031215613870575f80fd5b5051919050565b818103818111156106ca576106ca61371a565b5f61010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c08501526138da828501876130d7565b925080851660e085015250509998505050505050505050565b6001600160a01b038516815263ffffffff84166020820152606060408201525f613921606083018486613800565b9695505050505050565b601f8211156123d0575f81815260208120601f850160051c810160208610156139515750805b601f850160051c820191505b81811015610cba5782815560010161395d565b815167ffffffffffffffff81111561398a5761398a613268565b61399e8161399884546136ce565b8461392b565b602080601f8311600181146139d1575f84156139ba5750858301515b5f19600386901b1c1916600185901b178555610cba565b5f85815260208120601f198616915b828110156139ff578886015182559484019460019091019084016139e0565b5085821015613a1c57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f61010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c0850152613a7d8285018789613800565b925080851660e085015250509a9950505050505050505050565b5f60208284031215613aa7575f80fd5b815161311481613136565b63ffffffff8181168382160190808211156124615761246161371a565b5f8085851115613add575f80fd5b83861115613ae9575f80fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015613b1e5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a031215613b3c575f80fd5b8735613b4781612fa2565b96506020880135613b5781612fa2565b9550604088013594506060880135935060808801356131a181613136565b5f805f805f805f80610100898b031215613b8d575f80fd5b8835613b9881612fa2565b97506020890135613ba881612fa2565b965060408901359550606089013594506080890135613bc681612fee565b935060a0890135613bd681613136565b979a969950949793969295929450505060c08201359160e0013590565b600181815b80851115613c2d57815f1904821115613c1357613c1361371a565b80851615613c2057918102915b93841c9390800290613bf8565b509250929050565b5f82613c43575060016106ca565b81613c4f57505f6106ca565b8160018114613c655760028114613c6f57613c8b565b60019150506106ca565b60ff841115613c8057613c8061371a565b50506001821b6106ca565b5060208310610133831016604e8410600b8410161715613cae575081810a6106ca565b613cb88383613bf3565b805f1904821115613ccb57613ccb61371a565b029392505050565b5f6131148383613c35565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613d02575f80fd5b815167ffffffffffffffff811115613d18575f80fd5b8201601f81018413613d28575f80fd5b8051613d366132e1826132ad565b818152856020838501011115613d4a575f80fd5b613d5b8260208301602086016130b5565b95945050505050565b5f60208284031215613d74575f80fd5b815161311481612fee56fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220432f6d6b4446edbe1f73c19fd2115454d5c35d8b03b98a74fd46724151d7672264736f6c63430008140033" + }, + { + "contractName": "PolygonZkEVMBridge proxy", + "balance": "340282366920938463463374607431768211455", + "nonce": "1", + "address": "0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe", + "bytecode": "0x60806040526004361061005d575f3560e01c80635c60da1b116100425780635c60da1b146100a65780638f283970146100e3578063f851a440146101025761006c565b80633659cfe6146100745780634f1ef286146100935761006c565b3661006c5761006a610116565b005b61006a610116565b34801561007f575f80fd5b5061006a61008e366004610854565b610130565b61006a6100a136600461086d565b610178565b3480156100b1575f80fd5b506100ba6101eb565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ee575f80fd5b5061006a6100fd366004610854565b610228565b34801561010d575f80fd5b506100ba610255565b61011e610282565b61012e610129610359565b610362565b565b610138610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101705761016d8160405180602001604052805f8152505f6103bf565b50565b61016d610116565b610180610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101e3576101de8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250600192506103bf915050565b505050565b6101de610116565b5f6101f4610380565b73ffffffffffffffffffffffffffffffffffffffff16330361021d57610218610359565b905090565b610225610116565b90565b610230610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101705761016d816103e9565b5f61025e610380565b73ffffffffffffffffffffffffffffffffffffffff16330361021d57610218610380565b61028a610380565b73ffffffffffffffffffffffffffffffffffffffff16330361012e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b5f61021861044a565b365f80375f80365f845af43d5f803e80801561037c573d5ff35b3d5ffd5b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6103c883610471565b5f825111806103d45750805b156101de576103e383836104bd565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610412610380565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161016d816104e9565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103a3565b61047a816105f5565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606104e28383604051806060016040528060278152602001610977602791396106c0565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811661058c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610350565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b73ffffffffffffffffffffffffffffffffffffffff81163b610699576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610350565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105af565b60605f808573ffffffffffffffffffffffffffffffffffffffff16856040516106e9919061090b565b5f60405180830381855af49150503d805f8114610721576040519150601f19603f3d011682016040523d82523d5f602084013e610726565b606091505b509150915061073786838387610741565b9695505050505050565b606083156107d65782515f036107cf5773ffffffffffffffffffffffffffffffffffffffff85163b6107cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610350565b50816107e0565b6107e083836107e8565b949350505050565b8151156107f85781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103509190610926565b803573ffffffffffffffffffffffffffffffffffffffff8116811461084f575f80fd5b919050565b5f60208284031215610864575f80fd5b6104e28261082c565b5f805f6040848603121561087f575f80fd5b6108888461082c565b9250602084013567ffffffffffffffff808211156108a4575f80fd5b818601915086601f8301126108b7575f80fd5b8135818111156108c5575f80fd5b8760208285010111156108d6575f80fd5b6020830194508093505050509250925092565b5f5b838110156109035781810151838201526020016108eb565b50505f910152565b5f825161091c8184602087016108e9565b9190910192915050565b602081525f82518060208401526109448160408501602087016108e9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202ac98acbfbb3d3ac1b74050e18c4e76db25a3ff2801ec69bf85d0c61414d502b64736f6c63430008140033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0000000000000000000000000f99738b2fc14d77308337f3e2596b63ae7bcc4a", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000005ac4182a1dd41aeef465e40b82fd326bf66ab82c" + } + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 implementation", + "balance": "0", + "nonce": "1", + "address": "0x0200143Fa295EE4dffEF22eE2616c2E008D81688", + "bytecode": "0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c806301fd90441461004e578063257b36321461006a57806333d6247d14610089578063a3c573eb1461009e575b5f80fd5b61005760015481565b6040519081526020015b60405180910390f35b61005761007836600461015e565b5f6020819052908152604090205481565b61009c61009736600461015e565b6100ea565b005b6100c57f0000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610061565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede1614610159576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b5f6020828403121561016e575f80fd5b503591905056fea26469706673582212205108c6c4f924146b736832a1bdf696e20d900450207b7452462368d150f2c71c64736f6c63430008140033" + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 proxy", + "balance": "0", + "nonce": "1", + "address": "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa", + "bytecode": "0x60806040523661001357610011610017565b005b6100115b61001f6101b7565b6001600160a01b0316336001600160a01b0316141561016f5760606001600160e01b031960003516631b2ce7f360e11b8114156100655761005e6101ea565b9150610167565b6001600160e01b0319811663278f794360e11b14156100865761005e610241565b6001600160e01b031981166308f2839760e41b14156100a75761005e610287565b6001600160e01b031981166303e1469160e61b14156100c85761005e6102b8565b6001600160e01b03198116635c60da1b60e01b14156100e95761005e6102f8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b61017761030c565b565b606061019e83836040518060600160405280602781526020016108576027913961031c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101f4610394565b600061020336600481846106a2565b81019061021091906106e8565b905061022d8160405180602001604052806000815250600061039f565b505060408051602081019091526000815290565b606060008061025336600481846106a2565b8101906102609190610719565b915091506102708282600161039f565b604051806020016040528060008152509250505090565b6060610291610394565b60006102a036600481846106a2565b8101906102ad91906106e8565b905061022d816103cb565b60606102c2610394565b60006102cc6101b7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b6060610302610394565b60006102cc610422565b610177610317610422565b610431565b6060600080856001600160a01b0316856040516103399190610807565b600060405180830381855af49150503d8060008114610374576040519150601f19603f3d011682016040523d82523d6000602084013e610379565b606091505b509150915061038a86838387610455565b9695505050505050565b341561017757600080fd5b6103a8836104d3565b6000825111806103b55750805b156103c6576103c48383610179565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103f46101b7565b604080516001600160a01b03928316815291841660208301520160405180910390a161041f81610513565b50565b600061042c6105bc565b905090565b3660008037600080366000845af43d6000803e808015610450573d6000f35b3d6000fd5b606083156104c15782516104ba576001600160a01b0385163b6104ba5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161015e565b50816104cb565b6104cb83836105e4565b949350505050565b6104dc8161060e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105785760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161015e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101db565b8151156105f45781518083602001fd5b8060405162461bcd60e51b815260040161015e9190610823565b6001600160a01b0381163b61067b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161015e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61059b565b600080858511156106b257600080fd5b838611156106bf57600080fd5b5050820193919092039150565b80356001600160a01b03811681146106e357600080fd5b919050565b6000602082840312156106fa57600080fd5b61019e826106cc565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561072c57600080fd5b610735836106cc565b9150602083013567ffffffffffffffff8082111561075257600080fd5b818501915085601f83011261076657600080fd5b81358181111561077857610778610703565b604051601f8201601f19908116603f011681019083821181831017156107a0576107a0610703565b816040528281528860208487010111156107b957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107f65781810151838201526020016107de565b838111156103c45750506000910152565b600082516108198184602087016107db565b9190910192915050565b60208152600082518060208401526108428160408501602087016107db565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122012bb4f564f73959a03513dc74fc3c6e40e8386e6f02c16b78d6db00ce0aa16af64736f6c63430008090033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0000000000000000000000000f99738b2fc14d77308337f3e2596b63ae7bcc4a", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000000200143fa295ee4dffef22ee2616c2e008d81688" + } + }, + { + "contractName": "PolygonZkEVMTimelock", + "balance": "0", + "nonce": "1", + "address": "0xBBa0935Fa93Eb23de7990b47F0D96a8f75766d13", + "bytecode": "0x6080604052600436106101bd575f3560e01c806364d62353116100f2578063b1c5f42711610092578063d547741f11610062578063d547741f1461063a578063e38335e514610659578063f23a6e611461066c578063f27a0c92146106b0575f80fd5b8063b1c5f4271461058d578063bc197c81146105ac578063c4d252f5146105f0578063d45c44351461060f575f80fd5b80638f61f4f5116100cd5780638f61f4f5146104c557806391d14854146104f8578063a217fddf14610547578063b08e51c01461055a575f80fd5b806364d62353146104685780638065657f146104875780638f2a0bb0146104a6575f80fd5b8063248a9ca31161015d57806331d507501161013857806331d50750146103b357806336568abe146103d25780633a6aae72146103f1578063584b153e14610449575f80fd5b8063248a9ca3146103375780632ab0f529146103655780632f2ff15d14610394575f80fd5b80630d3cf6fc116101985780630d3cf6fc1461025e578063134008d31461029157806313bc9f20146102a4578063150b7a02146102c3575f80fd5b806301d5062a146101c857806301ffc9a7146101e957806307bd02651461021d575f80fd5b366101c457005b5f80fd5b3480156101d3575f80fd5b506101e76101e2366004611bf6565b6106c4565b005b3480156101f4575f80fd5b50610208610203366004611c65565b610757565b60405190151581526020015b60405180910390f35b348015610228575f80fd5b506102507fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610214565b348015610269575f80fd5b506102507f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101e761029f366004611ca4565b6107b2565b3480156102af575f80fd5b506102086102be366004611d0b565b6108a7565b3480156102ce575f80fd5b506103066102dd366004611e28565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610214565b348015610342575f80fd5b50610250610351366004611d0b565b5f9081526020819052604090206001015490565b348015610370575f80fd5b5061020861037f366004611d0b565b5f908152600160208190526040909120541490565b34801561039f575f80fd5b506101e76103ae366004611e8c565b6108cc565b3480156103be575f80fd5b506102086103cd366004611d0b565b6108f5565b3480156103dd575f80fd5b506101e76103ec366004611e8c565b61090d565b3480156103fc575f80fd5b506104247f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b348015610454575f80fd5b50610208610463366004611d0b565b6109c5565b348015610473575f80fd5b506101e7610482366004611d0b565b6109da565b348015610492575f80fd5b506102506104a1366004611ca4565b610aaa565b3480156104b1575f80fd5b506101e76104c0366004611ef7565b610ae8565b3480156104d0575f80fd5b506102507fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610503575f80fd5b50610208610512366004611e8c565b5f9182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b348015610552575f80fd5b506102505f81565b348015610565575f80fd5b506102507ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b348015610598575f80fd5b506102506105a7366004611fa0565b610d18565b3480156105b7575f80fd5b506103066105c63660046120be565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b3480156105fb575f80fd5b506101e761060a366004611d0b565b610d5c565b34801561061a575f80fd5b50610250610629366004611d0b565b5f9081526001602052604090205490565b348015610645575f80fd5b506101e7610654366004611e8c565b610e56565b6101e7610667366004611fa0565b610e7a565b348015610677575f80fd5b50610306610686366004612161565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106bb575f80fd5b50610250611121565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16106ee81611200565b5f6106fd898989898989610aaa565b9050610709818461120d565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a60405161074496959493929190612208565b60405180910390a3505050505050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107ac57506107ac82611359565b92915050565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661082e5761082e81336113ef565b5f61083d888888888888610aaa565b905061084981856114a6565b610855888888886115e2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a60405161088c9493929190612252565b60405180910390a361089d816116e2565b5050505050505050565b5f818152600160205260408120546001811180156108c55750428111155b9392505050565b5f828152602081905260409020600101546108e681611200565b6108f0838361178a565b505050565b5f8181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109c18282611878565b5050565b5f818152600160208190526040822054610906565b333014610a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109ae565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b5f868686868686604051602001610ac696959493929190612208565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b1281611200565b888714610ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b888514610c30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f610c418b8b8b8b8b8b8b8b610d18565b9050610c4d818461120d565b5f5b8a811015610d0a5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610c8c57610c8c612291565b9050602002016020810190610ca191906122be565b8d8d86818110610cb357610cb3612291565b905060200201358c8c87818110610ccc57610ccc612291565b9050602002810190610cde91906122d7565b8c8b604051610cf296959493929190612208565b60405180910390a3610d0381612365565b9050610c4f565b505050505050505050505050565b5f8888888888888888604051602001610d38989796959493929190612447565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610d8681611200565b610d8f826109c5565b610e1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109ae565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610e7081611200565b6108f08383611878565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610ef657610ef681336113ef565b878614610f85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b878414611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f6110258a8a8a8a8a8a8a8a610d18565b905061103181856114a6565b5f5b8981101561110b575f8b8b8381811061104e5761104e612291565b905060200201602081019061106391906122be565b90505f8a8a8481811061107857611078612291565b905060200201359050365f8a8a8681811061109557611095612291565b90506020028101906110a791906122d7565b915091506110b7848484846115e2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58868686866040516110ee9493929190612252565b60405180910390a3505050508061110490612365565b9050611033565b50611115816116e2565b50505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16158015906111ef57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ef919061250c565b156111f957505f90565b5060025490565b61120a81336113ef565b50565b611216826108f5565b156112a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109ae565b6112ab611121565b81101561133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109ae565b611344814261252b565b5f928352600160205260409092209190915550565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107ac57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107ac565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c15761142c8161192d565b61143783602061194c565b604051602001611448929190612560565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109ae916004016125e0565b6114af826108a7565b61153b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b80158061155657505f81815260016020819052604090912054145b6109c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f8473ffffffffffffffffffffffffffffffffffffffff1684848460405161160b929190612630565b5f6040518083038185875af1925050503d805f8114611645576040519150601f19603f3d011682016040523d82523d5f602084013e61164a565b606091505b50509050806116db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109ae565b5050505050565b6116eb816108a7565b611777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b5f90815260016020819052604090912055565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561181a3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107ac73ffffffffffffffffffffffffffffffffffffffff831660145b60605f61195a83600261263f565b61196590600261252b565b67ffffffffffffffff81111561197d5761197d611d22565b6040519080825280601f01601f1916602001820160405280156119a7576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106119dd576119dd612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a3f57611a3f612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f611a7984600261263f565b611a8490600161252b565b90505b6001811115611b20577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611ac557611ac5612291565b1a60f81b828281518110611adb57611adb612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535060049490941c93611b1981612656565b9050611a87565b5083156108c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109ae565b803573ffffffffffffffffffffffffffffffffffffffff81168114611bac575f80fd5b919050565b5f8083601f840112611bc1575f80fd5b50813567ffffffffffffffff811115611bd8575f80fd5b602083019150836020828501011115611bef575f80fd5b9250929050565b5f805f805f805f60c0888a031215611c0c575f80fd5b611c1588611b89565b965060208801359550604088013567ffffffffffffffff811115611c37575f80fd5b611c438a828b01611bb1565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f60208284031215611c75575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108c5575f80fd5b5f805f805f8060a08789031215611cb9575f80fd5b611cc287611b89565b955060208701359450604087013567ffffffffffffffff811115611ce4575f80fd5b611cf089828a01611bb1565b979a9699509760608101359660809091013595509350505050565b5f60208284031215611d1b575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d9657611d96611d22565b604052919050565b5f82601f830112611dad575f80fd5b813567ffffffffffffffff811115611dc757611dc7611d22565b611df860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611d4f565b818152846020838601011115611e0c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215611e3b575f80fd5b611e4485611b89565b9350611e5260208601611b89565b925060408501359150606085013567ffffffffffffffff811115611e74575f80fd5b611e8087828801611d9e565b91505092959194509250565b5f8060408385031215611e9d575f80fd5b82359150611ead60208401611b89565b90509250929050565b5f8083601f840112611ec6575f80fd5b50813567ffffffffffffffff811115611edd575f80fd5b6020830191508360208260051b8501011115611bef575f80fd5b5f805f805f805f805f60c08a8c031215611f0f575f80fd5b893567ffffffffffffffff80821115611f26575f80fd5b611f328d838e01611eb6565b909b50995060208c0135915080821115611f4a575f80fd5b611f568d838e01611eb6565b909950975060408c0135915080821115611f6e575f80fd5b50611f7b8c828d01611eb6565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f805f805f805f8060a0898b031215611fb7575f80fd5b883567ffffffffffffffff80821115611fce575f80fd5b611fda8c838d01611eb6565b909a50985060208b0135915080821115611ff2575f80fd5b611ffe8c838d01611eb6565b909850965060408b0135915080821115612016575f80fd5b506120238b828c01611eb6565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112612050575f80fd5b8135602067ffffffffffffffff82111561206c5761206c611d22565b8160051b61207b828201611d4f565b9283528481018201928281019087851115612094575f80fd5b83870192505b848310156120b35782358252918301919083019061209a565b979650505050505050565b5f805f805f60a086880312156120d2575f80fd5b6120db86611b89565b94506120e960208701611b89565b9350604086013567ffffffffffffffff80821115612105575f80fd5b61211189838a01612041565b94506060880135915080821115612126575f80fd5b61213289838a01612041565b93506080880135915080821115612147575f80fd5b5061215488828901611d9e565b9150509295509295909350565b5f805f805f60a08688031215612175575f80fd5b61217e86611b89565b945061218c60208701611b89565b93506040860135925060608601359150608086013567ffffffffffffffff8111156121b5575f80fd5b61215488828901611d9e565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a060408201525f61223d60a0830186886121c1565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201525f6122876060830184866121c1565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156122ce575f80fd5b6108c582611b89565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261230a575f80fd5b83018035915067ffffffffffffffff821115612324575f80fd5b602001915036819003821315611bef575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361239557612395612338565b5060010190565b8183525f6020808501808196508560051b81019150845f5b8781101561243a57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126123f2575f80fd5b8701858101903567ffffffffffffffff81111561240d575f80fd5b80360382131561241b575f80fd5b6124268682846121c1565b9a87019a95505050908401906001016123b4565b5091979650505050505050565b60a080825281018890525f8960c08301825b8b8110156124945773ffffffffffffffffffffffffffffffffffffffff61247f84611b89565b16825260209283019290910190600101612459565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8911156124cc575f80fd5b8860051b9150818a602083013701828103602090810160408501526124f4908201878961239c565b60608401959095525050608001529695505050505050565b5f6020828403121561251c575f80fd5b815180151581146108c5575f80fd5b808201808211156107ac576107ac612338565b5f5b83811015612558578181015183820152602001612540565b50505f910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f835161259781601785016020880161253e565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516125d481602884016020880161253e565b01602801949350505050565b602081525f82518060208401526125fe81604085016020870161253e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b818382375f9101908152919050565b80820281158282048414176107ac576107ac612338565b5f8161266457612664612338565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220e28ae7494480ab1c619fd775dc5ff665588c808a910d66178a982c2e7c76a1e664736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000000d2f00", + "0xb7dfbbca55dd7b7b40403b7620ec95da956b60d562518460548c310b9ba22ee5": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x9fa2d8034dbcb437bee38d61fbd100910e1342ffc07f128aa1b8e6790b7f3f68": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x64494413541ff93b31aa309254e3fed72a7456e9845988b915b4c7a7ceba8814": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x8af78a811b91830f719aeb3279e6ef47b4b581bcf168d6d9015d376b23a240bc": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x3412d5605ac6cd444957cedb533e5dacad6378b4bc819ebe3652188a665066d6": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x9b56cc8bdadd190ab692f9895be09d0edc2ddf428710bebe53c4911e5bc08f42": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d706a": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x74be529e918f2e5719738045bde8f05a9e9498aace6df8d886a992d046f546a1": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc3ad33e20b0c56a223ad5104fff154aa010f8715b9c981fd38fdc60a4d1a52fc": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" + } + }, + { + "accountName": "keyless Deployer", + "balance": "0", + "nonce": "1", + "address": "0x9d90066e7478496e2284E54c3548106bb4F90E50" + }, + { + "accountName": "deployer", + "balance": "0", + "nonce": "8", + "address": "0x4c1665d6651ecEfa59B9B3041951608468b18891" + } + ] + } \ No newline at end of file diff --git a/tools/addRollupType/addRollupType.ts b/tools/addRollupType/addRollupType.ts index 67eadf16b..959c17243 100644 --- a/tools/addRollupType/addRollupType.ts +++ b/tools/addRollupType/addRollupType.ts @@ -6,23 +6,26 @@ import fs = require("fs"); import * as dotenv from "dotenv"; dotenv.config({path: path.resolve(__dirname, "../../.env")}); -import {ethers, upgrades} from "hardhat"; +import {ethers, run} from "hardhat"; -const addRollupParameters = require("./add_rollup_type.json"); +const addRollupTypeParameters = require("./add_rollup_type.json"); const genesis = require("./genesis.json"); const dateStr = new Date().toISOString(); -const pathOutputJson = path.join(__dirname, `./add_rollup_type_output-${dateStr}.json`); +const pathOutputJson = addRollupTypeParameters.outputPath + ? path.join(__dirname, addRollupTypeParameters.outputPath) + : path.join(__dirname, `./add_rollup_type_output-${dateStr}.json`); import {PolygonRollupManager} from "../../typechain-types"; import "../../deployment/helpers/utils"; +import {supportedBridgeContracts} from "../utils"; async function main() { const outputJson = {} as any; /* * Check deploy parameters - * Check that every necessary parameter is fullfilled + * Check that every necessary parameter is fulfilled */ const mandatoryDeploymentParameters = [ "description", @@ -30,58 +33,60 @@ async function main() { "consensusContract", "polygonRollupManagerAddress", "verifierAddress", - "rollupCompatibilityID", "genesisRoot", + "programVKey", ]; for (const parameterName of mandatoryDeploymentParameters) { - if (addRollupParameters[parameterName] === undefined || addRollupParameters[parameterName] === "") { + if (addRollupTypeParameters[parameterName] === undefined || addRollupTypeParameters[parameterName] === "") { throw new Error(`Missing parameter: ${parameterName}`); } } const { description, - rollupCompatibilityID, forkID, consensusContract, polygonRollupManagerAddress, verifierAddress, genesisRoot, - } = addRollupParameters; + programVKey, + } = addRollupTypeParameters; - const supportedConensus = ["PolygonZkEVMEtrog", "PolygonValidiumEtrog"]; + const supportedConsensus = ["PolygonZkEVMEtrog", "PolygonValidiumEtrog", "PolygonPessimisticConsensus"]; + const isPessimistic = consensusContract === "PolygonPessimisticConsensus"; - if (!supportedConensus.includes(consensusContract)) { - throw new Error(`Consensus contract not supported, supported contracts are: ${supportedConensus}`); + if (!supportedConsensus.includes(consensusContract)) { + throw new Error(`Consensus contract not supported, supported contracts are: ${supportedConsensus}`); } // Load provider let currentProvider = ethers.provider; - if (addRollupParameters.multiplierGas || addRollupParameters.maxFeePerGas) { + if (addRollupTypeParameters.multiplierGas || addRollupTypeParameters.maxFeePerGas) { if (process.env.HARDHAT_NETWORK !== "hardhat") { currentProvider = ethers.getDefaultProvider( `https://${process.env.HARDHAT_NETWORK}.infura.io/v3/${process.env.INFURA_PROJECT_ID}` ) as any; - if (addRollupParameters.maxPriorityFeePerGas && addRollupParameters.maxFeePerGas) { + if (addRollupTypeParameters.maxPriorityFeePerGas && addRollupTypeParameters.maxFeePerGas) { console.log( - `Hardcoded gas used: MaxPriority${addRollupParameters.maxPriorityFeePerGas} gwei, MaxFee${addRollupParameters.maxFeePerGas} gwei` + `Hardcoded gas used: MaxPriority${addRollupTypeParameters.maxPriorityFeePerGas} gwei, MaxFee${addRollupTypeParameters.maxFeePerGas} gwei` ); const FEE_DATA = new ethers.FeeData( null, - ethers.parseUnits(addRollupParameters.maxFeePerGas, "gwei"), - ethers.parseUnits(addRollupParameters.maxPriorityFeePerGas, "gwei") + ethers.parseUnits(addRollupTypeParameters.maxFeePerGas, "gwei"), + ethers.parseUnits(addRollupTypeParameters.maxPriorityFeePerGas, "gwei") ); currentProvider.getFeeData = async () => FEE_DATA; } else { - console.log("Multiplier gas used: ", addRollupParameters.multiplierGas); + console.log("Multiplier gas used: ", addRollupTypeParameters.multiplierGas); async function overrideFeeData() { const feedata = await ethers.provider.getFeeData(); return new ethers.FeeData( null, - ((feedata.maxFeePerGas as bigint) * BigInt(addRollupParameters.multiplierGas)) / 1000n, - ((feedata.maxPriorityFeePerGas as bigint) * BigInt(addRollupParameters.multiplierGas)) / 1000n + ((feedata.maxFeePerGas as bigint) * BigInt(addRollupTypeParameters.multiplierGas)) / 1000n, + ((feedata.maxPriorityFeePerGas as bigint) * BigInt(addRollupTypeParameters.multiplierGas)) / + 1000n ); } currentProvider.getFeeData = overrideFeeData; @@ -91,8 +96,8 @@ async function main() { // Load deployer let deployer; - if (addRollupParameters.deployerPvtKey) { - deployer = new ethers.Wallet(addRollupParameters.deployerPvtKey, currentProvider); + if (addRollupTypeParameters.deployerPvtKey) { + deployer = new ethers.Wallet(addRollupTypeParameters.deployerPvtKey, currentProvider); } else if (process.env.MNEMONIC) { deployer = ethers.HDNodeWallet.fromMnemonic( ethers.Mnemonic.fromPhrase(process.env.MNEMONIC), @@ -105,8 +110,8 @@ async function main() { console.log("Using with: ", deployer.address); // Load Rollup manager - const PolgonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); - const rollupManagerContract = PolgonRollupManagerFactory.attach( + const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); + const rollupManagerContract = PolygonRollupManagerFactory.attach( polygonRollupManagerAddress ) as PolygonRollupManager; @@ -115,24 +120,29 @@ async function main() { const polygonZkEVMGlobalExitRootAddress = await rollupManagerContract.globalExitRootManager(); const polTokenAddress = await rollupManagerContract.pol(); - // Sanity checks genesisRoot - if (genesisRoot !== genesis.root) { - throw new Error(`Genesis root in the 'add_rollup_type.json' does not match the root in the 'genesis.json'`); - } + if (!isPessimistic) { + // checks for rollups + // Sanity checks genesisRoot + if (genesisRoot !== genesis.root) { + throw new Error(`Genesis root in the 'add_rollup_type.json' does not match the root in the 'genesis.json'`); + } - // get bridge address in genesis file - let genesisBridgeAddress = ethers.ZeroAddress; - for (let i = 0; i < genesis.genesis.length; i++) { - if (genesis.genesis[i].contractName === "PolygonZkEVMBridge proxy") { - genesisBridgeAddress = genesis.genesis[i].address; - break; + // get bridge address in genesis file + let genesisBridgeAddress = ethers.ZeroAddress; + let bridgeContractName = ""; + for (let i = 0; i < genesis.genesis.length; i++) { + if (supportedBridgeContracts.includes(genesis.genesis[i].contractName)) { + genesisBridgeAddress = genesis.genesis[i].address; + bridgeContractName = genesis.genesis[i].contractName; + break; + } } - } - if (polygonZkEVMBridgeAddress.toLowerCase() !== genesisBridgeAddress.toLowerCase()) { - throw new Error( - `'PolygonZkEVMBridge proxy' root in the 'genesis.json' does not match 'bridgeAddress' in the 'PolygonRollupManager'` - ); + if (polygonZkEVMBridgeAddress.toLowerCase() !== genesisBridgeAddress.toLowerCase()) { + throw new Error( + `'${bridgeContractName}' root in the 'genesis.json' does not match 'bridgeAddress' in the 'PolygonRollupManager'` + ); + } } // Check roles @@ -151,52 +161,80 @@ async function main() { await rollupManagerContract.grantRole(ADD_ROLLUP_TYPE_ROLE, deployer.address); // Create consensus implementation if needed - let polygonConsensusContractAddress; + let consensusContractAddress; if ( - typeof addRollupParameters.polygonconsensusContract !== "undefined" && - ethers.isAddress(addRollupParameters.polygonconsensusContract) + typeof addRollupTypeParameters.consensusContractAddress !== "undefined" && + ethers.isAddress(addRollupTypeParameters.consensusContractAddress) ) { - polygonConsensusContractAddress = addRollupParameters.polygonconsensusContract; + consensusContractAddress = addRollupTypeParameters.consensusContractAddress; } else { - const PolygonconsensusFactory = (await ethers.getContractFactory(consensusContract, deployer)) as any; - let PolygonconsensusContract; + const PolygonConsensusFactory = (await ethers.getContractFactory(consensusContract, deployer)) as any; + let PolygonConsensusContract; - PolygonconsensusContract = await PolygonconsensusFactory.deploy( + PolygonConsensusContract = await PolygonConsensusFactory.deploy( polygonZkEVMGlobalExitRootAddress, polTokenAddress, polygonZkEVMBridgeAddress, polygonRollupManagerAddress ); - await PolygonconsensusContract.waitForDeployment(); - + await PolygonConsensusContract.waitForDeployment(); console.log("#######################\n"); - console.log(`new PolygonconsensusContract impl: ${PolygonconsensusContract.target}`); + console.log(`new consensus name: ${consensusContract}`); + console.log(`new PolygonConsensusContract impl: ${PolygonConsensusContract.target}`); + + try { + console.log("Verifying contract..."); + await run("verify:verify", { + address: PolygonConsensusContract.target, + constructorArguments: [ + polygonZkEVMGlobalExitRootAddress, + polTokenAddress, + polygonZkEVMBridgeAddress, + polygonRollupManagerAddress, + ], + }); + } catch (e) { + console.log("Automatic verification failed. Please verify the contract manually."); + console.log("you can verify the new impl address with:"); + console.log( + `npx hardhat verify --constructor-args upgrade/arguments.js ${PolygonConsensusContract.target} --network ${process.env.HARDHAT_NETWORK}\n` + ); + console.log("Copy the following constructor arguments on: upgrade/arguments.js \n", [ + polygonZkEVMGlobalExitRootAddress, + polTokenAddress, + polygonZkEVMBridgeAddress, + polygonRollupManagerAddress, + ]); + } + consensusContractAddress = PolygonConsensusContract.target; + } - console.log("you can verify the new impl address with:"); - console.log( - `npx hardhat verify --constructor-args upgrade/arguments.js ${PolygonconsensusContract.target} --network ${process.env.HARDHAT_NETWORK}\n` - ); - console.log("Copy the following constructor arguments on: upgrade/arguments.js \n", [ - polygonZkEVMGlobalExitRootAddress, - polTokenAddress, - polygonZkEVMBridgeAddress, - polygonRollupManagerAddress, - ]); + // Add a new rollup type + let rollupVerifierType; + let genesisFinal; + let programVKeyFinal; - polygonConsensusContractAddress = PolygonconsensusContract.target; + if (consensusContract == "PolygonPessimisticConsensus") { + rollupVerifierType = 1; + genesisFinal = ethers.ZeroHash; + programVKeyFinal = programVKey || ethers.ZeroHash; + } else { + rollupVerifierType = 0; + genesisFinal = genesis.root; + programVKeyFinal = ethers.ZeroHash; } - // Add a new rollup type with timelock console.log( await ( await rollupManagerContract.addNewRollupType( - polygonConsensusContractAddress, + consensusContractAddress, verifierAddress, forkID, - rollupCompatibilityID, - genesis.root, - description + rollupVerifierType, + genesisFinal, + description, + programVKeyFinal ) ).wait() ); @@ -209,6 +247,8 @@ async function main() { outputJson.verifierAddress = verifierAddress; outputJson.consensusContract = consensusContract; outputJson.rollupTypeID = newRollupTypeID; + outputJson.programVKey = programVKeyFinal; + outputJson.consensusContractAddress = consensusContractAddress; // add time to output path fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); diff --git a/tools/addRollupType/addRollupTypeTimelock.ts b/tools/addRollupType/addRollupTypeTimelock.ts index 5951a3e3b..3403b84fe 100644 --- a/tools/addRollupType/addRollupTypeTimelock.ts +++ b/tools/addRollupType/addRollupTypeTimelock.ts @@ -6,85 +6,94 @@ import fs = require("fs"); import * as dotenv from "dotenv"; dotenv.config({path: path.resolve(__dirname, "../../.env")}); -import {ethers, upgrades} from "hardhat"; +import {ethers, run} from "hardhat"; -const addRollupParameters = require("./add_rollup_type.json"); +const addRollupTypeParameters = require("./add_rollup_type.json"); const genesis = require("./genesis.json"); const dateStr = new Date().toISOString(); -const pathOutputJson = path.join(__dirname, `./add_rollup_type_output-${dateStr}.json`); -import {PolygonRollupManager} from "../../typechain-types"; +const pathOutputJson = addRollupTypeParameters.outputPath + ? path.join(__dirname, addRollupTypeParameters.outputPath) + : path.join(__dirname, `./add_rollup_type_output-${dateStr}.json`); import "../../deployment/helpers/utils"; +import {supportedBridgeContracts} from "../utils"; async function main() { const outputJson = {} as any; /* * Check deploy parameters - * Check that every necessary parameter is fullfilled + * Check that every necessary parameter is fulfilled */ const mandatoryDeploymentParameters = [ "description", "forkID", "consensusContract", "verifierAddress", - "rollupCompatibilityID", "timelockDelay", "genesisRoot", + "programVKey", ]; for (const parameterName of mandatoryDeploymentParameters) { - if (addRollupParameters[parameterName] === undefined || addRollupParameters[parameterName] === "") { + if (addRollupTypeParameters[parameterName] === undefined || addRollupTypeParameters[parameterName] === "") { throw new Error(`Missing parameter: ${parameterName}`); } } const { description, - rollupCompatibilityID, forkID, consensusContract, polygonRollupManagerAddress, verifierAddress, timelockDelay, genesisRoot, - } = addRollupParameters; + programVKey, + } = addRollupTypeParameters; - const salt = addRollupParameters.timelockSalt || ethers.ZeroHash; - const predecessor = addRollupParameters.predecessor || ethers.ZeroHash; + const salt = addRollupTypeParameters.timelockSalt || ethers.ZeroHash; + const predecessor = addRollupTypeParameters.predecessor || ethers.ZeroHash; - const supportedConensus = ["PolygonZkEVMEtrog", "PolygonValidiumEtrog", "PolygonValidiumStorageMigration"]; + const supportedConsensus = [ + "PolygonZkEVMEtrog", + "PolygonValidiumEtrog", + "PolygonValidiumStorageMigration", + "PolygonPessimisticConsensus", + ]; + const isPessimistic = consensusContract === "PolygonPessimisticConsensus"; - if (!supportedConensus.includes(consensusContract)) { - throw new Error(`Consensus contract not supported, supported contracts are: ${supportedConensus}`); + if (!supportedConsensus.includes(consensusContract)) { + throw new Error(`Consensus contract not supported, supported contracts are: ${supportedConsensus}`); } // Load provider let currentProvider = ethers.provider; - if (addRollupParameters.multiplierGas || addRollupParameters.maxFeePerGas) { + if (addRollupTypeParameters.multiplierGas || addRollupTypeParameters.maxFeePerGas) { if (process.env.HARDHAT_NETWORK !== "hardhat") { currentProvider = ethers.getDefaultProvider( `https://${process.env.HARDHAT_NETWORK}.infura.io/v3/${process.env.INFURA_PROJECT_ID}` ) as any; - if (addRollupParameters.maxPriorityFeePerGas && addRollupParameters.maxFeePerGas) { + if (addRollupTypeParameters.maxPriorityFeePerGas && addRollupTypeParameters.maxFeePerGas) { console.log( - `Hardcoded gas used: MaxPriority${addRollupParameters.maxPriorityFeePerGas} gwei, MaxFee${addRollupParameters.maxFeePerGas} gwei` + `Hardcoded gas used: MaxPriority${addRollupTypeParameters.maxPriorityFeePerGas} gwei, MaxFee${addRollupTypeParameters.maxFeePerGas} gwei` ); const FEE_DATA = new ethers.FeeData( null, - ethers.parseUnits(addRollupParameters.maxFeePerGas, "gwei"), - ethers.parseUnits(addRollupParameters.maxPriorityFeePerGas, "gwei") + ethers.parseUnits(addRollupTypeParameters.maxFeePerGas, "gwei"), + ethers.parseUnits(addRollupTypeParameters.maxPriorityFeePerGas, "gwei") ); currentProvider.getFeeData = async () => FEE_DATA; } else { - console.log("Multiplier gas used: ", addRollupParameters.multiplierGas); + console.log("Multiplier gas used: ", addRollupTypeParameters.multiplierGas); async function overrideFeeData() { - const feedata = await ethers.provider.getFeeData(); + const feeData = await ethers.provider.getFeeData(); return new ethers.FeeData( null, - ((feedata.maxFeePerGas as bigint) * BigInt(addRollupParameters.multiplierGas)) / 1000n, - ((feedata.maxPriorityFeePerGas as bigint) * BigInt(addRollupParameters.multiplierGas)) / 1000n + ((feeData.maxFeePerGas as bigint) * BigInt(addRollupTypeParameters.multiplierGas)) / 1000n, + ((feeData.maxPriorityFeePerGas as bigint) * BigInt(addRollupTypeParameters.multiplierGas)) / + 1000n ); } currentProvider.getFeeData = overrideFeeData; @@ -94,8 +103,8 @@ async function main() { // Load deployer let deployer; - if (addRollupParameters.deployerPvtKey) { - deployer = new ethers.Wallet(addRollupParameters.deployerPvtKey, currentProvider); + if (addRollupTypeParameters.deployerPvtKey) { + deployer = new ethers.Wallet(addRollupTypeParameters.deployerPvtKey, currentProvider); } else if (process.env.MNEMONIC) { deployer = ethers.HDNodeWallet.fromMnemonic( ethers.Mnemonic.fromPhrase(process.env.MNEMONIC), @@ -108,8 +117,8 @@ async function main() { console.log("Using with: ", deployer.address); // Load Rollup manager - const PolgonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); - const rollupManagerContract = PolgonRollupManagerFactory.attach( + const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); + const rollupManagerContract = PolygonRollupManagerFactory.attach( polygonRollupManagerAddress ) as PolygonRollupManager; @@ -118,75 +127,111 @@ async function main() { const polygonZkEVMGlobalExitRootAddress = await rollupManagerContract.globalExitRootManager(); const polTokenAddress = await rollupManagerContract.pol(); - // Sanity checks genesisRoot - if (genesisRoot !== genesis.root) { - throw new Error(`Genesis root in the 'add_rollup_type.json' does not match the root in the 'genesis.json'`); - } + if (!isPessimistic) { + // checks for rollups + // Sanity checks genesisRoot + if (genesisRoot !== genesis.root) { + throw new Error(`Genesis root in the 'add_rollup_type.json' does not match the root in the 'genesis.json'`); + } - // get bridge address in genesis file - let genesisBridgeAddress = ethers.ZeroAddress; - for (let i = 0; i < genesis.genesis.length; i++) { - if (genesis.genesis[i].contractName === "PolygonZkEVMBridge proxy") { - genesisBridgeAddress = genesis.genesis[i].address; - break; + // get bridge address in genesis file + let genesisBridgeAddress = ethers.ZeroAddress; + let bridgeContractName = ""; + for (let i = 0; i < genesis.genesis.length; i++) { + if (supportedBridgeContracts.includes(genesis.genesis[i].contractName)) { + genesisBridgeAddress = genesis.genesis[i].address; + bridgeContractName = genesis.genesis[i].contractName; + break; + } } - } - if (polygonZkEVMBridgeAddress.toLowerCase() !== genesisBridgeAddress.toLowerCase()) { - throw new Error( - `'PolygonZkEVMBridge proxy' root in the 'genesis.json' does not match 'bridgeAddress' in the 'PolygonRollupManager'` - ); + if (polygonZkEVMBridgeAddress.toLowerCase() !== genesisBridgeAddress.toLowerCase()) { + throw new Error( + `'${bridgeContractName}' root in the 'genesis.json' does not match 'bridgeAddress' in the 'PolygonRollupManager'` + ); + } } - // Create consensus implementation - const PolygonconsensusFactory = (await ethers.getContractFactory(consensusContract, deployer)) as any; - let PolygonconsensusContract; - let PolygonconsensusContractAddress; + // Create consensus implementation if needed + const PolygonConsensusFactory = (await ethers.getContractFactory(consensusContract, deployer)) as any; + let PolygonConsensusContract; + let PolygonConsensusContractAddress; if ( - addRollupParameters.polygonconsensusContract === undefined || - addRollupParameters.polygonconsensusContract === "" + typeof addRollupTypeParameters.consensusContractAddress !== "undefined" && + ethers.isAddress(addRollupTypeParameters.consensusContractAddress) ) { - PolygonconsensusContract = await PolygonconsensusFactory.deploy( + PolygonConsensusContractAddress = addRollupTypeParameters.consensusContractAddress; + } else { + PolygonConsensusContract = await PolygonConsensusFactory.deploy( polygonZkEVMGlobalExitRootAddress, polTokenAddress, polygonZkEVMBridgeAddress, polygonRollupManagerAddress ); - await PolygonconsensusContract.waitForDeployment(); + await PolygonConsensusContract.waitForDeployment(); - PolygonconsensusContractAddress = PolygonconsensusContract.target; + PolygonConsensusContractAddress = PolygonConsensusContract.target; console.log("#######################\n"); - console.log(`new PolygonconsensusContract impl: ${PolygonconsensusContractAddress}`); - - console.log("you can verify the new impl address with:"); - console.log( - `npx hardhat verify --constructor-args upgrade/arguments.js ${PolygonconsensusContractAddress} --network ${process.env.HARDHAT_NETWORK}\n` - ); - console.log("Copy the following constructor arguments on: upgrade/arguments.js \n", [ - polygonZkEVMGlobalExitRootAddress, - polTokenAddress, - polygonZkEVMBridgeAddress, - polygonRollupManagerAddress, - ]); - } else { - PolygonconsensusContractAddress = addRollupParameters.polygonconsensusContract; + console.log(`new consensus name: ${consensusContract}`); + console.log(`new PolygonConsensusContract impl: ${PolygonConsensusContractAddress}`); + + try { + console.log("Verifying contract..."); + await run("verify:verify", { + address: PolygonConsensusContract.target, + constructorArguments: [ + polygonZkEVMGlobalExitRootAddress, + polTokenAddress, + polygonZkEVMBridgeAddress, + polygonRollupManagerAddress, + ], + }); + } catch (e) { + console.log("Automatic verification failed. Please verify the contract manually."); + console.log("you can verify the new impl address with:"); + console.log( + `npx hardhat verify --constructor-args upgrade/arguments.js ${PolygonConsensusContract.target} --network ${process.env.HARDHAT_NETWORK}\n` + ); + console.log("Copy the following constructor arguments on: upgrade/arguments.js \n", [ + polygonZkEVMGlobalExitRootAddress, + polTokenAddress, + polygonZkEVMBridgeAddress, + polygonRollupManagerAddress, + ]); + } } // load timelock const timelockContractFactory = await ethers.getContractFactory("PolygonZkEVMTimelock", deployer); + // Add a new rollup type + let rollupVerifierType; + let genesisFinal; + let programVKeyFinal; + + if (consensusContract == "PolygonPessimisticConsensus") { + rollupVerifierType = 1; + genesisFinal = ethers.ZeroHash; + programVKeyFinal = programVKey || ethers.ZeroHash; + } else { + rollupVerifierType = 0; + genesisFinal = genesis.root; + programVKeyFinal = ethers.ZeroHash; + } + const operation = genOperation( polygonRollupManagerAddress, 0, // value - PolgonRollupManagerFactory.interface.encodeFunctionData("addNewRollupType", [ - PolygonconsensusContractAddress, + PolygonRollupManagerFactory.interface.encodeFunctionData("addNewRollupType", [ + PolygonConsensusContractAddress, verifierAddress, forkID, - rollupCompatibilityID, - genesis.root, + rollupVerifierType, + genesisFinal, description, + programVKeyFinal, ]), predecessor, // predecessor salt // salt @@ -220,7 +265,7 @@ async function main() { outputJson.executeData = executeData; outputJson.id = operation.id; - // Decode the scheduleData for better readibility + // Decode the scheduleData for better readability const timelockTx = timelockContractFactory.interface.parseTransaction({data: scheduleData}); const paramsArray = timelockTx?.fragment.inputs; const objectDecoded = {}; @@ -231,7 +276,7 @@ async function main() { objectDecoded[currentParam.name] = timelockTx?.args[i]; if (currentParam.name == "data") { - const decodedRollupManagerData = PolgonRollupManagerFactory.interface.parseTransaction({ + const decodedRollupManagerData = PolygonRollupManagerFactory.interface.parseTransaction({ data: timelockTx?.args[i], }); const objectDecodedData = {}; @@ -247,7 +292,7 @@ async function main() { outputJson.decodedScheduleData = objectDecoded; - // Decode the schedule data to better readibiltiy: + // Decode the schedule data to better readability: fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); } diff --git a/tools/addRollupType/add_rollup_type.json.example b/tools/addRollupType/add_rollup_type.json.example index f65f64c56..d1e76ba2f 100644 --- a/tools/addRollupType/add_rollup_type.json.example +++ b/tools/addRollupType/add_rollup_type.json.example @@ -1,16 +1,16 @@ { "consensusContract": "PolygonValidiumEtrog", - "polygonconsensusContract": "", + "consensusContractAddress": "", "polygonRollupManagerAddress": "0x5132A183E9F3CB7C848b0AAC5Ae0c4f0491B7aB2", "verifierAddress": "0x1C3A3da552b8662CD69538356b1E7c2E9CC1EBD8", "description": "Type: Validium, Version: etrog, genesis: /ipfs/QmUXnRoPbUmZuEZCGyiHjEsoNcFVu3hLtSvhpnfBS2mAYU", "forkID": 7, - "rollupCompatibilityID": 0, "timelockDelay": 864000, "timelockSalt": "", "deployerPvtKey": "", "maxFeePerGas":"", "maxPriorityFeePerGas":"", "multiplierGas": "", - "genesisRoot": "0xe3a7d8bae497945ba8ddc51c69564f60ad4c1a990b9c7bdbd27f7929bfa8f272" + "genesisRoot": "0xe3a7d8bae497945ba8ddc51c69564f60ad4c1a990b9c7bdbd27f7929bfa8f272", + "programVKey": "0xaabbccddeeff00112233445566778899aabbccddeeff00112233445566778899" } diff --git a/tools/batchL2DataCreatedRollup/.gitignore b/tools/batchL2DataCreatedRollup/.gitignore new file mode 100644 index 000000000..e1239ebef --- /dev/null +++ b/tools/batchL2DataCreatedRollup/.gitignore @@ -0,0 +1,2 @@ +input.json +tx.json \ No newline at end of file diff --git a/tools/batchL2DataCreatedRollup/generateBatchL2DataCreatedRollup.ts b/tools/batchL2DataCreatedRollup/generateBatchL2DataCreatedRollup.ts new file mode 100644 index 000000000..58840e05c --- /dev/null +++ b/tools/batchL2DataCreatedRollup/generateBatchL2DataCreatedRollup.ts @@ -0,0 +1,37 @@ +import hre from "hardhat"; +import fs from "fs"; +import input from "./input.json"; +import { + PolygonZkEVMBridgeV2, +} from "../../typechain-types"; + +async function main() { + + // --network + const bridgeFactory = await hre.ethers.getContractFactory("PolygonZkEVMBridgeV2"); + const polygonZkEVMBridgeContract = bridgeFactory.attach(input.bridgeAddress) as PolygonZkEVMBridgeV2; + const gasTokenMetadata = await polygonZkEVMBridgeContract.getTokenMetadata(input.gasTokenAddress); + + // switch network hardhat + await hre.switchNetwork("hardhat"); + + const toolFactory = await hre.ethers.getContractFactory("BatchL2DataCreatedRollup"); + const toolContract = await toolFactory.deploy(); + await toolContract.waitForDeployment() + const tx = await toolContract.generateInitializeTransaction(input.networkID, input.bridgeAddress, input.gasTokenAddress, input.gasTokenNetwork, gasTokenMetadata) + const output = { + networkID: input.networkID, + tx: tx, + } + + // write tx.json + const txPath = "./tx.json" + fs.writeFileSync(txPath, JSON.stringify(output, null, 1)) +} +main().then(() => { + process.exit(0); +}, (err) => { + console.log(err.message); + console.log(err.stack); + process.exit(1); +}); \ No newline at end of file diff --git a/tools/batchL2DataCreatedRollup/input.json.example b/tools/batchL2DataCreatedRollup/input.json.example new file mode 100644 index 000000000..5e69a0d3e --- /dev/null +++ b/tools/batchL2DataCreatedRollup/input.json.example @@ -0,0 +1,6 @@ +{ + "networkID": 0, + "bridgeAddress": "0x9b28F436039654F8b948dd32599032F684899cF0", + "gasTokenAddress": "0x0000000000000000000000000000000000000000", + "gasTokenNetwork": 0 +} \ No newline at end of file diff --git a/tools/changeDelayTimelock/.gitignore b/tools/changeDelayTimelock/.gitignore new file mode 100644 index 000000000..bcbd021a1 --- /dev/null +++ b/tools/changeDelayTimelock/.gitignore @@ -0,0 +1,2 @@ +change_delay_output-* +change_delay_timelock.json \ No newline at end of file diff --git a/tools/changeDelayTimelock/README.md b/tools/changeDelayTimelock/README.md new file mode 100644 index 000000000..7df7878ab --- /dev/null +++ b/tools/changeDelayTimelock/README.md @@ -0,0 +1,35 @@ +# Change minDelay PolygonZkEVMTimelock +Script to change `minDelay` from `PolygonZkEVMTimelock` + +## Install +``` +npm i +``` + +## Setup +- Config file `change_delay_timelock.json`: + - `timelockContractAddress`: timelock contract address + - `newMinDelay`: new `minDelay` + - `timeLockDelay`: timelockDelay (by defalult `timeLockDelay` == current `minDelay`) + - `timelockSalt(optional)`: timelock salt + - `predecessor(optional)`: timelock predecessor +- A network should be selected when running the script + - examples: `--network sepolia` or `--network mainnet` + - This uses variables set in `hardhat.config.ts` + - Which uses some environment variables that should be set in `.env` +> All paths are from root repository + +## Usage +> All commands are done from root repository. + +- Copy configuration file: +``` +cp ./tools/changeDelayTimelock/change_delay_timelock.json.example ./tools/changeDelayTimelock/change_delay_timelock.json +``` +- Set your parameters +- Run tool: +``` +npx hardhat run ./tools/changeDelayTimelock/changeDelayTimelock.ts --network localhost +``` + + diff --git a/tools/changeDelayTimelock/changeDelayTimelock.ts b/tools/changeDelayTimelock/changeDelayTimelock.ts new file mode 100644 index 000000000..3fb5f1037 --- /dev/null +++ b/tools/changeDelayTimelock/changeDelayTimelock.ts @@ -0,0 +1,121 @@ +/* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if */ +/* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved */ +import {utils} from "ffjavascript"; +import path = require("path"); +import fs = require("fs"); + +import * as dotenv from "dotenv"; +dotenv.config({path: path.resolve(__dirname, "../../../.env")}); +import {ethers, network, upgrades} from "hardhat"; +import { PolygonZkEVMTimelock } from "../../typechain-types"; + +const parameters = require("./change_delay_timelock.json"); +const dateStr = new Date().toISOString(); +const pathOutputJson = path.resolve(__dirname, `./change_delay_output-${dateStr}.json`); + +async function main() { + + const outputJson = {} as any; + + const timelockContractFactory = await ethers.getContractFactory("PolygonZkEVMTimelock"); + const timelockContract = (await timelockContractFactory.attach( + parameters.timelockContractAddress + )) as PolygonZkEVMTimelock; + + console.log("#######################\n"); + console.log("timelockContract address: ", timelockContract.target) + console.log("#######################\n"); + + const timelockDelay = parameters.timeLockDelay ? parameters.timeLockDelay : Number(await timelockContract.getMinDelay()); + const salt = parameters.timelockSalt || ethers.ZeroHash; + const predecessor = parameters.predecessor || ethers.ZeroHash; + + const operation = genOperation( + parameters.timelockContractAddress, + 0, // value + timelockContract.interface.encodeFunctionData( + 'updateDelay', + [parameters.newMinDelay], + ), + predecessor, // predecessor + salt // salt + ); + + // Schedule operation + const scheduleData = timelockContractFactory.interface.encodeFunctionData("schedule", [ + operation.target, + operation.value, + operation.data, + operation.predecessor, + operation.salt, + timelockDelay, + ]); + + // Execute operation + const executeData = timelockContractFactory.interface.encodeFunctionData("execute", [ + operation.target, + operation.value, + operation.data, + operation.predecessor, + operation.salt, + ]); + + console.log("timelockDelay: ", timelockDelay) + console.log({scheduleData}); + console.log({executeData}); + + outputJson.scheduleData = scheduleData; + outputJson.executeData = executeData; + + // Decode the scheduleData for better readability + const timelockTx = timelockContractFactory.interface.parseTransaction({data: scheduleData}); + const paramsArray = timelockTx?.fragment.inputs as any; + const objectDecoded = {} as any; + + for (let i = 0; i < paramsArray?.length; i++) { + const currentParam = paramsArray[i]; + objectDecoded[currentParam.name] = timelockTx?.args[i]; + + if (currentParam.name == "data") { + const decodedTimelockTx = timelockContractFactory.interface.parseTransaction({ + data: timelockTx?.args[i], + }); + const objectDecodedData = {} as any; + const paramsArrayData = decodedTimelockTx?.fragment.inputs as any; + + objectDecodedData.signature = decodedTimelockTx?.signature; + objectDecodedData.selector = decodedTimelockTx?.selector; + + for (let j = 0; j < paramsArrayData?.length; j++) { + const currentParam = paramsArrayData[j]; + objectDecodedData[currentParam.name] = decodedTimelockTx?.args[j]; + } + objectDecoded["decodedData"] = objectDecodedData; + } + } + outputJson.decodedScheduleData = objectDecoded; + + await fs.writeFileSync(pathOutputJson, JSON.stringify(utils.stringifyBigInts(outputJson), null, 1)); +} + +// OZ test functions +function genOperation(target: any, value: any, data: any, predecessor: any, salt: any) { + const abiEncoded = ethers.AbiCoder.defaultAbiCoder().encode( + ["address", "uint256", "bytes", "uint256", "bytes32"], + [target, value, data, predecessor, salt] + ); + const id = ethers.keccak256(abiEncoded); + return { + id, + target, + value, + data, + predecessor, + salt, + }; +} + +main().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/tools/changeDelayTimelock/change_delay_timelock.json.example b/tools/changeDelayTimelock/change_delay_timelock.json.example new file mode 100644 index 000000000..0a4ec9d0f --- /dev/null +++ b/tools/changeDelayTimelock/change_delay_timelock.json.example @@ -0,0 +1,7 @@ +{ + "timelockContractAddress": "0x0165878A594ca255338adfa4d48449f69242Eb8F", + "newMinDelay": 1800, + "timeLockDelay": "", + "predecessor": "", + "timelockSalt": "" +} \ No newline at end of file diff --git a/tools/createNewRollup/.gitignore b/tools/createNewRollup/.gitignore new file mode 100644 index 000000000..bbc469664 --- /dev/null +++ b/tools/createNewRollup/.gitignore @@ -0,0 +1,5 @@ +create_new_rollup.json +genesis.json +genesis_sovereign.json +create_new_rollup_output.json +create_new_rollup_output*.json \ No newline at end of file diff --git a/tools/createNewRollup/README.md b/tools/createNewRollup/README.md new file mode 100644 index 000000000..c81a31ce9 --- /dev/null +++ b/tools/createNewRollup/README.md @@ -0,0 +1,69 @@ +# Create new Rollup +Script to call `createNewRollup` function. +- This script needs of a genesis as input only if we are trying to deploy a sovereign chain. The genesis will only be updated in case of trying to deploy a sovereign chain. In this case, this new sovereign genesis will be appended at the output file + +## Setup +- install packages +``` +npm i +``` + +- Set env variables +```` +cp .env.example .env +```` + +Fill `.env` with your `INFURA_PROJECT_ID` and `ETHERSCAN_API_KEY` + +- Copy configuration files: +``` +cp ./tools/createNewRollup/create_new_rollup.json.example ./tools/createNewRollup/create_new_rollup.json +``` + +- Copy genesis file (only for sovereign chains) +``` +cp ./tools/createNewRollup/genesis.json.example ./tools/createNewRollup/genesis.json +``` + +- Set your parameters -> create_new_rollup.json + - `type`: Specify the type of rollup creation, only available: + - `EOA`: If creating the rollup from a wallet, the script will execute the creation of the rollup on the specified network + - `Multisig`: If creating the rollup from a multisig, the script will output the calldata of the transaction to execute for creating the rollup + - `Timelock`: If creating the rollup through a timelock, the script will output the execute and schedule data to send to the timelock contract + - `trustedSequencerURL`: Sequencer URL of the new created rollup + - `networkName`: Network name of the new created rollup + - `trustedSequencer`: Sequencer address of the new created rollup + - `chainID`: ChainID of the rollup, must be a new one, can not have more than 32 bits + - `rollupAdminAddress`: Admin address of the new created rollup + - `consensusContractName`: select between consensus contract. Supported: `["PolygonZkEVMEtrog", "PolygonValidiumEtrog", "PolygonPessimisticConsensus"]`. This is the name of the consensus of the rollupType of the rollup to be created + - `gasTokenAddress`: Address of the native gas token of the rollup, zero if ether + - `deployerPvtKey`: Not mandatory, used to deploy from specific wallet + - `maxFeePerGas(optional)`: string, Set `maxFeePerGas`, must define as well `maxPriorityFeePerGas` to use it + - `maxPriorityFeePerGas(optional)`: string, Set `maxPriorityFeePerGas`, must define as well `maxFeePerGas` to use it + - `multiplierGas(optional)`: number, Gas multiplier with 3 decimals. If `maxFeePerGas` and `maxPriorityFeePerGas` are set, this will not take effect + - `timelockDelay(optional)`: timelock delay, only required on timelock type + - `timelockSalt(optional)`: timelock salt, only required on timelock type + - `rollupManagerAddress`: Address of deployed rollupManager contract + - `rollupTypeId`: The id of the rollup type of the rollup to deploy. WARNING: the type must match with the `consensusContractName`. Example: if the type is validium, the contract name has to be `PolygonValidiumEtrog` + - `isVanillaClient`: Flag for vanilla/sovereign clients handling + - `sovereignParams`: + - `bridgeManager`: bridge manager address + - `sovereignWETHAddress`: sovereign WETH address + - `sovereignWETHAddressIsNotMintable`: Flag to indicate if the wrapped ETH is not mintable + - `globalExitRootUpdater`: Address of globalExitRootUpdater for sovereign chains + - `globalExitRootRemover`: Address of globalExitRootRemover for sovereign chains + +- Set your parameters -> genesis.json + - Is the genesis used to create the rollupType + - It is only necessary in case you want to create a sovereign/vanilla chain because it will be updated + +- Run tool: +``` +npx hardhat run ./tools/createNewRollup/createNewRollup.ts --network sepolia +``` + +### More Info +- All commands are done from root repository +- The output files will be saved at `./tools/createNewRollup/create_new_rollup_output_{type}_{date}.json` +- In case is a sovereign chain, the updated genesis is saved inside the output file, the original `genesis.json` is not modified +- If the script fails, check the logs, most of the errors are handled and are auto explanatory \ No newline at end of file diff --git a/tools/createNewRollup/createNewRollup.ts b/tools/createNewRollup/createNewRollup.ts new file mode 100644 index 000000000..c26235592 --- /dev/null +++ b/tools/createNewRollup/createNewRollup.ts @@ -0,0 +1,577 @@ +/* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if */ +/* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved */ +import {expect} from "chai"; +import path = require("path"); +import fs = require("fs"); +import * as dotenv from "dotenv"; +dotenv.config({path: path.resolve(__dirname, "../../.env")}); +import {ethers, upgrades} from "hardhat"; +import {processorUtils, Constants} from "@0xpolygonhermez/zkevm-commonjs"; +import {VerifierType, ConsensusContracts} from "../../src/pessimistic-utils"; +const createRollupParameters = require("./create_new_rollup.json"); +import {genOperation, transactionTypes, convertBigIntsToNumbers} from "../utils"; +import updateVanillaGenesis from "../../deployment/v2/utils/updateVanillaGenesis"; + +import { + PolygonRollupManager, + PolygonZkEVMEtrog, + PolygonZkEVMBridgeV2, + PolygonValidiumEtrog, + PolygonPessimisticConsensus, +} from "../../typechain-types"; + +async function main() { + console.log(`Starting script to create new rollup from ${createRollupParameters.type}...`); + const outputJson = {} as any; + const dateStr = new Date().toISOString(); + const destPath = createRollupParameters.outputPath + ? path.join(__dirname, createRollupParameters.outputPath) + : path.join(__dirname, `create_new_rollup_output_${createRollupParameters.type}_${dateStr}.json`); + + /* + * Check deploy parameters + * Check that every necessary parameter is fulfilled + */ + const mandatoryDeploymentParameters = [ + "trustedSequencerURL", + "networkName", + "trustedSequencer", + "chainID", + "rollupAdminAddress", + "consensusContractName", + "rollupManagerAddress", + "rollupTypeId", + "gasTokenAddress", + "type", + ]; + // check create rollup type + switch (createRollupParameters.type) { + case transactionTypes.EOA: + case transactionTypes.MULTISIG: + break; + case transactionTypes.TIMELOCK: + mandatoryDeploymentParameters.push("timelockDelay"); + break; + default: + throw new Error(`Invalid type ${createRollupParameters.type}`); + } + for (const parameterName of mandatoryDeploymentParameters) { + if (createRollupParameters[parameterName] === undefined || createRollupParameters[parameterName] === "") { + throw new Error(`Missing parameter: ${parameterName}`); + } + } + + const { + trustedSequencerURL, + networkName, + trustedSequencer, + chainID, + rollupAdminAddress, + consensusContractName, + isVanillaClient, + sovereignParams, + } = createRollupParameters; + + // Check supported consensus is correct + const supportedConsensus = [ + ConsensusContracts.PolygonZkEVMEtrog, + ConsensusContracts.PolygonValidiumEtrog, + ConsensusContracts.PolygonPessimisticConsensus, + ]; + + if (!supportedConsensus.includes(consensusContractName)) { + throw new Error( + `Consensus contract ${consensusContractName} not supported, supported contracts are: ${supportedConsensus}` + ); + } + + // Check consensus compatibility + if (isVanillaClient) { + if (consensusContractName !== "PolygonPessimisticConsensus") { + throw new Error(`Vanilla client only supports PolygonPessimisticConsensus`); + } + // Check sovereign params + const mandatorySovereignParams = [ + "bridgeManager", + "sovereignWETHAddress", + "sovereignWETHAddressIsNotMintable", + "globalExitRootUpdater", + "globalExitRootRemover", + ]; + for (const parameterName of mandatorySovereignParams) { + if (typeof sovereignParams[parameterName] === undefined || sovereignParams[parameterName] === "") { + throw new Error(`Missing sovereign parameter: ${parameterName}`); + } + } + // Vanilla checks like in bridge contract + if ( + ethers.isAddress(createRollupParameters.gasTokenAddress) && + createRollupParameters.gasTokenAddress !== ethers.ZeroAddress && + sovereignParams.sovereignWETHAddress === ethers.ZeroAddress && + sovereignParams.sovereignWETHAddressIsNotMintable === true + ) { + throw new Error( + "InvalidSovereignWETHAddressParams: if gasTokenAddress is not 0x0, and sovereignWETHAddress is 0x0, sovereignWETHAddressIsNotMintable must be false" + ); + } + + if ( + createRollupParameters.gasTokenAddress === ethers.ZeroAddress && + (sovereignParams.sovereignWETHAddress !== ethers.ZeroAddress || + sovereignParams.sovereignWETHAddressIsNotMintable === true) + ) { + throw new Error( + "InvalidSovereignWETHAddressParams: If gasTokenAddress is 0x0, sovereignWETHAddress must be 0x0 and sovereignWETHAddressIsNotMintable must be false" + ); + } + } + + // Load provider + let currentProvider = ethers.provider; + if (createRollupParameters.multiplierGas || createRollupParameters.maxFeePerGas) { + if (process.env.HARDHAT_NETWORK !== "hardhat") { + currentProvider = ethers.getDefaultProvider( + `https://${process.env.HARDHAT_NETWORK}.infura.io/v3/${process.env.INFURA_PROJECT_ID}` + ) as any; + if (createRollupParameters.maxPriorityFeePerGas && createRollupParameters.maxFeePerGas) { + console.log( + `Hardcoded gas used: MaxPriority${createRollupParameters.maxPriorityFeePerGas} gwei, MaxFee${createRollupParameters.maxFeePerGas} gwei` + ); + const FEE_DATA = new ethers.FeeData( + null, + ethers.parseUnits(createRollupParameters.maxFeePerGas, "gwei"), + ethers.parseUnits(createRollupParameters.maxPriorityFeePerGas, "gwei") + ); + + currentProvider.getFeeData = async () => FEE_DATA; + } else { + console.log("Multiplier gas used: ", createRollupParameters.multiplierGas); + async function overrideFeeData() { + const feeData = await ethers.provider.getFeeData(); + return new ethers.FeeData( + null, + ((feeData.maxFeePerGas as bigint) * BigInt(createRollupParameters.multiplierGas)) / 1000n, + ((feeData.maxPriorityFeePerGas as bigint) * BigInt(createRollupParameters.multiplierGas)) / + 1000n + ); + } + currentProvider.getFeeData = overrideFeeData; + } + } + } + + // Load deployer + let deployer; + if (createRollupParameters.deployerPvtKey) { + deployer = new ethers.Wallet(createRollupParameters.deployerPvtKey, currentProvider); + } else if (process.env.MNEMONIC) { + deployer = ethers.HDNodeWallet.fromMnemonic( + ethers.Mnemonic.fromPhrase(process.env.MNEMONIC), + "m/44'/60'/0'/0/0" + ).connect(currentProvider); + } else { + [deployer] = await ethers.getSigners(); + } + + // Load Rollup manager + const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); + const rollupManagerContract = PolygonRollupManagerFactory.attach( + createRollupParameters.rollupManagerAddress + ) as PolygonRollupManager; + + // Load global exit root manager + const globalExitRootManagerFactory = await ethers.getContractFactory("PolygonZkEVMGlobalExitRootV2", deployer); + const globalExitRootManagerAddress = await rollupManagerContract.globalExitRootManager(); + const globalExitRootManagerContract = globalExitRootManagerFactory.attach( + globalExitRootManagerAddress + ) as PolygonRollupManager; + + // Check if the deployer has right to deploy new rollups from rollupManager contract + const DEFAULT_ADMIN_ROLE = ethers.ZeroHash; + if ((await rollupManagerContract.hasRole(DEFAULT_ADMIN_ROLE, deployer.address)) == false) { + throw new Error( + `Deployer does not have admin role. Use the test flag on deploy_parameters if this is a test deployment` + ); + } + const polygonConsensusFactory = (await ethers.getContractFactory(consensusContractName, deployer)) as any; + // Check chainID + let rollupID = await rollupManagerContract.chainIDToRollupID(chainID); + if (Number(rollupID) !== 0) { + throw new Error(`Rollup with chainID ${chainID} already exists`); + } + // Check rollupTypeId + const rollupType = await rollupManagerContract.rollupTypeMap(createRollupParameters.rollupTypeId); + const consensusContractAddress = rollupType[0]; + const verifierType = Number(rollupType[3]); + if ( + consensusContractName === ConsensusContracts.PolygonPessimisticConsensus && + verifierType !== VerifierType.Pessimistic + ) { + throw new Error( + `Mismatch RollupTypeID: Verifier type should be ${VerifierType.StateTransition} for ${consensusContractName}` + ); + } + if (consensusContractName !== ConsensusContracts.PolygonPessimisticConsensus) { + if (verifierType !== VerifierType.StateTransition) { + throw new Error( + `Mismatch RollupTypeID: Verifier type should be ${VerifierType.Pessimistic} for ${consensusContractName}` + ); + } + const polygonValidiumConsensusFactory = (await ethers.getContractFactory( + ConsensusContracts.PolygonValidiumEtrog, + deployer + )) as any; + const polygonValidiumConsensusContract = polygonValidiumConsensusFactory.attach( + consensusContractAddress + ) as PolygonValidiumEtrog; + + let hasMethodImplemented; + + try { + hasMethodImplemented = await polygonValidiumConsensusContract.isSequenceWithDataAvailabilityAllowed(); + } catch (error) { + console.log("RollupTypeID selected "); + } + + // Consensus PolygonZkEVMEtrog: if 'hasMethodImplemented' does not have any value + if (typeof hasMethodImplemented === "undefined") { + if (consensusContractName === ConsensusContracts.PolygonValidiumEtrog) { + throw new Error( + `The consensus contract at ${consensusContractAddress} does not have the public method "isSequenceWithDataAvailabilityAllowed", this means is a rollup and you are trying to create a validium` + ); + } + } else { + // Consensus PolygonValidiumEtrog: if 'hasMethodImplemented' does not have any value + if (consensusContractName === ConsensusContracts.PolygonZkEVMEtrog) { + throw new Error( + `The consensus contract at ${consensusContractAddress} does have the public var "isSequenceWithDataAvailabilityAllowed", this means is a validium and you are trying to create a rollup` + ); + } + } + } + + // Grant role CREATE_ROLLUP_ROLE to deployer + const CREATE_ROLLUP_ROLE = ethers.id("CREATE_ROLLUP_ROLE"); + if ((await rollupManagerContract.hasRole(CREATE_ROLLUP_ROLE, deployer.address)) == false) + await rollupManagerContract.grantRole(CREATE_ROLLUP_ROLE, deployer.address); + + // Get rollup address deterministically + const nonce = await currentProvider.getTransactionCount(rollupManagerContract.target); + const createdRollupAddress = ethers.getCreateAddress({ + from: rollupManagerContract.target as string, + nonce: nonce, + }); + let globalExitRoot = ""; + let batchData = {}; + // Populate output json + outputJson.consensusContractName = consensusContractName; + outputJson.rollupAddress = createdRollupAddress; + outputJson.genesis = rollupType.genesis; + outputJson.gasTokenAddress = createRollupParameters.gasTokenAddress; + outputJson.rollupManagerAddress = createRollupParameters.rollupManagerAddress; + if (createRollupParameters.type === transactionTypes.TIMELOCK) { + console.log("Creating timelock txs for rollup creation..."); + const salt = createRollupParameters.timelockSalt || ethers.ZeroHash; + const predecessor = ethers.ZeroHash; + const timelockContractFactory = await ethers.getContractFactory("PolygonZkEVMTimelock", deployer); + const operation = genOperation( + createRollupParameters.rollupManagerAddress, + 0, // value + PolygonRollupManagerFactory.interface.encodeFunctionData("createNewRollup", [ + createRollupParameters.rollupTypeId, + chainID, + rollupAdminAddress, + trustedSequencer, + createRollupParameters.gasTokenAddress, + trustedSequencerURL, + networkName, + ]), + predecessor, // predecessor + salt // salt + ); + // Schedule operation + const scheduleData = timelockContractFactory.interface.encodeFunctionData("schedule", [ + operation.target, + operation.value, + operation.data, + operation.predecessor, + operation.salt, + createRollupParameters.timelockDelay, + ]); + // Execute operation + const executeData = timelockContractFactory.interface.encodeFunctionData("execute", [ + operation.target, + operation.value, + operation.data, + operation.predecessor, + operation.salt, + ]); + console.log({scheduleData}); + console.log({executeData}); + outputJson.scheduleData = scheduleData; + outputJson.executeData = executeData; + // Decode the scheduleData for better readability + const timelockTx = timelockContractFactory.interface.parseTransaction({data: scheduleData}); + const paramsArray = timelockTx?.fragment.inputs; + const objectDecoded = {}; + for (let i = 0; i < paramsArray?.length; i++) { + const currentParam = paramsArray[i]; + + objectDecoded[currentParam.name] = timelockTx?.args[i]; + + if (currentParam.name == "data") { + const decodedRollupManagerData = PolygonRollupManagerFactory.interface.parseTransaction({ + data: timelockTx?.args[i], + }); + const objectDecodedData = {}; + const paramsArrayData = decodedRollupManagerData?.fragment.inputs; + + for (let j = 0; j < paramsArrayData?.length; j++) { + const currentParam = paramsArrayData[j]; + objectDecodedData[currentParam.name] = decodedRollupManagerData?.args[j]; + } + objectDecoded["decodedData"] = objectDecodedData; + } + } + + outputJson.decodedScheduleData = convertBigIntsToNumbers(objectDecoded); + fs.writeFileSync(destPath, JSON.stringify(outputJson, null, 1)); + console.log("Finished script, output saved at: ", destPath); + process.exit(0); + } else if (createRollupParameters.type === transactionTypes.MULTISIG) { + console.log("Creating calldata for rollup creation from multisig..."); + const txDeployRollupCalldata = PolygonRollupManagerFactory.interface.encodeFunctionData("createNewRollup", [ + createRollupParameters.rollupTypeId, + chainID, + rollupAdminAddress, + trustedSequencer, + createRollupParameters.gasTokenAddress, + trustedSequencerURL, + networkName, + ]); + outputJson.txDeployRollupCalldata = txDeployRollupCalldata; + fs.writeFileSync(destPath, JSON.stringify(outputJson, null, 1)); + console.log("Finished script, output saved at: ", destPath); + process.exit(0); + } else { + console.log("Deploying rollup...."); + // Create new rollup + const txDeployRollup = await rollupManagerContract.createNewRollup( + createRollupParameters.rollupTypeId, + chainID, + rollupAdminAddress, + trustedSequencer, + createRollupParameters.gasTokenAddress, + trustedSequencerURL, + networkName + ); + + const receipt = (await txDeployRollup.wait()) as any; + const blockDeploymentRollup = await receipt?.getBlock(); + + batchData = { + timestamp: blockDeploymentRollup.timestamp, + l1BlockNumber: blockDeploymentRollup.number, + l1BlockHash: blockDeploymentRollup.hash, + l1ParentHash: blockDeploymentRollup.parentHash, + }; + outputJson.createRollupBlockNumber = blockDeploymentRollup.number; + console.log("#######################\n"); + console.log( + `Created new ${consensusContractName} Rollup: ${createdRollupAddress} with rollupTypeId: ${createRollupParameters.rollupTypeId}` + ); + + // Search added global exit root on the logs + for (const log of receipt?.logs) { + if (log.address == createdRollupAddress) { + const parsedLog = polygonConsensusFactory.interface.parseLog(log); + if (parsedLog != null && parsedLog.name == "InitialSequenceBatches") { + globalExitRoot = parsedLog.args.lastGlobalExitRoot; + } + } + } + // Assert admin address + expect(await upgrades.erc1967.getAdminAddress(createdRollupAddress)).to.be.equal(rollupManagerContract.target); + expect(await upgrades.erc1967.getImplementationAddress(createdRollupAddress)).to.be.equal( + consensusContractAddress + ); + } + // Update rollupId + rollupID = await rollupManagerContract.chainIDToRollupID(chainID); + + // If is a validium, data committee must be set up + const dataAvailabilityProtocol = createRollupParameters.dataAvailabilityProtocol || "PolygonDataCommittee"; + if (consensusContractName.includes("PolygonValidiumEtrog") && dataAvailabilityProtocol === "PolygonDataCommittee") { + console.log("Is a validium, setting up data committee..."); + // deploy data committee + const PolygonDataCommitteeContract = (await ethers.getContractFactory("PolygonDataCommittee", deployer)) as any; + let polygonDataCommittee = await upgrades.deployProxy(PolygonDataCommitteeContract, [], { + unsafeAllow: ["constructor"], + }); + await polygonDataCommittee?.waitForDeployment(); + console.log(`Deployed PolygonDataCommittee at ${polygonDataCommittee?.address}`); + // Load data committee + const PolygonValidiumContract = (await polygonConsensusFactory.attach( + createdRollupAddress + )) as PolygonValidiumEtrog; + // add data committee to the consensus contract + if ((await PolygonValidiumContract.admin()) == deployer.address) { + await ( + await PolygonValidiumContract.setDataAvailabilityProtocol(polygonDataCommittee?.target as any) + ).wait(); + } else { + console.log("Is a validium, setting up data committee..."); + await (await polygonDataCommittee?.transferOwnership(rollupAdminAddress)).wait(); + console.log(`Transferred ownership of PolygonDataCommittee to ${rollupAdminAddress}`); + } + outputJson.polygonDataCommitteeAddress = polygonDataCommittee?.target; + } + + let gasTokenAddress, gasTokenNetwork, gasTokenMetadata; + + // Get bridge instance + const bridgeFactory = await ethers.getContractFactory("PolygonZkEVMBridgeV2", deployer); + const bridgeContractAddress = await rollupManagerContract.bridgeAddress(); + const rollupBridgeContract = bridgeFactory.attach(bridgeContractAddress) as PolygonZkEVMBridgeV2; + if ( + ethers.isAddress(createRollupParameters.gasTokenAddress) && + createRollupParameters.gasTokenAddress !== ethers.ZeroAddress + ) { + // Get token metadata + gasTokenMetadata = await rollupBridgeContract.getTokenMetadata(createRollupParameters.gasTokenAddress); + outputJson.gasTokenMetadata = gasTokenMetadata; + // If gas token metadata includes `0x124e4f545f56414c49445f454e434f44494e47 (NOT_VALID_ENCODING)` means there is no erc20 token deployed at the selected gas token network + if (gasTokenMetadata.includes("124e4f545f56414c49445f454e434f44494e47")) { + throw new Error( + `Invalid gas token address, no ERC20 token deployed at the selected gas token network ${createRollupParameters.gasTokenAddress}` + ); + } + const wrappedData = await rollupBridgeContract.wrappedTokenToTokenInfo(createRollupParameters.gasTokenAddress); + if (wrappedData.originNetwork != 0n) { + // Wrapped token + gasTokenAddress = wrappedData.originTokenAddress; + gasTokenNetwork = wrappedData.originNetwork; + } else { + // Mainnet token + gasTokenAddress = createRollupParameters.gasTokenAddress; + gasTokenNetwork = 0n; + } + } else { + gasTokenAddress = ethers.ZeroAddress; + gasTokenNetwork = 0; + gasTokenMetadata = "0x"; + } + + /** + If the system is running a "vanilla client" (i.e., a basic, unmodified Ethereum client or rollup setup), the genesis block should include the deployment of the sovereign contracts, and these contracts should already be initialized with their required initial state and configurations. This means that the genesis block will contain the initial state for these contracts, allowing the system to start running without needing any additional initialization steps. However, for other rollups, additional configuration is needed. In this case, instead of having everything pre-initialized in the genesis block, we must inject an "initialization batch" into the genesis file. This batch will contain specific instructions for initializing the contracts at the time of rollup deployment. The injected initialization batch allows the system to be configured dynamically during deployment. + */ + + if (isVanillaClient) { + console.log("Vanilla client detected, updating genesis..."); + const pathGenesis = path.join(__dirname, "./genesis.json"); + let genesis = JSON.parse(fs.readFileSync(pathGenesis, "utf8")); + const initializeParams = { + rollupID: rollupID, + gasTokenAddress, + gasTokenNetwork, + polygonRollupManager: ethers.ZeroAddress, + gasTokenMetadata, + bridgeManager: sovereignParams.bridgeManager, + sovereignWETHAddress: sovereignParams.sovereignWETHAddress, + sovereignWETHAddressIsNotMintable: sovereignParams.sovereignWETHAddressIsNotMintable, + globalExitRootUpdater: sovereignParams.globalExitRootUpdater, + globalExitRootRemover: sovereignParams.globalExitRootRemover, + }; + genesis = await updateVanillaGenesis(genesis, chainID, initializeParams); + // Add weth address to deployment output if gas token address is provided and sovereignWETHAddress is not provided + if ( + gasTokenAddress !== ethers.ZeroAddress && + ethers.isAddress(gasTokenAddress) && + (sovereignParams.sovereignWETHAddress === ethers.ZeroAddress || + !ethers.isAddress(sovereignParams.sovereignWETHAddress)) + ) { + console.log("Rollup with custom gas token, adding WETH address to deployment output..."); + const wethObject = genesis.genesis.find(function (obj: {contractName: string}) { + return obj.contractName == "WETH"; + }); + outputJson.WETHAddress = wethObject.address; + } + outputJson.genesis_sovereign = genesis; + } else { + if (consensusContractName === "PolygonPessimisticConsensus") { + console.log("Pessimistic rollup detected, injecting initialization batch..."); + // Add the first batch of the created rollup + const newPessimisticRollup = (await polygonConsensusFactory.attach( + createdRollupAddress + )) as PolygonPessimisticConsensus; + + // Get last GER + const lastGER = await globalExitRootManagerContract.getLastGlobalExitRoot(); + + const dataInjectedTx = await rollupBridgeContract.interface.encodeFunctionData("initialize", [ + rollupID, + gasTokenAddress, + gasTokenNetwork, + Constants.ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2, // Global exit root address on L2 + ethers.ZeroAddress, // Rollup manager on L2 does not exist + gasTokenMetadata as any, + ]); + + // check maximum length is 65535 + if ((dataInjectedTx.length - 2) / 2 > 0xffff) { + // throw error + throw new Error(`HugeTokenMetadataNotSupported`); + } + + const injectedTx = { + type: 0, // force ethers to parse it as a legacy transaction + chainId: 0, // force ethers to parse it as a pre-EIP155 transaction + to: await newPessimisticRollup.bridgeAddress(), + value: 0, + gasPrice: 0, + gasLimit: 30000000, + nonce: 0, + data: dataInjectedTx, + signature: { + v: "0x1b", + r: "0x00000000000000000000000000000000000000000000000000000005ca1ab1e0", + s: "0x000000000000000000000000000000000000000000000000000000005ca1ab1e", + }, + }; + + // serialize transactions + const txObject = ethers.Transaction.from(injectedTx); + + const customData = processorUtils.rawTxToCustomRawTx(txObject.serialized); + batchData = Object.assign(batchData, { + batchL2Data: customData, + globalExitRoot: lastGER, + sequencer: trustedSequencer, + }); + } else { + console.log("Setting initialization batch for the rollup..."); + // Add the first batch of the created rollup + const newRollupContract = (await polygonConsensusFactory.attach(createdRollupAddress)) as PolygonZkEVMEtrog; + batchData = Object.assign(batchData, { + batchL2Data: await newRollupContract.generateInitializeTransaction( + Number(rollupID), + gasTokenAddress, + gasTokenNetwork, + gasTokenMetadata as any + ), + globalExitRoot: globalExitRoot, + sequencer: trustedSequencer, + }); + } + } + outputJson.firstBatchData = batchData; + outputJson.rollupID = Number(rollupID); + + fs.writeFileSync(destPath, JSON.stringify(outputJson, null, 1)); + console.log("Finished script, output saved at: ", destPath); +} + +main().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/tools/createNewRollup/create_new_rollup.json.example b/tools/createNewRollup/create_new_rollup.json.example new file mode 100644 index 000000000..6528a9361 --- /dev/null +++ b/tools/createNewRollup/create_new_rollup.json.example @@ -0,0 +1,26 @@ +{ + "type":"EOA", + "trustedSequencerURL": "http://zkevm-json-rpc:8123", + "networkName": "zkevm", + "trustedSequencer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "chainID": 1001, + "rollupAdminAddress": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "consensusContractName": "PolygonZkEVMEtrog", + "gasTokenAddress": "0x0000000000000000000000000000000000000000", + "deployerPvtKey": "", + "maxFeePerGas": "", + "maxPriorityFeePerGas": "", + "multiplierGas": "", + "timelockDelay": 0, + "timelockSalt": "", + "rollupManagerAddress": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0", + "rollupTypeId": 1, + "isVanillaClient": false, + "sovereignParams": { + "bridgeManager": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "sovereignWETHAddress": "0x0000000000000000000000000000000000000000", + "sovereignWETHAddressIsNotMintable": false, + "globalExitRootUpdater": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "globalExitRootRemover": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } +} \ No newline at end of file diff --git a/tools/createNewRollup/genesis.json.example b/tools/createNewRollup/genesis.json.example new file mode 100644 index 000000000..b9567ecbb --- /dev/null +++ b/tools/createNewRollup/genesis.json.example @@ -0,0 +1,92 @@ +{ + "root": "0x433ba1f86d65cf39d003f7dec3c6dcdbf14b17c169fba89a16732b88254a3b1e", + "genesis": [ + { + "contractName": "PolygonZkEVMDeployer", + "balance": "0", + "nonce": "4", + "address": "0xFbD07134824dDEa24E4ae414c18ecbFa98169A24", + "bytecode": "0x60806040526004361061006e575f3560e01c8063715018a61161004c578063715018a6146100e25780638da5cb5b146100f6578063e11ae6cb1461011f578063f2fde38b14610132575f80fd5b80632b79805a146100725780634a94d487146100875780636d07dbf81461009a575b5f80fd5b610085610080366004610908565b610151565b005b6100856100953660046109a2565b6101c2565b3480156100a5575f80fd5b506100b96100b43660046109f5565b610203565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ed575f80fd5b50610085610215565b348015610101575f80fd5b505f5473ffffffffffffffffffffffffffffffffffffffff166100b9565b61008561012d366004610a15565b610228565b34801561013d575f80fd5b5061008561014c366004610a61565b61028e565b61015961034a565b5f6101658585856103ca565b90506101718183610527565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a15050505050565b6101ca61034a565b6101d583838361056a565b506040517f25adb19089b6a549831a273acdf7908cff8b7ee5f551f8d1d37996cf01c5df5b905f90a1505050565b5f61020e8383610598565b9392505050565b61021d61034a565b6102265f6105a4565b565b61023061034a565b5f61023c8484846103ca565b60405173ffffffffffffffffffffffffffffffffffffffff821681529091507fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a150505050565b61029661034a565b73ffffffffffffffffffffffffffffffffffffffff811661033e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610347816105a4565b50565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610226576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610335565b5f83471015610435576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401610335565b81515f0361049f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401610335565b8282516020840186f5905073ffffffffffffffffffffffffffffffffffffffff811661020e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401610335565b606061020e83835f6040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250610618565b6060610590848484604051806060016040528060298152602001610b0860299139610618565b949350505050565b5f61020e83833061072d565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060824710156106aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610335565b5f808673ffffffffffffffffffffffffffffffffffffffff1685876040516106d29190610a9c565b5f6040518083038185875af1925050503d805f811461070c576040519150601f19603f3d011682016040523d82523d5f602084013e610711565b606091505b509150915061072287838387610756565b979650505050505050565b5f604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b606083156107eb5782515f036107e45773ffffffffffffffffffffffffffffffffffffffff85163b6107e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610335565b5081610590565b61059083838151156108005781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103359190610ab7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f830112610870575f80fd5b813567ffffffffffffffff8082111561088b5761088b610834565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156108d1576108d1610834565b816040528381528660208588010111156108e9575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f806080858703121561091b575f80fd5b8435935060208501359250604085013567ffffffffffffffff80821115610940575f80fd5b61094c88838901610861565b93506060870135915080821115610961575f80fd5b5061096e87828801610861565b91505092959194509250565b803573ffffffffffffffffffffffffffffffffffffffff8116811461099d575f80fd5b919050565b5f805f606084860312156109b4575f80fd5b6109bd8461097a565b9250602084013567ffffffffffffffff8111156109d8575f80fd5b6109e486828701610861565b925050604084013590509250925092565b5f8060408385031215610a06575f80fd5b50508035926020909101359150565b5f805f60608486031215610a27575f80fd5b8335925060208401359150604084013567ffffffffffffffff811115610a4b575f80fd5b610a5786828701610861565b9150509250925092565b5f60208284031215610a71575f80fd5b61020e8261097a565b5f5b83811015610a94578181015183820152602001610a7c565b50505f910152565b5f8251610aad818460208701610a7a565b9190910192915050565b602081525f8251806020840152610ad5816040850160208701610a7a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220330b94dc698c4d290bf55c23f13b473cde6a6bae0030cb902de18af54e35839f64736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266" + } + }, + { + "contractName": "ProxyAdmin", + "balance": "0", + "nonce": "1", + "address": "0xfADB60b5059e31614e02083fF6C021a24C31c891", + "bytecode": "0x608060405260043610610079575f3560e01c80639623609d1161004c5780639623609d1461012357806399a88ec414610136578063f2fde38b14610155578063f3b7dead14610174575f80fd5b8063204e1c7a1461007d578063715018a6146100c55780637eff275e146100db5780638da5cb5b146100fa575b5f80fd5b348015610088575f80fd5b5061009c6100973660046105e8565b610193565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d0575f80fd5b506100d9610244565b005b3480156100e6575f80fd5b506100d96100f536600461060a565b610257565b348015610105575f80fd5b505f5473ffffffffffffffffffffffffffffffffffffffff1661009c565b6100d961013136600461066e565b6102e0565b348015610141575f80fd5b506100d961015036600461060a565b610371565b348015610160575f80fd5b506100d961016f3660046105e8565b6103cd565b34801561017f575f80fd5b5061009c61018e3660046105e8565b610489565b5f805f8373ffffffffffffffffffffffffffffffffffffffff166040516101dd907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b5f60405180830381855afa9150503d805f8114610215576040519150601f19603f3d011682016040523d82523d5f602084013e61021a565b606091505b509150915081610228575f80fd5b8080602001905181019061023c919061075b565b949350505050565b61024c6104d3565b6102555f610553565b565b61025f6104d3565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b5f604051808303815f87803b1580156102c6575f80fd5b505af11580156102d8573d5f803e3d5ffd5b505050505050565b6102e86104d3565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef28690349061033e9086908690600401610776565b5f604051808303818588803b158015610355575f80fd5b505af1158015610367573d5f803e3d5ffd5b5050505050505050565b6103796104d3565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016102af565b6103d56104d3565b73ffffffffffffffffffffffffffffffffffffffff811661047d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61048681610553565b50565b5f805f8373ffffffffffffffffffffffffffffffffffffffff166040516101dd907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610255576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610474565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610486575f80fd5b5f602082840312156105f8575f80fd5b8135610603816105c7565b9392505050565b5f806040838503121561061b575f80fd5b8235610626816105c7565b91506020830135610636816105c7565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f805f60608486031215610680575f80fd5b833561068b816105c7565b9250602084013561069b816105c7565b9150604084013567ffffffffffffffff808211156106b7575f80fd5b818601915086601f8301126106ca575f80fd5b8135818111156106dc576106dc610641565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561072257610722610641565b8160405282815289602084870101111561073a575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f6020828403121561076b575f80fd5b8151610603816105c7565b73ffffffffffffffffffffffffffffffffffffffff831681525f602060408184015283518060408501525f5b818110156107be578581018301518582016060015282016107a2565b505f6060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010192505050939250505056fea26469706673582212203083a4ccc2e42eed60bd19037f2efa77ed086dc7a5403f75bebb995dcba2221c64736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000165878a594ca255338adfa4d48449f69242eb8f" + } + }, + { + "contractName": "PolygonZkEVMBridgeV2 implementation", + "balance": "0", + "nonce": "1", + "address": "0xBC9585CB224A8F42EF9C9F0b99c531B450b11886", + "bytecode": "0x6080604052600436106101db575f3560e01c806383f24403116100fd578063ccaa2d1111610092578063ee25560b11610062578063ee25560b146105a9578063f5efcd79146105d4578063f811bff7146105f3578063fb57083414610612575f80fd5b8063ccaa2d111461053b578063cd5865791461055a578063d02103ca1461056d578063dbc1697614610595575f80fd5b8063bab161bf116100cd578063bab161bf146104b9578063be5831c7146104da578063c00f14ab146104fd578063cc4616321461051c575f80fd5b806383f244031461043d5780638ed7e3f21461045c578063aaa13cc21461047b578063b8b284d01461049a575f80fd5b80633cbc795b116101735780637843298b116101435780637843298b146103c257806379e2cf97146103e157806381b1c174146103f557806383c43a5514610429575f80fd5b80633cbc795b146103385780633e197043146103705780634b2f336d1461038f5780635ca1e165146103ae575f80fd5b806327aef4e8116101ae57806327aef4e81461026d5780632dfdf0b51461028e578063318aee3d146102b15780633c351e1014610319575f80fd5b806315064c96146101df5780632072f6c51461020d57806322e95f2c14610223578063240ff3781461025a575b5f80fd5b3480156101ea575f80fd5b506068546101f89060ff1681565b60405190151581526020015b60405180910390f35b348015610218575f80fd5b50610221610631565b005b34801561022e575f80fd5b5061024261023d366004612e6f565b610666565b6040516001600160a01b039091168152602001610204565b610221610268366004612ef6565b6106d0565b348015610278575f80fd5b50610281610759565b6040516102049190612fb8565b348015610299575f80fd5b506102a360535481565b604051908152602001610204565b3480156102bc575f80fd5b506102f56102cb366004612fd1565b606b6020525f908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201610204565b348015610324575f80fd5b50606d54610242906001600160a01b031681565b348015610343575f80fd5b50606d5461035b90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610204565b34801561037b575f80fd5b506102a361038a366004612ffa565b6107e5565b34801561039a575f80fd5b50606f54610242906001600160a01b031681565b3480156103b9575f80fd5b506102a361088e565b3480156103cd575f80fd5b506102426103dc366004613074565b61096a565b3480156103ec575f80fd5b50610221610993565b348015610400575f80fd5b5061024261040f3660046130ba565b606a6020525f90815260409020546001600160a01b031681565b348015610434575f80fd5b506102816109b4565b348015610448575f80fd5b506102a36104573660046130e2565b6109d3565b348015610467575f80fd5b50606c54610242906001600160a01b031681565b348015610486575f80fd5b506102426104953660046131e3565b610aa8565b3480156104a5575f80fd5b506102216104b4366004613279565b610be7565b3480156104c4575f80fd5b5060685461035b90610100900463ffffffff1681565b3480156104e5575f80fd5b5060685461035b90600160c81b900463ffffffff1681565b348015610508575f80fd5b50610281610517366004612fd1565b610c79565b348015610527575f80fd5b506101f86105363660046132f7565b610cbe565b348015610546575f80fd5b50610221610555366004613328565b610d46565b61022161056836600461340c565b611181565b348015610578575f80fd5b50606854610242906501000000000090046001600160a01b031681565b3480156105a0575f80fd5b5061022161154a565b3480156105b4575f80fd5b506102a36105c33660046130ba565b60696020525f908152604090205481565b3480156105df575f80fd5b506102216105ee366004613328565b61157d565b3480156105fe575f80fd5b5061022161060d36600461349c565b6117f9565b34801561061d575f80fd5b506101f861062c36600461353f565b611b14565b606c546001600160a01b0316331461065c57604051631736745960e31b815260040160405180910390fd5b610664611b2b565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091205f908152606a90915220546001600160a01b03165b92915050565b60685460ff16156106f457604051630bc011ff60e21b815260040160405180910390fd5b341580159061070d5750606f546001600160a01b031615155b15610744576040517f6f625c4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610752858534868686611b86565b5050505050565b606e805461076690613584565b80601f016020809104026020016040519081016040528092919081815260200182805461079290613584565b80156107dd5780601f106107b4576101008083540402835291602001916107dd565b820191905f5260205f20905b8154815290600101906020018083116107c057829003601f168201915b505050505081565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b6053545f90819081805b6020811015610961578083901c6001166001036108f557603381602081106108c2576108c26135bc565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610922565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b60408051602081018490529081018390526060016040516020818303038152906040528051906020012091508080610959906135e4565b915050610898565b50919392505050565b5f61098b848461097985611c50565b61098286611d3a565b61049587611e1b565b949350505050565b605354606854600160c81b900463ffffffff16101561066457610664611ee8565b60405180611ba00160405280611b668152602001613c36611b66913981565b5f83815b6020811015610a9f57600163ffffffff8516821c81169003610a4257848160208110610a0557610a056135bc565b602002013582604051602001610a25929190918252602082015260400190565b604051602081830303815290604052805190602001209150610a8d565b81858260208110610a5557610a556135bc565b6020020135604051602001610a74929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80610a97816135e4565b9150506109d7565b50949350505050565b6040516001600160e01b031960e087901b1660208201526bffffffffffffffffffffffff19606086901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180611ba00160405280611b668152602001613c36611b669139898989604051602001610b30939291906135fc565b60408051601f1981840301815290829052610b4e9291602001613634565b60405160208183030381529060405280519060200120604051602001610bc394939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60685460ff1615610c0b57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b0316610c4d576040517fdde3cda700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f54610c63906001600160a01b031685611f96565b610c71868686868686611b86565b505050505050565b6060610c8482611c50565b610c8d83611d3a565b610c9684611e1b565b604051602001610ca8939291906135fc565b6040516020818303038152906040529050919050565b6068545f908190610100900463ffffffff16158015610ce3575063ffffffff83166001145b15610cf5575063ffffffff8316610d1d565b610d0a64010000000063ffffffff8516613662565b610d1a9063ffffffff8616613679565b90505b600881901c5f90815260696020526040902054600160ff9092169190911b908116149392505050565b60685460ff1615610d6a57604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614610d9a576040516302caf51760e11b815260040160405180910390fd5b610dcd8c8c8c8c8c610dc85f8e8e8e8e8e8e8e604051610dbb92919061368c565b60405180910390206107e5565b612006565b6001600160a01b038616610ecd57606f546001600160a01b0316610eb1575f6001600160a01b03851684825b6040519080825280601f01601f191660200182016040528015610e23576020820181803683370190505b50604051610e31919061369b565b5f6040518083038185875af1925050503d805f8114610e6b576040519150601f19603f3d011682016040523d82523d5f602084013e610e70565b606091505b5050905080610eab576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611117565b606f54610ec8906001600160a01b03168585612198565b611117565b606d546001600160a01b038781169116148015610efb5750606d5463ffffffff888116600160a01b90920416145b15610f12575f6001600160a01b0385168482610df9565b60685463ffffffff610100909104811690881603610f3e57610ec86001600160a01b038716858561220a565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201525f9060380160408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b031680611109575f610fe88386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061228b92505050565b9050610ff5818888612198565b80606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a8388886040516110fb9594939291906136de565b60405180910390a150611114565b611114818787612198565b50505b604080518b815263ffffffff891660208201526001600160a01b0388811682840152861660608201526080810185905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a1505050505050505050505050565b60685460ff16156111a557604051630bc011ff60e21b815260040160405180910390fd5b6111ad61231e565b60685463ffffffff6101009091048116908816036111de576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b0388166112da5788341461122a576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff1694509061125790613584565b80601f016020809104026020016040519081016040528092919081815260200182805461128390613584565b80156112ce5780601f106112a5576101008083540402835291602001916112ce565b820191905f5260205f20905b8154815290600101906020018083116112b157829003601f168201915b505050505091506114c1565b3415611312576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546001600160a01b039081169089160361133757611332888a611f96565b6114c1565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901561139757611386898b611f96565b6020810151815190955093506114b4565b85156113a9576113a9898b8989612377565b6040516370a0823160e01b81523060048201525f906001600160a01b038b16906370a0823190602401602060405180830381865afa1580156113ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114119190613716565b90506114286001600160a01b038b1633308e612716565b6040516370a0823160e01b81523060048201525f906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561146c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114909190613716565b905061149c828261372d565b6068548c9850610100900463ffffffff169650935050505b6114bd89610c79565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e8688605354604051611500989796959493929190613740565b60405180910390a16115266115215f85878f8f8789805190602001206107e5565b612767565b861561153457611534611ee8565b5050505061154160018055565b50505050505050565b606c546001600160a01b0316331461157557604051631736745960e31b815260040160405180910390fd5b610664612868565b60685460ff16156115a157604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff86811661010090920416146115d1576040516302caf51760e11b815260040160405180910390fd5b6115f38c8c8c8c8c610dc860018e8e8e8e8e8e8e604051610dbb92919061368c565b606f545f906001600160a01b03166116a657846001600160a01b031684888a868660405160240161162794939291906137a9565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161165c919061369b565b5f6040518083038185875af1925050503d805f8114611696576040519150601f19603f3d011682016040523d82523d5f602084013e61169b565b606091505b505080915050611757565b606f546116bd906001600160a01b03168686612198565b846001600160a01b0316878985856040516024016116de94939291906137a9565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b17905251611713919061369b565b5f604051808303815f865af19150503d805f811461174c576040519150601f19603f3d011682016040523d82523d5f602084013e611751565b606091505b50909150505b8061178e576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518c815263ffffffff8a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a150505050505050505050505050565b5f54610100900460ff161580801561181757505f54600160ff909116105b806118305750303b15801561183057505f5460ff166001145b6118a75760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805460ff1916600117905580156118c8575f805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8a16027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038781169190910291909117909155606c805473ffffffffffffffffffffffffffffffffffffffff191685831617905586166119a35763ffffffff85161561199e576040517f1a874c1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611abf565b606d805463ffffffff8716600160a01b027fffffffffffffffff0000000000000000000000000000000000000000000000009091166001600160a01b03891617179055606e6119f28382613826565b50611a915f801b6012604051602001611a7d91906060808252600d908201527f5772617070656420457468657200000000000000000000000000000000000000608082015260a0602082018190526004908201527f574554480000000000000000000000000000000000000000000000000000000060c082015260ff91909116604082015260e00190565b60405160208183030381529060405261228b565b606f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03929092169190911790555b611ac76128d8565b8015611541575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b5f81611b218686866109d3565b1495945050505050565b60685460ff1615611b4f57604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b60685463ffffffff610100909104811690871603611bb7576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338989898888605354604051611c0b999897969594939291906138e2565b60405180910390a1611c426115216001606860019054906101000a900463ffffffff16338a8a8a8989604051610dbb92919061368c565b8215610c7157610c71611ee8565b60408051600481526024810182526020810180516001600160e01b03167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611caf919061369b565b5f60405180830381855afa9150503d805f8114611ce7576040519150601f19603f3d011682016040523d82523d5f602084013e611cec565b606091505b509150915081611d31576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525061098b565b61098b8161294a565b60408051600481526024810182526020810180516001600160e01b03167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611d99919061369b565b5f60405180830381855afa9150503d805f8114611dd1576040519150601f19603f3d011682016040523d82523d5f602084013e611dd6565b606091505b509150915081611d31576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525061098b565b60408051600481526024810182526020810180516001600160e01b03167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f91829182916001600160a01b03861691611e79919061369b565b5f60405180830381855afa9150503d805f8114611eb1576040519150601f19603f3d011682016040523d82523d5f602084013e611eb6565b606091505b5091509150818015611ec9575080516020145b611ed457601261098b565b8080602001905181019061098b919061394d565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d611f4961088e565b6040518263ffffffff1660e01b8152600401611f6791815260200190565b5f604051808303815f87803b158015611f7e575f80fd5b505af1158015611f90573d5f803e3d5ffd5b50505050565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152336004820152602481018290526001600160a01b03831690639dc29fac906044015f604051808303815f87803b158015611ff4575f80fd5b505af1158015610c71573d5f803e3d5ffd5b606854604080516020808201879052818301869052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f916501000000000090046001600160a01b03169063257b3632906084016020604051808303815f875af1158015612097573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120bb9190613716565b9050805f036120f5576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f806801000000000000000087161561213957869150612117848a8489611b14565b612134576040516338105f3b60e21b815260040160405180910390fd5b612183565b602087901c612149816001613968565b915087925061216461215c868c866109d3565b8a8389611b14565b612181576040516338105f3b60e21b815260040160405180910390fd5b505b61218d8282612b1a565b505050505050505050565b6040517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152602482018390528416906340c10f19906044015f604051808303815f87803b1580156121f8575f80fd5b505af1158015611541573d5f803e3d5ffd5b6040516001600160a01b0383166024820152604481018290526122869084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612bda565b505050565b5f8060405180611ba00160405280611b668152602001613c36611b669139836040516020016122bb929190613634565b6040516020818303038152906040529050838151602083015ff591506001600160a01b038216612317576040517fbefb092000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092915050565b6002600154036123705760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161189e565b6002600155565b5f6123856004828486613985565b61238e916139ac565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b0319821601612568575f8080808080806123d5896004818d613985565b8101906123e291906139dc565b9650965096509650965096509650336001600160a01b0316876001600160a01b0316146124225760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038616301461244b5760405163750643af60e01b815260040160405180910390fd5b8a8514612484576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169161251b919061369b565b5f604051808303815f865af19150503d805f8114612554576040519150601f19603f3d011682016040523d82523d5f602084013e612559565b606091505b50505050505050505050610752565b6001600160e01b031981166323f2ebc360e21b146125b2576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806125c78a6004818e613985565b8101906125d49190613a2b565b97509750975097509750975097509750336001600160a01b0316886001600160a01b0316146126165760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038716301461263f5760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f16916126c6919061369b565b5f604051808303815f865af19150503d805f81146126ff576040519150601f19603f3d011682016040523d82523d5f602084013e612704565b606091505b50505050505050505050505050505050565b6040516001600160a01b0380851660248301528316604482015260648101829052611f909085907f23b872dd000000000000000000000000000000000000000000000000000000009060840161224f565b80600161277660206002613b89565b612780919061372d565b605354106127ba576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f81546127c9906135e4565b918290555090505f5b6020811015612859578082901c6001166001036128055782603382602081106127fd576127fd6135bc565b015550505050565b60338160208110612818576128186135bc565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092508080612851906135e4565b9150506127d2565b50612286613b94565b60018055565b60685460ff166128a4576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f54610100900460ff166129425760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161189e565b610664612cbe565b6060604082511061296957818060200190518101906106ca9190613ba8565b8151602003612adc575f5b6020811080156129bb5750828181518110612991576129916135bc565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b156129d257806129ca816135e4565b915050612974565b805f03612a1457505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115612a2e57612a2e61311e565b6040519080825280601f01601f191660200182016040528015612a58576020820181803683370190505b5090505f5b82811015612ad457848181518110612a7757612a776135bc565b602001015160f81c60f81b828281518110612a9457612a946135bc565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080612acc816135e4565b915050612a5d565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b6068545f90610100900463ffffffff16158015612b3d575063ffffffff82166001145b15612b4f575063ffffffff8216612b77565b612b6464010000000063ffffffff8416613662565b612b749063ffffffff8516613679565b90505b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003611541576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612c2e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612d289092919063ffffffff16565b8051909150156122865780806020019051810190612c4c9190613c1a565b6122865760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161189e565b5f54610100900460ff166128625760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b606482015260840161189e565b606061098b84845f85855f80866001600160a01b03168587604051612d4d919061369b565b5f6040518083038185875af1925050503d805f8114612d87576040519150601f19603f3d011682016040523d82523d5f602084013e612d8c565b606091505b5091509150612d9d87838387612da8565b979650505050505050565b60608315612e165782515f03612e0f576001600160a01b0385163b612e0f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161189e565b508161098b565b61098b8383815115612e2b5781518083602001fd5b8060405162461bcd60e51b815260040161189e9190612fb8565b803563ffffffff81168114612b15575f80fd5b6001600160a01b0381168114612e6c575f80fd5b50565b5f8060408385031215612e80575f80fd5b612e8983612e45565b91506020830135612e9981612e58565b809150509250929050565b8015158114612e6c575f80fd5b5f8083601f840112612ec1575f80fd5b50813567ffffffffffffffff811115612ed8575f80fd5b602083019150836020828501011115612eef575f80fd5b9250929050565b5f805f805f60808688031215612f0a575f80fd5b612f1386612e45565b94506020860135612f2381612e58565b93506040860135612f3381612ea4565b9250606086013567ffffffffffffffff811115612f4e575f80fd5b612f5a88828901612eb1565b969995985093965092949392505050565b5f5b83811015612f85578181015183820152602001612f6d565b50505f910152565b5f8151808452612fa4816020860160208601612f6b565b601f01601f19169290920160200192915050565b602081525f612fca6020830184612f8d565b9392505050565b5f60208284031215612fe1575f80fd5b8135612fca81612e58565b60ff81168114612e6c575f80fd5b5f805f805f805f60e0888a031215613010575f80fd5b873561301b81612fec565b965061302960208901612e45565b9550604088013561303981612e58565b945061304760608901612e45565b9350608088013561305781612e58565b9699959850939692959460a0840135945060c09093013592915050565b5f805f60608486031215613086575f80fd5b61308f84612e45565b9250602084013561309f81612e58565b915060408401356130af81612e58565b809150509250925092565b5f602082840312156130ca575f80fd5b5035919050565b8061040081018310156106ca575f80fd5b5f805f61044084860312156130f5575f80fd5b8335925061310685602086016130d1565b91506131156104208501612e45565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561315b5761315b61311e565b604052919050565b5f67ffffffffffffffff82111561317c5761317c61311e565b50601f01601f191660200190565b5f61319c61319784613163565b613132565b90508281528383830111156131af575f80fd5b828260208301375f602084830101529392505050565b5f82601f8301126131d4575f80fd5b612fca8383356020850161318a565b5f805f805f60a086880312156131f7575f80fd5b61320086612e45565b9450602086013561321081612e58565b9350604086013567ffffffffffffffff8082111561322c575f80fd5b61323889838a016131c5565b9450606088013591508082111561324d575f80fd5b5061325a888289016131c5565b925050608086013561326b81612fec565b809150509295509295909350565b5f805f805f8060a0878903121561328e575f80fd5b61329787612e45565b955060208701356132a781612e58565b94506040870135935060608701356132be81612ea4565b9250608087013567ffffffffffffffff8111156132d9575f80fd5b6132e589828a01612eb1565b979a9699509497509295939492505050565b5f8060408385031215613308575f80fd5b61331183612e45565b915061331f60208401612e45565b90509250929050565b5f805f805f805f805f805f806109208d8f031215613344575f80fd5b61334e8e8e6130d1565b9b5061335e8e6104008f016130d1565b9a506108008d013599506108208d013598506108408d013597506133856108608e01612e45565b96506133956108808e0135612e58565b6108808d013595506133aa6108a08e01612e45565b94506133ba6108c08e0135612e58565b6108c08d013593506108e08d0135925067ffffffffffffffff6109008e013511156133e3575f80fd5b6133f48e6109008f01358f01612eb1565b81935080925050509295989b509295989b509295989b565b5f805f805f805f60c0888a031215613422575f80fd5b61342b88612e45565b9650602088013561343b81612e58565b955060408801359450606088013561345281612e58565b9350608088013561346281612ea4565b925060a088013567ffffffffffffffff81111561347d575f80fd5b6134898a828b01612eb1565b989b979a50959850939692959293505050565b5f805f805f8060c087890312156134b1575f80fd5b6134ba87612e45565b955060208701356134ca81612e58565b94506134d860408801612e45565b935060608701356134e881612e58565b925060808701356134f881612e58565b915060a087013567ffffffffffffffff811115613513575f80fd5b8701601f81018913613523575f80fd5b6135328982356020840161318a565b9150509295509295509295565b5f805f806104608587031215613553575f80fd5b8435935061356486602087016130d1565b92506135736104208601612e45565b939692955092936104400135925050565b600181811c9082168061359857607f821691505b6020821081036135b657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f600182016135f5576135f56135d0565b5060010190565b606081525f61360e6060830186612f8d565b82810360208401526136208186612f8d565b91505060ff83166040830152949350505050565b5f8351613645818460208801612f6b565b835190830190613659818360208801612f6b565b01949350505050565b80820281158282048414176106ca576106ca6135d0565b808201808211156106ca576106ca6135d0565b818382375f9101908152919050565b5f82516136ac818460208701612f6b565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681525f6001600160a01b03808716602084015280861660408401525060806060830152612d9d6080830184866136b6565b5f60208284031215613726575f80fd5b5051919050565b818103818111156106ca576106ca6135d0565b5f61010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c085015261379082850187612f8d565b925080851660e085015250509998505050505050505050565b6001600160a01b038516815263ffffffff84166020820152606060408201525f6137d76060830184866136b6565b9695505050505050565b601f821115612286575f81815260208120601f850160051c810160208610156138075750805b601f850160051c820191505b81811015610c7157828155600101613813565b815167ffffffffffffffff8111156138405761384061311e565b6138548161384e8454613584565b846137e1565b602080601f831160018114613887575f84156138705750858301515b5f19600386901b1c1916600185901b178555610c71565b5f85815260208120601f198616915b828110156138b557888601518255948401946001909101908401613896565b50858210156138d257878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f61010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c085015261393382850187896136b6565b925080851660e085015250509a9950505050505050505050565b5f6020828403121561395d575f80fd5b8151612fca81612fec565b63ffffffff818116838216019080821115612317576123176135d0565b5f8085851115613993575f80fd5b8386111561399f575f80fd5b5050820193919092039150565b6001600160e01b031981358181169160048510156139d45780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a0312156139f2575f80fd5b87356139fd81612e58565b96506020880135613a0d81612e58565b95506040880135945060608801359350608088013561305781612fec565b5f805f805f805f80610100898b031215613a43575f80fd5b8835613a4e81612e58565b97506020890135613a5e81612e58565b965060408901359550606089013594506080890135613a7c81612ea4565b935060a0890135613a8c81612fec565b979a969950949793969295929450505060c08201359160e0013590565b600181815b80851115613ae357815f1904821115613ac957613ac96135d0565b80851615613ad657918102915b93841c9390800290613aae565b509250929050565b5f82613af9575060016106ca565b81613b0557505f6106ca565b8160018114613b1b5760028114613b2557613b41565b60019150506106ca565b60ff841115613b3657613b366135d0565b50506001821b6106ca565b5060208310610133831016604e8410600b8410161715613b64575081810a6106ca565b613b6e8383613aa9565b805f1904821115613b8157613b816135d0565b029392505050565b5f612fca8383613aeb565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613bb8575f80fd5b815167ffffffffffffffff811115613bce575f80fd5b8201601f81018413613bde575f80fd5b8051613bec61319782613163565b818152856020838501011115613c00575f80fd5b613c11826020830160208601612f6b565b95945050505050565b5f60208284031215613c2a575f80fd5b8151612fca81612ea456fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220b1fe94b20ec78ba8655e62b6a2f33873bb846d19da5ab9523a4def0b2135654564736f6c63430008140033" + }, + { + "contractName": "PolygonZkEVMBridgeV2 proxy", + "balance": "340282366920938463463374607431768211455", + "nonce": "1", + "address": "0xf93FA1eD44BbbE74855f6FaFD8e7c517F8aa3716", + "bytecode": "0x60806040526004361061005d575f3560e01c80635c60da1b116100425780635c60da1b146100a65780638f283970146100e3578063f851a440146101025761006c565b80633659cfe6146100745780634f1ef286146100935761006c565b3661006c5761006a610116565b005b61006a610116565b34801561007f575f80fd5b5061006a61008e366004610854565b610130565b61006a6100a136600461086d565b610178565b3480156100b1575f80fd5b506100ba6101eb565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ee575f80fd5b5061006a6100fd366004610854565b610228565b34801561010d575f80fd5b506100ba610255565b61011e610282565b61012e610129610359565b610362565b565b610138610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101705761016d8160405180602001604052805f8152505f6103bf565b50565b61016d610116565b610180610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101e3576101de8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250600192506103bf915050565b505050565b6101de610116565b5f6101f4610380565b73ffffffffffffffffffffffffffffffffffffffff16330361021d57610218610359565b905090565b610225610116565b90565b610230610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101705761016d816103e9565b5f61025e610380565b73ffffffffffffffffffffffffffffffffffffffff16330361021d57610218610380565b61028a610380565b73ffffffffffffffffffffffffffffffffffffffff16330361012e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b5f61021861044a565b365f80375f80365f845af43d5f803e80801561037c573d5ff35b3d5ffd5b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6103c883610471565b5f825111806103d45750805b156101de576103e383836104bd565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610412610380565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161016d816104e9565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103a3565b61047a816105f5565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606104e28383604051806060016040528060278152602001610977602791396106c0565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811661058c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610350565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b73ffffffffffffffffffffffffffffffffffffffff81163b610699576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610350565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105af565b60605f808573ffffffffffffffffffffffffffffffffffffffff16856040516106e9919061090b565b5f60405180830381855af49150503d805f8114610721576040519150601f19603f3d011682016040523d82523d5f602084013e610726565b606091505b509150915061073786838387610741565b9695505050505050565b606083156107d65782515f036107cf5773ffffffffffffffffffffffffffffffffffffffff85163b6107cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610350565b50816107e0565b6107e083836107e8565b949350505050565b8151156107f85781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103509190610926565b803573ffffffffffffffffffffffffffffffffffffffff8116811461084f575f80fd5b919050565b5f60208284031215610864575f80fd5b6104e28261082c565b5f805f6040848603121561087f575f80fd5b6108888461082c565b9250602084013567ffffffffffffffff808211156108a4575f80fd5b818601915086601f8301126108b7575f80fd5b8135818111156108c5575f80fd5b8760208285010111156108d6575f80fd5b6020830194508093505050509250925092565b5f5b838110156109035781810151838201526020016108eb565b50505f910152565b5f825161091c8184602087016108e9565b9190910192915050565b602081525f82518060208401526109448160408501602087016108e9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202ac98acbfbb3d3ac1b74050e18c4e76db25a3ff2801ec69bf85d0c61414d502b64736f6c63430008140033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000fadb60b5059e31614e02083ff6c021a24c31c891", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000bc9585cb224a8f42ef9c9f0b99c531b450b11886" + } + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 implementation", + "balance": "0", + "nonce": "1", + "address": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9", + "bytecode": "0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c806301fd90441461004e578063257b36321461006a57806333d6247d14610089578063a3c573eb1461009e575b5f80fd5b61005760015481565b6040519081526020015b60405180910390f35b61005761007836600461015e565b5f6020819052908152604090205481565b61009c61009736600461015e565b6100ea565b005b6100c57f000000000000000000000000f93fa1ed44bbbe74855f6fafd8e7c517f8aa371681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610061565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f93fa1ed44bbbe74855f6fafd8e7c517f8aa37161614610159576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b5f6020828403121561016e575f80fd5b503591905056fea2646970667358221220b0e055b3a526de8b3e41419aba10074521f2fc6fc76f05d25e4055bd2429ed5b64736f6c63430008140033" + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 proxy", + "balance": "0", + "nonce": "1", + "address": "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa", + "bytecode": "0x60806040523661001357610011610017565b005b6100115b61001f6101b7565b6001600160a01b0316336001600160a01b0316141561016f5760606001600160e01b031960003516631b2ce7f360e11b8114156100655761005e6101ea565b9150610167565b6001600160e01b0319811663278f794360e11b14156100865761005e610241565b6001600160e01b031981166308f2839760e41b14156100a75761005e610287565b6001600160e01b031981166303e1469160e61b14156100c85761005e6102b8565b6001600160e01b03198116635c60da1b60e01b14156100e95761005e6102f8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b61017761030c565b565b606061019e83836040518060600160405280602781526020016108576027913961031c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101f4610394565b600061020336600481846106a2565b81019061021091906106e8565b905061022d8160405180602001604052806000815250600061039f565b505060408051602081019091526000815290565b606060008061025336600481846106a2565b8101906102609190610719565b915091506102708282600161039f565b604051806020016040528060008152509250505090565b6060610291610394565b60006102a036600481846106a2565b8101906102ad91906106e8565b905061022d816103cb565b60606102c2610394565b60006102cc6101b7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b6060610302610394565b60006102cc610422565b610177610317610422565b610431565b6060600080856001600160a01b0316856040516103399190610807565b600060405180830381855af49150503d8060008114610374576040519150601f19603f3d011682016040523d82523d6000602084013e610379565b606091505b509150915061038a86838387610455565b9695505050505050565b341561017757600080fd5b6103a8836104d3565b6000825111806103b55750805b156103c6576103c48383610179565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103f46101b7565b604080516001600160a01b03928316815291841660208301520160405180910390a161041f81610513565b50565b600061042c6105bc565b905090565b3660008037600080366000845af43d6000803e808015610450573d6000f35b3d6000fd5b606083156104c15782516104ba576001600160a01b0385163b6104ba5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161015e565b50816104cb565b6104cb83836105e4565b949350505050565b6104dc8161060e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105785760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161015e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101db565b8151156105f45781518083602001fd5b8060405162461bcd60e51b815260040161015e9190610823565b6001600160a01b0381163b61067b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161015e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61059b565b600080858511156106b257600080fd5b838611156106bf57600080fd5b5050820193919092039150565b80356001600160a01b03811681146106e357600080fd5b919050565b6000602082840312156106fa57600080fd5b61019e826106cc565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561072c57600080fd5b610735836106cc565b9150602083013567ffffffffffffffff8082111561075257600080fd5b818501915085601f83011261076657600080fd5b81358181111561077857610778610703565b604051601f8201601f19908116603f011681019083821181831017156107a0576107a0610703565b816040528281528860208487010111156107b957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107f65781810151838201526020016107de565b838111156103c45750506000910152565b600082516108198184602087016107db565b9190910192915050565b60208152600082518060208401526108428160408501602087016107db565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122012bb4f564f73959a03513dc74fc3c6e40e8386e6f02c16b78d6db00ce0aa16af64736f6c63430008090033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x000000000000000000000000fadb60b5059e31614e02083ff6c021a24c31c891", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000dc64a140aa3e981100a9beca4e685f962f0cf6c9" + } + }, + { + "contractName": "PolygonZkEVMTimelock", + "balance": "0", + "nonce": "1", + "address": "0x0165878A594ca255338adfa4d48449f69242Eb8F", + "bytecode": "0x6080604052600436106101bd575f3560e01c806364d62353116100f2578063b1c5f42711610092578063d547741f11610062578063d547741f1461063a578063e38335e514610659578063f23a6e611461066c578063f27a0c92146106b0575f80fd5b8063b1c5f4271461058d578063bc197c81146105ac578063c4d252f5146105f0578063d45c44351461060f575f80fd5b80638f61f4f5116100cd5780638f61f4f5146104c557806391d14854146104f8578063a217fddf14610547578063b08e51c01461055a575f80fd5b806364d62353146104685780638065657f146104875780638f2a0bb0146104a6575f80fd5b8063248a9ca31161015d57806331d507501161013857806331d50750146103b357806336568abe146103d25780633a6aae72146103f1578063584b153e14610449575f80fd5b8063248a9ca3146103375780632ab0f529146103655780632f2ff15d14610394575f80fd5b80630d3cf6fc116101985780630d3cf6fc1461025e578063134008d31461029157806313bc9f20146102a4578063150b7a02146102c3575f80fd5b806301d5062a146101c857806301ffc9a7146101e957806307bd02651461021d575f80fd5b366101c457005b5f80fd5b3480156101d3575f80fd5b506101e76101e2366004611bf6565b6106c4565b005b3480156101f4575f80fd5b50610208610203366004611c65565b610757565b60405190151581526020015b60405180910390f35b348015610228575f80fd5b506102507fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610214565b348015610269575f80fd5b506102507f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101e761029f366004611ca4565b6107b2565b3480156102af575f80fd5b506102086102be366004611d0b565b6108a7565b3480156102ce575f80fd5b506103066102dd366004611e28565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610214565b348015610342575f80fd5b50610250610351366004611d0b565b5f9081526020819052604090206001015490565b348015610370575f80fd5b5061020861037f366004611d0b565b5f908152600160208190526040909120541490565b34801561039f575f80fd5b506101e76103ae366004611e8c565b6108cc565b3480156103be575f80fd5b506102086103cd366004611d0b565b6108f5565b3480156103dd575f80fd5b506101e76103ec366004611e8c565b61090d565b3480156103fc575f80fd5b506104247f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b348015610454575f80fd5b50610208610463366004611d0b565b6109c5565b348015610473575f80fd5b506101e7610482366004611d0b565b6109da565b348015610492575f80fd5b506102506104a1366004611ca4565b610aaa565b3480156104b1575f80fd5b506101e76104c0366004611ef7565b610ae8565b3480156104d0575f80fd5b506102507fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610503575f80fd5b50610208610512366004611e8c565b5f9182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b348015610552575f80fd5b506102505f81565b348015610565575f80fd5b506102507ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b348015610598575f80fd5b506102506105a7366004611fa0565b610d18565b3480156105b7575f80fd5b506103066105c63660046120be565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b3480156105fb575f80fd5b506101e761060a366004611d0b565b610d5c565b34801561061a575f80fd5b50610250610629366004611d0b565b5f9081526001602052604090205490565b348015610645575f80fd5b506101e7610654366004611e8c565b610e56565b6101e7610667366004611fa0565b610e7a565b348015610677575f80fd5b50610306610686366004612161565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106bb575f80fd5b50610250611121565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16106ee81611200565b5f6106fd898989898989610aaa565b9050610709818461120d565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a60405161074496959493929190612208565b60405180910390a3505050505050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107ac57506107ac82611359565b92915050565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661082e5761082e81336113ef565b5f61083d888888888888610aaa565b905061084981856114a6565b610855888888886115e2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a60405161088c9493929190612252565b60405180910390a361089d816116e2565b5050505050505050565b5f818152600160205260408120546001811180156108c55750428111155b9392505050565b5f828152602081905260409020600101546108e681611200565b6108f0838361178a565b505050565b5f8181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109c18282611878565b5050565b5f818152600160208190526040822054610906565b333014610a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109ae565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b5f868686868686604051602001610ac696959493929190612208565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b1281611200565b888714610ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b888514610c30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f610c418b8b8b8b8b8b8b8b610d18565b9050610c4d818461120d565b5f5b8a811015610d0a5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610c8c57610c8c612291565b9050602002016020810190610ca191906122be565b8d8d86818110610cb357610cb3612291565b905060200201358c8c87818110610ccc57610ccc612291565b9050602002810190610cde91906122d7565b8c8b604051610cf296959493929190612208565b60405180910390a3610d0381612365565b9050610c4f565b505050505050505050505050565b5f8888888888888888604051602001610d38989796959493929190612447565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610d8681611200565b610d8f826109c5565b610e1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109ae565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610e7081611200565b6108f08383611878565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610ef657610ef681336113ef565b878614610f85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b878414611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f6110258a8a8a8a8a8a8a8a610d18565b905061103181856114a6565b5f5b8981101561110b575f8b8b8381811061104e5761104e612291565b905060200201602081019061106391906122be565b90505f8a8a8481811061107857611078612291565b905060200201359050365f8a8a8681811061109557611095612291565b90506020028101906110a791906122d7565b915091506110b7848484846115e2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58868686866040516110ee9493929190612252565b60405180910390a3505050508061110490612365565b9050611033565b50611115816116e2565b50505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16158015906111ef57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ef919061250c565b156111f957505f90565b5060025490565b61120a81336113ef565b50565b611216826108f5565b156112a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109ae565b6112ab611121565b81101561133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109ae565b611344814261252b565b5f928352600160205260409092209190915550565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107ac57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107ac565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c15761142c8161192d565b61143783602061194c565b604051602001611448929190612560565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109ae916004016125e0565b6114af826108a7565b61153b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b80158061155657505f81815260016020819052604090912054145b6109c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f8473ffffffffffffffffffffffffffffffffffffffff1684848460405161160b929190612630565b5f6040518083038185875af1925050503d805f8114611645576040519150601f19603f3d011682016040523d82523d5f602084013e61164a565b606091505b50509050806116db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109ae565b5050505050565b6116eb816108a7565b611777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b5f90815260016020819052604090912055565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561181a3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107ac73ffffffffffffffffffffffffffffffffffffffff831660145b60605f61195a83600261263f565b61196590600261252b565b67ffffffffffffffff81111561197d5761197d611d22565b6040519080825280601f01601f1916602001820160405280156119a7576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106119dd576119dd612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a3f57611a3f612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f611a7984600261263f565b611a8490600161252b565b90505b6001811115611b20577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611ac557611ac5612291565b1a60f81b828281518110611adb57611adb612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535060049490941c93611b1981612656565b9050611a87565b5083156108c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109ae565b803573ffffffffffffffffffffffffffffffffffffffff81168114611bac575f80fd5b919050565b5f8083601f840112611bc1575f80fd5b50813567ffffffffffffffff811115611bd8575f80fd5b602083019150836020828501011115611bef575f80fd5b9250929050565b5f805f805f805f60c0888a031215611c0c575f80fd5b611c1588611b89565b965060208801359550604088013567ffffffffffffffff811115611c37575f80fd5b611c438a828b01611bb1565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f60208284031215611c75575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108c5575f80fd5b5f805f805f8060a08789031215611cb9575f80fd5b611cc287611b89565b955060208701359450604087013567ffffffffffffffff811115611ce4575f80fd5b611cf089828a01611bb1565b979a9699509760608101359660809091013595509350505050565b5f60208284031215611d1b575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d9657611d96611d22565b604052919050565b5f82601f830112611dad575f80fd5b813567ffffffffffffffff811115611dc757611dc7611d22565b611df860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611d4f565b818152846020838601011115611e0c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215611e3b575f80fd5b611e4485611b89565b9350611e5260208601611b89565b925060408501359150606085013567ffffffffffffffff811115611e74575f80fd5b611e8087828801611d9e565b91505092959194509250565b5f8060408385031215611e9d575f80fd5b82359150611ead60208401611b89565b90509250929050565b5f8083601f840112611ec6575f80fd5b50813567ffffffffffffffff811115611edd575f80fd5b6020830191508360208260051b8501011115611bef575f80fd5b5f805f805f805f805f60c08a8c031215611f0f575f80fd5b893567ffffffffffffffff80821115611f26575f80fd5b611f328d838e01611eb6565b909b50995060208c0135915080821115611f4a575f80fd5b611f568d838e01611eb6565b909950975060408c0135915080821115611f6e575f80fd5b50611f7b8c828d01611eb6565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f805f805f805f8060a0898b031215611fb7575f80fd5b883567ffffffffffffffff80821115611fce575f80fd5b611fda8c838d01611eb6565b909a50985060208b0135915080821115611ff2575f80fd5b611ffe8c838d01611eb6565b909850965060408b0135915080821115612016575f80fd5b506120238b828c01611eb6565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112612050575f80fd5b8135602067ffffffffffffffff82111561206c5761206c611d22565b8160051b61207b828201611d4f565b9283528481018201928281019087851115612094575f80fd5b83870192505b848310156120b35782358252918301919083019061209a565b979650505050505050565b5f805f805f60a086880312156120d2575f80fd5b6120db86611b89565b94506120e960208701611b89565b9350604086013567ffffffffffffffff80821115612105575f80fd5b61211189838a01612041565b94506060880135915080821115612126575f80fd5b61213289838a01612041565b93506080880135915080821115612147575f80fd5b5061215488828901611d9e565b9150509295509295909350565b5f805f805f60a08688031215612175575f80fd5b61217e86611b89565b945061218c60208701611b89565b93506040860135925060608601359150608086013567ffffffffffffffff8111156121b5575f80fd5b61215488828901611d9e565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a060408201525f61223d60a0830186886121c1565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201525f6122876060830184866121c1565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156122ce575f80fd5b6108c582611b89565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261230a575f80fd5b83018035915067ffffffffffffffff821115612324575f80fd5b602001915036819003821315611bef575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361239557612395612338565b5060010190565b8183525f6020808501808196508560051b81019150845f5b8781101561243a57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126123f2575f80fd5b8701858101903567ffffffffffffffff81111561240d575f80fd5b80360382131561241b575f80fd5b6124268682846121c1565b9a87019a95505050908401906001016123b4565b5091979650505050505050565b60a080825281018890525f8960c08301825b8b8110156124945773ffffffffffffffffffffffffffffffffffffffff61247f84611b89565b16825260209283019290910190600101612459565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8911156124cc575f80fd5b8860051b9150818a602083013701828103602090810160408501526124f4908201878961239c565b60608401959095525050608001529695505050505050565b5f6020828403121561251c575f80fd5b815180151581146108c5575f80fd5b808201808211156107ac576107ac612338565b5f5b83811015612558578181015183820152602001612540565b50505f910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f835161259781601785016020880161253e565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516125d481602884016020880161253e565b01602801949350505050565b602081525f82518060208401526125fe81604085016020870161253e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b818382375f9101908152919050565b80820281158282048414176107ac576107ac612338565b5f8161266457612664612338565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220af70dfb7a469eaff210674e43170a7e152bbb10571ef60492e6d753b73b32d1a64736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x0000000000000000000000000000000000000000000000000000000000000e10", + "0xaedcc9e7897c0d335bdc5d92fe3a8b4f23727fe558cd1c19f332b28716a30559": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xf5e61edb9c9cc6bfbae4463e9a2b1dd6ac3b44ddef38f18016e56ba0363910d9": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x64494413541ff93b31aa309254e3fed72a7456e9845988b915b4c7a7ceba8814": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x60b9d94c75b7b3f721925089391e4644cd890cb5e6466f9596dfbd2c54e0b280": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x3412d5605ac6cd444957cedb533e5dacad6378b4bc819ebe3652188a665066d6": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x4b63b79f1e338a49559dcd3193ac9eecc50d0f275d24e97cc8c319e5a31a8bd0": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d706a": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x800d5dfe4bba53eedee06cd4546a27da8de00f12db83f56062976d4493fda899": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc3ad33e20b0c56a223ad5104fff154aa010f8715b9c981fd38fdc60a4d1a52fc": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" + } + }, + { + "accountName": "keyless Deployer", + "balance": "0", + "nonce": "1", + "address": "0x694AB5383a002a4796f95530c14Cf0C25ec3EA03" + }, + { + "accountName": "deployer", + "balance": "100000000000000000000000", + "nonce": "8", + "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ] +} \ No newline at end of file diff --git a/tools/createSovereignGenesis/.gitignore b/tools/createSovereignGenesis/.gitignore new file mode 100644 index 000000000..f13a0cb8b --- /dev/null +++ b/tools/createSovereignGenesis/.gitignore @@ -0,0 +1,4 @@ +genesis-rollupID-*.json +output-rollupID-*.json +genesis-base.json +create-genesis-sovereign-params.json \ No newline at end of file diff --git a/tools/createSovereignGenesis/README.md b/tools/createSovereignGenesis/README.md new file mode 100644 index 000000000..d2d9ed695 --- /dev/null +++ b/tools/createSovereignGenesis/README.md @@ -0,0 +1,61 @@ +# Create sovereign genesis +Script to generate the genesis file for a rollup with `SovereignContracts`. This genesis si aim to be used for chains that are run with vanilla clients. +This script should be run after the rollup is created, so its `rollupID` and the bridge initialization parameters are known. +The script does the following: +- read base genesis file +- deploy sovereign cobtracts +- initialize them + +## Setup +- install packages +``` +npm i +``` + +- Set env variables +```` +cp .env.example .env +```` + +Fill `.env` with your `INFURA_PROJECT_ID` and `ETHERSCAN_API_KEY` + +- Copy configuration files: +``` +cp ./tools/createSovereignGenesis/create-genesis-sovereign-params.json.example ./tools/createSovereignGenesis/create-genesis-sovereign-params.json +``` + +- Copy genesis base file: +``` +cp ./tools/createSovereignGenesis/genesis-base.json.example ./tools/createSovereignGenesis/genesis-base.json +``` + +- Set your parameters + - `rollupManagerAddress`: `polygonRollupManager` smart contract address + - `rollupID`: Rollup identifier. Assigned to a rollup when it is created in the contracts + - `chainID`: ChainID of the rollup + - `gasTokenAddress`: Address of the native gas token of the rollup, zero if ether + - `bridgeManager`: bridge manager address + - `sovereignWETHAddress`: sovereign WETH address + - `sovereignWETHAddressIsNotMintable`: Flag to indicate if the wrapped ETH is not mintable + - `globalExitRootUpdater`: Address of globalExitRootUpdater for sovereign chains + - `globalExitRootRemover`: Address of globalExitRootRemover for sovereign chains + - `setPreMintAccount`: indicates if a preMint accounts going to be added + - `preMintAccount.address`: ethereum address to receive an initial balance + - `preMintAccount.balance`: balance credited to the preminted address + - `setTimelockParameters`: indicates if the timelock parameters are going to be changed + - `timelockParameters.adminAddress`: address that will have all timelocks roles (ADMIN, PROPOSER, CANCELLER, EXECUTOR) + - `timelockParameters.minDelay`: minimum delay set in the timelock smart contract +- Optional parameters + - `format`: choose genesis output format. Supported ones: `geth` + +- Run tool: +``` +npx hardhat run ./tools/createSovereignGenesis/create-sovereign-genesis.ts --network sepolia +``` + +### More Info +- All commands are done from root repository +- The output files are: + - `genesis-rollupID-${rollupID}__${timestamp}`: genesis file + - `output-rollupID-${rollupID}__${timestamp}`: input parameters, gastokenAddress information and network used +- outputs are saved in the tool folder: `./tools/createSovereignGenesis` \ No newline at end of file diff --git a/tools/createSovereignGenesis/create-genesis-sovereign-params.json.example b/tools/createSovereignGenesis/create-genesis-sovereign-params.json.example new file mode 100644 index 000000000..86bbf5bdb --- /dev/null +++ b/tools/createSovereignGenesis/create-genesis-sovereign-params.json.example @@ -0,0 +1,28 @@ +{ + "rollupManagerAddress": "0xe983fD1798689eee00c0Fb77e79B8f372DF41060", + "rollupID": 3, + "chainID": 1001, + "gasTokenAddress": "0x0000000000000000000000000000000000000000", + "bridgeManager": "0x8576158a89648aA88B6036f47B8b74Fc0C2b5c66", + "sovereignWETHAddress": "0x0000000000000000000000000000000000000000", + "sovereignWETHAddressIsNotMintable": false, + "globalExitRootUpdater": "0x8576158a89648aA88B6036f47B8b74Fc0C2b5c66", + "globalExitRootRemover": "0x8576158a89648aA88B6036f47B8b74Fc0C2b5c66", + "setPreMintAccounts": true, + "preMintAccounts": [ + { + "balance": "1000000000000000000", + "address": "0x8576158a89648aA88B6036f47B8b74Fc0C2b5c66" + }, + { + "balance": "1000000000000000000", + "address": "0xb420EAAbFeFA05b39dE520f811325A463E023954" + }, + ], + "setTimelockParameters": true, + "timelockParameters": { + "adminAddress": "0x8576158a89648aA88B6036f47B8b74Fc0C2b5c66", + "minDelay": 3600 + }, + "formatGenesis": "geth" +} \ No newline at end of file diff --git a/tools/createSovereignGenesis/create-sovereign-genesis.ts b/tools/createSovereignGenesis/create-sovereign-genesis.ts new file mode 100644 index 000000000..b243c634b --- /dev/null +++ b/tools/createSovereignGenesis/create-sovereign-genesis.ts @@ -0,0 +1,366 @@ +/* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if */ +/* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved */ +// external dependencies +import path = require("path"); +import fs = require("fs"); + +import * as dotenv from "dotenv"; +dotenv.config({path: path.resolve(__dirname, "../../.env")}); +import {ethers, hardhatArguments} from "hardhat"; + +// internal dependencies +import {MemDB, ZkEVMDB, getPoseidon, smtUtils} from "@0xpolygonhermez/zkevm-commonjs"; +import updateVanillaGenesis from "../../deployment/v2/utils/updateVanillaGenesis"; +import { PolygonRollupManager, PolygonZkEVMBridgeV2} from "../../typechain-types"; +import "../../deployment/helpers/utils"; +import { initializeTimelockStorage } from "../../src/genesis/genesis-helpers"; +import { checkParams } from '../../src/utils'; +import { logger } from "../../src/logger"; +import { formatGenesis, getGitInfo } from "./helpers"; +import { checkBridgeAddress } from "../utils"; + +// script utils +const dateStr = new Date().toISOString(); + +// read files +const genesisBase = require("./genesis-base.json"); +const createGenesisSovereignParams = require("./create-genesis-sovereign-params.json"); + +async function main() { + logger.info('Start create-sovereign-genesis tool'); + + ///////////////////////////// + /// CHECK TOOL PARAMS /// + ///////////////////////////// + logger.info('Check initial parameters'); + + const mandatoryParameters = [ + "rollupManagerAddress", + "rollupID", + "chainID", + "bridgeManager", + "gasTokenAddress", + "sovereignWETHAddress", + "sovereignWETHAddressIsNotMintable", + "globalExitRootUpdater", + "globalExitRootRemover", + "setPreMintAccounts", + "setTimelockParameters", + ]; + + // check global parameters + checkParams(createGenesisSovereignParams, mandatoryParameters); + + // check preMintedAccounts parameters + if (createGenesisSovereignParams.setPreMintAccounts === true) { + if (createGenesisSovereignParams.preMintAccounts === undefined || createGenesisSovereignParams.preMintAccounts === '') { + logger.error('setPreMintAccounts is set to true but missing parameter preMintAccounts'); + process.exit(1); + } + + // Check all preMintAccounts parameters + for (const preMintAccount of createGenesisSovereignParams.preMintAccounts) { + const paramsPreMintAccount = [ + 'balance', + 'address', + ]; + + checkParams(preMintAccount, paramsPreMintAccount); + + if (ethers.isAddress(preMintAccount.address) == false) { + logger.error(`preMintAccount.address ${preMintAccount.address}: not a valid address`); + process.exit(1); + } + } + } + + // check timelock parameters + if (createGenesisSovereignParams.setTimelockParameters === true) { + if (createGenesisSovereignParams.timelockParameters === undefined || createGenesisSovereignParams.timelockParameters === '') { + logger.error('setTimelockParameters is set to true but missing parameter timelockParameters'); + process.exit(1); + } + + const paramsTimelockParameters = [ + 'adminAddress', + 'minDelay', + ]; + + checkParams(createGenesisSovereignParams.timelockParameters, paramsTimelockParameters); + } + + ///////////////////////////////////////////// + /// CHECK SC PARAMS & ON-CHAIN DATA /// + ///////////////////////////////////////////// + logger.info('Check SovereignBridge requirements for its correct initialization'); + + // Load Rollup manager + const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager"); + const rollupManagerContract = PolygonRollupManagerFactory.attach( + createGenesisSovereignParams.rollupManagerAddress + ) as PolygonRollupManager; + + // Checks like in bridge contract + if ( + ethers.isAddress(createGenesisSovereignParams.gasTokenAddress) && + createGenesisSovereignParams.gasTokenAddress !== ethers.ZeroAddress && + createGenesisSovereignParams.sovereignWETHAddress === ethers.ZeroAddress && + createGenesisSovereignParams.sovereignWETHAddressIsNotMintable === true + ) { + throw new Error( + "InvalidSovereignWETHAddressParams: if gasTokenAddress is not 0x0, and sovereignWETHAddress is 0x0, sovereignWETHAddressIsNotMintable must be false" + ); + } + + if ( + createGenesisSovereignParams.gasTokenAddress === ethers.ZeroAddress && + (createGenesisSovereignParams.sovereignWETHAddress !== ethers.ZeroAddress || + createGenesisSovereignParams.sovereignWETHAddressIsNotMintable === true) + ) { + throw new Error( + "InvalidSovereignWETHAddressParams: If gasTokenAddress is 0x0, sovereignWETHAddress must be 0x0 and sovereignWETHAddressIsNotMintable must be false" + ); + } + + // Create output + const outputJson = {} as any; + + // get token information + let gasTokenAddress, gasTokenNetwork, gasTokenMetadata; + + // Get bridge instance + const bridgeFactory = await ethers.getContractFactory("PolygonZkEVMBridgeV2"); + const bridgeContractAddress = await rollupManagerContract.bridgeAddress(); + const rollupBridgeContract = bridgeFactory.attach(bridgeContractAddress) as PolygonZkEVMBridgeV2; + + // check bridge address is the same in genesisBase and on-chain + checkBridgeAddress(genesisBase, bridgeContractAddress); + + if ( + ethers.isAddress(createGenesisSovereignParams.gasTokenAddress) && + createGenesisSovereignParams.gasTokenAddress !== ethers.ZeroAddress + ) { + logger.info('Getting data from the gasTokenAddress'); + // Get token metadata + gasTokenMetadata = await rollupBridgeContract.getTokenMetadata(createGenesisSovereignParams.gasTokenAddress); + outputJson.gasTokenMetadata = gasTokenMetadata; + // If gas token metadata includes `0x124e4f545f56414c49445f454e434f44494e47 (NOT_VALID_ENCODING)` means there is no erc20 token deployed at the selected gas token network + if (gasTokenMetadata.includes("124e4f545f56414c49445f454e434f44494e47")) { + throw new Error( + `Invalid gas token address, no ERC20 token deployed at the selected gas token network ${createGenesisSovereignParams.gasTokenAddress}` + ); + } + const wrappedData = await rollupBridgeContract.wrappedTokenToTokenInfo(createGenesisSovereignParams.gasTokenAddress); + if (wrappedData.originNetwork != 0n) { + // Wrapped token + gasTokenAddress = wrappedData.originTokenAddress; + gasTokenNetwork = wrappedData.originNetwork; + } else { + // Mainnet token + gasTokenAddress = createGenesisSovereignParams.gasTokenAddress; + gasTokenNetwork = 0n; + } + } else { + gasTokenAddress = ethers.ZeroAddress; + gasTokenNetwork = 0; + gasTokenMetadata = "0x"; + } + + + //////////////////////////////////// + /// FINAL GENESIS CREATION /// + //////////////////////////////////// + + // start final genesis creation + let finalGenesis = genesisBase; + + // initialize sovereign bridge parameters + const initializeParams = { + rollupID: createGenesisSovereignParams.rollupID, + gasTokenAddress, + gasTokenNetwork, + polygonRollupManager: ethers.ZeroAddress, + gasTokenMetadata, + bridgeManager: createGenesisSovereignParams.bridgeManager, + sovereignWETHAddress: createGenesisSovereignParams.sovereignWETHAddress, + sovereignWETHAddressIsNotMintable: createGenesisSovereignParams.sovereignWETHAddressIsNotMintable, + globalExitRootUpdater: createGenesisSovereignParams.globalExitRootUpdater, + globalExitRootRemover: createGenesisSovereignParams.globalExitRootRemover, + }; + + logger.info('Update genesis-base to the SovereignContracts'); + finalGenesis = await updateVanillaGenesis(finalGenesis, createGenesisSovereignParams.chainID, initializeParams); + + // Add weth address to deployment output if gas token address is provided and sovereignWETHAddress is not provided + let outWETHAddress; + if ( + gasTokenAddress !== ethers.ZeroAddress && + ethers.isAddress(gasTokenAddress) && + (createGenesisSovereignParams.sovereignWETHAddress === ethers.ZeroAddress || + !ethers.isAddress(createGenesisSovereignParams.sovereignWETHAddress)) + ) { + console.log("Rollup with custom gas token, adding WETH address to deployment output..."); + const wethObject = genesisBase.genesis.find(function (obj: {contractName: string}) { + return obj.contractName == "WETH"; + }); + outWETHAddress = wethObject.address; + } + + // set preMintAccounts + let totalPreMintedAmount = BigInt(0); + if (createGenesisSovereignParams.setPreMintAccounts === true) { + logger.info('Add preMintAccounts'); + + // iterate over all premintAccounts + for (let i = 0; i < createGenesisSovereignParams.preMintAccounts.length; i++) { + const preMintAccount = createGenesisSovereignParams.preMintAccounts[i]; + + // check if preMintAccount is in the current genesis + const preMintAccountExist = finalGenesis.genesis.find(function (obj) { + return obj.address.toLowerCase() === preMintAccount.address.toLowerCase(); + }); + + if (typeof preMintAccountExist !== 'undefined') { + // check if preMintAccount has code + if (preMintAccountExist.bytecode !== undefined) { + logger.error(`preMintAccount ${preMintAccount.address} code is not empty`); + process.exit(1); + } + preMintAccountExist.balance = BigInt(preMintAccount.balance).toString(); + } else { + // add preMintAccount.address & preMintAccount.balance + finalGenesis.genesis.push({ + accountName: `preMintAccount_${i}`, + balance: BigInt(preMintAccount.balance).toString(), + address: preMintAccount.address, + }); + } + + totalPreMintedAmount += BigInt(preMintAccount.balance); + } + } + + // set timelock storage + if (createGenesisSovereignParams.setTimelockParameters === true) { + logger.info('Add timelockParameters'); + const timelockContractInfo = finalGenesis.genesis.find(function (obj) { + return obj.contractName === 'PolygonZkEVMTimelock'; + }); + + const storageTimelock = initializeTimelockStorage( + createGenesisSovereignParams.timelockParameters.minDelay, + createGenesisSovereignParams.timelockParameters.adminAddress, + timelockContractInfo.address, + ); + + timelockContractInfo.storage = storageTimelock; + } + + // regenerate root with the zkEVM root + const poseidon = await getPoseidon(); + const {F} = poseidon; + + const zkEVMDB = await ZkEVMDB.newZkEVM( + new MemDB(F), + poseidon, + [F.zero, F.zero, F.zero, F.zero], + [F.zero, F.zero, F.zero, F.zero], + finalGenesis.genesis, + null, + null, + createGenesisSovereignParams.chainID + ); + + // update genesis root + finalGenesis.root = smtUtils.h4toString(zkEVMDB.getCurrentStateRoot()); + + // extract all [names <--> address] from genesis + const genesisSCNames = finalGenesis.genesis.reduce((acc: any, obj: any) => { + if (obj.bytecode !== undefined) { + acc[obj.contractName] = obj.address; + } + return acc; + }, {}); + + // format genesis + if (createGenesisSovereignParams.formatGenesis !== undefined) { + logger.info(`Formatting genesis output to: ${createGenesisSovereignParams.formatGenesis}`); + finalGenesis = formatGenesis(finalGenesis, createGenesisSovereignParams.formatGenesis); + } + + // get L1 information + logger.info(`Getting L1 information`); + const RollupManagerInfo = {} as any; + + const rollupData = await rollupManagerContract.rollupIDToRollupData(createGenesisSovereignParams.rollupID); + + RollupManagerInfo.bridgeAddress = await rollupManagerContract.bridgeAddress(); + RollupManagerInfo.globalExitRootManager = await rollupManagerContract.globalExitRootManager(); + RollupManagerInfo.pol = await rollupManagerContract.pol(); + RollupManagerInfo.rollupData = { + rollupID: createGenesisSovereignParams.rollupID, + rollupAddress: rollupData[0], + } + + // Populate final output + const gitInfo = getGitInfo(); + outputJson.gitInfo = gitInfo; + outputJson.network = hardhatArguments.network; + outputJson.rollupManagerAddress = createGenesisSovereignParams.rollupManagerAddress; + outputJson.RollupManagerInfo = RollupManagerInfo; + outputJson.gasTokenAddress = gasTokenAddress; + outputJson.gasTokenNetwork = gasTokenNetwork; + outputJson.gasTokenMetadata = gasTokenMetadata; + outputJson.chainID = createGenesisSovereignParams.chainID; + outputJson.bridgeManager = createGenesisSovereignParams.bridgeManager; + outputJson.sovereignWETHAddress = createGenesisSovereignParams.sovereignWETHAddress; + outputJson.sovereignWETHAddressIsNotMintable = createGenesisSovereignParams.sovereignWETHAddressIsNotMintable; + outputJson.globalExitRootUpdater = createGenesisSovereignParams.globalExitRootUpdater; + outputJson.globalExitRootRemover = createGenesisSovereignParams.globalExitRootRemover; + outputJson.genesisSCNames = genesisSCNames; + + if (createGenesisSovereignParams.setPreMintAccounts === true) { + outputJson.preMintAccounts = createGenesisSovereignParams.preMintAccounts; + outputJson.totalPreMintedAmount = totalPreMintedAmount.toString(); + } + + if (createGenesisSovereignParams.setTimelockParameters === true) { + outputJson.timelockParameters = createGenesisSovereignParams.timelockParameters; + } + + if (typeof outWETHAddress !== 'undefined') { + outputJson.WETHAddress = outWETHAddress; + } + + if (createGenesisSovereignParams.formatGenesis !== undefined) { + outputJson.formatGenesis = createGenesisSovereignParams.formatGenesis; + } + + + /////////////////////////////////// + /// WRITE FINAL FILES /// + /////////////////////////////////// + logger.info('Writing final output files'); + + // path output genesis + const pathOutputGenesisJson = createGenesisSovereignParams.outputGenesisPath + ? path.join(__dirname, createGenesisSovereignParams.outputGenesisPath) + : path.join(__dirname, `./genesis-rollupID-${createGenesisSovereignParams.rollupID}__${dateStr}.json`); + + const pathOutputJson = createGenesisSovereignParams.outputPath + ? path.join(__dirname, createGenesisSovereignParams.outputPath) + : path.join(__dirname, `./output-rollupID-${createGenesisSovereignParams.rollupID}__${dateStr}.json`); + + // write files + fs.writeFileSync(pathOutputGenesisJson, JSON.stringify(finalGenesis, null, 1)); + fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); + + logger.info("Output saved at:"); + logger.info(` output genesis: ${pathOutputGenesisJson}`); + logger.info(` output info : ${pathOutputJson}`); +} + +main().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/tools/createSovereignGenesis/genesis-base.json.example b/tools/createSovereignGenesis/genesis-base.json.example new file mode 100644 index 000000000..1004ccbc7 --- /dev/null +++ b/tools/createSovereignGenesis/genesis-base.json.example @@ -0,0 +1,92 @@ +{ + "root": "0xe3a7d8bae497945ba8ddc51c69564f60ad4c1a990b9c7bdbd27f7929bfa8f272", + "genesis": [ + { + "contractName": "PolygonZkEVMDeployer", + "balance": "0", + "nonce": "4", + "address": "0xCB19eDdE626906eB1EE52357a27F62dd519608C2", + "bytecode": "0x60806040526004361061006e575f3560e01c8063715018a61161004c578063715018a6146100e25780638da5cb5b146100f6578063e11ae6cb1461011f578063f2fde38b14610132575f80fd5b80632b79805a146100725780634a94d487146100875780636d07dbf81461009a575b5f80fd5b610085610080366004610908565b610151565b005b6100856100953660046109a2565b6101c2565b3480156100a5575f80fd5b506100b96100b43660046109f5565b610203565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ed575f80fd5b50610085610215565b348015610101575f80fd5b505f5473ffffffffffffffffffffffffffffffffffffffff166100b9565b61008561012d366004610a15565b610228565b34801561013d575f80fd5b5061008561014c366004610a61565b61028e565b61015961034a565b5f6101658585856103ca565b90506101718183610527565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a15050505050565b6101ca61034a565b6101d583838361056a565b506040517f25adb19089b6a549831a273acdf7908cff8b7ee5f551f8d1d37996cf01c5df5b905f90a1505050565b5f61020e8383610598565b9392505050565b61021d61034a565b6102265f6105a4565b565b61023061034a565b5f61023c8484846103ca565b60405173ffffffffffffffffffffffffffffffffffffffff821681529091507fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a150505050565b61029661034a565b73ffffffffffffffffffffffffffffffffffffffff811661033e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610347816105a4565b50565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610226576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610335565b5f83471015610435576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e63650000006044820152606401610335565b81515f0361049f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f6044820152606401610335565b8282516020840186f5905073ffffffffffffffffffffffffffffffffffffffff811661020e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f79000000000000006044820152606401610335565b606061020e83835f6040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250610618565b6060610590848484604051806060016040528060298152602001610b0860299139610618565b949350505050565b5f61020e83833061072d565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060824710156106aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610335565b5f808673ffffffffffffffffffffffffffffffffffffffff1685876040516106d29190610a9c565b5f6040518083038185875af1925050503d805f811461070c576040519150601f19603f3d011682016040523d82523d5f602084013e610711565b606091505b509150915061072287838387610756565b979650505050505050565b5f604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b606083156107eb5782515f036107e45773ffffffffffffffffffffffffffffffffffffffff85163b6107e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610335565b5081610590565b61059083838151156108005781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103359190610ab7565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f830112610870575f80fd5b813567ffffffffffffffff8082111561088b5761088b610834565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156108d1576108d1610834565b816040528381528660208588010111156108e9575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f806080858703121561091b575f80fd5b8435935060208501359250604085013567ffffffffffffffff80821115610940575f80fd5b61094c88838901610861565b93506060870135915080821115610961575f80fd5b5061096e87828801610861565b91505092959194509250565b803573ffffffffffffffffffffffffffffffffffffffff8116811461099d575f80fd5b919050565b5f805f606084860312156109b4575f80fd5b6109bd8461097a565b9250602084013567ffffffffffffffff8111156109d8575f80fd5b6109e486828701610861565b925050604084013590509250925092565b5f8060408385031215610a06575f80fd5b50508035926020909101359150565b5f805f60608486031215610a27575f80fd5b8335925060208401359150604084013567ffffffffffffffff811115610a4b575f80fd5b610a5786828701610861565b9150509250925092565b5f60208284031215610a71575f80fd5b61020e8261097a565b5f5b83811015610a94578181015183820152602001610a7c565b50505f910152565b5f8251610aad818460208701610a7a565b9190910192915050565b602081525f8251806020840152610ad5816040850160208701610a7a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a2646970667358221220330b94dc698c4d290bf55c23f13b473cde6a6bae0030cb902de18af54e35839f64736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000004c1665d6651ecefa59b9b3041951608468b18891" + } + }, + { + "contractName": "ProxyAdmin", + "balance": "0", + "nonce": "1", + "address": "0x0F99738B2Fc14D77308337f3e2596b63aE7BCC4A", + "bytecode": "0x608060405260043610610079575f3560e01c80639623609d1161004c5780639623609d1461012357806399a88ec414610136578063f2fde38b14610155578063f3b7dead14610174575f80fd5b8063204e1c7a1461007d578063715018a6146100c55780637eff275e146100db5780638da5cb5b146100fa575b5f80fd5b348015610088575f80fd5b5061009c6100973660046105e8565b610193565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100d0575f80fd5b506100d9610244565b005b3480156100e6575f80fd5b506100d96100f536600461060a565b610257565b348015610105575f80fd5b505f5473ffffffffffffffffffffffffffffffffffffffff1661009c565b6100d961013136600461066e565b6102e0565b348015610141575f80fd5b506100d961015036600461060a565b610371565b348015610160575f80fd5b506100d961016f3660046105e8565b6103cd565b34801561017f575f80fd5b5061009c61018e3660046105e8565b610489565b5f805f8373ffffffffffffffffffffffffffffffffffffffff166040516101dd907f5c60da1b00000000000000000000000000000000000000000000000000000000815260040190565b5f60405180830381855afa9150503d805f8114610215576040519150601f19603f3d011682016040523d82523d5f602084013e61021a565b606091505b509150915081610228575f80fd5b8080602001905181019061023c919061075b565b949350505050565b61024c6104d3565b6102555f610553565b565b61025f6104d3565b6040517f8f28397000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690638f283970906024015b5f604051808303815f87803b1580156102c6575f80fd5b505af11580156102d8573d5f803e3d5ffd5b505050505050565b6102e86104d3565b6040517f4f1ef28600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841690634f1ef28690349061033e9086908690600401610776565b5f604051808303818588803b158015610355575f80fd5b505af1158015610367573d5f803e3d5ffd5b5050505050505050565b6103796104d3565b6040517f3659cfe600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152831690633659cfe6906024016102af565b6103d56104d3565b73ffffffffffffffffffffffffffffffffffffffff811661047d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b61048681610553565b50565b5f805f8373ffffffffffffffffffffffffffffffffffffffff166040516101dd907ff851a44000000000000000000000000000000000000000000000000000000000815260040190565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610255576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610474565b5f805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff81168114610486575f80fd5b5f602082840312156105f8575f80fd5b8135610603816105c7565b9392505050565b5f806040838503121561061b575f80fd5b8235610626816105c7565b91506020830135610636816105c7565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f805f60608486031215610680575f80fd5b833561068b816105c7565b9250602084013561069b816105c7565b9150604084013567ffffffffffffffff808211156106b7575f80fd5b818601915086601f8301126106ca575f80fd5b8135818111156106dc576106dc610641565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561072257610722610641565b8160405282815289602084870101111561073a575f80fd5b826020860160208301375f6020848301015280955050505050509250925092565b5f6020828403121561076b575f80fd5b8151610603816105c7565b73ffffffffffffffffffffffffffffffffffffffff831681525f602060408184015283518060408501525f5b818110156107be578581018301518582016060015282016107a2565b505f6060828601015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010192505050939250505056fea26469706673582212203083a4ccc2e42eed60bd19037f2efa77ed086dc7a5403f75bebb995dcba2221c64736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x000000000000000000000000bba0935fa93eb23de7990b47f0d96a8f75766d13" + } + }, + { + "contractName": "PolygonZkEVMBridge implementation", + "balance": "0", + "nonce": "1", + "address": "0x5ac4182A1dd41AeEf465E40B82fd326BF66AB82C", + "bytecode": "0x6080604052600436106101db575f3560e01c806383f24403116100fd578063ccaa2d1111610092578063ee25560b11610062578063ee25560b146105a9578063f5efcd79146105d4578063f811bff7146105f3578063fb57083414610612575f80fd5b8063ccaa2d111461053b578063cd5865791461055a578063d02103ca1461056d578063dbc1697614610595575f80fd5b8063bab161bf116100cd578063bab161bf146104b9578063be5831c7146104da578063c00f14ab146104fd578063cc4616321461051c575f80fd5b806383f244031461043d5780638ed7e3f21461045c578063aaa13cc21461047b578063b8b284d01461049a575f80fd5b80633cbc795b116101735780637843298b116101435780637843298b146103c257806379e2cf97146103e157806381b1c174146103f557806383c43a5514610429575f80fd5b80633cbc795b146103385780633e197043146103705780634b2f336d1461038f5780635ca1e165146103ae575f80fd5b806327aef4e8116101ae57806327aef4e81461026d5780632dfdf0b51461028e578063318aee3d146102b15780633c351e1014610319575f80fd5b806315064c96146101df5780632072f6c51461020d57806322e95f2c14610223578063240ff3781461025a575b5f80fd5b3480156101ea575f80fd5b506068546101f89060ff1681565b60405190151581526020015b60405180910390f35b348015610218575f80fd5b50610221610631565b005b34801561022e575f80fd5b5061024261023d366004612fb9565b610666565b6040516001600160a01b039091168152602001610204565b610221610268366004613040565b6106d0565b348015610278575f80fd5b50610281610759565b6040516102049190613102565b348015610299575f80fd5b506102a360535481565b604051908152602001610204565b3480156102bc575f80fd5b506102f56102cb36600461311b565b606b6020525f908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201610204565b348015610324575f80fd5b50606d54610242906001600160a01b031681565b348015610343575f80fd5b50606d5461035b90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610204565b34801561037b575f80fd5b506102a361038a366004613144565b6107e5565b34801561039a575f80fd5b50606f54610242906001600160a01b031681565b3480156103b9575f80fd5b506102a361088e565b3480156103cd575f80fd5b506102426103dc3660046131be565b61096a565b3480156103ec575f80fd5b50610221610993565b348015610400575f80fd5b5061024261040f366004613204565b606a6020525f90815260409020546001600160a01b031681565b348015610434575f80fd5b506102816109b4565b348015610448575f80fd5b506102a361045736600461322c565b6109d3565b348015610467575f80fd5b50606c54610242906001600160a01b031681565b348015610486575f80fd5b5061024261049536600461332d565b610aa8565b3480156104a5575f80fd5b506102216104b43660046133c3565b610be7565b3480156104c4575f80fd5b5060685461035b90610100900463ffffffff1681565b3480156104e5575f80fd5b5060685461035b90600160c81b900463ffffffff1681565b348015610508575f80fd5b5061028161051736600461311b565b610cc2565b348015610527575f80fd5b506101f8610536366004613441565b610d07565b348015610546575f80fd5b50610221610555366004613472565b610d8f565b610221610568366004613556565b6112c0565b348015610578575f80fd5b50606854610242906501000000000090046001600160a01b031681565b3480156105a0575f80fd5b5061022161172c565b3480156105b4575f80fd5b506102a36105c3366004613204565b60696020525f908152604090205481565b3480156105df575f80fd5b506102216105ee366004613472565b61175f565b3480156105fe575f80fd5b5061022161060d3660046135e6565b611a25565b34801561061d575f80fd5b506101f861062c366004613689565b611d40565b606c546001600160a01b0316331461065c57604051631736745960e31b815260040160405180910390fd5b610664611d57565b565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091205f908152606a90915220546001600160a01b03165b92915050565b60685460ff16156106f457604051630bc011ff60e21b815260040160405180910390fd5b341580159061070d5750606f546001600160a01b031615155b15610744576040517f6f625c4000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610752858534868686611db2565b5050505050565b606e8054610766906136ce565b80601f0160208091040260200160405190810160405280929190818152602001828054610792906136ce565b80156107dd5780601f106107b4576101008083540402835291602001916107dd565b820191905f5260205f20905b8154815290600101906020018083116107c057829003601f168201915b505050505081565b6040517fff0000000000000000000000000000000000000000000000000000000000000060f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d82015260518101839052607181018290525f90609101604051602081830303815290604052805190602001209050979650505050505050565b6053545f90819081805b6020811015610961578083901c6001166001036108f557603381602081106108c2576108c2613706565b01546040805160208101929092528101859052606001604051602081830303815290604052805190602001209350610922565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b604080516020810184905290810183905260600160405160208183030381529060405280519060200120915080806109599061372e565b915050610898565b50919392505050565b5f61098b848461097985611e7c565b61098286611f66565b61049587612047565b949350505050565b605354606854600160c81b900463ffffffff16101561066457610664612114565b60405180611ba00160405280611b668152602001613d80611b66913981565b5f83815b6020811015610a9f57600163ffffffff8516821c81169003610a4257848160208110610a0557610a05613706565b602002013582604051602001610a25929190918252602082015260400190565b604051602081830303815290604052805190602001209150610a8d565b81858260208110610a5557610a55613706565b6020020135604051602001610a74929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b80610a978161372e565b9150506109d7565b50949350505050565b6040516001600160e01b031960e087901b1660208201526bffffffffffffffffffffffff19606086901b1660248201525f9081906038016040516020818303038152906040528051906020012090505f60ff60f81b308360405180611ba00160405280611b668152602001613d80611b669139898989604051602001610b3093929190613746565b60408051601f1981840301815290829052610b4e929160200161377e565b60405160208183030381529060405280519060200120604051602001610bc394939291907fff0000000000000000000000000000000000000000000000000000000000000094909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f19018152919052805160209091012098975050505050505050565b60685460ff1615610c0b57604051630bc011ff60e21b815260040160405180910390fd5b606f546001600160a01b0316610c4d576040517fdde3cda700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f54604051632770a7eb60e21b8152336004820152602481018690526001600160a01b0390911690639dc29fac906044015f604051808303815f87803b158015610c96575f80fd5b505af1158015610ca8573d5f803e3d5ffd5b50505050610cba868686868686611db2565b505050505050565b6060610ccd82611e7c565b610cd683611f66565b610cdf84612047565b604051602001610cf193929190613746565b6040516020818303038152906040529050919050565b6068545f908190610100900463ffffffff16158015610d2c575063ffffffff83166001145b15610d3e575063ffffffff8316610d66565b610d5364010000000063ffffffff85166137ac565b610d639063ffffffff86166137c3565b90505b600881901c5f90815260696020526040902054600160ff9092169190911b908116149392505050565b60685460ff1615610db357604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff8681166101009092041614610de3576040516302caf51760e11b815260040160405180910390fd5b610e168c8c8c8c8c610e115f8e8e8e8e8e8e8e604051610e049291906137d6565b60405180910390206107e5565b6121c2565b6001600160a01b038616610f6057606f546001600160a01b0316610efa575f6001600160a01b03851684825b6040519080825280601f01601f191660200182016040528015610e6c576020820181803683370190505b50604051610e7a91906137e5565b5f6040518083038185875af1925050503d805f8114610eb4576040519150601f19603f3d011682016040523d82523d5f602084013e610eb9565b606091505b5050905080610ef4576040517f6747a28800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611256565b606f546040516340c10f1960e01b81526001600160a01b03868116600483015260248201869052909116906340c10f19906044015f604051808303815f87803b158015610f45575f80fd5b505af1158015610f57573d5f803e3d5ffd5b50505050611256565b606d546001600160a01b038781169116148015610f8e5750606d5463ffffffff888116600160a01b90920416145b15610fa5575f6001600160a01b0385168482610e42565b60685463ffffffff610100909104811690881603610fd657610fd16001600160a01b0387168585612354565b611256565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201525f9060380160408051601f1981840301815291815281516020928301205f818152606a9093529120549091506001600160a01b0316806111f5575f6110808386868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506123d592505050565b6040516340c10f1960e01b81526001600160a01b03898116600483015260248201899052919250908216906340c10f19906044015f604051808303815f87803b1580156110cb575f80fd5b505af11580156110dd573d5f803e3d5ffd5b5050505080606a5f8581526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808b63ffffffff1681526020018a6001600160a01b0316815250606b5f836001600160a01b03166001600160a01b031681526020019081526020015f205f820151815f015f6101000a81548163ffffffff021916908363ffffffff1602179055506020820151815f0160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398a8a8388886040516111e7959493929190613828565b60405180910390a150611253565b6040516340c10f1960e01b81526001600160a01b038781166004830152602482018790528216906340c10f19906044015f604051808303815f87803b15801561123c575f80fd5b505af115801561124e573d5f803e3d5ffd5b505050505b50505b604080518b815263ffffffff891660208201526001600160a01b0388811682840152861660608201526080810185905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a1505050505050505050505050565b60685460ff16156112e457604051630bc011ff60e21b815260040160405180910390fd5b6112ec612468565b60685463ffffffff61010090910481169088160361131d576040516302caf51760e11b815260040160405180910390fd5b5f806060876001600160a01b03881661141957883414611369576040517fb89240f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606d54606e80546001600160a01b0383169650600160a01b90920463ffffffff16945090611396906136ce565b80601f01602080910402602001604051908101604052809291908181526020018280546113c2906136ce565b801561140d5780601f106113e45761010080835404028352916020019161140d565b820191905f5260205f20905b8154815290600101906020018083116113f057829003601f168201915b505050505091506116a3565b3415611451576040517f798ee6f100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606f546001600160a01b03908116908916036114c757604051632770a7eb60e21b8152336004820152602481018a90526001600160a01b03891690639dc29fac906044015f604051808303815f87803b1580156114ac575f80fd5b505af11580156114be573d5f803e3d5ffd5b505050506116a3565b6001600160a01b038089165f908152606b602090815260409182902082518084019093525463ffffffff811683526401000000009004909216918101829052901561157957604051632770a7eb60e21b8152336004820152602481018b90526001600160a01b038a1690639dc29fac906044015f604051808303815f87803b158015611551575f80fd5b505af1158015611563573d5f803e3d5ffd5b5050505080602001519450805f01519350611696565b851561158b5761158b898b89896124c1565b6040516370a0823160e01b81523060048201525f906001600160a01b038b16906370a0823190602401602060405180830381865afa1580156115cf573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115f39190613860565b905061160a6001600160a01b038b1633308e612860565b6040516370a0823160e01b81523060048201525f906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561164e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116729190613860565b905061167e8282613877565b6068548c9850610100900463ffffffff169650935050505b61169f89610cc2565b9250505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b5f84868e8e86886053546040516116e298979695949392919061388a565b60405180910390a16117086117035f85878f8f8789805190602001206107e5565b6128b1565b861561171657611716612114565b5050505061172360018055565b50505050505050565b606c546001600160a01b0316331461175757604051631736745960e31b815260040160405180910390fd5b6106646129b2565b60685460ff161561178357604051630bc011ff60e21b815260040160405180910390fd5b60685463ffffffff86811661010090920416146117b3576040516302caf51760e11b815260040160405180910390fd5b6117d58c8c8c8c8c610e1160018e8e8e8e8e8e8e604051610e049291906137d6565b606f545f906001600160a01b031661188857846001600160a01b031684888a868660405160240161180994939291906138f3565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161183e91906137e5565b5f6040518083038185875af1925050503d805f8114611878576040519150601f19603f3d011682016040523d82523d5f602084013e61187d565b606091505b505080915050611983565b606f546040516340c10f1960e01b81526001600160a01b03878116600483015260248201879052909116906340c10f19906044015f604051808303815f87803b1580156118d3575f80fd5b505af11580156118e5573d5f803e3d5ffd5b50505050846001600160a01b03168789858560405160240161190a94939291906138f3565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b1790525161193f91906137e5565b5f604051808303815f865af19150503d805f8114611978576040519150601f19603f3d011682016040523d82523d5f602084013e61197d565b606091505b50909150505b806119ba576040517f37e391c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518c815263ffffffff8a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f1df3f2a973a00d6635911755c260704e95e8a5876997546798770f76396fda4d9181900360a00190a150505050505050505050505050565b5f54610100900460ff1615808015611a4357505f54600160ff909116105b80611a5c5750303b158015611a5c57505f5460ff166001145b611ad35760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084015b60405180910390fd5b5f805460ff191660011790558015611af4575f805461ff0019166101001790555b606880547fffffffffffffff000000000000000000000000000000000000000000000000ff1661010063ffffffff8a16027fffffffffffffff0000000000000000000000000000000000000000ffffffffff1617650100000000006001600160a01b038781169190910291909117909155606c805473ffffffffffffffffffffffffffffffffffffffff19168583161790558616611bcf5763ffffffff851615611bca576040517f1a874c1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ceb565b606d805463ffffffff8716600160a01b027fffffffffffffffff0000000000000000000000000000000000000000000000009091166001600160a01b03891617179055606e611c1e8382613970565b50611cbd5f801b6012604051602001611ca991906060808252600d908201527f5772617070656420457468657200000000000000000000000000000000000000608082015260a0602082018190526004908201527f574554480000000000000000000000000000000000000000000000000000000060c082015260ff91909116604082015260e00190565b6040516020818303038152906040526123d5565b606f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03929092169190911790555b611cf3612a22565b8015611723575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b5f81611d4d8686866109d3565b1495945050505050565b60685460ff1615611d7b57604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a5497905f90a1565b60685463ffffffff610100909104811690871603611de3576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606860019054906101000a900463ffffffff16338989898888605354604051611e3799989796959493929190613a2c565b60405180910390a1611e6e6117036001606860019054906101000a900463ffffffff16338a8a8a8989604051610e049291906137d6565b8215610cba57610cba612114565b60408051600481526024810182526020810180516001600160e01b03167f06fdde030000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611edb91906137e5565b5f60405180830381855afa9150503d805f8114611f13576040519150601f19603f3d011682016040523d82523d5f602084013e611f18565b606091505b509150915081611f5d576040518060400160405280600781526020017f4e4f5f4e414d450000000000000000000000000000000000000000000000000081525061098b565b61098b81612a94565b60408051600481526024810182526020810180516001600160e01b03167f95d89b410000000000000000000000000000000000000000000000000000000017905290516060915f9182916001600160a01b03861691611fc591906137e5565b5f60405180830381855afa9150503d805f8114611ffd576040519150601f19603f3d011682016040523d82523d5f602084013e612002565b606091505b509150915081611f5d576040518060400160405280600981526020017f4e4f5f53594d424f4c000000000000000000000000000000000000000000000081525061098b565b60408051600481526024810182526020810180516001600160e01b03167f313ce5670000000000000000000000000000000000000000000000000000000017905290515f91829182916001600160a01b038616916120a591906137e5565b5f60405180830381855afa9150503d805f81146120dd576040519150601f19603f3d011682016040523d82523d5f602084013e6120e2565b606091505b50915091508180156120f5575080516020145b61210057601261098b565b8080602001905181019061098b9190613a97565b6053546068805463ffffffff909216600160c81b027fffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117908190556001600160a01b0365010000000000909104166333d6247d61217561088e565b6040518263ffffffff1660e01b815260040161219391815260200190565b5f604051808303815f87803b1580156121aa575f80fd5b505af11580156121bc573d5f803e3d5ffd5b50505050565b606854604080516020808201879052818301869052825180830384018152606083019384905280519101207f257b36320000000000000000000000000000000000000000000000000000000090925260648101919091525f916501000000000090046001600160a01b03169063257b3632906084016020604051808303815f875af1158015612253573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122779190613860565b9050805f036122b1576040517e2f6fad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f80680100000000000000008716156122f5578691506122d3848a8489611d40565b6122f0576040516338105f3b60e21b815260040160405180910390fd5b61233f565b602087901c612305816001613ab2565b9150879250612320612318868c866109d3565b8a8389611d40565b61233d576040516338105f3b60e21b815260040160405180910390fd5b505b6123498282612c64565b505050505050505050565b6040516001600160a01b0383166024820152604481018290526123d09084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152612d24565b505050565b5f8060405180611ba00160405280611b668152602001613d80611b6691398360405160200161240592919061377e565b6040516020818303038152906040529050838151602083015ff591506001600160a01b038216612461576040517fbefb092000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5092915050565b6002600154036124ba5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401611aca565b6002600155565b5f6124cf6004828486613acf565b6124d891613af6565b90507f2afa5331000000000000000000000000000000000000000000000000000000006001600160e01b03198216016126b2575f80808080808061251f896004818d613acf565b81019061252c9190613b26565b9650965096509650965096509650336001600160a01b0316876001600160a01b03161461256c5760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03861630146125955760405163750643af60e01b815260040160405180910390fd5b8a85146125ce576040517f03fffc4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b03167fd505accf000000000000000000000000000000000000000000000000000000001790529151918e169161266591906137e5565b5f604051808303815f865af19150503d805f811461269e576040519150601f19603f3d011682016040523d82523d5f602084013e6126a3565b606091505b50505050505050505050610752565b6001600160e01b031981166323f2ebc360e21b146126fc576040517fe282c0ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f808080808080806127118a6004818e613acf565b81019061271e9190613b75565b97509750975097509750975097509750336001600160a01b0316886001600160a01b0316146127605760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b03871630146127895760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f169161281091906137e5565b5f604051808303815f865af19150503d805f8114612849576040519150601f19603f3d011682016040523d82523d5f602084013e61284e565b606091505b50505050505050505050505050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526121bc9085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612399565b8060016128c060206002613cd3565b6128ca9190613877565b60535410612904576040517fef5ccf6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60535f81546129139061372e565b918290555090505f5b60208110156129a3578082901c60011660010361294f57826033826020811061294757612947613706565b015550505050565b6033816020811061296257612962613706565b01546040805160208101929092528101849052606001604051602081830303815290604052805190602001209250808061299b9061372e565b91505061291c565b506123d0613cde565b60018055565b60685460ff166129ee576040517f5386698100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b3905f90a1565b5f54610100900460ff16612a8c5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611aca565b610664612e08565b60606040825110612ab357818060200190518101906106ca9190613cf2565b8151602003612c26575f5b602081108015612b055750828181518110612adb57612adb613706565b01602001517fff000000000000000000000000000000000000000000000000000000000000001615155b15612b1c5780612b148161372e565b915050612abe565b805f03612b5e57505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e4700000000000000000000000000006020820152919050565b5f8167ffffffffffffffff811115612b7857612b78613268565b6040519080825280601f01601f191660200182016040528015612ba2576020820181803683370190505b5090505f5b82811015612c1e57848181518110612bc157612bc1613706565b602001015160f81c60f81b828281518110612bde57612bde613706565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535080612c168161372e565b915050612ba7565b509392505050565b505060408051808201909152601281527f4e4f545f56414c49445f454e434f44494e470000000000000000000000000000602082015290565b919050565b6068545f90610100900463ffffffff16158015612c87575063ffffffff82166001145b15612c99575063ffffffff8216612cc1565b612cae64010000000063ffffffff84166137ac565b612cbe9063ffffffff85166137c3565b90505b600881901c5f8181526069602052604081208054600160ff861690811b91821892839055929091908183169003611723576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f612d78826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612e729092919063ffffffff16565b8051909150156123d05780806020019051810190612d969190613d64565b6123d05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401611aca565b5f54610100900460ff166129ac5760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401611aca565b606061098b84845f85855f80866001600160a01b03168587604051612e9791906137e5565b5f6040518083038185875af1925050503d805f8114612ed1576040519150601f19603f3d011682016040523d82523d5f602084013e612ed6565b606091505b5091509150612ee787838387612ef2565b979650505050505050565b60608315612f605782515f03612f59576001600160a01b0385163b612f595760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401611aca565b508161098b565b61098b8383815115612f755781518083602001fd5b8060405162461bcd60e51b8152600401611aca9190613102565b803563ffffffff81168114612c5f575f80fd5b6001600160a01b0381168114612fb6575f80fd5b50565b5f8060408385031215612fca575f80fd5b612fd383612f8f565b91506020830135612fe381612fa2565b809150509250929050565b8015158114612fb6575f80fd5b5f8083601f84011261300b575f80fd5b50813567ffffffffffffffff811115613022575f80fd5b602083019150836020828501011115613039575f80fd5b9250929050565b5f805f805f60808688031215613054575f80fd5b61305d86612f8f565b9450602086013561306d81612fa2565b9350604086013561307d81612fee565b9250606086013567ffffffffffffffff811115613098575f80fd5b6130a488828901612ffb565b969995985093965092949392505050565b5f5b838110156130cf5781810151838201526020016130b7565b50505f910152565b5f81518084526130ee8160208601602086016130b5565b601f01601f19169290920160200192915050565b602081525f61311460208301846130d7565b9392505050565b5f6020828403121561312b575f80fd5b813561311481612fa2565b60ff81168114612fb6575f80fd5b5f805f805f805f60e0888a03121561315a575f80fd5b873561316581613136565b965061317360208901612f8f565b9550604088013561318381612fa2565b945061319160608901612f8f565b935060808801356131a181612fa2565b9699959850939692959460a0840135945060c09093013592915050565b5f805f606084860312156131d0575f80fd5b6131d984612f8f565b925060208401356131e981612fa2565b915060408401356131f981612fa2565b809150509250925092565b5f60208284031215613214575f80fd5b5035919050565b8061040081018310156106ca575f80fd5b5f805f610440848603121561323f575f80fd5b83359250613250856020860161321b565b915061325f6104208501612f8f565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156132a5576132a5613268565b604052919050565b5f67ffffffffffffffff8211156132c6576132c6613268565b50601f01601f191660200190565b5f6132e66132e1846132ad565b61327c565b90508281528383830111156132f9575f80fd5b828260208301375f602084830101529392505050565b5f82601f83011261331e575f80fd5b613114838335602085016132d4565b5f805f805f60a08688031215613341575f80fd5b61334a86612f8f565b9450602086013561335a81612fa2565b9350604086013567ffffffffffffffff80821115613376575f80fd5b61338289838a0161330f565b94506060880135915080821115613397575f80fd5b506133a48882890161330f565b92505060808601356133b581613136565b809150509295509295909350565b5f805f805f8060a087890312156133d8575f80fd5b6133e187612f8f565b955060208701356133f181612fa2565b945060408701359350606087013561340881612fee565b9250608087013567ffffffffffffffff811115613423575f80fd5b61342f89828a01612ffb565b979a9699509497509295939492505050565b5f8060408385031215613452575f80fd5b61345b83612f8f565b915061346960208401612f8f565b90509250929050565b5f805f805f805f805f805f806109208d8f03121561348e575f80fd5b6134988e8e61321b565b9b506134a88e6104008f0161321b565b9a506108008d013599506108208d013598506108408d013597506134cf6108608e01612f8f565b96506134df6108808e0135612fa2565b6108808d013595506134f46108a08e01612f8f565b94506135046108c08e0135612fa2565b6108c08d013593506108e08d0135925067ffffffffffffffff6109008e0135111561352d575f80fd5b61353e8e6109008f01358f01612ffb565b81935080925050509295989b509295989b509295989b565b5f805f805f805f60c0888a03121561356c575f80fd5b61357588612f8f565b9650602088013561358581612fa2565b955060408801359450606088013561359c81612fa2565b935060808801356135ac81612fee565b925060a088013567ffffffffffffffff8111156135c7575f80fd5b6135d38a828b01612ffb565b989b979a50959850939692959293505050565b5f805f805f8060c087890312156135fb575f80fd5b61360487612f8f565b9550602087013561361481612fa2565b945061362260408801612f8f565b9350606087013561363281612fa2565b9250608087013561364281612fa2565b915060a087013567ffffffffffffffff81111561365d575f80fd5b8701601f8101891361366d575f80fd5b61367c898235602084016132d4565b9150509295509295509295565b5f805f80610460858703121561369d575f80fd5b843593506136ae866020870161321b565b92506136bd6104208601612f8f565b939692955092936104400135925050565b600181811c908216806136e257607f821691505b60208210810361370057634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b5f6001820161373f5761373f61371a565b5060010190565b606081525f61375860608301866130d7565b828103602084015261376a81866130d7565b91505060ff83166040830152949350505050565b5f835161378f8184602088016130b5565b8351908301906137a38183602088016130b5565b01949350505050565b80820281158282048414176106ca576106ca61371a565b808201808211156106ca576106ca61371a565b818382375f9101908152919050565b5f82516137f68184602087016130b5565b9190910192915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff861681525f6001600160a01b03808716602084015280861660408401525060806060830152612ee7608083018486613800565b5f60208284031215613870575f80fd5b5051919050565b818103818111156106ca576106ca61371a565b5f61010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c08501526138da828501876130d7565b925080851660e085015250509998505050505050505050565b6001600160a01b038516815263ffffffff84166020820152606060408201525f613921606083018486613800565b9695505050505050565b601f8211156123d0575f81815260208120601f850160051c810160208610156139515750805b601f850160051c820191505b81811015610cba5782815560010161395d565b815167ffffffffffffffff81111561398a5761398a613268565b61399e8161399884546136ce565b8461392b565b602080601f8311600181146139d1575f84156139ba5750858301515b5f19600386901b1c1916600185901b178555610cba565b5f85815260208120601f198616915b828110156139ff578886015182559484019460019091019084016139e0565b5085821015613a1c57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f61010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c0850152613a7d8285018789613800565b925080851660e085015250509a9950505050505050505050565b5f60208284031215613aa7575f80fd5b815161311481613136565b63ffffffff8181168382160190808211156124615761246161371a565b5f8085851115613add575f80fd5b83861115613ae9575f80fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015613b1e5780818660040360031b1b83161692505b505092915050565b5f805f805f805f60e0888a031215613b3c575f80fd5b8735613b4781612fa2565b96506020880135613b5781612fa2565b9550604088013594506060880135935060808801356131a181613136565b5f805f805f805f80610100898b031215613b8d575f80fd5b8835613b9881612fa2565b97506020890135613ba881612fa2565b965060408901359550606089013594506080890135613bc681612fee565b935060a0890135613bd681613136565b979a969950949793969295929450505060c08201359160e0013590565b600181815b80851115613c2d57815f1904821115613c1357613c1361371a565b80851615613c2057918102915b93841c9390800290613bf8565b509250929050565b5f82613c43575060016106ca565b81613c4f57505f6106ca565b8160018114613c655760028114613c6f57613c8b565b60019150506106ca565b60ff841115613c8057613c8061371a565b50506001821b6106ca565b5060208310610133831016604e8410600b8410161715613cae575081810a6106ca565b613cb88383613bf3565b805f1904821115613ccb57613ccb61371a565b029392505050565b5f6131148383613c35565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613d02575f80fd5b815167ffffffffffffffff811115613d18575f80fd5b8201601f81018413613d28575f80fd5b8051613d366132e1826132ad565b818152856020838501011115613d4a575f80fd5b613d5b8260208301602086016130b5565b95945050505050565b5f60208284031215613d74575f80fd5b815161311481612fee56fe6101006040523480156200001257600080fd5b5060405162001b6638038062001b6683398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e0516116aa620004bc6000396000610237015260008181610307015281816105c001526106a70152600061053a015260008181610379015261050401526116aa6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806370a08231116100d8578063a457c2d71161008c578063d505accf11610066578063d505accf1461039b578063dd62ed3e146103ae578063ffa1ad74146103f457600080fd5b8063a457c2d71461034e578063a9059cbb14610361578063cd0d00961461037457600080fd5b806395d89b41116100bd57806395d89b41146102e75780639dc29fac146102ef578063a3c573eb1461030257600080fd5b806370a08231146102915780637ecebe00146102c757600080fd5b806330adf81f1161012f5780633644e515116101145780633644e51514610261578063395093511461026957806340c10f191461027c57600080fd5b806330adf81f14610209578063313ce5671461023057600080fd5b806318160ddd1161016057806318160ddd146101bd57806320606b70146101cf57806323b872dd146101f657600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b610184610430565b60405161019191906113e4565b60405180910390f35b6101ad6101a8366004611479565b6104c2565b6040519015158152602001610191565b6002545b604051908152602001610191565b6101c17f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b6101ad6102043660046114a3565b6104dc565b6101c17f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610191565b6101c1610500565b6101ad610277366004611479565b61055c565b61028f61028a366004611479565b6105a8565b005b6101c161029f3660046114df565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b6101c16102d53660046114df565b60056020526000908152604090205481565b610184610680565b61028f6102fd366004611479565b61068f565b6103297f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b6101ad61035c366004611479565b61075e565b6101ad61036f366004611479565b61082f565b6101c17f000000000000000000000000000000000000000000000000000000000000000081565b61028f6103a9366004611501565b61083d565b6101c16103bc366004611574565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6101846040518060400160405280600181526020017f310000000000000000000000000000000000000000000000000000000000000081525081565b60606003805461043f906115a7565b80601f016020809104026020016040519081016040528092919081815260200182805461046b906115a7565b80156104b85780601f1061048d576101008083540402835291602001916104b8565b820191906000526020600020905b81548152906001019060200180831161049b57829003601f168201915b5050505050905090565b6000336104d0818585610b73565b60019150505b92915050565b6000336104ea858285610d27565b6104f5858585610dfe565b506001949350505050565b60007f00000000000000000000000000000000000000000000000000000000000000004614610537576105324661106d565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091906104d090829086906105a3908790611629565b610b73565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d4272696467650000000000000000000000000000000060648201526084015b60405180910390fd5b61067c8282611135565b5050565b60606004805461043f906115a7565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610754576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201527f6c79676f6e5a6b45564d427269646765000000000000000000000000000000006064820152608401610669565b61067c8282611228565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919083811015610822576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f0000000000000000000000000000000000000000000000000000006064820152608401610669565b6104f58286868403610b73565b6000336104d0818585610dfe565b834211156108cc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a204578706972656420706560448201527f726d6974000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866109268361163c565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810186905260e0016040516020818303038152906040528051906020012090506000610991610500565b6040517f19010000000000000000000000000000000000000000000000000000000000006020820152602281019190915260428101839052606201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610a55573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590610ad057508973ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b610b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c696420736960448201527f676e6174757265000000000000000000000000000000000000000000000000006064820152608401610669565b610b678a8a8a610b73565b50505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8316610c15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610cb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610df85781811015610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610669565b610df88484848403610b73565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ea1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff8216610f44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610ffa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610df8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611098610430565b8051602091820120604080518082018252600181527f310000000000000000000000000000000000000000000000000000000000000090840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b73ffffffffffffffffffffffffffffffffffffffff82166111b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610669565b80600260008282546111c49190611629565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82166112cb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604090205481811015611381576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610669565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610d1a565b600060208083528351808285015260005b81811015611411578581018301518582016040015282016113f5565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461147457600080fd5b919050565b6000806040838503121561148c57600080fd5b61149583611450565b946020939093013593505050565b6000806000606084860312156114b857600080fd5b6114c184611450565b92506114cf60208501611450565b9150604084013590509250925092565b6000602082840312156114f157600080fd5b6114fa82611450565b9392505050565b600080600080600080600060e0888a03121561151c57600080fd5b61152588611450565b965061153360208901611450565b95506040880135945060608801359350608088013560ff8116811461155757600080fd5b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121561158757600080fd5b61159083611450565b915061159e60208401611450565b90509250929050565b600181811c908216806115bb57607f821691505b6020821081036115f4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156104d6576104d66115fa565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361166d5761166d6115fa565b506001019056fea26469706673582212208d88fee561cff7120d381c345cfc534cef8229a272dc5809d4bbb685ad67141164736f6c63430008110033a2646970667358221220432f6d6b4446edbe1f73c19fd2115454d5c35d8b03b98a74fd46724151d7672264736f6c63430008140033" + }, + { + "contractName": "PolygonZkEVMBridge proxy", + "balance": "340282366920938463463374607431768211455", + "nonce": "1", + "address": "0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe", + "bytecode": "0x60806040526004361061005d575f3560e01c80635c60da1b116100425780635c60da1b146100a65780638f283970146100e3578063f851a440146101025761006c565b80633659cfe6146100745780634f1ef286146100935761006c565b3661006c5761006a610116565b005b61006a610116565b34801561007f575f80fd5b5061006a61008e366004610854565b610130565b61006a6100a136600461086d565b610178565b3480156100b1575f80fd5b506100ba6101eb565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ee575f80fd5b5061006a6100fd366004610854565b610228565b34801561010d575f80fd5b506100ba610255565b61011e610282565b61012e610129610359565b610362565b565b610138610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101705761016d8160405180602001604052805f8152505f6103bf565b50565b61016d610116565b610180610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101e3576101de8383838080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250600192506103bf915050565b505050565b6101de610116565b5f6101f4610380565b73ffffffffffffffffffffffffffffffffffffffff16330361021d57610218610359565b905090565b610225610116565b90565b610230610380565b73ffffffffffffffffffffffffffffffffffffffff1633036101705761016d816103e9565b5f61025e610380565b73ffffffffffffffffffffffffffffffffffffffff16330361021d57610218610380565b61028a610380565b73ffffffffffffffffffffffffffffffffffffffff16330361012e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b5f61021861044a565b365f80375f80365f845af43d5f803e80801561037c573d5ff35b3d5ffd5b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6103c883610471565b5f825111806103d45750805b156101de576103e383836104bd565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f610412610380565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161016d816104e9565b5f7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6103a3565b61047a816105f5565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606104e28383604051806060016040528060278152602001610977602791396106c0565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811661058c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610350565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b73ffffffffffffffffffffffffffffffffffffffff81163b610699576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e7472616374000000000000000000000000000000000000006064820152608401610350565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6105af565b60605f808573ffffffffffffffffffffffffffffffffffffffff16856040516106e9919061090b565b5f60405180830381855af49150503d805f8114610721576040519150601f19603f3d011682016040523d82523d5f602084013e610726565b606091505b509150915061073786838387610741565b9695505050505050565b606083156107d65782515f036107cf5773ffffffffffffffffffffffffffffffffffffffff85163b6107cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610350565b50816107e0565b6107e083836107e8565b949350505050565b8151156107f85781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103509190610926565b803573ffffffffffffffffffffffffffffffffffffffff8116811461084f575f80fd5b919050565b5f60208284031215610864575f80fd5b6104e28261082c565b5f805f6040848603121561087f575f80fd5b6108888461082c565b9250602084013567ffffffffffffffff808211156108a4575f80fd5b818601915086601f8301126108b7575f80fd5b8135818111156108c5575f80fd5b8760208285010111156108d6575f80fd5b6020830194508093505050509250925092565b5f5b838110156109035781810151838201526020016108eb565b50505f910152565b5f825161091c8184602087016108e9565b9190910192915050565b602081525f82518060208401526109448160408501602087016108e9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212202ac98acbfbb3d3ac1b74050e18c4e76db25a3ff2801ec69bf85d0c61414d502b64736f6c63430008140033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0000000000000000000000000f99738b2fc14d77308337f3e2596b63ae7bcc4a", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000005ac4182a1dd41aeef465e40b82fd326bf66ab82c" + } + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 implementation", + "balance": "0", + "nonce": "1", + "address": "0x0200143Fa295EE4dffEF22eE2616c2E008D81688", + "bytecode": "0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c806301fd90441461004e578063257b36321461006a57806333d6247d14610089578063a3c573eb1461009e575b5f80fd5b61005760015481565b6040519081526020015b60405180910390f35b61005761007836600461015e565b5f6020819052908152604090205481565b61009c61009736600461015e565b6100ea565b005b6100c57f0000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610061565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002a3dd3eb832af982ec71669e178424b10dca2ede1614610159576040517fb49365dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600155565b5f6020828403121561016e575f80fd5b503591905056fea26469706673582212205108c6c4f924146b736832a1bdf696e20d900450207b7452462368d150f2c71c64736f6c63430008140033" + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 proxy", + "balance": "0", + "nonce": "1", + "address": "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa", + "bytecode": "0x60806040523661001357610011610017565b005b6100115b61001f6101b7565b6001600160a01b0316336001600160a01b0316141561016f5760606001600160e01b031960003516631b2ce7f360e11b8114156100655761005e6101ea565b9150610167565b6001600160e01b0319811663278f794360e11b14156100865761005e610241565b6001600160e01b031981166308f2839760e41b14156100a75761005e610287565b6001600160e01b031981166303e1469160e61b14156100c85761005e6102b8565b6001600160e01b03198116635c60da1b60e01b14156100e95761005e6102f8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b61017761030c565b565b606061019e83836040518060600160405280602781526020016108576027913961031c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101f4610394565b600061020336600481846106a2565b81019061021091906106e8565b905061022d8160405180602001604052806000815250600061039f565b505060408051602081019091526000815290565b606060008061025336600481846106a2565b8101906102609190610719565b915091506102708282600161039f565b604051806020016040528060008152509250505090565b6060610291610394565b60006102a036600481846106a2565b8101906102ad91906106e8565b905061022d816103cb565b60606102c2610394565b60006102cc6101b7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b6060610302610394565b60006102cc610422565b610177610317610422565b610431565b6060600080856001600160a01b0316856040516103399190610807565b600060405180830381855af49150503d8060008114610374576040519150601f19603f3d011682016040523d82523d6000602084013e610379565b606091505b509150915061038a86838387610455565b9695505050505050565b341561017757600080fd5b6103a8836104d3565b6000825111806103b55750805b156103c6576103c48383610179565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103f46101b7565b604080516001600160a01b03928316815291841660208301520160405180910390a161041f81610513565b50565b600061042c6105bc565b905090565b3660008037600080366000845af43d6000803e808015610450573d6000f35b3d6000fd5b606083156104c15782516104ba576001600160a01b0385163b6104ba5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161015e565b50816104cb565b6104cb83836105e4565b949350505050565b6104dc8161060e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105785760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161015e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101db565b8151156105f45781518083602001fd5b8060405162461bcd60e51b815260040161015e9190610823565b6001600160a01b0381163b61067b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161015e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61059b565b600080858511156106b257600080fd5b838611156106bf57600080fd5b5050820193919092039150565b80356001600160a01b03811681146106e357600080fd5b919050565b6000602082840312156106fa57600080fd5b61019e826106cc565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561072c57600080fd5b610735836106cc565b9150602083013567ffffffffffffffff8082111561075257600080fd5b818501915085601f83011261076657600080fd5b81358181111561077857610778610703565b604051601f8201601f19908116603f011681019083821181831017156107a0576107a0610703565b816040528281528860208487010111156107b957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107f65781810151838201526020016107de565b838111156103c45750506000910152565b600082516108198184602087016107db565b9190910192915050565b60208152600082518060208401526108428160408501602087016107db565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122012bb4f564f73959a03513dc74fc3c6e40e8386e6f02c16b78d6db00ce0aa16af64736f6c63430008090033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0000000000000000000000000f99738b2fc14d77308337f3e2596b63ae7bcc4a", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x0000000000000000000000000200143fa295ee4dffef22ee2616c2e008d81688" + } + }, + { + "contractName": "PolygonZkEVMTimelock", + "balance": "0", + "nonce": "1", + "address": "0xBBa0935Fa93Eb23de7990b47F0D96a8f75766d13", + "bytecode": "0x6080604052600436106101bd575f3560e01c806364d62353116100f2578063b1c5f42711610092578063d547741f11610062578063d547741f1461063a578063e38335e514610659578063f23a6e611461066c578063f27a0c92146106b0575f80fd5b8063b1c5f4271461058d578063bc197c81146105ac578063c4d252f5146105f0578063d45c44351461060f575f80fd5b80638f61f4f5116100cd5780638f61f4f5146104c557806391d14854146104f8578063a217fddf14610547578063b08e51c01461055a575f80fd5b806364d62353146104685780638065657f146104875780638f2a0bb0146104a6575f80fd5b8063248a9ca31161015d57806331d507501161013857806331d50750146103b357806336568abe146103d25780633a6aae72146103f1578063584b153e14610449575f80fd5b8063248a9ca3146103375780632ab0f529146103655780632f2ff15d14610394575f80fd5b80630d3cf6fc116101985780630d3cf6fc1461025e578063134008d31461029157806313bc9f20146102a4578063150b7a02146102c3575f80fd5b806301d5062a146101c857806301ffc9a7146101e957806307bd02651461021d575f80fd5b366101c457005b5f80fd5b3480156101d3575f80fd5b506101e76101e2366004611bf6565b6106c4565b005b3480156101f4575f80fd5b50610208610203366004611c65565b610757565b60405190151581526020015b60405180910390f35b348015610228575f80fd5b506102507fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6381565b604051908152602001610214565b348015610269575f80fd5b506102507f5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca581565b6101e761029f366004611ca4565b6107b2565b3480156102af575f80fd5b506102086102be366004611d0b565b6108a7565b3480156102ce575f80fd5b506103066102dd366004611e28565b7f150b7a0200000000000000000000000000000000000000000000000000000000949350505050565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610214565b348015610342575f80fd5b50610250610351366004611d0b565b5f9081526020819052604090206001015490565b348015610370575f80fd5b5061020861037f366004611d0b565b5f908152600160208190526040909120541490565b34801561039f575f80fd5b506101e76103ae366004611e8c565b6108cc565b3480156103be575f80fd5b506102086103cd366004611d0b565b6108f5565b3480156103dd575f80fd5b506101e76103ec366004611e8c565b61090d565b3480156103fc575f80fd5b506104247f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610214565b348015610454575f80fd5b50610208610463366004611d0b565b6109c5565b348015610473575f80fd5b506101e7610482366004611d0b565b6109da565b348015610492575f80fd5b506102506104a1366004611ca4565b610aaa565b3480156104b1575f80fd5b506101e76104c0366004611ef7565b610ae8565b3480156104d0575f80fd5b506102507fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc181565b348015610503575f80fd5b50610208610512366004611e8c565b5f9182526020828152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b348015610552575f80fd5b506102505f81565b348015610565575f80fd5b506102507ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78381565b348015610598575f80fd5b506102506105a7366004611fa0565b610d18565b3480156105b7575f80fd5b506103066105c63660046120be565b7fbc197c810000000000000000000000000000000000000000000000000000000095945050505050565b3480156105fb575f80fd5b506101e761060a366004611d0b565b610d5c565b34801561061a575f80fd5b50610250610629366004611d0b565b5f9081526001602052604090205490565b348015610645575f80fd5b506101e7610654366004611e8c565b610e56565b6101e7610667366004611fa0565b610e7a565b348015610677575f80fd5b50610306610686366004612161565b7ff23a6e610000000000000000000000000000000000000000000000000000000095945050505050565b3480156106bb575f80fd5b50610250611121565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc16106ee81611200565b5f6106fd898989898989610aaa565b9050610709818461120d565b5f817f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8b8b8b8b8b8a60405161074496959493929190612208565b60405180910390a3505050505050505050565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f4e2312e00000000000000000000000000000000000000000000000000000000014806107ac57506107ac82611359565b92915050565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff1661082e5761082e81336113ef565b5f61083d888888888888610aaa565b905061084981856114a6565b610855888888886115e2565b5f817fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b588a8a8a8a60405161088c9493929190612252565b60405180910390a361089d816116e2565b5050505050505050565b5f818152600160205260408120546001811180156108c55750428111155b9392505050565b5f828152602081905260409020600101546108e681611200565b6108f0838361178a565b505050565b5f8181526001602052604081205481905b1192915050565b73ffffffffffffffffffffffffffffffffffffffff811633146109b7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c66000000000000000000000000000000000060648201526084015b60405180910390fd5b6109c18282611878565b5050565b5f818152600160208190526040822054610906565b333014610a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f54696d656c6f636b436f6e74726f6c6c65723a2063616c6c6572206d7573742060448201527f62652074696d656c6f636b00000000000000000000000000000000000000000060648201526084016109ae565b60025460408051918252602082018390527f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5910160405180910390a1600255565b5f868686868686604051602001610ac696959493929190612208565b6040516020818303038152906040528051906020012090509695505050505050565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc1610b1281611200565b888714610ba1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b888514610c30576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f610c418b8b8b8b8b8b8b8b610d18565b9050610c4d818461120d565b5f5b8a811015610d0a5780827f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca8e8e85818110610c8c57610c8c612291565b9050602002016020810190610ca191906122be565b8d8d86818110610cb357610cb3612291565b905060200201358c8c87818110610ccc57610ccc612291565b9050602002810190610cde91906122d7565b8c8b604051610cf296959493929190612208565b60405180910390a3610d0381612365565b9050610c4f565b505050505050505050505050565b5f8888888888888888604051602001610d38989796959493929190612447565b60405160208183030381529060405280519060200120905098975050505050505050565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f783610d8681611200565b610d8f826109c5565b610e1b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20636160448201527f6e6e6f742062652063616e63656c6c656400000000000000000000000000000060648201526084016109ae565b5f828152600160205260408082208290555183917fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb7091a25050565b5f82815260208190526040902060010154610e7081611200565b6108f08383611878565b5f80527fdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d70696020527f5ba6852781629bcdcd4bdaa6de76d786f1c64b16acdac474e55bebc0ea157951547fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e639060ff16610ef657610ef681336113ef565b878614610f85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b878414611014576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f54696d656c6f636b436f6e74726f6c6c65723a206c656e677468206d69736d6160448201527f746368000000000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f6110258a8a8a8a8a8a8a8a610d18565b905061103181856114a6565b5f5b8981101561110b575f8b8b8381811061104e5761104e612291565b905060200201602081019061106391906122be565b90505f8a8a8481811061107857611078612291565b905060200201359050365f8a8a8681811061109557611095612291565b90506020028101906110a791906122d7565b915091506110b7848484846115e2565b84867fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58868686866040516110ee9493929190612252565b60405180910390a3505050508061110490612365565b9050611033565b50611115816116e2565b50505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16158015906111ef57507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166315064c966040518163ffffffff1660e01b8152600401602060405180830381865afa1580156111cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ef919061250c565b156111f957505f90565b5060025490565b61120a81336113ef565b50565b611216826108f5565b156112a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20616c60448201527f7265616479207363686564756c6564000000000000000000000000000000000060648201526084016109ae565b6112ab611121565b81101561133a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a20696e73756666696369656e7460448201527f2064656c6179000000000000000000000000000000000000000000000000000060648201526084016109ae565b611344814261252b565b5f928352600160205260409092209190915550565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107ac57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107ac565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c15761142c8161192d565b61143783602061194c565b604051602001611448929190612560565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f08c379a00000000000000000000000000000000000000000000000000000000082526109ae916004016125e0565b6114af826108a7565b61153b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b80158061155657505f81815260016020819052604090912054145b6109c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f54696d656c6f636b436f6e74726f6c6c65723a206d697373696e67206465706560448201527f6e64656e6379000000000000000000000000000000000000000000000000000060648201526084016109ae565b5f8473ffffffffffffffffffffffffffffffffffffffff1684848460405161160b929190612630565b5f6040518083038185875af1925050503d805f8114611645576040519150601f19603f3d011682016040523d82523d5f602084013e61164a565b606091505b50509050806116db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f54696d656c6f636b436f6e74726f6c6c65723a20756e6465726c79696e67207460448201527f72616e73616374696f6e2072657665727465640000000000000000000000000060648201526084016109ae565b5050505050565b6116eb816108a7565b611777576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f54696d656c6f636b436f6e74726f6c6c65723a206f7065726174696f6e20697360448201527f206e6f742072656164790000000000000000000000000000000000000000000060648201526084016109ae565b5f90815260016020819052604090912055565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff166109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff85168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561181a3390565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b5f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16156109c1575f8281526020818152604080832073ffffffffffffffffffffffffffffffffffffffff8516808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b60606107ac73ffffffffffffffffffffffffffffffffffffffff831660145b60605f61195a83600261263f565b61196590600261252b565b67ffffffffffffffff81111561197d5761197d611d22565b6040519080825280601f01601f1916602001820160405280156119a7576020820181803683370190505b5090507f3000000000000000000000000000000000000000000000000000000000000000815f815181106119dd576119dd612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053507f780000000000000000000000000000000000000000000000000000000000000081600181518110611a3f57611a3f612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a9053505f611a7984600261263f565b611a8490600161252b565b90505b6001811115611b20577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110611ac557611ac5612291565b1a60f81b828281518110611adb57611adb612291565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191690815f1a90535060049490941c93611b1981612656565b9050611a87565b5083156108c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016109ae565b803573ffffffffffffffffffffffffffffffffffffffff81168114611bac575f80fd5b919050565b5f8083601f840112611bc1575f80fd5b50813567ffffffffffffffff811115611bd8575f80fd5b602083019150836020828501011115611bef575f80fd5b9250929050565b5f805f805f805f60c0888a031215611c0c575f80fd5b611c1588611b89565b965060208801359550604088013567ffffffffffffffff811115611c37575f80fd5b611c438a828b01611bb1565b989b979a50986060810135976080820135975060a09091013595509350505050565b5f60208284031215611c75575f80fd5b81357fffffffff00000000000000000000000000000000000000000000000000000000811681146108c5575f80fd5b5f805f805f8060a08789031215611cb9575f80fd5b611cc287611b89565b955060208701359450604087013567ffffffffffffffff811115611ce4575f80fd5b611cf089828a01611bb1565b979a9699509760608101359660809091013595509350505050565b5f60208284031215611d1b575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611d9657611d96611d22565b604052919050565b5f82601f830112611dad575f80fd5b813567ffffffffffffffff811115611dc757611dc7611d22565b611df860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611d4f565b818152846020838601011115611e0c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f8060808587031215611e3b575f80fd5b611e4485611b89565b9350611e5260208601611b89565b925060408501359150606085013567ffffffffffffffff811115611e74575f80fd5b611e8087828801611d9e565b91505092959194509250565b5f8060408385031215611e9d575f80fd5b82359150611ead60208401611b89565b90509250929050565b5f8083601f840112611ec6575f80fd5b50813567ffffffffffffffff811115611edd575f80fd5b6020830191508360208260051b8501011115611bef575f80fd5b5f805f805f805f805f60c08a8c031215611f0f575f80fd5b893567ffffffffffffffff80821115611f26575f80fd5b611f328d838e01611eb6565b909b50995060208c0135915080821115611f4a575f80fd5b611f568d838e01611eb6565b909950975060408c0135915080821115611f6e575f80fd5b50611f7b8c828d01611eb6565b9a9d999c50979a969997986060880135976080810135975060a0013595509350505050565b5f805f805f805f8060a0898b031215611fb7575f80fd5b883567ffffffffffffffff80821115611fce575f80fd5b611fda8c838d01611eb6565b909a50985060208b0135915080821115611ff2575f80fd5b611ffe8c838d01611eb6565b909850965060408b0135915080821115612016575f80fd5b506120238b828c01611eb6565b999c989b509699959896976060870135966080013595509350505050565b5f82601f830112612050575f80fd5b8135602067ffffffffffffffff82111561206c5761206c611d22565b8160051b61207b828201611d4f565b9283528481018201928281019087851115612094575f80fd5b83870192505b848310156120b35782358252918301919083019061209a565b979650505050505050565b5f805f805f60a086880312156120d2575f80fd5b6120db86611b89565b94506120e960208701611b89565b9350604086013567ffffffffffffffff80821115612105575f80fd5b61211189838a01612041565b94506060880135915080821115612126575f80fd5b61213289838a01612041565b93506080880135915080821115612147575f80fd5b5061215488828901611d9e565b9150509295509295909350565b5f805f805f60a08688031215612175575f80fd5b61217e86611b89565b945061218c60208701611b89565b93506040860135925060608601359150608086013567ffffffffffffffff8111156121b5575f80fd5b61215488828901611d9e565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b73ffffffffffffffffffffffffffffffffffffffff8716815285602082015260a060408201525f61223d60a0830186886121c1565b60608301949094525060800152949350505050565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152606060408201525f6122876060830184866121c1565b9695505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156122ce575f80fd5b6108c582611b89565b5f8083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261230a575f80fd5b83018035915067ffffffffffffffff821115612324575f80fd5b602001915036819003821315611bef575f80fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361239557612395612338565b5060010190565b8183525f6020808501808196508560051b81019150845f5b8781101561243a57828403895281357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030181126123f2575f80fd5b8701858101903567ffffffffffffffff81111561240d575f80fd5b80360382131561241b575f80fd5b6124268682846121c1565b9a87019a95505050908401906001016123b4565b5091979650505050505050565b60a080825281018890525f8960c08301825b8b8110156124945773ffffffffffffffffffffffffffffffffffffffff61247f84611b89565b16825260209283019290910190600101612459565b5083810360208501528881527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8911156124cc575f80fd5b8860051b9150818a602083013701828103602090810160408501526124f4908201878961239c565b60608401959095525050608001529695505050505050565b5f6020828403121561251c575f80fd5b815180151581146108c5575f80fd5b808201808211156107ac576107ac612338565b5f5b83811015612558578181015183820152602001612540565b50505f910152565b7f416363657373436f6e74726f6c3a206163636f756e742000000000000000000081525f835161259781601785016020880161253e565b7f206973206d697373696e6720726f6c652000000000000000000000000000000060179184019182015283516125d481602884016020880161253e565b01602801949350505050565b602081525f82518060208401526125fe81604085016020870161253e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b818382375f9101908152919050565b80820281158282048414176107ac576107ac612338565b5f8161266457612664612338565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea2646970667358221220e28ae7494480ab1c619fd775dc5ff665588c808a910d66178a982c2e7c76a1e664736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x00000000000000000000000000000000000000000000000000000000000d2f00", + "0xb7dfbbca55dd7b7b40403b7620ec95da956b60d562518460548c310b9ba22ee5": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x9fa2d8034dbcb437bee38d61fbd100910e1342ffc07f128aa1b8e6790b7f3f68": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x64494413541ff93b31aa309254e3fed72a7456e9845988b915b4c7a7ceba8814": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x8af78a811b91830f719aeb3279e6ef47b4b581bcf168d6d9015d376b23a240bc": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x3412d5605ac6cd444957cedb533e5dacad6378b4bc819ebe3652188a665066d6": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x9b56cc8bdadd190ab692f9895be09d0edc2ddf428710bebe53c4911e5bc08f42": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xdae2aa361dfd1ca020a396615627d436107c35eff9fe7738a3512819782d706a": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5", + "0x74be529e918f2e5719738045bde8f05a9e9498aace6df8d886a992d046f546a1": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0xc3ad33e20b0c56a223ad5104fff154aa010f8715b9c981fd38fdc60a4d1a52fc": "0x5f58e3a2316349923ce3780f8d587db2d72378aed66a8261c916544fa6846ca5" + } + }, + { + "accountName": "keyless Deployer", + "balance": "0", + "nonce": "1", + "address": "0x9d90066e7478496e2284E54c3548106bb4F90E50" + }, + { + "accountName": "deployer", + "balance": "0", + "nonce": "8", + "address": "0x4c1665d6651ecEfa59B9B3041951608468b18891" + } + ] +} \ No newline at end of file diff --git a/tools/createSovereignGenesis/helpers.ts b/tools/createSovereignGenesis/helpers.ts new file mode 100644 index 000000000..a4d5ba2cc --- /dev/null +++ b/tools/createSovereignGenesis/helpers.ts @@ -0,0 +1,68 @@ +import { execSync } from "child_process"; + +/** + * Format genesis file to a specific format + * @param genesis original legacy genesis file + * @param format Format type + * @returns new genesis format + */ +function formatGenesis(genesis: { genesis: any[]; }, format: any){ + switch (format) { + case "geth": + return _formatGeth(genesis); + default: + throw new Error(`formatGenesis: unknown format: ${format}`); + } +} + +/** + * Format legacy genesis file to geth format + * @param genesis legacy genesis file + * @returns Geth genesis format + */ +function _formatGeth(genesis: { genesis: any[]; }) { + return genesis.genesis.reduce((acc, contract) => { + acc[contract.address] = {}; + + if (contract.bytecode !== undefined) { + acc[contract.address].code = contract.bytecode; + } + + if (contract.storage !== undefined) { + acc[contract.address].storage = contract.storage; + } + + if (contract.balance !== undefined) { + acc[contract.address].balance = `0x${BigInt(contract.balance).toString(16)}`; + } + + if (contract.nonce !== undefined) { + acc[contract.address].nonce = `0x${BigInt(contract.nonce).toString(16)}`; + } + + return acc; + }, {}); +} + +/** + * Retrieves the current Git commit hash and repository URL + * @returns An object containing the commit hash and repository URL, or null if an error occurs + */ +function getGitInfo(): { commit: string; repo: string } | null { + try { + // Get the latest commit hash + const commit = execSync("git rev-parse HEAD").toString().trim(); + + // Get the repository URL + const repo = execSync("git config --get remote.origin.url").toString().trim(); + + return { commit, repo }; + } catch (error) { + throw new Error(`getGitInfo: ${error}`); + } +} + +module.exports = { + formatGenesis, + getGitInfo, +}; \ No newline at end of file diff --git a/tools/createSovereignGenesisWithHardhat/.gitignore b/tools/createSovereignGenesisWithHardhat/.gitignore new file mode 100644 index 000000000..90d5f2d60 --- /dev/null +++ b/tools/createSovereignGenesisWithHardhat/.gitignore @@ -0,0 +1 @@ +genesis-sovereign_hardhat.json \ No newline at end of file diff --git a/tools/createSovereignGenesisWithHardhat/createSovereignGenesisWithHardhat.ts b/tools/createSovereignGenesisWithHardhat/createSovereignGenesisWithHardhat.ts new file mode 100644 index 000000000..ec8ca6eca --- /dev/null +++ b/tools/createSovereignGenesisWithHardhat/createSovereignGenesisWithHardhat.ts @@ -0,0 +1,506 @@ +/* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if, import/no-dynamic-require */ +/* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved, no-restricted-syntax */ +import {expect} from "chai"; +import path = require("path"); +import fs = require("fs"); + +import * as dotenv from "dotenv"; +dotenv.config({path: path.resolve(__dirname, "../../.env")}); +import yargs from "yargs/yargs"; +import {getStorageAt, setCode, setNonce, setStorageAt} from "@nomicfoundation/hardhat-network-helpers"; + +const argv = yargs(process.argv.slice(2)) + .options({ + test: {type: "boolean", default: false}, + input: {type: "string", default: "../../deployment/v2/deploy_parameters.json"}, + out: {type: "string", default: "./genesis-sovereign_hardhat.json"}, + }) + .parse() as any; + +const DEFAULT_MNEMONIC = "test test test test test test test test test test test junk"; +process.env.HARDHAT_NETWORK = "hardhat"; +process.env.MNEMONIC = argv.test ? DEFAULT_MNEMONIC : process.env.MNEMONIC; +import {ethers, upgrades} from "hardhat"; +import {MemDB, ZkEVMDB, getPoseidon, smtUtils} from "@0xpolygonhermez/zkevm-commonjs"; + +import {deployPolygonZkEVMDeployer, create2Deployment} from "../../deployment/helpers/deployment-helpers"; +import {ProxyAdmin, BridgeL2SovereignChain} from "../../typechain-types"; +import {Addressable} from "ethers"; + +import "../../deployment/helpers/utils"; + +const deployParameters = require(argv.input); +const pathOutputJson = path.join(__dirname, argv.out); +const genesisSovereign = require("../../docker/deploymentOutput/genesis_sovereign.json"); +const createRollupParameters = require("../../deployment/v2/create_rollup_parameters.json"); +const createRollupOutput = require("../../docker/deploymentOutput/create_rollup_output.json"); +/* + * bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; + * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + */ +const _ADMIN_SLOT = "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103" as any; +const _IMPLEMENTATION_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" as any; + +const zkevmAddressL2 = ethers.ZeroAddress; +const globalExitRootL2ProxyAddress = "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa"; + +async function main() { + // Constant variables + const balanceBridge = BigInt("0xffffffffffffffffffffffffffffffff"); // 128 bits + const genesis = []; + + // load deploy parameters + const mandatoryDeploymentParameters = [ + "timelockAdminAddress", + "minDelayTimelock", + "salt", + "initialZkEVMDeployerOwner", + ]; + + for (const parameterName of mandatoryDeploymentParameters) { + if (deployParameters[parameterName] === undefined || deployParameters[parameterName] === "") { + throw new Error(`Missing parameter: ${parameterName}`); + } + } + let {timelockAdminAddress, minDelayTimelock, salt, initialZkEVMDeployerOwner} = deployParameters; + + // Load deployer + await ethers.provider.send("hardhat_impersonateAccount", [initialZkEVMDeployerOwner]); + await ethers.provider.send("hardhat_setBalance", [initialZkEVMDeployerOwner, "0xffffffffffffffff"]); // 18 ethers aprox + const deployer = await ethers.getSigner(initialZkEVMDeployerOwner); + + // Deploy PolygonZkEVMDeployer if is not deployed already + const [zkEVMDeployerContract, keylessDeployer] = await deployPolygonZkEVMDeployer( + initialZkEVMDeployerOwner, + deployer + ); + const finalDeployer = deployer.address; + const finalKeylessDeployer = keylessDeployer; + const finalZkEVMDeployerAddress = zkEVMDeployerContract.target; + /* + * Deploy Bridge + * Deploy admin --> implementation --> proxy + */ + + // Deploy proxy admin: + const proxyAdminFactory = await ethers.getContractFactory( + "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol:ProxyAdmin", + deployer + ); + const deployTransactionAdmin = (await proxyAdminFactory.getDeployTransaction()).data; + const dataCallAdmin = proxyAdminFactory.interface.encodeFunctionData("transferOwnership", [deployer.address]); + const [proxyAdminAddress] = await create2Deployment( + zkEVMDeployerContract, + salt, + deployTransactionAdmin, + dataCallAdmin, + deployer, + null + ); + + // Deploy implementation SovereignBridge + const bridgeContractName = "BridgeL2SovereignChain"; + const sovereignBridgeFactory = await ethers.getContractFactory(bridgeContractName, deployer); + const deployTransactionBridge = (await sovereignBridgeFactory.getDeployTransaction()).data; + // Mandatory to override the gasLimit since the estimation with create are mess up D: + const overrideGasLimit = BigInt(5500000); + let [bridgeImplementationAddress] = await create2Deployment( + zkEVMDeployerContract, + salt, + deployTransactionBridge, + null, + deployer, + overrideGasLimit + ); + // Get genesis params + const sovereignGenesisBridgeProxy = genesisSovereign.genesis.find(function (obj) { + return obj.contractName == "BridgeL2SovereignChain proxy"; + }); + const sovereignGenesisBridgeImplementation = genesisSovereign.genesis.find(function (obj) { + return obj.contractName == "BridgeL2SovereignChain"; + }); + const sovereignGenesisGERProxy = genesisSovereign.genesis.find(function (obj) { + return obj.contractName == "GlobalExitRootManagerL2SovereignChain proxy"; + }); + const sovereignGenesisGERImplementation = genesisSovereign.genesis.find(function (obj) { + return obj.contractName == "GlobalExitRootManagerL2SovereignChain"; + }); + const sovereignDeployerAccount = genesisSovereign.genesis.find(function (obj) { + return obj.accountName == "deployer"; + }); + // Change bridge implementation address to the one set at original sovereign genesis. The address is different because they have different initcode + const deployedBytecode = await ethers.provider.getCode(bridgeImplementationAddress as string); + bridgeImplementationAddress = sovereignGenesisBridgeImplementation.address; + await setCode(bridgeImplementationAddress as string, deployedBytecode); + await setNonce(bridgeImplementationAddress as string, 1); + /* + * deploy bridge proxy and initialize + */ + const transparentProxyFactory = await ethers.getContractFactory( + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy", + deployer + ); + const initializeEmptyDataProxy = "0x"; + const deployTransactionProxy = ( + await transparentProxyFactory.getDeployTransaction( + bridgeImplementationAddress as string, // must have bytecode + proxyAdminAddress as string, + initializeEmptyDataProxy + ) + ).data; + + let [proxyBridgeAddress] = await create2Deployment( + zkEVMDeployerContract, + salt, + deployTransactionProxy, + null, + deployer, + null + ); + // Import OZ manifest the deployed contracts, its enough to import just the proxy, the rest are imported automatically ( admin/impl) + await upgrades.forceImport(proxyBridgeAddress as string, sovereignBridgeFactory, "transparent" as any); + /* + *Deployment Global exit root manager implementation, proxy and initialize + */ + const {sovereignParams} = createRollupParameters; + const globalExitRootContractName = "GlobalExitRootManagerL2SovereignChain"; + const GERSovereignFactory = await ethers.getContractFactory(globalExitRootContractName, deployer); + const proxyGERContract = await upgrades.deployProxy(GERSovereignFactory, [sovereignParams.globalExitRootUpdater], { + constructorArgs: [proxyBridgeAddress as string], + unsafeAllow: ["constructor", "state-variable-immutable"], + }); + const proxyGERAddress = proxyGERContract.target; + let GERImplementationAddress = await upgrades.erc1967.getImplementationAddress(proxyGERAddress as string); + + expect(sovereignGenesisGERImplementation.bytecode).to.be.equal( + await ethers.provider.getCode(GERImplementationAddress) + ); + // Compare storage + for (const key in sovereignGenesisGERProxy.storage) { + expect(sovereignGenesisGERProxy.storage[key]).to.be.equal(await getStorageAt(proxyGERAddress as string, key)); + } + // Assert admin address + expect(await upgrades.erc1967.getAdminAddress(proxyGERAddress as string)).to.be.equal(proxyAdminAddress); + expect(await upgrades.erc1967.getAdminAddress(proxyBridgeAddress as string)).to.be.equal(proxyAdminAddress); + + const timelockContractFactory = await ethers.getContractFactory("PolygonZkEVMTimelock", deployer); + const timelockContract = await timelockContractFactory.deploy( + minDelayTimelock, + [timelockAdminAddress], + [timelockAdminAddress], + timelockAdminAddress, + zkevmAddressL2 + ); + await timelockContract.waitForDeployment(); + const finalTimelockContractAddress = timelockContract.target; + + // Transfer ownership of the proxyAdmin to timelock + const proxyAdminInstance = proxyAdminFactory.attach(proxyAdminAddress as string) as ProxyAdmin; + await (await proxyAdminInstance.connect(deployer).transferOwnership(finalTimelockContractAddress as string)).wait(); + + // Initialize bridge + const sovereignBridgeContract = sovereignBridgeFactory.attach( + bridgeImplementationAddress as string + ) as BridgeL2SovereignChain; + let gasTokenMetadata, gasTokenAddress, gasTokenNetwork; + if ( + createRollupParameters.gasTokenAddress && + createRollupParameters.gasTokenAddress !== "" && + createRollupParameters.gasTokenAddress !== ethers.ZeroAddress + ) { + gasTokenMetadata = createRollupOutput.gasTokenMetadata + gasTokenAddress = createRollupParameters.gasTokenAddress; + const wrappedData = await sovereignBridgeContract.wrappedTokenToTokenInfo( + createRollupParameters.gasTokenAddress + ); + if (wrappedData.originNetwork != 0n) { + // Wrapped token + gasTokenAddress = wrappedData.originTokenAddress; + gasTokenNetwork = wrappedData.originNetwork; + } else { + // Mainnet token + gasTokenAddress = createRollupParameters.gasTokenAddress; + gasTokenNetwork = 0; + } + } else { + gasTokenMetadata = "0x"; + gasTokenAddress = ethers.ZeroAddress; + gasTokenNetwork = 0; + } + const initializeData = sovereignBridgeFactory.interface.encodeFunctionData( + "initialize(uint32,address,uint32,address,address,bytes,address,address,bool)", + [ + 1, //rollupID + gasTokenAddress, + gasTokenNetwork, //gasTokenNetwork, + sovereignGenesisGERProxy.address, // GlobalExitRootManager address + ethers.ZeroAddress, //polygonRollupManager + gasTokenMetadata, //gasTokenMetadata, + sovereignParams.bridgeManager, + sovereignParams.sovereignWETHAddress, + sovereignParams.sovereignWETHAddressIsNotMintable, + ] + ); + await deployer.sendTransaction({ + to: proxyBridgeAddress as string, + data: initializeData, + }); + // Check bytecode + expect(sovereignGenesisBridgeProxy.bytecode).to.be.equal( + await ethers.provider.getCode(proxyBridgeAddress as string) + ); + // Check storage + for (const key in sovereignGenesisBridgeProxy.storage) { + const as = await getStorageAt(proxyBridgeAddress as string, key) + expect(sovereignGenesisBridgeProxy.storage[key]).to.be.equal( + await getStorageAt(proxyBridgeAddress as string, key) + ); + } + + // Check weth + if ( + createRollupParameters.gasTokenAddress && + createRollupParameters.gasTokenAddress !== "" && + createRollupParameters.gasTokenAddress !== ethers.ZeroAddress + ) { + const sovereignBridgeProxyContract = sovereignBridgeFactory.attach( + proxyBridgeAddress as string + ) as BridgeL2SovereignChain; + // Add deployed weth + const wethAddress = await sovereignBridgeProxyContract.WETHToken() + const wethBytecode = await ethers.provider.getCode(wethAddress) + const sovereignWETH = genesisSovereign.genesis.find(function (obj) { + return obj.contractName == "WETH"; + }); + // Check storage + for (const key in sovereignWETH.storage) { + expect(sovereignWETH.storage[key]).to.be.equal(await getStorageAt(wethAddress, key)); + } + genesis.push({ + contractName: "WETH", + balance: "0", + nonce: "1", + address: wethAddress, + bytecode: wethBytecode, + storage: sovereignWETH.storage, + }); + } + + // ZKEVMDeployer + const zkEVMDeployerInfo = await getAddressInfo(zkEVMDeployerContract.target); + genesis.push({ + contractName: "PolygonZkEVMDeployer", + balance: "0", + nonce: zkEVMDeployerInfo.nonce.toString(), + address: finalZkEVMDeployerAddress, + bytecode: zkEVMDeployerInfo.bytecode, + storage: zkEVMDeployerInfo.storage, + }); + + // Proxy Admin + const proxyAdminInfo = await getAddressInfo(proxyAdminAddress as string); + genesis.push({ + contractName: "ProxyAdmin", + balance: "0", + nonce: proxyAdminInfo.nonce.toString(), + address: proxyAdminAddress, + bytecode: proxyAdminInfo.bytecode, + storage: proxyAdminInfo.storage, + }); + + // Bridge implementation + const bridgeImplementationInfo = await getAddressInfo(bridgeImplementationAddress as string); + genesis.push({ + contractName: `${bridgeContractName}`, + balance: "0", + nonce: bridgeImplementationInfo.nonce.toString(), + address: bridgeImplementationAddress, + bytecode: bridgeImplementationInfo.bytecode, + // storage: bridgeImplementationInfo.storage, implementation do not have storage + }); + + // Bridge proxy + const bridgeProxyInfo = await getAddressInfo(proxyBridgeAddress as string); + // Override admin and implementation slots: + bridgeProxyInfo.storage[_ADMIN_SLOT] = ethers.zeroPadValue(proxyAdminAddress as string, 32); + bridgeProxyInfo.storage[_IMPLEMENTATION_SLOT] = ethers.zeroPadValue(bridgeImplementationAddress as string, 32); + + genesis.push({ + contractName: `${bridgeContractName} proxy`, + balance: balanceBridge, + nonce: bridgeProxyInfo.nonce.toString(), + address: proxyBridgeAddress, + bytecode: bridgeProxyInfo.bytecode, + storage: sovereignGenesisBridgeProxy.storage, // Already checked is the same + }); + + // GER Manager implementation + const implGlobalExitRootL2Info = await getAddressInfo(GERImplementationAddress as string); + + genesis.push({ + contractName: `${globalExitRootContractName}`, + balance: "0", + nonce: implGlobalExitRootL2Info.nonce.toString(), + address: GERImplementationAddress, + bytecode: implGlobalExitRootL2Info.bytecode, + }); + + // polygonZkEVMGlobalExitRootL2 proxy + const proxyGlobalExitRootL2Info = await getAddressInfo(proxyGERAddress as string); + + proxyGlobalExitRootL2Info.storage[_ADMIN_SLOT] = ethers.zeroPadValue(proxyAdminAddress as string, 32); + proxyGlobalExitRootL2Info.storage[_IMPLEMENTATION_SLOT] = ethers.zeroPadValue( + GERImplementationAddress as string, + 32 + ); + + genesis.push({ + contractName: `${globalExitRootContractName} proxy`, + balance: "0", + nonce: proxyGlobalExitRootL2Info.nonce.toString(), + address: globalExitRootL2ProxyAddress, + bytecode: proxyGlobalExitRootL2Info.bytecode, + storage: proxyGlobalExitRootL2Info.storage, + }); + + // Timelock + const timelockInfo = await getAddressInfo(timelockContract.target); + + /* + * Since roles are used, most storage is written in pseudoRandom storage slots + * bytes32 public constant TIMELOCK_ADMIN_ROLE = keccak256("TIMELOCK_ADMIN_ROLE"); + * bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE"); + * bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); + * bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE"); + */ + const timelockRolesHash = [ + ethers.id("TIMELOCK_ADMIN_ROLE"), + ethers.id("PROPOSER_ROLE"), + ethers.id("EXECUTOR_ROLE"), + ethers.id("CANCELLER_ROLE"), + ]; + + for (let i = 0; i < timelockRolesHash.length; i++) { + const rolesMappingStoragePositionStruct = 0; + const storagePosition = ethers.solidityPackedKeccak256( + ["uint256", "uint256"], + [timelockRolesHash[i], rolesMappingStoragePositionStruct] + ); + + // check timelock address manager, and timelock address itself + const addressArray = [timelockAdminAddress, timelockContract.target]; + for (let j = 0; j < addressArray.length; j++) { + const storagePositionRole = ethers.solidityPackedKeccak256( + ["uint256", "uint256"], + [addressArray[j], storagePosition] + ); + const valueRole = await ethers.provider.getStorage(timelockContract.target, storagePositionRole); + if (valueRole !== "0x0000000000000000000000000000000000000000000000000000000000000000") { + timelockInfo.storage[storagePositionRole] = valueRole; + } + } + const roleAdminSlot = ethers.zeroPadValue(ethers.toQuantity(ethers.toBigInt(storagePosition) + 1n), 32); + const valueRoleAdminSlot = await ethers.provider.getStorage(timelockContract.target, roleAdminSlot); + if (valueRoleAdminSlot !== "0x0000000000000000000000000000000000000000000000000000000000000000") { + timelockInfo.storage[roleAdminSlot] = valueRoleAdminSlot; + } + } + + genesis.push({ + contractName: "PolygonZkEVMTimelock", + balance: "0", + nonce: timelockInfo.nonce.toString(), + address: finalTimelockContractAddress, + bytecode: timelockInfo.bytecode, + storage: timelockInfo.storage, + }); + + // Put nonces on deployers + + // Keyless deployer + genesis.push({ + accountName: "keyless Deployer", + balance: "0", + nonce: "1", + address: finalKeylessDeployer, + }); + + // deployer + const deployerInfo = await getAddressInfo(deployer.address); + genesis.push({ + accountName: "deployer", + balance: "0", + nonce: sovereignDeployerAccount.nonce, // We get nonce from sovereign genesis because the number of transactions is different. With hardhat proxies are deployed and initialized in same transaction + address: finalDeployer, + }); + + if (deployParameters.test) { + // Add tester account with ether + genesis[genesis.length - 1].balance = "100000000000000000000000"; + } + + // calculate root + const poseidon = await getPoseidon(); + const {F} = poseidon; + const db = new MemDB(F); + const genesisRoot = [F.zero, F.zero, F.zero, F.zero]; + const accHashInput = [F.zero, F.zero, F.zero, F.zero]; + const defaultChainId = 1000; + + const zkEVMDB = await ZkEVMDB.newZkEVM( + db, + poseidon, + genesisRoot, + accHashInput, + genesis, + null, + null, + defaultChainId + ); + // Check roots match + const SR = smtUtils.h4toString(zkEVMDB.stateRoot) + //expect(SR).to.be.equal(genesisSovereign.root); + fs.writeFileSync( + pathOutputJson, + JSON.stringify( + { + root: SR, + genesis: genesis, + }, + null, + 1 + ) + ); +} + +main().catch((e) => { + console.error(e); + process.exit(1); +}); + +async function getAddressInfo(address: string | Addressable) { + const nonce = await ethers.provider.getTransactionCount(address); + const bytecode = await ethers.provider.getCode(address); + + const storage = {} as { + [key: string]: number | string; + }; + + for (let i = 0; i < 200; i++) { + const storageValue = await ethers.provider.getStorage(address, i); + if (storageValue !== "0x0000000000000000000000000000000000000000000000000000000000000000") { + storage[ethers.toBeHex(i, 32)] = storageValue; + } + } + + const valueAdminSlot = await ethers.provider.getStorage(address, _ADMIN_SLOT); + if (valueAdminSlot !== "0x0000000000000000000000000000000000000000000000000000000000000000") { + storage[_ADMIN_SLOT] = valueAdminSlot; + } + const valueImplementationSlot = await ethers.provider.getStorage(address, _IMPLEMENTATION_SLOT); + if (valueImplementationSlot !== "0x0000000000000000000000000000000000000000000000000000000000000000") { + storage[_IMPLEMENTATION_SLOT] = valueImplementationSlot; + } + + return {nonce, bytecode, storage}; +} diff --git a/tools/deployClaimCompressor/.gitignore b/tools/deployClaimCompressor/.gitignore new file mode 100644 index 000000000..a87ce8439 --- /dev/null +++ b/tools/deployClaimCompressor/.gitignore @@ -0,0 +1,2 @@ +deploy_claimCompressor.json +deploy_claim_compressor_output.json diff --git a/tools/deployClaimCompressor/README.md b/tools/deployClaimCompressor/README.md new file mode 100644 index 000000000..f65c3b2f8 --- /dev/null +++ b/tools/deployClaimCompressor/README.md @@ -0,0 +1,57 @@ +# Deploy ClaimCompressor +Script to deploy `ClaimCompressor.sol` + +## Install +``` +npm i +``` + +## Setup +- Config file `deploy_claimCompressor.json`: + - `bridgeAddress`: polygonZkEVMBridgeAddress + - `networkId` + - `deployerPvtKey`: private key deployer + - First option will load `deployerPvtKey`. Otherwise, `process.env.MNEMONIC` will be loaded from the `.env` file + - `maxFeePerGas`: set custom gas + - `maxPriorityFeePerGas`: set custom gas + - `multiplierGas`: set custom gas +- A network should be selected when running the script + - examples: `--network sepolia` or `--network mainnet` + - This uses variables set in `hardhat.config.ts` + - Which uses some environment variables that should be set in `.env` +## Usage + +- Copy configuration file: +``` +cp ./tools/deployClaimCompressor/deploy_claimCompressor.json.example ./tools/deployClaimCompressor/deploy_claimCompressor.json +``` + +- Set your parameters +- Run tool: +``` +npx hardhat run ./tools/deployClaimCompressor/deployClaimCompressor.ts --network +``` + +- Output: + - `deploy_claim_compressor_output.json`: + ``` + { + "deployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "ClaimCompressorContract": "0x851356ae760d987E095750cCeb3bC6014560891C" + } + ``` + - logs: + ``` + deploying with: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 + ####################### + + Claim Compressor deployed to: 0xc5a5C42992dECbae36851359345FE25997F5C42d + ####################### + + you can verify the contract address with: + npx hardhat verify --constructor-args upgrade/arguments.js 0xc5a5C42992dECbae36851359345FE25997F5C42d --network localhost + + Copy the following constructor arguments on: upgrade/arguments.js + [ '0x124fBB77374f2D2F0d716973C23Ab06AE49ACde5', 0 ] + + ``` \ No newline at end of file diff --git a/tools/deployClaimCompressor/deployClaimCompressor.ts b/tools/deployClaimCompressor/deployClaimCompressor.ts index d182df6f4..2e643109a 100644 --- a/tools/deployClaimCompressor/deployClaimCompressor.ts +++ b/tools/deployClaimCompressor/deployClaimCompressor.ts @@ -8,6 +8,7 @@ import * as dotenv from "dotenv"; dotenv.config({path: path.resolve(__dirname, "../../../.env")}); import {ethers, network, upgrades} from "hardhat"; const deployParameters = require("./deploy_claimCompressor.json"); +const pathOutput = path.resolve(__dirname, "./deploy_claim_compressor_output.json") async function main() { // Load provider @@ -68,6 +69,11 @@ async function main() { const ClaimCompressorContract = await ClaimCompressor.deploy(bridgeAddress, networkId); await ClaimCompressorContract.waitForDeployment(); + const outputJson = { + deployer: deployer.address, + ClaimCompressorContract: ClaimCompressorContract.target + }; + console.log("#######################\n"); console.log("Claim Compressor deployed to:", ClaimCompressorContract.target); console.log("#######################\n"); @@ -77,6 +83,8 @@ async function main() { `npx hardhat verify --constructor-args upgrade/arguments.js ${ClaimCompressorContract.target} --network ${process.env.HARDHAT_NETWORK}\n` ); console.log("Copy the following constructor arguments on: upgrade/arguments.js \n", [bridgeAddress, networkId]); + + await fs.writeFileSync(pathOutput, JSON.stringify(outputJson, null, 1)); } main().catch((e) => { diff --git a/tools/deployPolygonDataCommittee/.gitignore b/tools/deployPolygonDataCommittee/.gitignore new file mode 100644 index 000000000..cb5432160 --- /dev/null +++ b/tools/deployPolygonDataCommittee/.gitignore @@ -0,0 +1,2 @@ +deploy_dataCommittee_output.json +deploy_dataCommittee_parameters.json \ No newline at end of file diff --git a/tools/deployPolygonDataCommittee/README.md b/tools/deployPolygonDataCommittee/README.md new file mode 100644 index 000000000..84c9c7806 --- /dev/null +++ b/tools/deployPolygonDataCommittee/README.md @@ -0,0 +1,56 @@ +# Deploy PolygonDataCommittee +Script to deploy `PolygonDataCommittee.sol` + +## Install +``` +npm i +``` + +## Setup +- Config file `deploy_dataCommittee_parameters.json`: + - `admin` + - `networkId` + - `deployerPvtKey`: private key deployer + - First option will load `deployerPvtKey`. Otherwise, `process.env.MNEMONIC` will be loaded from the `.env` file + - `maxFeePerGas`: set custom gas + - `maxPriorityFeePerGas`: set custom gas + - `multiplierGas`: set custom gas +- A network should be selected when running the script + - examples: `--network sepolia` or `--network mainnet` + - This uses variables set in `hardhat.config.ts` + - Which uses some environment variables that should be set in `.env` + +## Usage +> All commands are done from root repository. + +- Copy configuration file: +``` +cp ./tools/deployPolygonDataCommittee/deploy_dataCommittee_parameters.json.example ./tools/deployPolygonDataCommittee/deploy_dataCommittee_parameters.json +``` + +- Run tool: +``` +npx hardhat run ./tools/deployPolygonDataCommittee/deployPolygonDataCommittee.ts --network +``` + +- Output: + - `deploy_dataCommittee_output.json`: + ``` + { + "polygonDataCommitteeAddress": "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690", + "proxyAdmin": "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E" + } + ``` + - logs: + ``` + deploying with: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 + + ####################### + + PolygonDataCommittee deployed to: 0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690 + ####################### + + polygonDataCommittee deployed to: 0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690 + you can verify the new polygonDataCommittee address with: + npx hardhat verify 0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690 --network localhost + ``` diff --git a/tools/deployPolygonDataCommittee/deploy_dataCommittee_parameters.example b/tools/deployPolygonDataCommittee/deploy_dataCommittee_parameters.json.example similarity index 100% rename from tools/deployPolygonDataCommittee/deploy_dataCommittee_parameters.example rename to tools/deployPolygonDataCommittee/deploy_dataCommittee_parameters.json.example diff --git a/tools/deployVerifier/.gitignore b/tools/deployVerifier/.gitignore index f5c01b984..f7240c80c 100644 --- a/tools/deployVerifier/.gitignore +++ b/tools/deployVerifier/.gitignore @@ -1 +1,2 @@ +deploy_verifier_output.json deploy_verifier_parameters.json \ No newline at end of file diff --git a/tools/deployVerifier/README.md b/tools/deployVerifier/README.md index 1d2864d90..142da8e86 100644 --- a/tools/deployVerifier/README.md +++ b/tools/deployVerifier/README.md @@ -7,7 +7,7 @@ npm i ``` ## Setup -- Config file +- Config file `deploy_verifier_parameters.json`: - `realVerifier`: select between a real or a mock verifer - `forkID`: Select fork to verifier to be deployed (if a real verfifier is selected) - `deployerPvtKey`: private key deployer @@ -26,11 +26,33 @@ npm i - Copy configuration file: ``` -cp ./tools/deployVerifier/deploy_verifier_parameters.example ./tools/deployVerifier/deploy_verifier_parameters.json +cp ./tools/deployVerifier/deploy_verifier_parameters.json.example ./tools/deployVerifier/deploy_verifier_parameters.json ``` - - Set your parameters - Run tool: ``` -npx hardhat run ./tools/deployVerifier/deployVerifier.ts --network sepolia +npx hardhat run ./tools/deployVerifier/deployVerifier.ts --network ``` +- Output: + - `deploy_verifier_output.json`: + ``` + { + "deployer": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "verifier": "FflonkVerifier_12", + "verifierContract": "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8" + } + ``` + - logs: + ``` + --> Deploying with: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 + --> Deploying verifier: FflonkVerifier_12 + + ####################### + Verifier deployed to: 0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9 + ####################### + + ####################### + you can verify the new verifierContract address with the following command: + npx hardhat verify 0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9 --network localhost + ####################### + ``` \ No newline at end of file diff --git a/tools/deployVerifier/deployVerifier.ts b/tools/deployVerifier/deployVerifier.ts index 89a1eecbb..ae2845fa4 100644 --- a/tools/deployVerifier/deployVerifier.ts +++ b/tools/deployVerifier/deployVerifier.ts @@ -8,6 +8,7 @@ import * as dotenv from "dotenv"; dotenv.config({path: path.resolve(__dirname, "../../../.env")}); import {ethers, upgrades} from "hardhat"; const deployParameters = require("./deploy_verifier_parameters.json"); +const pathOutput = path.resolve(__dirname, "./deploy_verifier_output.json") async function main() { // Load provider @@ -74,6 +75,11 @@ async function main() { verifierContract = await VerifierRollupHelperFactory.deploy(); await verifierContract.waitForDeployment(); } + const outputJson = { + deployer: deployer.address, + verifier: verifierName, + verifierContract: verifierContract.target + }; // print contract address deployed console.log("\n#######################"); console.log("Verifier deployed to:", verifierContract.target); @@ -83,6 +89,8 @@ async function main() { console.log("you can verify the new verifierContract address with the following command:"); console.log(`npx hardhat verify ${verifierContract.target} --network ${process.env.HARDHAT_NETWORK}`); console.log("#######################"); + + await fs.writeFileSync(pathOutput, JSON.stringify(outputJson, null, 1)); } main().catch((e) => { diff --git a/tools/deployVerifier/deploy_verifier_parameters.example b/tools/deployVerifier/deploy_verifier_parameters.json.example similarity index 100% rename from tools/deployVerifier/deploy_verifier_parameters.example rename to tools/deployVerifier/deploy_verifier_parameters.json.example diff --git a/tools/getRollupData/.gitignore b/tools/getRollupData/.gitignore new file mode 100644 index 000000000..655a5338e --- /dev/null +++ b/tools/getRollupData/.gitignore @@ -0,0 +1,3 @@ +create_rollup_output* +deploy_output.json +rollupDataParams.json \ No newline at end of file diff --git a/tools/getRollupData/README.md b/tools/getRollupData/README.md new file mode 100644 index 000000000..503ca59e1 --- /dev/null +++ b/tools/getRollupData/README.md @@ -0,0 +1,54 @@ +# Get Rollup Data +Script to get rollup data. + +## Install +``` +npm i +``` + +## Setup +- Config file `rollupDataParams.json`: + - `polygonRollupManagerAddress`: rollupManager address, + - `rollupID`: rollup ID +- A network should be selected when running the script + - examples: `--network sepolia` or `--network mainnet` + - This uses variables set in `hardhat.config.ts` + - Which uses some environment variables that should be set in `.env` +> All paths are from root repository + +## Usage +> All commands are done from root repository. + +- Copy configuration file: +``` +cp tools/getRollupData/rollupDataParams.json.example tools/getRollupData/rollupDataParams.json +``` +- Set your parameters +- Run tool: +``` +npx hardhat run tools/getRollupData/getRollupData.ts --network +``` +- Output: + - `deploy_output.json`: + ``` + { + "polygonRollupManagerAddress": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0", + "polygonZkEVMBridgeAddress": "0x124fBB77374f2D2F0d716973C23Ab06AE49ACde5", + "polygonZkEVMGlobalExitRootAddress": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788", + "polTokenAddress": "0x5FbDB2315678afecb367f032d93F642f64180aa3", + "deploymentRollupManagerBlockNumber": 43 + } + ``` + + - `create_rollup_output_X`: + ``` + { + "genesis": "0x0000000000000000000000000000000000000000000000000000000000000000", + "createRollupBlockNumber": 49, + "rollupAddress": "0x1F708C24a0D3A740cD47cC0444E9480899f3dA7D", + "consensusContract": "0.0.1", + "rollupID": 1, + "L2ChainID": 1001, + "gasTokenAddress": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" + } + ``` diff --git a/tools/getRollupData/getRollupData.ts b/tools/getRollupData/getRollupData.ts index b5b66d72e..de43c7f4e 100644 --- a/tools/getRollupData/getRollupData.ts +++ b/tools/getRollupData/getRollupData.ts @@ -10,7 +10,7 @@ import {ethers, upgrades} from "hardhat"; const getRollupParams = require("./rollupDataParams.json"); import {PolygonRollupManager} from "../../typechain-types"; const pathOutputJson = path.join(__dirname, "./deploy_output.json"); -const pathCreateRollupOutput = path.join(__dirname, "./create_rollup_output.json"); +const pathCreateRollupOutput = path.join(__dirname, "./create_rollup_output"); async function main() { const RollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager"); @@ -22,16 +22,22 @@ async function main() { const polygonZkEVMBridgeAddress = await rollupManager.bridgeAddress(); const polygonZkEVMGlobalExitRootAddress = await rollupManager.globalExitRootManager(); const polTokenAddress = await rollupManager.pol(); - - // FIlter first rollup ID ( the one on migration) + // Filter first rollup ID ( the one on migration) const filterInit = rollupManager.filters.Initialized(undefined); const eventsInit = await rollupManager.queryFilter(filterInit, 0, "latest"); const deploymentRollupManagerBlockNumber = eventsInit[0].blockNumber; - + // Filter first initialization (deployment) const filter = rollupManager.filters.AddExistingRollup(1); const eventsAddRollup = await rollupManager.queryFilter(filter, 0, "latest"); - const upgradeToULxLyBlockNumber = eventsAddRollup[0].blockNumber; + let upgradeToULxLyBlockNumber; + if (eventsAddRollup.length > 0) { + upgradeToULxLyBlockNumber = eventsAddRollup[0].blockNumber; + } else { + console.log("No event AddExistingRollup"); + upgradeToULxLyBlockNumber = eventsInit[0].blockNumber; + } + const deployOutput = { polygonRollupManagerAddress: rollupManager.target, polygonZkEVMBridgeAddress, @@ -50,31 +56,36 @@ async function main() { undefined ); const eventsCreateNewRollup = await rollupManager.queryFilter(filter2, 0, "latest"); - const {rollupID, rollupAddress, chainID, gasTokenAddress, rollupTypeID} = eventsCreateNewRollup[0].args; - const filter3 = rollupManager.filters.AddNewRollupType( - rollupTypeID, - undefined, - undefined, - undefined, - undefined, - undefined - ); + if (eventsCreateNewRollup.length > 0) { + const {rollupID, rollupAddress, chainID, gasTokenAddress, rollupTypeID} = eventsCreateNewRollup[0].args; + + const filter3 = rollupManager.filters.AddNewRollupType( + rollupTypeID, + undefined, + undefined, + undefined, + undefined, + undefined + ); - const eventsAddRollupType = await rollupManager.queryFilter(filter3, 0, "latest"); - const {forkID, genesis, description} = eventsAddRollupType[0].args; + const eventsAddRollupType = await rollupManager.queryFilter(filter3, 0, "latest"); + const {forkID, genesis, description} = eventsAddRollupType[0].args; - // Add the first batch of the created rollup - const outputCreateRollup = {} as any; - outputCreateRollup.genesis = genesis; - outputCreateRollup.createRollupBlockNumber = eventsCreateNewRollup[0].blockNumber; - outputCreateRollup.rollupAddress = rollupAddress; - outputCreateRollup.consensusContract = description; - outputCreateRollup.rollupID = Number(rollupID); - outputCreateRollup.L2ChainID = Number(chainID); - outputCreateRollup.gasTokenAddress = gasTokenAddress; + // Add the first batch of the created rollup + const outputCreateRollup = {} as any; + outputCreateRollup.genesis = genesis; + outputCreateRollup.createRollupBlockNumber = eventsCreateNewRollup[0].blockNumber; + outputCreateRollup.rollupAddress = rollupAddress; + outputCreateRollup.consensusContract = description; + outputCreateRollup.rollupID = Number(rollupID); + outputCreateRollup.L2ChainID = Number(chainID); + outputCreateRollup.gasTokenAddress = gasTokenAddress; - fs.writeFileSync(pathCreateRollupOutput, JSON.stringify(outputCreateRollup, null, 1)); + await fs.writeFileSync(`${pathCreateRollupOutput}_${rollupID}.json`, JSON.stringify(outputCreateRollup, null, 1)); + } else { + console.log("No event CreateNewRollup"); + } } main().catch((e) => { diff --git a/tools/grantRole/.gitignore b/tools/grantRole/.gitignore new file mode 100644 index 000000000..dc198fa26 --- /dev/null +++ b/tools/grantRole/.gitignore @@ -0,0 +1,2 @@ +grantRoleOutput.json +grantRole.json \ No newline at end of file diff --git a/tools/grantRole/README.md b/tools/grantRole/README.md new file mode 100644 index 000000000..c264af6fe --- /dev/null +++ b/tools/grantRole/README.md @@ -0,0 +1,62 @@ +# Get Rollup Data +Script to get rollup data. + +## Install +``` +npm i +``` + +## Setup +- Config file `grantRole.json`: + - `roleName`: + - "ADD_ROLLUP_TYPE_ROLE" + - "OBSOLETE_ROLLUP_TYPE_ROLE" + - "CREATE_ROLLUP_ROLE" + - "ADD_EXISTING_ROLLUP_ROLE" + - "UPDATE_ROLLUP_ROLE" + - "TRUSTED_AGGREGATOR_ROLE" + - "TRUSTED_AGGREGATOR_ROLE_ADMIN" + - "SET_FEE_ROLE" + - "STOP_EMERGENCY_ROLE" + - "EMERGENCY_COUNCIL_ROLE" + - `accountToGrantRole`: address to grantRole + - `polygonRollupManagerAddress`: rollupManager address + - `timelockDelay`: timelock delay +- A network should be selected when running the script + - examples: `--network sepolia` or `--network mainnet` + - This uses variables set in `hardhat.config.ts` + - Which uses some environment variables that should be set in `.env` +> All paths are from root repository + +## Usage +> All commands are done from root repository. + +- Copy configuration file: +``` +cp ./tools/grantRole/grantRole.json.example ./tools/grantRole/grantRole.json +``` +- Set your parameters +- Run tool: +``` +npx hardhat run tools/grantRole/grantRole.ts --network +``` +- Output: + - `granRoleOutput.json`: + ``` + { + "scheduleData": "0x01d5062a000000000000000000000000a51c1fc2f0d1a1b8494ed1fe312d7c3a78ed91c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e1000000000000000000000000000000000000000000000000000000000000000442f2ff15dac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f590000000000000000000000000a51c1fc2f0d1a1b8494ed1fe312d7c3a78ed91c000000000000000000000000000000000000000000000000000000000", + "executeData": "0x134008d3000000000000000000000000a51c1fc2f0d1a1b8494ed1fe312d7c3a78ed91c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000442f2ff15dac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f590000000000000000000000000a51c1fc2f0d1a1b8494ed1fe312d7c3a78ed91c000000000000000000000000000000000000000000000000000000000", + "decodedScheduleData": { + "target": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0", + "value": "0", + "data": "0x2f2ff15dac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f590000000000000000000000000a51c1fc2f0d1a1b8494ed1fe312d7c3a78ed91c0", + "decodedData": { + "role": "0xac75d24dbb35ea80e25fab167da4dea46c1915260426570db84f184891f5f590", + "account": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0" + }, + "predecessor": "0x0000000000000000000000000000000000000000000000000000000000000000", + "salt": "0x0000000000000000000000000000000000000000000000000000000000000000", + "delay": "3600" + } + } + ``` diff --git a/tools/grantRole/grantRole.json.example b/tools/grantRole/grantRole.json.example index fc6189db1..2264e6ada 100644 --- a/tools/grantRole/grantRole.json.example +++ b/tools/grantRole/grantRole.json.example @@ -2,9 +2,5 @@ "roleName": "roleName", "accountToGrantRole": "0xaddress", "polygonRollupManagerAddress": "0xaddress", - "timelockDelay": 3600, - "deployerPvtKey": "", - "maxFeePerGas": "", - "maxPriorityFeePerGas": "", - "multiplierGas": "" + "timelockDelay": 3600 } diff --git a/tools/grantRole/grantRole.ts b/tools/grantRole/grantRole.ts index d9c5f91bd..a486fb741 100644 --- a/tools/grantRole/grantRole.ts +++ b/tools/grantRole/grantRole.ts @@ -54,59 +54,11 @@ async function main() { } const roleID = ethers.id(roleName); - // Load provider - let currentProvider = ethers.provider; - if (addRollupParameters.multiplierGas || addRollupParameters.maxFeePerGas) { - if (process.env.HARDHAT_NETWORK !== "hardhat") { - currentProvider = ethers.getDefaultProvider( - `https://${process.env.HARDHAT_NETWORK}.infura.io/v3/${process.env.INFURA_PROJECT_ID}` - ) as any; - if (addRollupParameters.maxPriorityFeePerGas && addRollupParameters.maxFeePerGas) { - console.log( - `Hardcoded gas used: MaxPriority${addRollupParameters.maxPriorityFeePerGas} gwei, MaxFee${addRollupParameters.maxFeePerGas} gwei` - ); - const FEE_DATA = new ethers.FeeData( - null, - ethers.parseUnits(addRollupParameters.maxFeePerGas, "gwei"), - ethers.parseUnits(addRollupParameters.maxPriorityFeePerGas, "gwei") - ); - - currentProvider.getFeeData = async () => FEE_DATA; - } else { - console.log("Multiplier gas used: ", addRollupParameters.multiplierGas); - async function overrideFeeData() { - const feedata = await ethers.provider.getFeeData(); - return new ethers.FeeData( - null, - ((feedata.maxFeePerGas as bigint) * BigInt(addRollupParameters.multiplierGas)) / 1000n, - ((feedata.maxPriorityFeePerGas as bigint) * BigInt(addRollupParameters.multiplierGas)) / 1000n - ); - } - currentProvider.getFeeData = overrideFeeData; - } - } - } - - // Load deployer - let deployer; - if (addRollupParameters.deployerPvtKey) { - deployer = new ethers.Wallet(addRollupParameters.deployerPvtKey, currentProvider); - } else if (process.env.MNEMONIC) { - deployer = ethers.HDNodeWallet.fromMnemonic( - ethers.Mnemonic.fromPhrase(process.env.MNEMONIC), - "m/44'/60'/0'/0/0" - ).connect(currentProvider); - } else { - [deployer] = await ethers.getSigners(); - } - - console.log("Using with: ", deployer.address); - // load timelock - const timelockContractFactory = await ethers.getContractFactory("PolygonZkEVMTimelock", deployer); + const timelockContractFactory = await ethers.getContractFactory("PolygonZkEVMTimelock"); // Load Rollup manager - const PolgonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); + const PolgonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager"); const operation = genOperation( polygonRollupManagerAddress, @@ -142,8 +94,8 @@ async function main() { // Decode the scheduleData for better readibility const timelockTx = timelockContractFactory.interface.parseTransaction({data: scheduleData}); - const paramsArray = timelockTx?.fragment.inputs; - const objectDecoded = {}; + const paramsArray = timelockTx?.fragment.inputs as any; + const objectDecoded = {} as any; for (let i = 0; i < paramsArray?.length; i++) { const currentParam = paramsArray[i]; @@ -153,8 +105,8 @@ async function main() { const decodedRollupManagerData = PolgonRollupManagerFactory.interface.parseTransaction({ data: timelockTx?.args[i], }); - const objectDecodedData = {}; - const paramsArrayData = decodedRollupManagerData?.fragment.inputs; + const objectDecodedData = {} as any; + const paramsArrayData = decodedRollupManagerData?.fragment.inputs as any; for (let j = 0; j < paramsArrayData?.length; j++) { const currentParam = paramsArrayData[j]; diff --git a/tools/updateRollup/README.md b/tools/updateRollup/README.md index 13193ff25..36f6d158b 100644 --- a/tools/updateRollup/README.md +++ b/tools/updateRollup/README.md @@ -1,5 +1,5 @@ # Update rollup -Script to deploy call `updateRollup` function in the `PolygonRollupManager.sol` smart contract +Script to deploy call `updateRollup` function in the `PolygonRollupManager.sol` smart contract. ## Install ``` @@ -7,10 +7,12 @@ npm i ``` ## Setup +### updateRollup - Config file - - `rollupAddress`: rollup address of the rollup that is going to be updated - - `newRollupTypeID`: select which is the `rollupTypeID` to upgrade - - `upgradeData`: data necessary to perform the upgrade (default to `0x`) + - `type`: Specify the type of rollup creation, only available: + - `EOA`: If creating the rollup from a wallet, the script will execute the creation of the rollup on the specified network + - `Multisig`: If creating the rollup from a multisig, the script will output the calldata of the transaction to execute for creating the rollup + - `Timelock`: If creating the rollup through a timelock, the script will output the execute and schedule data to send to the timelock contract - `polygonRollupManagerAddress`: `PolygonRollupManager.sol` SC address - `timelockDelay (optional)`: at least it should be the minimum delay of the timelock smart contract - `deployerPvtKey`: private key deployer @@ -22,12 +24,16 @@ npm i - examples: `-- sepolia` or `--mainnet` - This uses variables set in `hardhat.config.ts` - Which uses some environment variables that should be set in `.env` + - `rollups`, array where for each rollup: + - `rollupAddress`: rollup address of the rollup that is going to be updated + - `newRollupTypeID`: select which is the `rollupTypeID` to upgrade + - `upgradeData`: data necessary to perform the upgrade (default to `0x`) > All paths are from root repository ## Usage > All commands are done from root repository. -### Call 'addNewRollupType' from an EOA +### Call 'updateRollup' - Copy configuration file: ``` cp ./tools/updateRollup/updateRollup.json.example ./tools/updateRollup/updateRollup.json @@ -35,22 +41,23 @@ cp ./tools/updateRollup/updateRollup.json.example ./tools/updateRollup/updateRol - Set your parameters - Run tool: -- Standrad transaction: ``` -npx hardhat run ./tools/updateRollup/updateRollup.ts --network sepolia +npx hardhat run ./tools/updateRollup/updateRollup.ts --network ``` -### Generate 'updateRollup' data to the Timelock SC +### 'updateRollup' from an EOA -- Copy configuration file: -``` -cp ./tools/updateRollup/updateRollup.json.example ./tools/updateRollup/updateRollup.json -``` +Running the tool, the updateRollup transaction will be sent directly + +### 'updateRollup' Multisig +- Output: Transaction to update the rollup + +### Generate 'updateRollup' data to the Timelock SC - Set your parameters - Run tool: ``` -npx hardhat run ./tools/updateRollup/updateRollupTimelock.ts --network sepolia +npx hardhat run ./tools/updateRollup/updateRollupTimelock.ts --network ``` - Output: - scheduleData diff --git a/tools/updateRollup/updateRollup.json.example b/tools/updateRollup/updateRollup.json.example index fda30151f..38534ceb4 100644 --- a/tools/updateRollup/updateRollup.json.example +++ b/tools/updateRollup/updateRollup.json.example @@ -1,11 +1,16 @@ { - "rollupAddress": "0xaddress", - "newRollupTypeID": 1, - "upgradeData": "0x", + "type": "EOA", "polygonRollupManagerAddress": "0xaddress", "timelockDelay": 0, "deployerPvtKey": "", "maxFeePerGas": "", "maxPriorityFeePerGas": "", - "multiplierGas": "" -} + "multiplierGas": "", + "rollups": [ + { + "rollupAddress": "0xaddress", + "newRollupTypeID": 1, + "upgradeData": "0x" + } + ] +} \ No newline at end of file diff --git a/tools/updateRollup/updateRollup.ts b/tools/updateRollup/updateRollup.ts index a4fb86381..5c1563881 100644 --- a/tools/updateRollup/updateRollup.ts +++ b/tools/updateRollup/updateRollup.ts @@ -1,6 +1,5 @@ /* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if */ /* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved */ -import {expect} from "chai"; import path = require("path"); import fs = require("fs"); @@ -8,61 +7,69 @@ import * as dotenv from "dotenv"; dotenv.config({path: path.resolve(__dirname, "../../.env")}); import {ethers, network} from "hardhat"; -const addRollupParameters = require("./updateRollup.json"); - +const updateRollupsParameters = require("./updateRollup.json"); const dateStr = new Date().toISOString(); const pathOutputJson = path.join(__dirname, `./updateRollupOutput-${dateStr}.json`); import {PolygonRollupManager} from "../../typechain-types"; +import { transactionTypes, genOperation } from "../utils"; import "../../deployment/helpers/utils"; async function main() { - const outputJson = {} as any; - /* - * Check deploy parameters + * Check parameters * Check that every necessary parameter is fullfilled */ const mandatoryDeploymentParameters = [ - "rollupAddress", - "newRollupTypeID", - "upgradeData", + "type", "polygonRollupManagerAddress", ]; + // check create rollup type + switch (updateRollupsParameters.type) { + case transactionTypes.EOA: + case transactionTypes.MULTISIG: + break; + case transactionTypes.TIMELOCK: + mandatoryDeploymentParameters.push("timelockDelay"); + break; + default: + throw new Error(`Invalid type ${updateRollupsParameters.type}`); + } + for (const parameterName of mandatoryDeploymentParameters) { - if (addRollupParameters[parameterName] === undefined || addRollupParameters[parameterName] === "") { + if (updateRollupsParameters[parameterName] === undefined || updateRollupsParameters[parameterName] === "") { throw new Error(`Missing parameter: ${parameterName}`); } } - - const {rollupAddress, newRollupTypeID, upgradeData, polygonRollupManagerAddress} = addRollupParameters; + console.log(`Starting script to update rollup from ${updateRollupsParameters.type}`) // Load provider let currentProvider = ethers.provider; - if (addRollupParameters.multiplierGas || addRollupParameters.maxFeePerGas) { + if (updateRollupsParameters.multiplierGas || updateRollupsParameters.maxFeePerGas) { if (process.env.HARDHAT_NETWORK !== "hardhat") { currentProvider = ethers.getDefaultProvider( `https://${process.env.HARDHAT_NETWORK}.infura.io/v3/${process.env.INFURA_PROJECT_ID}` ) as any; - if (addRollupParameters.maxPriorityFeePerGas && addRollupParameters.maxFeePerGas) { + if (updateRollupsParameters.maxPriorityFeePerGas && updateRollupsParameters.maxFeePerGas) { console.log( - `Hardcoded gas used: MaxPriority${addRollupParameters.maxPriorityFeePerGas} gwei, MaxFee${addRollupParameters.maxFeePerGas} gwei` + `Hardcoded gas used: MaxPriority${updateRollupsParameters.maxPriorityFeePerGas} gwei, MaxFee${updateRollupsParameters.maxFeePerGas} gwei` ); const FEE_DATA = new ethers.FeeData( null, - ethers.parseUnits(addRollupParameters.maxFeePerGas, "gwei"), - ethers.parseUnits(addRollupParameters.maxPriorityFeePerGas, "gwei") + ethers.parseUnits(updateRollupsParameters.maxFeePerGas, "gwei"), + ethers.parseUnits(updateRollupsParameters.maxPriorityFeePerGas, "gwei") ); currentProvider.getFeeData = async () => FEE_DATA; } else { - console.log("Multiplier gas used: ", addRollupParameters.multiplierGas); + console.log("Multiplier gas used: ", updateRollupsParameters.multiplierGas); async function overrideFeeData() { const feedata = await ethers.provider.getFeeData(); return new ethers.FeeData( null, - ((feedata.maxFeePerGas as bigint) * BigInt(addRollupParameters.multiplierGas)) / 1000n, - ((feedata.maxPriorityFeePerGas as bigint) * BigInt(addRollupParameters.multiplierGas)) / 1000n + ((feedata.maxFeePerGas as bigint) * BigInt(updateRollupsParameters.multiplierGas)) / 1000n, + ((feedata.maxPriorityFeePerGas as bigint) * BigInt(updateRollupsParameters.multiplierGas)) / + 1000n ); } currentProvider.getFeeData = overrideFeeData; @@ -72,8 +79,8 @@ async function main() { // Load deployer let deployer; - if (addRollupParameters.deployerPvtKey) { - deployer = new ethers.Wallet(addRollupParameters.deployerPvtKey, currentProvider); + if (updateRollupsParameters.deployerPvtKey) { + deployer = new ethers.Wallet(updateRollupsParameters.deployerPvtKey, currentProvider); } else if (process.env.MNEMONIC) { deployer = ethers.HDNodeWallet.fromMnemonic( ethers.Mnemonic.fromPhrase(process.env.MNEMONIC), @@ -85,31 +92,175 @@ async function main() { console.log("Using with: ", deployer.address); + const { polygonRollupManagerAddress } = updateRollupsParameters; + // Load Rollup manager const PolgonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); const rollupManagerContract = PolgonRollupManagerFactory.attach( polygonRollupManagerAddress ) as PolygonRollupManager; - // Check role - const UPDATE_ROLLUP_ROLE = ethers.id("UPDATE_ROLLUP_ROLE"); + const outputsJson = [] as any; - if ((await rollupManagerContract.hasRole(UPDATE_ROLLUP_ROLE, deployer.address)) == false) { - // log that address ha sno role - throw new Error(`Address ${deployer.address} does not have the UPDATE_ROLLUP_ROLE role`); - } + // Timelock vars + const operations = {} as any; + operations.target = []; + operations.value = []; + operations.data = []; + const predecessor = ethers.ZeroHash; + const salt = updateRollupsParameters.timelockSalt || ethers.ZeroHash; - // Add a new rollup type with timelock - console.log(await (await rollupManagerContract.updateRollup(rollupAddress, newRollupTypeID, upgradeData)).wait()); + if(updateRollupsParameters.rollups.length === 0) { + throw new Error("No rollups") + } else { + for(let i = 0; i < updateRollupsParameters.rollups.length; i++) { + const outputJson = {} as any; + const updateRollupParameters = updateRollupsParameters.rollups[i]; + /* + * Check parameters + * Check that every necessary parameter is fullfilled + */ + const mandatoryParametersRollup = [ + "rollupAddress", + "newRollupTypeID", + "upgradeData", + ]; + + for (const parameterName of mandatoryParametersRollup) { + if (updateRollupParameters[parameterName] === undefined || updateRollupParameters[parameterName] === "") { + throw new Error(`Missing rollup[${i}] parameter: ${parameterName}`); + } + } + + const {rollupAddress, newRollupTypeID, upgradeData} = updateRollupParameters; + + outputJson.networkName = network.name; + outputJson.polygonRollupManagerAddress = polygonRollupManagerAddress; + outputJson.rollupAddress = rollupAddress; + outputJson.newRollupTypeID = newRollupTypeID; + outputJson.upgradeData = upgradeData; + + if(updateRollupsParameters.type === transactionTypes.EOA) { + // Check role + const UPDATE_ROLLUP_ROLE = ethers.id("UPDATE_ROLLUP_ROLE"); + if ((await rollupManagerContract.hasRole(UPDATE_ROLLUP_ROLE, deployer.address)) == false) { + // log that address has no role + throw new Error(`Address ${deployer.address} does not have the UPDATE_ROLLUP_ROLE role`); + } + console.log(`Updating rollup ${rollupAddress}...`) + try { + console.log(await (await rollupManagerContract.updateRollup(rollupAddress, newRollupTypeID, upgradeData)).wait()); + outputJson.successUpdate = true; + } catch (e) { + outputJson.successUpdate = false; + console.log(`Error updating ${rollupAddress}`); + console.log(e); + } + + } else if(updateRollupsParameters.type === transactionTypes.TIMELOCK) { + console.log(`Creating timelock txs for update rollup ${rollupAddress}...`) + const operation = genOperation( + polygonRollupManagerAddress, + 0, // value + PolgonRollupManagerFactory.interface.encodeFunctionData("updateRollup", [ + rollupAddress, + newRollupTypeID, + upgradeData, + ]), + predecessor, // predecessor + salt // salt + ); + operations.target.push(operation.target); + operations.value.push(operation.value); + operations.data.push(operation.data); + } else { + console.log(`Creating calldata for update rollup from multisig ${rollupAddress}...`); + const txUpdateRollup = PolgonRollupManagerFactory.interface.encodeFunctionData("updateRollup", [ + rollupAddress, + newRollupTypeID, + upgradeData, + ]); + outputJson.txUpdateRollup = txUpdateRollup; + } + outputsJson.push(outputJson); + } + + // if type === Timelock --> get scheduleData & executeData + if(updateRollupsParameters.type === transactionTypes.TIMELOCK){ + console.log(`Get scheduleData & executeData...`) + const { timelockDelay } = updateRollupsParameters; + // load timelock + const timelockContractFactory = await ethers.getContractFactory("PolygonZkEVMTimelock", deployer); + + // Schedule operation + const scheduleData = timelockContractFactory.interface.encodeFunctionData("scheduleBatch", [ + operations.target, + operations.value, + operations.data, + predecessor, + salt, + timelockDelay, + ]); + + // Execute operation + const executeData = timelockContractFactory.interface.encodeFunctionData("executeBatch", [ + operations.target, + operations.value, + operations.data, + predecessor, + salt, + ]); + + console.log({scheduleData}); + console.log({executeData}); - outputJson.networkName = network.name; - outputJson.polygonRollupManagerAddress = polygonRollupManagerAddress; - outputJson.rollupAddress = rollupAddress; - outputJson.newRollupTypeID = newRollupTypeID; - outputJson.upgradeData = upgradeData; + // Decode the scheduleData for better readibility + const timelockTx = timelockContractFactory.interface.parseTransaction({data: scheduleData}); + const paramsArray = timelockTx?.fragment.inputs; + const objectDecoded = {}; - // add time to output path - fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); + for (let i = 0; i < paramsArray?.length; i++) { + const currentParam = paramsArray[i]; + objectDecoded[currentParam.name] = timelockTx?.args[i]; + + if (currentParam.name == "payloads") { + // for each payload + const payloads = timelockTx?.args[i]; + for (let j = 0; j < payloads.length; j++) { + const data = payloads[j]; + const decodedProxyAdmin = PolgonRollupManagerFactory.interface.parseTransaction({ + data, + }); + + const resultDecodeProxyAdmin = {}; + resultDecodeProxyAdmin.signature = decodedProxyAdmin?.signature; + resultDecodeProxyAdmin.selector = decodedProxyAdmin?.selector; + + const paramsArrayData = decodedProxyAdmin?.fragment.inputs; + + for (let n = 0; n < paramsArrayData?.length; n++) { + const currentParam = paramsArrayData[n]; + resultDecodeProxyAdmin[currentParam.name] = decodedProxyAdmin?.args[n]; + } + objectDecoded[`decodePayload_${j}`] = resultDecodeProxyAdmin; + } + } + } + const outputTimelock = { + rollups: outputsJson, + scheduleData, + executeData, + decodeScheduleData: objectDecoded, + } + + fs.writeFileSync(pathOutputJson, JSON.stringify(outputTimelock, null, 1)); + } else { + fs.writeFileSync(pathOutputJson, JSON.stringify(outputsJson, null, 1)); + } + + console.log("Finished script, output saved at: ", pathOutputJson) + + } } main().catch((e) => { diff --git a/tools/updateRollup/updateRollupTimelock.ts b/tools/updateRollup/updateRollupTimelock.ts deleted file mode 100644 index e0f1eb301..000000000 --- a/tools/updateRollup/updateRollupTimelock.ts +++ /dev/null @@ -1,184 +0,0 @@ -/* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if */ -/* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved */ -import {expect} from "chai"; -import path = require("path"); -import fs = require("fs"); - -import * as dotenv from "dotenv"; -dotenv.config({path: path.resolve(__dirname, "../../.env")}); -import {ethers, network} from "hardhat"; - -const addRollupParameters = require("./updateRollup.json"); - -const dateStr = new Date().toISOString(); -const pathOutputJson = path.join(__dirname, `./updateRollupOutput-${dateStr}.json`); -import "../../deployment/helpers/utils"; - -async function main() { - const outputJson = {} as any; - - /* - * Check deploy parameters - * Check that every necessary parameter is fullfilled - */ - const mandatoryDeploymentParameters = [ - "rollupAddress", - "newRollupTypeID", - "upgradeData", - "polygonRollupManagerAddress", - "timelockDelay", - ]; - - for (const parameterName of mandatoryDeploymentParameters) { - if (addRollupParameters[parameterName] === undefined || addRollupParameters[parameterName] === "") { - throw new Error(`Missing parameter: ${parameterName}`); - } - } - - const {rollupAddress, newRollupTypeID, upgradeData, polygonRollupManagerAddress, timelockDelay} = - addRollupParameters; - - const salt = addRollupParameters.timelockSalt || ethers.ZeroHash; - - // Load provider - let currentProvider = ethers.provider; - if (addRollupParameters.multiplierGas || addRollupParameters.maxFeePerGas) { - if (process.env.HARDHAT_NETWORK !== "hardhat") { - currentProvider = ethers.getDefaultProvider( - `https://${process.env.HARDHAT_NETWORK}.infura.io/v3/${process.env.INFURA_PROJECT_ID}` - ) as any; - if (addRollupParameters.maxPriorityFeePerGas && addRollupParameters.maxFeePerGas) { - console.log( - `Hardcoded gas used: MaxPriority${addRollupParameters.maxPriorityFeePerGas} gwei, MaxFee${addRollupParameters.maxFeePerGas} gwei` - ); - const FEE_DATA = new ethers.FeeData( - null, - ethers.parseUnits(addRollupParameters.maxFeePerGas, "gwei"), - ethers.parseUnits(addRollupParameters.maxPriorityFeePerGas, "gwei") - ); - - currentProvider.getFeeData = async () => FEE_DATA; - } else { - console.log("Multiplier gas used: ", addRollupParameters.multiplierGas); - async function overrideFeeData() { - const feedata = await ethers.provider.getFeeData(); - return new ethers.FeeData( - null, - ((feedata.maxFeePerGas as bigint) * BigInt(addRollupParameters.multiplierGas)) / 1000n, - ((feedata.maxPriorityFeePerGas as bigint) * BigInt(addRollupParameters.multiplierGas)) / 1000n - ); - } - currentProvider.getFeeData = overrideFeeData; - } - } - } - - // Load deployer - let deployer; - if (addRollupParameters.deployerPvtKey) { - deployer = new ethers.Wallet(addRollupParameters.deployerPvtKey, currentProvider); - } else if (process.env.MNEMONIC) { - deployer = ethers.HDNodeWallet.fromMnemonic( - ethers.Mnemonic.fromPhrase(process.env.MNEMONIC), - "m/44'/60'/0'/0/0" - ).connect(currentProvider); - } else { - [deployer] = await ethers.getSigners(); - } - - console.log("Using with: ", deployer.address); - - // load timelock - const timelockContractFactory = await ethers.getContractFactory("PolygonZkEVMTimelock", deployer); - - // Load Rollup manager - const PolgonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); - - const operation = genOperation( - polygonRollupManagerAddress, - 0, // value - PolgonRollupManagerFactory.interface.encodeFunctionData("updateRollup", [ - rollupAddress, - newRollupTypeID, - upgradeData, - ]), - ethers.ZeroHash, // predecesoor - salt // salt - ); - - // Schedule operation - const scheduleData = timelockContractFactory.interface.encodeFunctionData("schedule", [ - operation.target, - operation.value, - operation.data, - operation.predecessor, - operation.salt, - timelockDelay, - ]); - // Execute operation - const executeData = timelockContractFactory.interface.encodeFunctionData("execute", [ - operation.target, - operation.value, - operation.data, - operation.predecessor, - operation.salt, - ]); - - console.log({scheduleData}); - console.log({executeData}); - - outputJson.networkName = network.name; - outputJson.scheduleData = scheduleData; - outputJson.executeData = executeData; - - // Decode the scheduleData for better readibility - const timelockTx = timelockContractFactory.interface.parseTransaction({data: scheduleData}); - const paramsArray = timelockTx?.fragment.inputs; - const objectDecoded = {}; - - for (let i = 0; i < paramsArray?.length; i++) { - const currentParam = paramsArray[i]; - - objectDecoded[currentParam.name] = timelockTx?.args[i]; - - if (currentParam.name == "data") { - const decodedRollupManagerData = PolgonRollupManagerFactory.interface.parseTransaction({ - data: timelockTx?.args[i], - }); - const objectDecodedData = {}; - const paramsArrayData = decodedRollupManagerData?.fragment.inputs; - - for (let j = 0; j < paramsArrayData?.length; j++) { - const currentParam = paramsArrayData[j]; - objectDecodedData[currentParam.name] = decodedRollupManagerData?.args[j]; - } - objectDecoded["decodedData"] = objectDecodedData; - } - } - - outputJson.decodedScheduleData = objectDecoded; - - fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); -} - -main().catch((e) => { - console.error(e); - process.exit(1); -}); - -// OZ test functions -function genOperation(target: any, value: any, data: any, predecessor: any, salt: any) { - const abiEncoded = ethers.AbiCoder.defaultAbiCoder().encode( - ["address", "uint256", "bytes", "uint256", "bytes32"], - [target, value, data, predecessor, salt] - ); - const id = ethers.keccak256(abiEncoded); - return { - id, - target, - value, - data, - predecessor, - salt, - }; -} diff --git a/tools/upgradePreEtrogGenesis/.gitignore b/tools/upgradePreEtrogGenesis/.gitignore new file mode 100644 index 000000000..24cc9592b --- /dev/null +++ b/tools/upgradePreEtrogGenesis/.gitignore @@ -0,0 +1 @@ +upgrade_pre_etrog_genesis.json \ No newline at end of file diff --git a/tools/upgradePreEtrogGenesis/README.md b/tools/upgradePreEtrogGenesis/README.md new file mode 100644 index 000000000..be3b25871 --- /dev/null +++ b/tools/upgradePreEtrogGenesis/README.md @@ -0,0 +1,32 @@ +# Upgrade pre etrog genesis +Script to migrate a non-LxLY genesis (previous genesis) to an LxLY genesis (etrog fork). + +## Install +``` +npm i +``` + +## Setup +- Config file `upgrade_pre_etrog_genesis.json`: + - `test`: bool, Indicate if it's a test deployment, which will fund the deployer address with pre minted ether and will give more powers to the deployer address to make easier the flow. + - `timelockAdminAddress`: address, Timelock owner address, able to send start an upgradeability process via timelock + - `minDelayTimelock`: number, Minimum timelock delay, + - `initialZkEVMDeployerOwner`: address, Initial owner of the `PolygonZkEVMDeployer` +- A network should be selected when running the script + - examples: `--network sepolia` or `--network mainnet` + - This uses variables set in `hardhat.config.ts` + - Which uses some environment variables that should be set in `.env` + +## Usage + +- Copy configuration file: +``` +cp ./tools/upgradePreEtrogGenesis/upgrade_pre_etrog_genesis.json.example ./tools/upgradePreEtrogGenesis/upgrade_pre_etrog_genesis.json +``` +- Set your parameters +- Run tool: +``` +npx hardhat run ./tools/upgradePreEtrogGenesis/upgradePreEtrogGenesis.ts +``` + +- Output: `new_genesis.json` \ No newline at end of file diff --git a/tools/createGenesis/genesis_base.json b/tools/upgradePreEtrogGenesis/genesis_base.json similarity index 100% rename from tools/createGenesis/genesis_base.json rename to tools/upgradePreEtrogGenesis/genesis_base.json diff --git a/tools/createGenesis/new_genesis.json b/tools/upgradePreEtrogGenesis/new_genesis.json similarity index 100% rename from tools/createGenesis/new_genesis.json rename to tools/upgradePreEtrogGenesis/new_genesis.json diff --git a/tools/createGenesis/generateGenesis.ts b/tools/upgradePreEtrogGenesis/upgradePreEtrogGenesis.ts similarity index 98% rename from tools/createGenesis/generateGenesis.ts rename to tools/upgradePreEtrogGenesis/upgradePreEtrogGenesis.ts index 591c01396..3d8f5667c 100644 --- a/tools/createGenesis/generateGenesis.ts +++ b/tools/upgradePreEtrogGenesis/upgradePreEtrogGenesis.ts @@ -29,7 +29,7 @@ import {ProxyAdmin} from "../../typechain-types"; import {Addressable} from "ethers"; import "../../deployment/helpers/utils"; -const deployParameters = require("./deploy_parameters.json"); +const genesisParameters = require("./upgrade_pre_etrog_genesis.json"); const genesisBase = require("./genesis_base.json"); const pathOutputJson = path.join(__dirname, argv.out); @@ -72,9 +72,9 @@ const keylessDeployerMainnet = baseGenesisInfo.find( const deployerMainnet = baseGenesisInfo.find((account: any) => account.accountName === "deployer").address; -const mainnetMultisig = deployParameters.timelockAddress; -const mainnetInitialZkEVMDeployerOwner = deployParameters.initialZkEVMDeployerOwner; -const mainnetMinDelayTimelock = deployParameters.minDelayTimelock; +const mainnetMultisig = genesisParameters.timelockAddress; +const mainnetInitialZkEVMDeployerOwner = genesisParameters.initialZkEVMDeployerOwner; +const mainnetMinDelayTimelock = genesisParameters.minDelayTimelock; const globalExitRootL2Address = "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa"; const zkevmAddressL2 = ethers.ZeroAddress; @@ -383,7 +383,7 @@ async function main() { address: finalDeployer, }); - if (deployParameters.test) { + if (genesisParameters.test) { // Add tester account with ether genesis[genesis.length - 1].balance = "100000000000000000000000"; } diff --git a/tools/upgradePreEtrogGenesis/upgrade_pre_etrog_genesis.json.example b/tools/upgradePreEtrogGenesis/upgrade_pre_etrog_genesis.json.example new file mode 100644 index 000000000..b8fe8ff3e --- /dev/null +++ b/tools/upgradePreEtrogGenesis/upgrade_pre_etrog_genesis.json.example @@ -0,0 +1,6 @@ +{ + "timelockAddress": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "initialZkEVMDeployerOwner": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "minDelayTimelock": 3600, + "test": true +} \ No newline at end of file diff --git a/tools/utils.js b/tools/utils.js new file mode 100644 index 000000000..76454e868 --- /dev/null +++ b/tools/utils.js @@ -0,0 +1,81 @@ +/* eslint-disable no-prototype-builtins */ +/* eslint-disable no-restricted-syntax */ +const ethers = require('ethers'); + +const supportedBridgeContracts = ['PolygonZkEVMBridgeV2 proxy', 'PolygonZkEVMBridge proxy', 'BridgeL2SovereignChain proxy']; + +function genOperation(target, value, data, predecessor, salt) { + const abiEncoded = ethers.AbiCoder.defaultAbiCoder().encode( + ['address', 'uint256', 'bytes', 'uint256', 'bytes32'], + [target, value, data, predecessor, salt], + ); + const id = ethers.keccak256(abiEncoded); + return { + id, + target, + value, + data, + predecessor, + salt, + }; +} + +const transactionTypes = { + EOA: 'EOA', + MULTISIG: 'Multisig', + TIMELOCK: 'Timelock', +}; + +// Function to recursively convert BigInts to Numbers +function convertBigIntsToNumbers(obj) { + if (typeof obj === 'bigint') { + if (obj > BigInt(Number.MAX_SAFE_INTEGER)) { + throw new Error(`convertBigIntsToNumbers: BigInt exceeds maximum safe integer: ${obj}`); + } + return Number(obj); // Convert BigInt to Number + } + + if (Array.isArray(obj)) { + return obj.map(convertBigIntsToNumbers); // Recursively process each element in the array + } + + if (typeof obj === 'object' && obj !== null) { + const newObj = {}; + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + newObj[key] = convertBigIntsToNumbers(obj[key]); // Recursively process each property + } + } + return newObj; + } + + return obj; // Return the value if it's not a BigInt, object, or array +} + +function checkBridgeAddress(genesis, expectedBridgeAddress){ + // get bridge address in genesis file + let genesisBridgeAddress = ethers.ZeroAddress; + let bridgeContractName = ""; + + for (let i = 0; i < genesis.genesis.length; i++) { + if (supportedBridgeContracts.includes(genesis.genesis[i].contractName)) { + genesisBridgeAddress = genesis.genesis[i].address; + bridgeContractName = genesis.genesis[i].contractName; + break; + } + } + + if (expectedBridgeAddress.toLowerCase() !== genesisBridgeAddress.toLowerCase()) { + throw new Error( + `checkBridgeAddress: '${bridgeContractName}' address in the 'genesis.json' does not match the 'expectedBridgeAddress'` + ); + } +} + +module.exports = { + genOperation, + transactionTypes, + convertBigIntsToNumbers, + supportedBridgeContracts, + checkBridgeAddress, +}; diff --git a/tools/verify-etherscan/.gitignore b/tools/verify-etherscan/.gitignore new file mode 100644 index 000000000..9079d7157 --- /dev/null +++ b/tools/verify-etherscan/.gitignore @@ -0,0 +1 @@ +arguments.js \ No newline at end of file diff --git a/tools/verify-etherscan/README.md b/tools/verify-etherscan/README.md new file mode 100644 index 000000000..f20057019 --- /dev/null +++ b/tools/verify-etherscan/README.md @@ -0,0 +1,11 @@ +# Verify etherscan +This is just an example of the `arguments.js` file to provide in etherscan verification command using hardhat. +- Copy example file: +``` +cp arguments.js.example arguments.js +``` +- Update arguments.js +- Run hardhat command: +``` +npx hardhat verify --constructor-args tools/verify-etherscan/arguments.js ${address} --network ${network-name} +``` \ No newline at end of file diff --git a/tools/verify-etherscan/arguments.js.example b/tools/verify-etherscan/arguments.js.example new file mode 100644 index 000000000..72c7116c5 --- /dev/null +++ b/tools/verify-etherscan/arguments.js.example @@ -0,0 +1,8 @@ +module.exports = [ + '0x6407cf296a27B38fd29c401518504D388F1DFB3d', + '0xF1b13757bcF3EF902a7847f409A6068BA43a89D4', + '0x4ceB990D2E2ee6d0e163fa80d12bac72C0F28D52', + '0xcFA773Cc48FBde3CA4D24eeCb19D224d697026b2', + 1440, + 2 +] \ No newline at end of file diff --git a/upgrade/upgradePessimistic/mainnet-info/mainnet.json b/upgrade/upgradePessimistic/mainnet-info/mainnet.json new file mode 100644 index 000000000..b67ebe2e6 --- /dev/null +++ b/upgrade/upgradePessimistic/mainnet-info/mainnet.json @@ -0,0 +1,4106 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0x0F99738B2Fc14D77308337f3e2596b63aE7BCC4A" + }, + "proxies": [ + { + "address": "0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe", + "kind": "transparent" + }, + { + "address": "0x580bda1e7A0CFAe92Fa7F6c20A3794F169CE3CFb", + "txHash": "0x9946be78d6c6d19dd1c6c7134a8fac27e76d32cad36dae2398d28fe6ff838f10", + "kind": "transparent" + }, + { + "address": "0x5132A183E9F3CB7C848b0AAC5Ae0c4f0491B7aB2", + "txHash": "0xe34243804e1f7257acb09c97d0d6f023663200c39ee85a1e6927b0b391710bbb", + "kind": "transparent" + } + ], + "impls": { + "7d81d3d49439b439759dc4a136c30bff477402e06213014f3132a9b83751e779": { + "address": "0x5ac4182A1dd41AeEf465E40B82fd326BF66AB82C", + "layout": { + "solcVersion": "0.8.17", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "_status", + "offset": 0, + "slot": "1", + "type": "t_uint256", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "2", + "type": "t_array(t_uint256)49_storage", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:80" + }, + { + "label": "_branch", + "offset": 0, + "slot": "51", + "type": "t_array(t_bytes32)32_storage", + "contract": "DepositContract", + "src": "contracts/lib/DepositContract.sol:25" + }, + { + "label": "depositCount", + "offset": 0, + "slot": "83", + "type": "t_uint256", + "contract": "DepositContract", + "src": "contracts/lib/DepositContract.sol:28" + }, + { + "label": "_gap", + "offset": 0, + "slot": "84", + "type": "t_array(t_uint256)10_storage", + "contract": "DepositContract", + "src": "contracts/lib/DepositContract.sol:34" + }, + { + "label": "_gap", + "offset": 0, + "slot": "94", + "type": "t_array(t_uint256)10_storage", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:23" + }, + { + "label": "isEmergencyState", + "offset": 0, + "slot": "104", + "type": "t_bool", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:26" + }, + { + "label": "networkID", + "offset": 1, + "slot": "104", + "type": "t_uint32", + "contract": "PolygonZkEVMBridge", + "src": "contracts/PolygonZkEVMBridge.sol:51" + }, + { + "label": "globalExitRootManager", + "offset": 5, + "slot": "104", + "type": "t_contract(IBasePolygonZkEVMGlobalExitRoot)10065", + "contract": "PolygonZkEVMBridge", + "src": "contracts/PolygonZkEVMBridge.sol:54" + }, + { + "label": "lastUpdatedDepositCount", + "offset": 25, + "slot": "104", + "type": "t_uint32", + "contract": "PolygonZkEVMBridge", + "src": "contracts/PolygonZkEVMBridge.sol:57" + }, + { + "label": "claimedBitMap", + "offset": 0, + "slot": "105", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "PolygonZkEVMBridge", + "src": "contracts/PolygonZkEVMBridge.sol:60" + }, + { + "label": "tokenInfoToWrappedToken", + "offset": 0, + "slot": "106", + "type": "t_mapping(t_bytes32,t_address)", + "contract": "PolygonZkEVMBridge", + "src": "contracts/PolygonZkEVMBridge.sol:63" + }, + { + "label": "wrappedTokenToTokenInfo", + "offset": 0, + "slot": "107", + "type": "t_mapping(t_address,t_struct(TokenInformation)8241_storage)", + "contract": "PolygonZkEVMBridge", + "src": "contracts/PolygonZkEVMBridge.sol:66" + }, + { + "label": "polygonZkEVMaddress", + "offset": 0, + "slot": "108", + "type": "t_address", + "contract": "PolygonZkEVMBridge", + "src": "contracts/PolygonZkEVMBridge.sol:69" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)32_storage": { + "label": "bytes32[32]", + "numberOfBytes": "1024" + }, + "t_array(t_uint256)10_storage": { + "label": "uint256[10]", + "numberOfBytes": "320" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IBasePolygonZkEVMGlobalExitRoot)10065": { + "label": "contract IBasePolygonZkEVMGlobalExitRoot", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_struct(TokenInformation)8241_storage)": { + "label": "mapping(address => struct PolygonZkEVMBridge.TokenInformation)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(TokenInformation)8241_storage": { + "label": "struct PolygonZkEVMBridge.TokenInformation", + "members": [ + { + "label": "originNetwork", + "type": "t_uint32", + "offset": 0, + "slot": "0" + }, + { + "label": "originTokenAddress", + "type": "t_address", + "offset": 4, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "ce5f0c71bed14342c9985301ac01d3f106aecc5e1faee3ca7b5845eede57422f": { + "address": "0xbc1ea504fC54D078514eFCCA1F6860B5219B6BC3", + "txHash": "0x56b5e9a0955c816edefa8ab4cc057b7a41ef97c472c9027049c9353a01a8bea4", + "layout": { + "solcVersion": "0.8.17", + "storage": [ + { + "label": "lastRollupExitRoot", + "offset": 0, + "slot": "0", + "type": "t_bytes32", + "contract": "PolygonZkEVMGlobalExitRoot", + "src": "contracts/PolygonZkEVMGlobalExitRoot.sol:19" + }, + { + "label": "lastMainnetExitRoot", + "offset": 0, + "slot": "1", + "type": "t_bytes32", + "contract": "PolygonZkEVMGlobalExitRoot", + "src": "contracts/PolygonZkEVMGlobalExitRoot.sol:22" + }, + { + "label": "globalExitRootMap", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_bytes32,t_uint256)", + "contract": "PolygonZkEVMGlobalExitRoot", + "src": "contracts/PolygonZkEVMGlobalExitRoot.sol:25" + } + ], + "types": { + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + } + } + } + }, + "4c7ed8ca43394b0ba1dd706ad28512fc2a3a8db4899762861bf5582c75c8b607": { + "address": "0xe262Ea2782e2e8dbFe354048c3B5d6DE9603EfEF", + "txHash": "0xc93e7884d6c7f6bf332cf154977f58840b1b0e82be46b2ee3ec04fd979e9a2bc", + "layout": { + "solcVersion": "0.8.17", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)10_storage", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:23" + }, + { + "label": "isEmergencyState", + "offset": 0, + "slot": "111", + "type": "t_bool", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:26" + }, + { + "label": "verifyBatchTimeTarget", + "offset": 1, + "slot": "111", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:167" + }, + { + "label": "multiplierBatchFee", + "offset": 9, + "slot": "111", + "type": "t_uint16", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:170" + }, + { + "label": "trustedSequencer", + "offset": 11, + "slot": "111", + "type": "t_address", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:173" + }, + { + "label": "batchFee", + "offset": 0, + "slot": "112", + "type": "t_uint256", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:176" + }, + { + "label": "forcedBatches", + "offset": 0, + "slot": "113", + "type": "t_mapping(t_uint64,t_bytes32)", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:182" + }, + { + "label": "sequencedBatches", + "offset": 0, + "slot": "114", + "type": "t_mapping(t_uint64,t_struct(SequencedBatchData)5680_storage)", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:186" + }, + { + "label": "lastTimestamp", + "offset": 0, + "slot": "115", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:189" + }, + { + "label": "lastBatchSequenced", + "offset": 8, + "slot": "115", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:192" + }, + { + "label": "lastForceBatchSequenced", + "offset": 16, + "slot": "115", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:195" + }, + { + "label": "lastForceBatch", + "offset": 24, + "slot": "115", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:198" + }, + { + "label": "lastVerifiedBatch", + "offset": 0, + "slot": "116", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:201" + }, + { + "label": "trustedAggregator", + "offset": 8, + "slot": "116", + "type": "t_address", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:204" + }, + { + "label": "batchNumToStateRoot", + "offset": 0, + "slot": "117", + "type": "t_mapping(t_uint64,t_bytes32)", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:208" + }, + { + "label": "trustedSequencerURL", + "offset": 0, + "slot": "118", + "type": "t_string_storage", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:211" + }, + { + "label": "networkName", + "offset": 0, + "slot": "119", + "type": "t_string_storage", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:214" + }, + { + "label": "pendingStateTransitions", + "offset": 0, + "slot": "120", + "type": "t_mapping(t_uint256,t_struct(PendingState)5689_storage)", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:218" + }, + { + "label": "lastPendingState", + "offset": 0, + "slot": "121", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:221" + }, + { + "label": "lastPendingStateConsolidated", + "offset": 8, + "slot": "121", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:224" + }, + { + "label": "pendingStateTimeout", + "offset": 16, + "slot": "121", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:227" + }, + { + "label": "trustedAggregatorTimeout", + "offset": 24, + "slot": "121", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:231" + }, + { + "label": "admin", + "offset": 0, + "slot": "122", + "type": "t_address", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:234" + }, + { + "label": "pendingAdmin", + "offset": 0, + "slot": "123", + "type": "t_address", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:237" + }, + { + "label": "forceBatchTimeout", + "offset": 20, + "slot": "123", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:240" + }, + { + "label": "isForcedBatchDisallowed", + "offset": 28, + "slot": "123", + "type": "t_bool", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:243" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)10_storage": { + "label": "uint256[10]", + "numberOfBytes": "320" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(PendingState)5689_storage)": { + "label": "mapping(uint256 => struct PolygonZkEVM.PendingState)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_bytes32)": { + "label": "mapping(uint64 => bytes32)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(SequencedBatchData)5680_storage)": { + "label": "mapping(uint64 => struct PolygonZkEVM.SequencedBatchData)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(PendingState)5689_storage": { + "label": "struct PolygonZkEVM.PendingState", + "members": [ + { + "label": "timestamp", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "lastVerifiedBatch", + "type": "t_uint64", + "offset": 8, + "slot": "0" + }, + { + "label": "exitRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "stateRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_struct(SequencedBatchData)5680_storage": { + "label": "struct PolygonZkEVM.SequencedBatchData", + "members": [ + { + "label": "accInputHash", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "sequencedTimestamp", + "type": "t_uint64", + "offset": 0, + "slot": "1" + }, + { + "label": "previousLastBatchSequenced", + "type": "t_uint64", + "offset": 8, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "e0de5cb0e66c4e74b3f8f18ec5f07b6d781194a34a618b25f6325b5fe1ebfba3": { + "address": "0x301442aA888701c8B86727d42F3C55Fb0dd9eF7F", + "txHash": "0xeb9e883290a29cd74f2c8097b1f85b6b95d52733a9b6361b6c9f59a5513e0ec7", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)10_storage", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:23" + }, + { + "label": "isEmergencyState", + "offset": 0, + "slot": "111", + "type": "t_bool", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:26" + }, + { + "label": "verifyBatchTimeTarget", + "offset": 1, + "slot": "111", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:167" + }, + { + "label": "multiplierBatchFee", + "offset": 9, + "slot": "111", + "type": "t_uint16", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:170" + }, + { + "label": "trustedSequencer", + "offset": 11, + "slot": "111", + "type": "t_address", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:173" + }, + { + "label": "batchFee", + "offset": 0, + "slot": "112", + "type": "t_uint256", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:176" + }, + { + "label": "forcedBatches", + "offset": 0, + "slot": "113", + "type": "t_mapping(t_uint64,t_bytes32)", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:182" + }, + { + "label": "sequencedBatches", + "offset": 0, + "slot": "114", + "type": "t_mapping(t_uint64,t_struct(SequencedBatchData)5683_storage)", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:186" + }, + { + "label": "lastTimestamp", + "offset": 0, + "slot": "115", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:189" + }, + { + "label": "lastBatchSequenced", + "offset": 8, + "slot": "115", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:192" + }, + { + "label": "lastForceBatchSequenced", + "offset": 16, + "slot": "115", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:195" + }, + { + "label": "lastForceBatch", + "offset": 24, + "slot": "115", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:198" + }, + { + "label": "lastVerifiedBatch", + "offset": 0, + "slot": "116", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:201" + }, + { + "label": "trustedAggregator", + "offset": 8, + "slot": "116", + "type": "t_address", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:204" + }, + { + "label": "batchNumToStateRoot", + "offset": 0, + "slot": "117", + "type": "t_mapping(t_uint64,t_bytes32)", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:208" + }, + { + "label": "trustedSequencerURL", + "offset": 0, + "slot": "118", + "type": "t_string_storage", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:211" + }, + { + "label": "networkName", + "offset": 0, + "slot": "119", + "type": "t_string_storage", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:214" + }, + { + "label": "pendingStateTransitions", + "offset": 0, + "slot": "120", + "type": "t_mapping(t_uint256,t_struct(PendingState)5693_storage)", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:218" + }, + { + "label": "lastPendingState", + "offset": 0, + "slot": "121", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:221" + }, + { + "label": "lastPendingStateConsolidated", + "offset": 8, + "slot": "121", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:224" + }, + { + "label": "pendingStateTimeout", + "offset": 16, + "slot": "121", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:227" + }, + { + "label": "trustedAggregatorTimeout", + "offset": 24, + "slot": "121", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:231" + }, + { + "label": "admin", + "offset": 0, + "slot": "122", + "type": "t_address", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:234" + }, + { + "label": "pendingAdmin", + "offset": 0, + "slot": "123", + "type": "t_address", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:237" + }, + { + "label": "forceBatchTimeout", + "offset": 20, + "slot": "123", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:240" + }, + { + "label": "isForcedBatchDisallowed", + "offset": 28, + "slot": "123", + "type": "t_bool", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:243" + }, + { + "label": "version", + "offset": 0, + "slot": "124", + "type": "t_uint256", + "contract": "PolygonZkEVMUpgraded", + "src": "contracts/mainnetUpgraded/PolygonZkEVMUpgraded.sol:15" + }, + { + "label": "lastVerifiedBatchBeforeUpgrade", + "offset": 0, + "slot": "125", + "type": "t_uint256", + "contract": "PolygonZkEVMUpgraded", + "src": "contracts/mainnetUpgraded/PolygonZkEVMUpgraded.sol:18" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)10_storage": { + "label": "uint256[10]", + "numberOfBytes": "320" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(PendingState)5693_storage)": { + "label": "mapping(uint256 => struct PolygonZkEVM.PendingState)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_bytes32)": { + "label": "mapping(uint64 => bytes32)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(SequencedBatchData)5683_storage)": { + "label": "mapping(uint64 => struct PolygonZkEVM.SequencedBatchData)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(PendingState)5693_storage": { + "label": "struct PolygonZkEVM.PendingState", + "members": [ + { + "label": "timestamp", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "lastVerifiedBatch", + "type": "t_uint64", + "offset": 8, + "slot": "0" + }, + { + "label": "exitRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "stateRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_struct(SequencedBatchData)5683_storage": { + "label": "struct PolygonZkEVM.SequencedBatchData", + "members": [ + { + "label": "accInputHash", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "sequencedTimestamp", + "type": "t_uint64", + "offset": 0, + "slot": "1" + }, + { + "label": "previousLastBatchSequenced", + "type": "t_uint64", + "offset": 8, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + }, + "5cd0db59b0eeb57c4ea1d368b5b6558e055166c8d2d5b6a32c78020af986fb5e": { + "address": "0xb1585916487AcEdD99952086f2950763D253b923", + "txHash": "0x1e28f164ca48acc0766d1ef801f2852804a24704cda619ab762254ac22957612", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_owner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "52", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + }, + { + "label": "_gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)10_storage", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:23" + }, + { + "label": "isEmergencyState", + "offset": 0, + "slot": "111", + "type": "t_bool", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:26" + }, + { + "label": "verifyBatchTimeTarget", + "offset": 1, + "slot": "111", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:167" + }, + { + "label": "multiplierBatchFee", + "offset": 9, + "slot": "111", + "type": "t_uint16", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:170" + }, + { + "label": "trustedSequencer", + "offset": 11, + "slot": "111", + "type": "t_address", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:173" + }, + { + "label": "batchFee", + "offset": 0, + "slot": "112", + "type": "t_uint256", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:176" + }, + { + "label": "forcedBatches", + "offset": 0, + "slot": "113", + "type": "t_mapping(t_uint64,t_bytes32)", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:182" + }, + { + "label": "sequencedBatches", + "offset": 0, + "slot": "114", + "type": "t_mapping(t_uint64,t_struct(SequencedBatchData)5683_storage)", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:186" + }, + { + "label": "lastTimestamp", + "offset": 0, + "slot": "115", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:189" + }, + { + "label": "lastBatchSequenced", + "offset": 8, + "slot": "115", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:192" + }, + { + "label": "lastForceBatchSequenced", + "offset": 16, + "slot": "115", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:195" + }, + { + "label": "lastForceBatch", + "offset": 24, + "slot": "115", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:198" + }, + { + "label": "lastVerifiedBatch", + "offset": 0, + "slot": "116", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:201" + }, + { + "label": "trustedAggregator", + "offset": 8, + "slot": "116", + "type": "t_address", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:204" + }, + { + "label": "batchNumToStateRoot", + "offset": 0, + "slot": "117", + "type": "t_mapping(t_uint64,t_bytes32)", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:208" + }, + { + "label": "trustedSequencerURL", + "offset": 0, + "slot": "118", + "type": "t_string_storage", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:211" + }, + { + "label": "networkName", + "offset": 0, + "slot": "119", + "type": "t_string_storage", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:214" + }, + { + "label": "pendingStateTransitions", + "offset": 0, + "slot": "120", + "type": "t_mapping(t_uint256,t_struct(PendingState)5693_storage)", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:218" + }, + { + "label": "lastPendingState", + "offset": 0, + "slot": "121", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:221" + }, + { + "label": "lastPendingStateConsolidated", + "offset": 8, + "slot": "121", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:224" + }, + { + "label": "pendingStateTimeout", + "offset": 16, + "slot": "121", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:227" + }, + { + "label": "trustedAggregatorTimeout", + "offset": 24, + "slot": "121", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:231" + }, + { + "label": "admin", + "offset": 0, + "slot": "122", + "type": "t_address", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:234" + }, + { + "label": "pendingAdmin", + "offset": 0, + "slot": "123", + "type": "t_address", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:237" + }, + { + "label": "forceBatchTimeout", + "offset": 20, + "slot": "123", + "type": "t_uint64", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:240" + }, + { + "label": "isForcedBatchDisallowed", + "offset": 28, + "slot": "123", + "type": "t_bool", + "contract": "PolygonZkEVM", + "src": "contracts/PolygonZkEVM.sol:243" + }, + { + "label": "version", + "offset": 0, + "slot": "124", + "type": "t_uint256", + "contract": "PolygonZkEVMUpgraded", + "src": "contracts/mainnetUpgraded/PolygonZkEVMUpgraded.sol:15" + }, + { + "label": "lastVerifiedBatchBeforeUpgrade", + "offset": 0, + "slot": "125", + "type": "t_uint256", + "contract": "PolygonZkEVMUpgraded", + "src": "contracts/mainnetUpgraded/PolygonZkEVMUpgraded.sol:18" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)10_storage": { + "label": "uint256[10]", + "numberOfBytes": "320" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(PendingState)5693_storage)": { + "label": "mapping(uint256 => struct PolygonZkEVM.PendingState)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_bytes32)": { + "label": "mapping(uint64 => bytes32)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(SequencedBatchData)5683_storage)": { + "label": "mapping(uint64 => struct PolygonZkEVM.SequencedBatchData)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(PendingState)5693_storage": { + "label": "struct PolygonZkEVM.PendingState", + "members": [ + { + "label": "timestamp", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "lastVerifiedBatch", + "type": "t_uint64", + "offset": 8, + "slot": "0" + }, + { + "label": "exitRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "stateRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_struct(SequencedBatchData)5683_storage": { + "label": "struct PolygonZkEVM.SequencedBatchData", + "members": [ + { + "label": "accInputHash", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "sequencedTimestamp", + "type": "t_uint64", + "offset": 0, + "slot": "1" + }, + { + "label": "previousLastBatchSequenced", + "type": "t_uint64", + "offset": 8, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "79801cf42fb30168bed48ec167efe6a64d9c46e15685898f72431bb91455bb0a": { + "address": "0x0FeB850B183C57534b56b7d56520133C8f9BDB65", + "txHash": "0x4b0fb5c86ce3a7ba42a2ad487f838c50c1dd3102b9009d8d1b3dbc1d0ccbf98a", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "_status", + "offset": 0, + "slot": "1", + "type": "t_uint256", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:38" + }, + { + "label": "__gap", + "offset": 0, + "slot": "2", + "type": "t_array(t_uint256)49_storage", + "contract": "ReentrancyGuardUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol:80" + }, + { + "label": "_branch", + "offset": 0, + "slot": "51", + "type": "t_array(t_bytes32)32_storage", + "contract": "DepositContractBase", + "src": "contracts/v2/lib/DepositContractBase.sol:23" + }, + { + "label": "depositCount", + "offset": 0, + "slot": "83", + "type": "t_uint256", + "contract": "DepositContractBase", + "src": "contracts/v2/lib/DepositContractBase.sol:26" + }, + { + "label": "_gap", + "offset": 0, + "slot": "84", + "type": "t_array(t_uint256)10_storage", + "contract": "DepositContractBase", + "src": "contracts/v2/lib/DepositContractBase.sol:32" + }, + { + "label": "_gap", + "offset": 0, + "slot": "94", + "type": "t_array(t_uint256)10_storage", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:23" + }, + { + "label": "isEmergencyState", + "offset": 0, + "slot": "104", + "type": "t_bool", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:26" + }, + { + "label": "networkID", + "offset": 1, + "slot": "104", + "type": "t_uint32", + "contract": "PolygonZkEVMBridgeV2", + "src": "contracts/v2/PolygonZkEVMBridgeV2.sol:61" + }, + { + "label": "globalExitRootManager", + "offset": 5, + "slot": "104", + "type": "t_contract(IBasePolygonZkEVMGlobalExitRoot)1675", + "contract": "PolygonZkEVMBridgeV2", + "src": "contracts/v2/PolygonZkEVMBridgeV2.sol:64" + }, + { + "label": "lastUpdatedDepositCount", + "offset": 25, + "slot": "104", + "type": "t_uint32", + "contract": "PolygonZkEVMBridgeV2", + "src": "contracts/v2/PolygonZkEVMBridgeV2.sol:67" + }, + { + "label": "claimedBitMap", + "offset": 0, + "slot": "105", + "type": "t_mapping(t_uint256,t_uint256)", + "contract": "PolygonZkEVMBridgeV2", + "src": "contracts/v2/PolygonZkEVMBridgeV2.sol:70" + }, + { + "label": "tokenInfoToWrappedToken", + "offset": 0, + "slot": "106", + "type": "t_mapping(t_bytes32,t_address)", + "contract": "PolygonZkEVMBridgeV2", + "src": "contracts/v2/PolygonZkEVMBridgeV2.sol:73" + }, + { + "label": "wrappedTokenToTokenInfo", + "offset": 0, + "slot": "107", + "type": "t_mapping(t_address,t_struct(TokenInformation)2064_storage)", + "contract": "PolygonZkEVMBridgeV2", + "src": "contracts/v2/PolygonZkEVMBridgeV2.sol:76" + }, + { + "label": "polygonRollupManager", + "offset": 0, + "slot": "108", + "type": "t_address", + "contract": "PolygonZkEVMBridgeV2", + "src": "contracts/v2/PolygonZkEVMBridgeV2.sol:80", + "renamedFrom": "polygonZkEVMaddress" + }, + { + "label": "gasTokenAddress", + "offset": 0, + "slot": "109", + "type": "t_address", + "contract": "PolygonZkEVMBridgeV2", + "src": "contracts/v2/PolygonZkEVMBridgeV2.sol:83" + }, + { + "label": "gasTokenNetwork", + "offset": 20, + "slot": "109", + "type": "t_uint32", + "contract": "PolygonZkEVMBridgeV2", + "src": "contracts/v2/PolygonZkEVMBridgeV2.sol:86" + }, + { + "label": "gasTokenMetadata", + "offset": 0, + "slot": "110", + "type": "t_bytes_storage", + "contract": "PolygonZkEVMBridgeV2", + "src": "contracts/v2/PolygonZkEVMBridgeV2.sol:89" + }, + { + "label": "WETHToken", + "offset": 0, + "slot": "111", + "type": "t_contract(TokenWrapped)2037", + "contract": "PolygonZkEVMBridgeV2", + "src": "contracts/v2/PolygonZkEVMBridgeV2.sol:92" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)32_storage": { + "label": "bytes32[32]", + "numberOfBytes": "1024" + }, + "t_array(t_uint256)10_storage": { + "label": "uint256[10]", + "numberOfBytes": "320" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes_storage": { + "label": "bytes", + "numberOfBytes": "32" + }, + "t_contract(IBasePolygonZkEVMGlobalExitRoot)1675": { + "label": "contract IBasePolygonZkEVMGlobalExitRoot", + "numberOfBytes": "20" + }, + "t_contract(TokenWrapped)2037": { + "label": "contract TokenWrapped", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_struct(TokenInformation)2064_storage)": { + "label": "mapping(address => struct PolygonZkEVMBridgeV2.TokenInformation)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_address)": { + "label": "mapping(bytes32 => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_uint256)": { + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32" + }, + "t_struct(TokenInformation)2064_storage": { + "label": "struct PolygonZkEVMBridgeV2.TokenInformation", + "members": [ + { + "label": "originNetwork", + "type": "t_uint32", + "offset": 0, + "slot": "0" + }, + { + "label": "originTokenAddress", + "type": "t_address", + "offset": 4, + "slot": "0" + } + ], + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "0276720dd07b80a08f307a7d10b2a30c8973b8dad1bb0fef986ed1e3b6a2a9c4": { + "address": "0x2E38cD55163137483E30580Cb468C2dFf1d85077", + "txHash": "0xe15832f3a7bac8245a57bf658f49b60fb06e91b6c60645ac1489c5e04a76decf", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "lastRollupExitRoot", + "offset": 0, + "slot": "0", + "type": "t_bytes32", + "contract": "PolygonZkEVMGlobalExitRootBaseStorage", + "src": "contracts/v2/lib/PolygonZkEVMGlobalExitRootBaseStorage.sol:14" + }, + { + "label": "lastMainnetExitRoot", + "offset": 0, + "slot": "1", + "type": "t_bytes32", + "contract": "PolygonZkEVMGlobalExitRootBaseStorage", + "src": "contracts/v2/lib/PolygonZkEVMGlobalExitRootBaseStorage.sol:17" + }, + { + "label": "globalExitRootMap", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_bytes32,t_uint256)", + "contract": "PolygonZkEVMGlobalExitRootBaseStorage", + "src": "contracts/v2/lib/PolygonZkEVMGlobalExitRootBaseStorage.sol:21" + }, + { + "label": "_branch", + "offset": 0, + "slot": "3", + "type": "t_array(t_bytes32)32_storage", + "contract": "DepositContractBase", + "src": "contracts/v2/lib/DepositContractBase.sol:23" + }, + { + "label": "depositCount", + "offset": 0, + "slot": "35", + "type": "t_uint256", + "contract": "DepositContractBase", + "src": "contracts/v2/lib/DepositContractBase.sol:26" + }, + { + "label": "_gap", + "offset": 0, + "slot": "36", + "type": "t_array(t_uint256)10_storage", + "contract": "DepositContractBase", + "src": "contracts/v2/lib/DepositContractBase.sol:32" + } + ], + "types": { + "t_array(t_bytes32)32_storage": { + "label": "bytes32[32]", + "numberOfBytes": "1024" + }, + "t_array(t_uint256)10_storage": { + "label": "uint256[10]", + "numberOfBytes": "320" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + } + }, + "namespaces": {} + } + }, + "55d2f394d0399c9e6e9a2e9773726fe47025d9e46193ddce8361a97fc7a550a6": { + "address": "0x3b82Da772c825283d85d5d6717A77C6Ff582053b", + "txHash": "0x19d27fa6f277e99c64a02af1a3d7532c24cabe58505f334ab98f8a5b7ac5d565", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_legacyOwner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "PolygonAccessControlUpgradeable", + "src": "contracts/v2/lib/PolygonAccessControlUpgradeable.sol:29", + "renamedFrom": "_owner" + }, + { + "label": "_roles", + "offset": 0, + "slot": "52", + "type": "t_mapping(t_bytes32,t_struct(RoleData)7463_storage)", + "contract": "PolygonAccessControlUpgradeable", + "src": "contracts/v2/lib/PolygonAccessControlUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "53", + "type": "t_array(t_uint256)48_storage", + "contract": "PolygonAccessControlUpgradeable", + "src": "contracts/v2/lib/PolygonAccessControlUpgradeable.sol:244" + }, + { + "label": "_gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)10_storage", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:23" + }, + { + "label": "isEmergencyState", + "offset": 0, + "slot": "111", + "type": "t_bool", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:26" + }, + { + "label": "_legacyVerifyBatchTimeTarget", + "offset": 1, + "slot": "111", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:45", + "renamedFrom": "verifyBatchTimeTarget" + }, + { + "label": "_legacyMultiplierBatchFee", + "offset": 9, + "slot": "111", + "type": "t_uint16", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:49", + "renamedFrom": "multiplierBatchFee" + }, + { + "label": "_legacyTrustedSequencer", + "offset": 11, + "slot": "111", + "type": "t_address", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:53", + "renamedFrom": "trustedSequencer" + }, + { + "label": "_legacyBatchFee", + "offset": 0, + "slot": "112", + "type": "t_uint256", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:57", + "renamedFrom": "batchFee" + }, + { + "label": "_legacyForcedBatches", + "offset": 0, + "slot": "113", + "type": "t_mapping(t_uint64,t_bytes32)", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:64", + "renamedFrom": "forcedBatches" + }, + { + "label": "_legacySequencedBatches", + "offset": 0, + "slot": "114", + "type": "t_mapping(t_uint64,t_struct(SequencedBatchData)7334_storage)", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:69", + "renamedFrom": "sequencedBatches" + }, + { + "label": "_legacyLastTimestamp", + "offset": 0, + "slot": "115", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:73", + "renamedFrom": "lastTimestamp" + }, + { + "label": "_legacylastBatchSequenced", + "offset": 8, + "slot": "115", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:77", + "renamedFrom": "lastBatchSequenced" + }, + { + "label": "_legacyLastForceBatchSequenced", + "offset": 16, + "slot": "115", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:81", + "renamedFrom": "lastForceBatchSequenced" + }, + { + "label": "_legacyLastForceBatch", + "offset": 24, + "slot": "115", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:85", + "renamedFrom": "lastForceBatch" + }, + { + "label": "_legacyLastVerifiedBatch", + "offset": 0, + "slot": "116", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:89", + "renamedFrom": "lastVerifiedBatch" + }, + { + "label": "_legacyTrustedAggregator", + "offset": 8, + "slot": "116", + "type": "t_address", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:93", + "renamedFrom": "trustedAggregator" + }, + { + "label": "_legacyBatchNumToStateRoot", + "offset": 0, + "slot": "117", + "type": "t_mapping(t_uint64,t_bytes32)", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:98", + "renamedFrom": "batchNumToStateRoot" + }, + { + "label": "_legacyTrustedSequencerURL", + "offset": 0, + "slot": "118", + "type": "t_string_storage", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:102", + "renamedFrom": "trustedSequencerURL" + }, + { + "label": "_legacyNetworkName", + "offset": 0, + "slot": "119", + "type": "t_string_storage", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:106", + "renamedFrom": "networkName" + }, + { + "label": "_legacyPendingStateTransitions", + "offset": 0, + "slot": "120", + "type": "t_mapping(t_uint256,t_struct(PendingState)7344_storage)", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:111", + "renamedFrom": "pendingStateTransitions" + }, + { + "label": "_legacyLastPendingState", + "offset": 0, + "slot": "121", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:115", + "renamedFrom": "lastPendingState" + }, + { + "label": "_legacyLastPendingStateConsolidated", + "offset": 8, + "slot": "121", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:119", + "renamedFrom": "lastPendingStateConsolidated" + }, + { + "label": "_legacyPendingStateTimeout", + "offset": 16, + "slot": "121", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:123", + "renamedFrom": "pendingStateTimeout" + }, + { + "label": "_legacyTrustedAggregatorTimeout", + "offset": 24, + "slot": "121", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:128", + "renamedFrom": "trustedAggregatorTimeout" + }, + { + "label": "_legacyAdmin", + "offset": 0, + "slot": "122", + "type": "t_address", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:132", + "renamedFrom": "admin" + }, + { + "label": "_legacyPendingAdmin", + "offset": 0, + "slot": "123", + "type": "t_address", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:136", + "renamedFrom": "pendingAdmin" + }, + { + "label": "_legacyForceBatchTimeout", + "offset": 20, + "slot": "123", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:140", + "renamedFrom": "forceBatchTimeout" + }, + { + "label": "_legacyIsForcedBatchDisallowed", + "offset": 28, + "slot": "123", + "type": "t_bool", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:144", + "renamedFrom": "isForcedBatchDisallowed" + }, + { + "label": "_legacyVersion", + "offset": 0, + "slot": "124", + "type": "t_uint256", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:148", + "renamedFrom": "version" + }, + { + "label": "_legacyLastVerifiedBatchBeforeUpgrade", + "offset": 0, + "slot": "125", + "type": "t_uint256", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:152", + "renamedFrom": "lastVerifiedBatchBeforeUpgrade" + }, + { + "label": "rollupTypeCount", + "offset": 0, + "slot": "126", + "type": "t_uint32", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:170" + }, + { + "label": "rollupTypeMap", + "offset": 0, + "slot": "127", + "type": "t_mapping(t_uint32,t_struct(RollupType)3613_storage)", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:173" + }, + { + "label": "rollupCount", + "offset": 0, + "slot": "128", + "type": "t_uint32", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:176" + }, + { + "label": "rollupIDToRollupData", + "offset": 0, + "slot": "129", + "type": "t_mapping(t_uint32,t_struct(RollupData)3655_storage)", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:179" + }, + { + "label": "rollupAddressToID", + "offset": 0, + "slot": "130", + "type": "t_mapping(t_address,t_uint32)", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:182" + }, + { + "label": "chainIDToRollupID", + "offset": 0, + "slot": "131", + "type": "t_mapping(t_uint64,t_uint32)", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:186" + }, + { + "label": "totalSequencedBatches", + "offset": 0, + "slot": "132", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:189" + }, + { + "label": "totalVerifiedBatches", + "offset": 8, + "slot": "132", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:192" + }, + { + "label": "lastAggregationTimestamp", + "offset": 16, + "slot": "132", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:195" + }, + { + "label": "trustedAggregatorTimeout", + "offset": 24, + "slot": "132", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:199" + }, + { + "label": "pendingStateTimeout", + "offset": 0, + "slot": "133", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:202" + }, + { + "label": "verifyBatchTimeTarget", + "offset": 8, + "slot": "133", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:206" + }, + { + "label": "multiplierBatchFee", + "offset": 16, + "slot": "133", + "type": "t_uint16", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:209" + }, + { + "label": "_batchFee", + "offset": 0, + "slot": "134", + "type": "t_uint256", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:213" + }, + { + "label": "lastDeactivatedEmergencyStateTimestamp", + "offset": 0, + "slot": "135", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:216" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)10_storage": { + "label": "uint256[10]", + "numberOfBytes": "320" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IPolygonRollupBase)6982": { + "label": "contract IPolygonRollupBase", + "numberOfBytes": "20" + }, + "t_contract(IVerifierRollup)3495": { + "label": "contract IVerifierRollup", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint32)": { + "label": "mapping(address => uint32)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)7463_storage)": { + "label": "mapping(bytes32 => struct PolygonAccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(PendingState)7344_storage)": { + "label": "mapping(uint256 => struct LegacyZKEVMStateVariables.PendingState)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint32,t_struct(RollupData)3655_storage)": { + "label": "mapping(uint32 => struct PolygonRollupManager.RollupData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint32,t_struct(RollupType)3613_storage)": { + "label": "mapping(uint32 => struct PolygonRollupManager.RollupType)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_bytes32)": { + "label": "mapping(uint64 => bytes32)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(SequencedBatchData)7334_storage)": { + "label": "mapping(uint64 => struct LegacyZKEVMStateVariables.SequencedBatchData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_uint32)": { + "label": "mapping(uint64 => uint32)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(PendingState)7344_storage": { + "label": "struct LegacyZKEVMStateVariables.PendingState", + "members": [ + { + "label": "timestamp", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "lastVerifiedBatch", + "type": "t_uint64", + "offset": 8, + "slot": "0" + }, + { + "label": "exitRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "stateRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_struct(RoleData)7463_storage": { + "label": "struct PolygonAccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(RollupData)3655_storage": { + "label": "struct PolygonRollupManager.RollupData", + "members": [ + { + "label": "rollupContract", + "type": "t_contract(IPolygonRollupBase)6982", + "offset": 0, + "slot": "0" + }, + { + "label": "chainID", + "type": "t_uint64", + "offset": 20, + "slot": "0" + }, + { + "label": "verifier", + "type": "t_contract(IVerifierRollup)3495", + "offset": 0, + "slot": "1" + }, + { + "label": "forkID", + "type": "t_uint64", + "offset": 20, + "slot": "1" + }, + { + "label": "batchNumToStateRoot", + "type": "t_mapping(t_uint64,t_bytes32)", + "offset": 0, + "slot": "2" + }, + { + "label": "sequencedBatches", + "type": "t_mapping(t_uint64,t_struct(SequencedBatchData)7334_storage)", + "offset": 0, + "slot": "3" + }, + { + "label": "pendingStateTransitions", + "type": "t_mapping(t_uint256,t_struct(PendingState)7344_storage)", + "offset": 0, + "slot": "4" + }, + { + "label": "lastLocalExitRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "5" + }, + { + "label": "lastBatchSequenced", + "type": "t_uint64", + "offset": 0, + "slot": "6" + }, + { + "label": "lastVerifiedBatch", + "type": "t_uint64", + "offset": 8, + "slot": "6" + }, + { + "label": "lastPendingState", + "type": "t_uint64", + "offset": 16, + "slot": "6" + }, + { + "label": "lastPendingStateConsolidated", + "type": "t_uint64", + "offset": 24, + "slot": "6" + }, + { + "label": "lastVerifiedBatchBeforeUpgrade", + "type": "t_uint64", + "offset": 0, + "slot": "7" + }, + { + "label": "rollupTypeID", + "type": "t_uint64", + "offset": 8, + "slot": "7" + }, + { + "label": "rollupCompatibilityID", + "type": "t_uint8", + "offset": 16, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_struct(RollupType)3613_storage": { + "label": "struct PolygonRollupManager.RollupType", + "members": [ + { + "label": "consensusImplementation", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "verifier", + "type": "t_contract(IVerifierRollup)3495", + "offset": 0, + "slot": "1" + }, + { + "label": "forkID", + "type": "t_uint64", + "offset": 20, + "slot": "1" + }, + { + "label": "rollupCompatibilityID", + "type": "t_uint8", + "offset": 28, + "slot": "1" + }, + { + "label": "obsolete", + "type": "t_bool", + "offset": 29, + "slot": "1" + }, + { + "label": "genesis", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_struct(SequencedBatchData)7334_storage": { + "label": "struct LegacyZKEVMStateVariables.SequencedBatchData", + "members": [ + { + "label": "accInputHash", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "sequencedTimestamp", + "type": "t_uint64", + "offset": 0, + "slot": "1" + }, + { + "label": "previousLastBatchSequenced", + "type": "t_uint64", + "offset": 8, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "a3d4b058e74fe980dbf467091a7b6a272bb85c59e68bdcdacefe9389c98e3059": { + "address": "0x9Bdda421219900454E94e01d641fE64c60D8f4C8", + "txHash": "0x50dacd70e51e240a3996b61cc054934bdcbd896c426c1a9fcfe41e60f0685848", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "lastRollupExitRoot", + "offset": 0, + "slot": "0", + "type": "t_bytes32", + "contract": "PolygonZkEVMGlobalExitRootBaseStorage", + "src": "contracts/v2/lib/PolygonZkEVMGlobalExitRootBaseStorage.sol:14" + }, + { + "label": "lastMainnetExitRoot", + "offset": 0, + "slot": "1", + "type": "t_bytes32", + "contract": "PolygonZkEVMGlobalExitRootBaseStorage", + "src": "contracts/v2/lib/PolygonZkEVMGlobalExitRootBaseStorage.sol:17" + }, + { + "label": "globalExitRootMap", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_bytes32,t_uint256)", + "contract": "PolygonZkEVMGlobalExitRootBaseStorage", + "src": "contracts/v2/lib/PolygonZkEVMGlobalExitRootBaseStorage.sol:21" + }, + { + "label": "_branch", + "offset": 0, + "slot": "3", + "type": "t_array(t_bytes32)32_storage", + "contract": "DepositContractBase", + "src": "contracts/v2/lib/DepositContractBase.sol:23" + }, + { + "label": "depositCount", + "offset": 0, + "slot": "35", + "type": "t_uint256", + "contract": "DepositContractBase", + "src": "contracts/v2/lib/DepositContractBase.sol:26" + }, + { + "label": "_gap", + "offset": 0, + "slot": "36", + "type": "t_array(t_uint256)10_storage", + "contract": "DepositContractBase", + "src": "contracts/v2/lib/DepositContractBase.sol:32" + }, + { + "label": "_initialized", + "offset": 0, + "slot": "46", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "46", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "l1InfoRootMap", + "offset": 0, + "slot": "47", + "type": "t_mapping(t_uint32,t_bytes32)", + "contract": "PolygonZkEVMGlobalExitRootV2", + "src": "contracts/v2/PolygonZkEVMGlobalExitRootV2.sol:26" + } + ], + "types": { + "t_array(t_bytes32)32_storage": { + "label": "bytes32[32]", + "numberOfBytes": "1024" + }, + "t_array(t_uint256)10_storage": { + "label": "uint256[10]", + "numberOfBytes": "320" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_uint256)": { + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint32,t_bytes32)": { + "label": "mapping(uint32 => bytes32)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "e81dad715669290426e2ace87376be8949fd6f394237dc4ac4dedaf1cb234ee1": { + "address": "0x103388f5661d224F4aFb555C7E4a8FB52d0b752d", + "txHash": "0x5035aa7da7f57c8e83b1510d5a88ba511cf5a74cfb7b6cd6c3f114a3f2643ad1", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_legacyOwner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "PolygonAccessControlUpgradeable", + "src": "contracts/v2/lib/PolygonAccessControlUpgradeable.sol:29", + "renamedFrom": "_owner" + }, + { + "label": "_roles", + "offset": 0, + "slot": "52", + "type": "t_mapping(t_bytes32,t_struct(RoleData)7648_storage)", + "contract": "PolygonAccessControlUpgradeable", + "src": "contracts/v2/lib/PolygonAccessControlUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "53", + "type": "t_array(t_uint256)48_storage", + "contract": "PolygonAccessControlUpgradeable", + "src": "contracts/v2/lib/PolygonAccessControlUpgradeable.sol:244" + }, + { + "label": "_gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)10_storage", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:23" + }, + { + "label": "isEmergencyState", + "offset": 0, + "slot": "111", + "type": "t_bool", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:26" + }, + { + "label": "_legacyVerifyBatchTimeTarget", + "offset": 1, + "slot": "111", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:45", + "renamedFrom": "verifyBatchTimeTarget" + }, + { + "label": "_legacyMultiplierBatchFee", + "offset": 9, + "slot": "111", + "type": "t_uint16", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:49", + "renamedFrom": "multiplierBatchFee" + }, + { + "label": "_legacyTrustedSequencer", + "offset": 11, + "slot": "111", + "type": "t_address", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:53", + "renamedFrom": "trustedSequencer" + }, + { + "label": "_legacyBatchFee", + "offset": 0, + "slot": "112", + "type": "t_uint256", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:57", + "renamedFrom": "batchFee" + }, + { + "label": "_legacyForcedBatches", + "offset": 0, + "slot": "113", + "type": "t_mapping(t_uint64,t_bytes32)", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:64", + "renamedFrom": "forcedBatches" + }, + { + "label": "_legacySequencedBatches", + "offset": 0, + "slot": "114", + "type": "t_mapping(t_uint64,t_struct(SequencedBatchData)7519_storage)", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:69", + "renamedFrom": "sequencedBatches" + }, + { + "label": "_legacyLastTimestamp", + "offset": 0, + "slot": "115", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:73", + "renamedFrom": "lastTimestamp" + }, + { + "label": "_legacylastBatchSequenced", + "offset": 8, + "slot": "115", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:77", + "renamedFrom": "lastBatchSequenced" + }, + { + "label": "_legacyLastForceBatchSequenced", + "offset": 16, + "slot": "115", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:81", + "renamedFrom": "lastForceBatchSequenced" + }, + { + "label": "_legacyLastForceBatch", + "offset": 24, + "slot": "115", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:85", + "renamedFrom": "lastForceBatch" + }, + { + "label": "_legacyLastVerifiedBatch", + "offset": 0, + "slot": "116", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:89", + "renamedFrom": "lastVerifiedBatch" + }, + { + "label": "_legacyTrustedAggregator", + "offset": 8, + "slot": "116", + "type": "t_address", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:93", + "renamedFrom": "trustedAggregator" + }, + { + "label": "_legacyBatchNumToStateRoot", + "offset": 0, + "slot": "117", + "type": "t_mapping(t_uint64,t_bytes32)", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:98", + "renamedFrom": "batchNumToStateRoot" + }, + { + "label": "_legacyTrustedSequencerURL", + "offset": 0, + "slot": "118", + "type": "t_string_storage", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:102", + "renamedFrom": "trustedSequencerURL" + }, + { + "label": "_legacyNetworkName", + "offset": 0, + "slot": "119", + "type": "t_string_storage", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:106", + "renamedFrom": "networkName" + }, + { + "label": "_legacyPendingStateTransitions", + "offset": 0, + "slot": "120", + "type": "t_mapping(t_uint256,t_struct(PendingState)7529_storage)", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:111", + "renamedFrom": "pendingStateTransitions" + }, + { + "label": "_legacyLastPendingState", + "offset": 0, + "slot": "121", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:115", + "renamedFrom": "lastPendingState" + }, + { + "label": "_legacyLastPendingStateConsolidated", + "offset": 8, + "slot": "121", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:119", + "renamedFrom": "lastPendingStateConsolidated" + }, + { + "label": "_legacyPendingStateTimeout", + "offset": 16, + "slot": "121", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:123", + "renamedFrom": "pendingStateTimeout" + }, + { + "label": "_legacyTrustedAggregatorTimeout", + "offset": 24, + "slot": "121", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:128", + "renamedFrom": "trustedAggregatorTimeout" + }, + { + "label": "_legacyAdmin", + "offset": 0, + "slot": "122", + "type": "t_address", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:132", + "renamedFrom": "admin" + }, + { + "label": "_legacyPendingAdmin", + "offset": 0, + "slot": "123", + "type": "t_address", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:136", + "renamedFrom": "pendingAdmin" + }, + { + "label": "_legacyForceBatchTimeout", + "offset": 20, + "slot": "123", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:140", + "renamedFrom": "forceBatchTimeout" + }, + { + "label": "_legacyIsForcedBatchDisallowed", + "offset": 28, + "slot": "123", + "type": "t_bool", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:144", + "renamedFrom": "isForcedBatchDisallowed" + }, + { + "label": "_legacyVersion", + "offset": 0, + "slot": "124", + "type": "t_uint256", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:148", + "renamedFrom": "version" + }, + { + "label": "_legacyLastVerifiedBatchBeforeUpgrade", + "offset": 0, + "slot": "125", + "type": "t_uint256", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:152", + "renamedFrom": "lastVerifiedBatchBeforeUpgrade" + }, + { + "label": "rollupTypeCount", + "offset": 0, + "slot": "126", + "type": "t_uint32", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:170" + }, + { + "label": "rollupTypeMap", + "offset": 0, + "slot": "127", + "type": "t_mapping(t_uint32,t_struct(RollupType)3621_storage)", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:173" + }, + { + "label": "rollupCount", + "offset": 0, + "slot": "128", + "type": "t_uint32", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:176" + }, + { + "label": "rollupIDToRollupData", + "offset": 0, + "slot": "129", + "type": "t_mapping(t_uint32,t_struct(RollupData)3663_storage)", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:179" + }, + { + "label": "rollupAddressToID", + "offset": 0, + "slot": "130", + "type": "t_mapping(t_address,t_uint32)", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:182" + }, + { + "label": "chainIDToRollupID", + "offset": 0, + "slot": "131", + "type": "t_mapping(t_uint64,t_uint32)", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:186" + }, + { + "label": "totalSequencedBatches", + "offset": 0, + "slot": "132", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:189" + }, + { + "label": "totalVerifiedBatches", + "offset": 8, + "slot": "132", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:192" + }, + { + "label": "lastAggregationTimestamp", + "offset": 16, + "slot": "132", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:195" + }, + { + "label": "trustedAggregatorTimeout", + "offset": 24, + "slot": "132", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:199" + }, + { + "label": "pendingStateTimeout", + "offset": 0, + "slot": "133", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:202" + }, + { + "label": "verifyBatchTimeTarget", + "offset": 8, + "slot": "133", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:206" + }, + { + "label": "multiplierBatchFee", + "offset": 16, + "slot": "133", + "type": "t_uint16", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:209" + }, + { + "label": "_batchFee", + "offset": 0, + "slot": "134", + "type": "t_uint256", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:213" + }, + { + "label": "lastDeactivatedEmergencyStateTimestamp", + "offset": 0, + "slot": "135", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:216" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)10_storage": { + "label": "uint256[10]", + "numberOfBytes": "320" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IPolygonRollupBase)7091": { + "label": "contract IPolygonRollupBase", + "numberOfBytes": "20" + }, + "t_contract(IVerifierRollup)3503": { + "label": "contract IVerifierRollup", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint32)": { + "label": "mapping(address => uint32)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)7648_storage)": { + "label": "mapping(bytes32 => struct PolygonAccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(PendingState)7529_storage)": { + "label": "mapping(uint256 => struct LegacyZKEVMStateVariables.PendingState)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint32,t_struct(RollupData)3663_storage)": { + "label": "mapping(uint32 => struct PolygonRollupManager.RollupData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint32,t_struct(RollupType)3621_storage)": { + "label": "mapping(uint32 => struct PolygonRollupManager.RollupType)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_bytes32)": { + "label": "mapping(uint64 => bytes32)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(SequencedBatchData)7519_storage)": { + "label": "mapping(uint64 => struct LegacyZKEVMStateVariables.SequencedBatchData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_uint32)": { + "label": "mapping(uint64 => uint32)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(PendingState)7529_storage": { + "label": "struct LegacyZKEVMStateVariables.PendingState", + "members": [ + { + "label": "timestamp", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "lastVerifiedBatch", + "type": "t_uint64", + "offset": 8, + "slot": "0" + }, + { + "label": "exitRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "stateRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_struct(RoleData)7648_storage": { + "label": "struct PolygonAccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(RollupData)3663_storage": { + "label": "struct PolygonRollupManager.RollupData", + "members": [ + { + "label": "rollupContract", + "type": "t_contract(IPolygonRollupBase)7091", + "offset": 0, + "slot": "0" + }, + { + "label": "chainID", + "type": "t_uint64", + "offset": 20, + "slot": "0" + }, + { + "label": "verifier", + "type": "t_contract(IVerifierRollup)3503", + "offset": 0, + "slot": "1" + }, + { + "label": "forkID", + "type": "t_uint64", + "offset": 20, + "slot": "1" + }, + { + "label": "batchNumToStateRoot", + "type": "t_mapping(t_uint64,t_bytes32)", + "offset": 0, + "slot": "2" + }, + { + "label": "sequencedBatches", + "type": "t_mapping(t_uint64,t_struct(SequencedBatchData)7519_storage)", + "offset": 0, + "slot": "3" + }, + { + "label": "pendingStateTransitions", + "type": "t_mapping(t_uint256,t_struct(PendingState)7529_storage)", + "offset": 0, + "slot": "4" + }, + { + "label": "lastLocalExitRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "5" + }, + { + "label": "lastBatchSequenced", + "type": "t_uint64", + "offset": 0, + "slot": "6" + }, + { + "label": "lastVerifiedBatch", + "type": "t_uint64", + "offset": 8, + "slot": "6" + }, + { + "label": "lastPendingState", + "type": "t_uint64", + "offset": 16, + "slot": "6" + }, + { + "label": "lastPendingStateConsolidated", + "type": "t_uint64", + "offset": 24, + "slot": "6" + }, + { + "label": "lastVerifiedBatchBeforeUpgrade", + "type": "t_uint64", + "offset": 0, + "slot": "7" + }, + { + "label": "rollupTypeID", + "type": "t_uint64", + "offset": 8, + "slot": "7" + }, + { + "label": "rollupCompatibilityID", + "type": "t_uint8", + "offset": 16, + "slot": "7" + } + ], + "numberOfBytes": "256" + }, + "t_struct(RollupType)3621_storage": { + "label": "struct PolygonRollupManager.RollupType", + "members": [ + { + "label": "consensusImplementation", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "verifier", + "type": "t_contract(IVerifierRollup)3503", + "offset": 0, + "slot": "1" + }, + { + "label": "forkID", + "type": "t_uint64", + "offset": 20, + "slot": "1" + }, + { + "label": "rollupCompatibilityID", + "type": "t_uint8", + "offset": 28, + "slot": "1" + }, + { + "label": "obsolete", + "type": "t_bool", + "offset": 29, + "slot": "1" + }, + { + "label": "genesis", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_struct(SequencedBatchData)7519_storage": { + "label": "struct LegacyZKEVMStateVariables.SequencedBatchData", + "members": [ + { + "label": "accInputHash", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "sequencedTimestamp", + "type": "t_uint64", + "offset": 0, + "slot": "1" + }, + { + "label": "previousLastBatchSequenced", + "type": "t_uint64", + "offset": 8, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + }, + "a450e577c140682dc145643c778d87fdc12555158db14a7a92ef84024655bb44": { + "address": "0xA33619940bceb9be7c9679Dd80FA2918C2476382", + "txHash": "0xb779797cb34a0557f251f1bbd65fe9ab0b2e33bfa016a629125e235c5e822a73", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "_legacyOwner", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "PolygonAccessControlUpgradeable", + "src": "contracts/v2/lib/PolygonAccessControlUpgradeable.sol:29", + "renamedFrom": "_owner" + }, + { + "label": "_roles", + "offset": 0, + "slot": "52", + "type": "t_mapping(t_bytes32,t_struct(RoleData)7254_storage)", + "contract": "PolygonAccessControlUpgradeable", + "src": "contracts/v2/lib/PolygonAccessControlUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "53", + "type": "t_array(t_uint256)48_storage", + "contract": "PolygonAccessControlUpgradeable", + "src": "contracts/v2/lib/PolygonAccessControlUpgradeable.sol:244" + }, + { + "label": "_gap", + "offset": 0, + "slot": "101", + "type": "t_array(t_uint256)10_storage", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:23" + }, + { + "label": "isEmergencyState", + "offset": 0, + "slot": "111", + "type": "t_bool", + "contract": "EmergencyManager", + "src": "contracts/lib/EmergencyManager.sol:26" + }, + { + "label": "_legacyVerifyBatchTimeTarget", + "offset": 1, + "slot": "111", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:45", + "renamedFrom": "verifyBatchTimeTarget" + }, + { + "label": "_legacyMultiplierBatchFee", + "offset": 9, + "slot": "111", + "type": "t_uint16", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:49", + "renamedFrom": "multiplierBatchFee" + }, + { + "label": "_legacyTrustedSequencer", + "offset": 11, + "slot": "111", + "type": "t_address", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:53", + "renamedFrom": "trustedSequencer" + }, + { + "label": "_legacyBatchFee", + "offset": 0, + "slot": "112", + "type": "t_uint256", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:57", + "renamedFrom": "batchFee" + }, + { + "label": "_legacyForcedBatches", + "offset": 0, + "slot": "113", + "type": "t_mapping(t_uint64,t_bytes32)", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:64", + "renamedFrom": "forcedBatches" + }, + { + "label": "_legacySequencedBatches", + "offset": 0, + "slot": "114", + "type": "t_mapping(t_uint64,t_struct(SequencedBatchData)7125_storage)", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:69", + "renamedFrom": "sequencedBatches" + }, + { + "label": "_legacyLastTimestamp", + "offset": 0, + "slot": "115", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:73", + "renamedFrom": "lastTimestamp" + }, + { + "label": "_legacylastBatchSequenced", + "offset": 8, + "slot": "115", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:77", + "renamedFrom": "lastBatchSequenced" + }, + { + "label": "_legacyLastForceBatchSequenced", + "offset": 16, + "slot": "115", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:81", + "renamedFrom": "lastForceBatchSequenced" + }, + { + "label": "_legacyLastForceBatch", + "offset": 24, + "slot": "115", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:85", + "renamedFrom": "lastForceBatch" + }, + { + "label": "_legacyLastVerifiedBatch", + "offset": 0, + "slot": "116", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:89", + "renamedFrom": "lastVerifiedBatch" + }, + { + "label": "_legacyTrustedAggregator", + "offset": 8, + "slot": "116", + "type": "t_address", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:93", + "renamedFrom": "trustedAggregator" + }, + { + "label": "_legacyBatchNumToStateRoot", + "offset": 0, + "slot": "117", + "type": "t_mapping(t_uint64,t_bytes32)", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:98", + "renamedFrom": "batchNumToStateRoot" + }, + { + "label": "_legacyTrustedSequencerURL", + "offset": 0, + "slot": "118", + "type": "t_string_storage", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:102", + "renamedFrom": "trustedSequencerURL" + }, + { + "label": "_legacyNetworkName", + "offset": 0, + "slot": "119", + "type": "t_string_storage", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:106", + "renamedFrom": "networkName" + }, + { + "label": "_legacyPendingStateTransitions", + "offset": 0, + "slot": "120", + "type": "t_mapping(t_uint256,t_struct(PendingState)7135_storage)", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:111", + "renamedFrom": "pendingStateTransitions" + }, + { + "label": "_legacyLastPendingState", + "offset": 0, + "slot": "121", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:115", + "renamedFrom": "lastPendingState" + }, + { + "label": "_legacyLastPendingStateConsolidated", + "offset": 8, + "slot": "121", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:119", + "renamedFrom": "lastPendingStateConsolidated" + }, + { + "label": "_legacyPendingStateTimeout", + "offset": 16, + "slot": "121", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:123", + "renamedFrom": "pendingStateTimeout" + }, + { + "label": "_legacyTrustedAggregatorTimeout", + "offset": 24, + "slot": "121", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:128", + "renamedFrom": "trustedAggregatorTimeout" + }, + { + "label": "_legacyAdmin", + "offset": 0, + "slot": "122", + "type": "t_address", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:132", + "renamedFrom": "admin" + }, + { + "label": "_legacyPendingAdmin", + "offset": 0, + "slot": "123", + "type": "t_address", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:136", + "renamedFrom": "pendingAdmin" + }, + { + "label": "_legacyForceBatchTimeout", + "offset": 20, + "slot": "123", + "type": "t_uint64", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:140", + "renamedFrom": "forceBatchTimeout" + }, + { + "label": "_legacyIsForcedBatchDisallowed", + "offset": 28, + "slot": "123", + "type": "t_bool", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:144", + "renamedFrom": "isForcedBatchDisallowed" + }, + { + "label": "_legacyVersion", + "offset": 0, + "slot": "124", + "type": "t_uint256", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:148", + "renamedFrom": "version" + }, + { + "label": "_legacyLastVerifiedBatchBeforeUpgrade", + "offset": 0, + "slot": "125", + "type": "t_uint256", + "contract": "LegacyZKEVMStateVariables", + "src": "contracts/v2/lib/LegacyZKEVMStateVariables.sol:152", + "renamedFrom": "lastVerifiedBatchBeforeUpgrade" + }, + { + "label": "rollupTypeCount", + "offset": 0, + "slot": "126", + "type": "t_uint32", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:247" + }, + { + "label": "rollupTypeMap", + "offset": 0, + "slot": "127", + "type": "t_mapping(t_uint32,t_struct(RollupType)3633_storage)", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:251", + "retypedFrom": "PolygonRollupManagerPrevious.RollupType" + }, + { + "label": "rollupCount", + "offset": 0, + "slot": "128", + "type": "t_uint32", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:254" + }, + { + "label": "_rollupIDToRollupData", + "offset": 0, + "slot": "129", + "type": "t_mapping(t_uint32,t_struct(RollupData)3683_storage)", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:258", + "retypedFrom": "PolygonRollupManagerPrevious.RollupData" + }, + { + "label": "rollupAddressToID", + "offset": 0, + "slot": "130", + "type": "t_mapping(t_address,t_uint32)", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:261" + }, + { + "label": "chainIDToRollupID", + "offset": 0, + "slot": "131", + "type": "t_mapping(t_uint64,t_uint32)", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:265" + }, + { + "label": "totalSequencedBatches", + "offset": 0, + "slot": "132", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:268" + }, + { + "label": "totalVerifiedBatches", + "offset": 8, + "slot": "132", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:271" + }, + { + "label": "lastAggregationTimestamp", + "offset": 16, + "slot": "132", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:274" + }, + { + "label": "__legacyTrustedAggregatorTimeout", + "offset": 24, + "slot": "132", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:279", + "renamedFrom": "trustedAggregatorTimeout" + }, + { + "label": "__legacyPendingStateTimeout", + "offset": 0, + "slot": "133", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:283", + "renamedFrom": "pendingStateTimeout" + }, + { + "label": "__legacyVerifyBatchTimeTarget", + "offset": 8, + "slot": "133", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:288", + "renamedFrom": "verifyBatchTimeTarget" + }, + { + "label": "__legacyMultiplierBatchFee", + "offset": 16, + "slot": "133", + "type": "t_uint16", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:292", + "renamedFrom": "multiplierBatchFee" + }, + { + "label": "_batchFee", + "offset": 0, + "slot": "134", + "type": "t_uint256", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:296" + }, + { + "label": "lastDeactivatedEmergencyStateTimestamp", + "offset": 0, + "slot": "135", + "type": "t_uint64", + "contract": "PolygonRollupManager", + "src": "contracts/v2/PolygonRollupManager.sol:299" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)10_storage": { + "label": "uint256[10]", + "numberOfBytes": "320" + }, + "t_array(t_uint256)48_storage": { + "label": "uint256[48]", + "numberOfBytes": "1536" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IPolygonRollupBase)6433": { + "label": "contract IPolygonRollupBase", + "numberOfBytes": "20" + }, + "t_enum(VerifierType)6622": { + "label": "enum IPolygonRollupManager.VerifierType", + "members": [ + "StateTransition", + "Pessimistic" + ], + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint32)": { + "label": "mapping(address => uint32)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)7254_storage)": { + "label": "mapping(bytes32 => struct PolygonAccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_struct(PendingState)7135_storage)": { + "label": "mapping(uint256 => struct LegacyZKEVMStateVariables.PendingState)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint32,t_struct(RollupData)3683_storage)": { + "label": "mapping(uint32 => struct PolygonRollupManager.RollupData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint32,t_struct(RollupType)3633_storage)": { + "label": "mapping(uint32 => struct PolygonRollupManager.RollupType)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_bytes32)": { + "label": "mapping(uint64 => bytes32)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_struct(SequencedBatchData)7125_storage)": { + "label": "mapping(uint64 => struct LegacyZKEVMStateVariables.SequencedBatchData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint64,t_uint32)": { + "label": "mapping(uint64 => uint32)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(PendingState)7135_storage": { + "label": "struct LegacyZKEVMStateVariables.PendingState", + "members": [ + { + "label": "timestamp", + "type": "t_uint64", + "offset": 0, + "slot": "0" + }, + { + "label": "lastVerifiedBatch", + "type": "t_uint64", + "offset": 8, + "slot": "0" + }, + { + "label": "exitRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + }, + { + "label": "stateRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + } + ], + "numberOfBytes": "96" + }, + "t_struct(RoleData)7254_storage": { + "label": "struct PolygonAccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_struct(RollupData)3683_storage": { + "label": "struct PolygonRollupManager.RollupData", + "members": [ + { + "label": "rollupContract", + "type": "t_contract(IPolygonRollupBase)6433", + "offset": 0, + "slot": "0" + }, + { + "label": "chainID", + "type": "t_uint64", + "offset": 20, + "slot": "0" + }, + { + "label": "verifier", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "forkID", + "type": "t_uint64", + "offset": 20, + "slot": "1" + }, + { + "label": "batchNumToStateRoot", + "type": "t_mapping(t_uint64,t_bytes32)", + "offset": 0, + "slot": "2" + }, + { + "label": "sequencedBatches", + "type": "t_mapping(t_uint64,t_struct(SequencedBatchData)7125_storage)", + "offset": 0, + "slot": "3" + }, + { + "label": "_legacyPendingStateTransitions", + "type": "t_mapping(t_uint256,t_struct(PendingState)7135_storage)", + "offset": 0, + "slot": "4" + }, + { + "label": "lastLocalExitRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "5" + }, + { + "label": "lastBatchSequenced", + "type": "t_uint64", + "offset": 0, + "slot": "6" + }, + { + "label": "lastVerifiedBatch", + "type": "t_uint64", + "offset": 8, + "slot": "6" + }, + { + "label": "_legacyLastPendingState", + "type": "t_uint64", + "offset": 16, + "slot": "6" + }, + { + "label": "_legacyLastPendingStateConsolidated", + "type": "t_uint64", + "offset": 24, + "slot": "6" + }, + { + "label": "lastVerifiedBatchBeforeUpgrade", + "type": "t_uint64", + "offset": 0, + "slot": "7" + }, + { + "label": "rollupTypeID", + "type": "t_uint64", + "offset": 8, + "slot": "7" + }, + { + "label": "rollupVerifierType", + "type": "t_enum(VerifierType)6622", + "offset": 16, + "slot": "7" + }, + { + "label": "lastPessimisticRoot", + "type": "t_bytes32", + "offset": 0, + "slot": "8" + }, + { + "label": "programVKey", + "type": "t_bytes32", + "offset": 0, + "slot": "9" + } + ], + "numberOfBytes": "320" + }, + "t_struct(RollupType)3633_storage": { + "label": "struct PolygonRollupManager.RollupType", + "members": [ + { + "label": "consensusImplementation", + "type": "t_address", + "offset": 0, + "slot": "0" + }, + { + "label": "verifier", + "type": "t_address", + "offset": 0, + "slot": "1" + }, + { + "label": "forkID", + "type": "t_uint64", + "offset": 20, + "slot": "1" + }, + { + "label": "rollupVerifierType", + "type": "t_enum(VerifierType)6622", + "offset": 28, + "slot": "1" + }, + { + "label": "obsolete", + "type": "t_bool", + "offset": 29, + "slot": "1" + }, + { + "label": "genesis", + "type": "t_bytes32", + "offset": 0, + "slot": "2" + }, + { + "label": "programVKey", + "type": "t_bytes32", + "offset": 0, + "slot": "3" + } + ], + "numberOfBytes": "128" + }, + "t_struct(SequencedBatchData)7125_storage": { + "label": "struct LegacyZKEVMStateVariables.SequencedBatchData", + "members": [ + { + "label": "accInputHash", + "type": "t_bytes32", + "offset": 0, + "slot": "0" + }, + { + "label": "sequencedTimestamp", + "type": "t_uint64", + "offset": 0, + "slot": "1" + }, + { + "label": "previousLastBatchSequenced", + "type": "t_uint64", + "offset": 8, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint16": { + "label": "uint16", + "numberOfBytes": "2" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint64": { + "label": "uint64", + "numberOfBytes": "8" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + } + } +} diff --git a/upgrade/upgradePessimistic/mainnet-info/upgrade_output.json b/upgrade/upgradePessimistic/mainnet-info/upgrade_output.json new file mode 100644 index 000000000..3253af405 --- /dev/null +++ b/upgrade/upgradePessimistic/mainnet-info/upgrade_output.json @@ -0,0 +1,20 @@ +{ + "scheduleData": "0x01d5062a0000000000000000000000000f99738b2fc14d77308337f3e2596b63ae7bcc4a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d2f0000000000000000000000000000000000000000000000000000000000000000a49623609d0000000000000000000000005132a183e9f3cb7c848b0aac5ae0c4f0491b7ab2000000000000000000000000a33619940bceb9be7c9679dd80fa2918c2476382000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000048129fc1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "executeData": "0x134008d30000000000000000000000000f99738b2fc14d77308337f3e2596b63ae7bcc4a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a49623609d0000000000000000000000005132a183e9f3cb7c848b0aac5ae0c4f0491b7ab2000000000000000000000000a33619940bceb9be7c9679dd80fa2918c2476382000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000048129fc1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "timelockContractAddress": "0xEf1462451C30Ea7aD8555386226059Fe837CA4EF", + "decodedScheduleData": { + "target": "0x0F99738B2Fc14D77308337f3e2596b63aE7BCC4A", + "value": "0", + "data": "0x9623609d0000000000000000000000005132a183e9f3cb7c848b0aac5ae0c4f0491b7ab2000000000000000000000000a33619940bceb9be7c9679dd80fa2918c2476382000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000", + "decodedData": { + "signature": "upgradeAndCall(address,address,bytes)", + "selector": "0x9623609d", + "proxy": "0x5132A183E9F3CB7C848b0AAC5Ae0c4f0491B7aB2", + "implementation": "0xA33619940bceb9be7c9679Dd80FA2918C2476382", + "data": "0x8129fc1c" + }, + "predecessor": "0x0000000000000000000000000000000000000000000000000000000000000000", + "salt": "0x0000000000000000000000000000000000000000000000000000000000000000", + "delay": "864000" + } +} \ No newline at end of file diff --git a/upgrade/upgradePessimistic/upgradePessimistic.ts b/upgrade/upgradePessimistic/upgradePessimistic.ts new file mode 100644 index 000000000..7d3e27255 --- /dev/null +++ b/upgrade/upgradePessimistic/upgradePessimistic.ts @@ -0,0 +1,218 @@ +/* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if */ +/* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved */ +import {expect} from "chai"; +import path = require("path"); +import fs = require("fs"); +import {utils} from "ffjavascript"; + +import * as dotenv from "dotenv"; +dotenv.config({path: path.resolve(__dirname, "../../.env")}); +import {ethers, upgrades} from "hardhat"; +import {PolygonRollupManager} from "../../typechain-types"; + +const pathOutputJson = path.join(__dirname, "./upgrade_output.json"); + +const upgradeParameters = require("./upgrade_parameters.json"); + +async function main() { + upgrades.silenceWarnings(); + + /* + * Check upgrade parameters + * Check that every necessary parameter is fulfilled + */ + const mandatoryUpgradeParameters = ["rollupManagerAddress", "timelockDelay"]; + + for (const parameterName of mandatoryUpgradeParameters) { + if (upgradeParameters[parameterName] === undefined || upgradeParameters[parameterName] === "") { + throw new Error(`Missing parameter: ${parameterName}`); + } + } + const {rollupManagerAddress, timelockDelay} = upgradeParameters; + const salt = upgradeParameters.timelockSalt || ethers.ZeroHash; + + // Load onchain parameters + const polygonRMFactory = await ethers.getContractFactory("PolygonRollupManagerPrevious"); + const polygonRMContract = (await polygonRMFactory.attach(rollupManagerAddress)) as PolygonRollupManager; + + const globalExitRootManagerAddress = await polygonRMContract.globalExitRootManager(); + const polAddress = await polygonRMContract.pol(); + const bridgeAddress = await polygonRMContract.bridgeAddress(); + + // Load provider + const currentProvider = ethers.provider; + if (upgradeParameters.multiplierGas || upgradeParameters.maxFeePerGas) { + if (process.env.HARDHAT_NETWORK !== "hardhat") { + currentProvider = ethers.getDefaultProvider( + `https://${process.env.HARDHAT_NETWORK}.infura.io/v3/${process.env.INFURA_PROJECT_ID}` + ) as any; + if (upgradeParameters.maxPriorityFeePerGas && upgradeParameters.maxFeePerGas) { + console.log( + `Hardcoded gas used: MaxPriority${upgradeParameters.maxPriorityFeePerGas} gwei, MaxFee${upgradeParameters.maxFeePerGas} gwei` + ); + const FEE_DATA = new ethers.FeeData( + null, + ethers.parseUnits(upgradeParameters.maxFeePerGas, "gwei"), + ethers.parseUnits(upgradeParameters.maxPriorityFeePerGas, "gwei") + ); + + currentProvider.getFeeData = async () => FEE_DATA; + } else { + console.log("Multiplier gas used: ", upgradeParameters.multiplierGas); + async function overrideFeeData() { + const feeData = await ethers.provider.getFeeData(); + return new ethers.FeeData( + null, + ((feeData.maxFeePerGas as bigint) * BigInt(upgradeParameters.multiplierGas)) / 1000n, + ((feeData.maxPriorityFeePerGas as bigint) * BigInt(upgradeParameters.multiplierGas)) / 1000n + ); + } + currentProvider.getFeeData = overrideFeeData; + } + } + } + + // Load deployer + let deployer; + if (upgradeParameters.deployerPvtKey) { + deployer = new ethers.Wallet(upgradeParameters.deployerPvtKey, currentProvider); + } else if (process.env.MNEMONIC) { + deployer = ethers.HDNodeWallet.fromMnemonic( + ethers.Mnemonic.fromPhrase(process.env.MNEMONIC), + "m/44'/60'/0'/0/0" + ).connect(currentProvider); + } else { + [deployer] = await ethers.getSigners(); + } + + console.log("deploying with: ", deployer.address); + + const proxyAdmin = await upgrades.admin.getInstance(); + + // Assert correct admin + expect(await upgrades.erc1967.getAdminAddress(rollupManagerAddress as string)).to.be.equal(proxyAdmin.target); + + const timelockAddress = await proxyAdmin.owner(); + + // load timelock + const timelockContractFactory = await ethers.getContractFactory("PolygonZkEVMTimelock", deployer); + + // prepare upgrades + + // Upgrade to rollup manager + const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManager", deployer); + + const implRollupManager = await upgrades.prepareUpgrade(rollupManagerAddress, PolygonRollupManagerFactory, { + constructorArgs: [globalExitRootManagerAddress, polAddress, bridgeAddress], + unsafeAllow: ["constructor", "state-variable-immutable", "enum-definition", "struct-definition"], + unsafeAllowRenames: true, + unsafeAllowCustomTypes: true, + unsafeSkipStorageCheck: true, + }); + + console.log("#######################\n"); + console.log(`Polygon rollup manager: ${implRollupManager}`); + + console.log("you can verify the new impl address with:"); + console.log( + `npx hardhat verify --constructor-args upgrade/arguments.js ${implRollupManager} --network ${process.env.HARDHAT_NETWORK}\n` + ); + console.log("Copy the following constructor arguments on: upgrade/arguments.js \n", [ + globalExitRootManagerAddress, + polAddress, + bridgeAddress, + ]); + + const operationRollupManager = genOperation( + proxyAdmin.target, + 0, // value + proxyAdmin.interface.encodeFunctionData("upgradeAndCall", [ + rollupManagerAddress, + implRollupManager, + PolygonRollupManagerFactory.interface.encodeFunctionData("initialize", []), + ]), // data + ethers.ZeroHash, // predecessor + salt // salt + ); + + // Schedule operation + const scheduleData = timelockContractFactory.interface.encodeFunctionData("schedule", [ + operationRollupManager.target, + operationRollupManager.value, + operationRollupManager.data, + ethers.ZeroHash, // predecessor + salt, // salt + timelockDelay, + ]); + + // Execute operation + const executeData = timelockContractFactory.interface.encodeFunctionData("execute", [ + operationRollupManager.target, + operationRollupManager.value, + operationRollupManager.data, + ethers.ZeroHash, // predecessor + salt, // salt + ]); + + console.log({scheduleData}); + console.log({executeData}); + + const outputJson = { + scheduleData, + executeData, + timelockContractAddress: timelockAddress, + }; + + // Decode the scheduleData for better readability + const timelockTx = timelockContractFactory.interface.parseTransaction({data: scheduleData}); + const paramsArray = timelockTx?.fragment.inputs as any; + const objectDecoded = {} as any; + + for (let i = 0; i < paramsArray?.length; i++) { + const currentParam = paramsArray[i]; + objectDecoded[currentParam.name] = timelockTx?.args[i]; + + if (currentParam.name == "data") { + const decodedProxyAdmin = proxyAdmin.interface.parseTransaction({ + data: timelockTx?.args[i], + }); + const objectDecodedData = {} as any; + const paramsArrayData = decodedProxyAdmin?.fragment.inputs as any; + + objectDecodedData.signature = decodedProxyAdmin?.signature; + objectDecodedData.selector = decodedProxyAdmin?.selector; + + for (let j = 0; j < paramsArrayData?.length; j++) { + const currentParam = paramsArrayData[j]; + objectDecodedData[currentParam.name] = decodedProxyAdmin?.args[j]; + } + objectDecoded["decodedData"] = objectDecodedData; + } + } + + outputJson.decodedScheduleData = objectDecoded; + + fs.writeFileSync(pathOutputJson, JSON.stringify(utils.stringifyBigInts(outputJson), null, 1)); +} + +main().catch((e) => { + console.error(e); + process.exit(1); +}); + +// OZ test functions +function genOperation(target: any, value: any, data: any, predecessor: any, salt: any) { + const abiEncoded = ethers.AbiCoder.defaultAbiCoder().encode( + ["address", "uint256", "bytes", "uint256", "bytes32"], + [target, value, data, predecessor, salt] + ); + const id = ethers.keccak256(abiEncoded); + return { + id, + target, + value, + data, + predecessor, + salt, + }; +} diff --git a/upgrade/upgradePessimistic/upgrade_parameters.json.example b/upgrade/upgradePessimistic/upgrade_parameters.json.example new file mode 100644 index 000000000..ba1e2fb60 --- /dev/null +++ b/upgrade/upgradePessimistic/upgrade_parameters.json.example @@ -0,0 +1,9 @@ +{ + "rollupManagerAddress": "0x00..", + "timelockDelay": 0, + "timelockSalt": "", + "deployerPvtKey": "", + "maxFeePerGas": "", + "maxPriorityFeePerGas": "", + "multiplierGas": "" +}