From 73236b461b9d93de3d54eef010c98fef1d4ac205 Mon Sep 17 00:00:00 2001 From: teddy Date: Thu, 8 Aug 2024 14:38:56 -0300 Subject: [PATCH 01/56] chore: configure medusa with basic supERC20 self-bridging - used --foundry-compile-all to ensure the test contract under `test/properties` is compiled (otherwise it is not compiled and medusa crashes when it can't find it's compiled representation) - set src,test,script to test/properties/medusa to not waste time compiling contracts that are not required for the medusa campaign - used an atomic bridge, which doesnt allow for testing of several of the proposed invariants --- packages/contracts-bedrock/.gitignore | 1 + packages/contracts-bedrock/foundry.toml | 5 + packages/contracts-bedrock/justfile | 3 + packages/contracts-bedrock/medusa.json | 82 ++++++++++ .../test/properties/PROPERTIES.md | 71 ++++++++ .../test/properties/SUMMARY.md | 43 +++++ .../test/properties/helpers/Utils.sol | 14 ++ .../properties/medusa/ProtocolAtomic.t.sol | 151 ++++++++++++++++++ 8 files changed, 370 insertions(+) create mode 100644 packages/contracts-bedrock/medusa.json create mode 100644 packages/contracts-bedrock/test/properties/PROPERTIES.md create mode 100644 packages/contracts-bedrock/test/properties/SUMMARY.md create mode 100644 packages/contracts-bedrock/test/properties/helpers/Utils.sol create mode 100644 packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol diff --git a/packages/contracts-bedrock/.gitignore b/packages/contracts-bedrock/.gitignore index 96e09c8c7190..396c03d4458d 100644 --- a/packages/contracts-bedrock/.gitignore +++ b/packages/contracts-bedrock/.gitignore @@ -6,6 +6,7 @@ broadcast kout-deployment kout-proofs test/kontrol/logs +test/properties/medusa/corpus/ # Metrics coverage.out diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 9edf752f983d..3b69c67412f6 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -96,3 +96,8 @@ src = 'test/kontrol/proofs' out = 'kout-proofs' test = 'test/kontrol/proofs' script = 'test/kontrol/proofs' + +[profile.medusa] +src = 'test/properties/medusa/' +test = 'test/properties/medusa/' +script = 'test/properties/medusa/' diff --git a/packages/contracts-bedrock/justfile b/packages/contracts-bedrock/justfile index 45cdd14cfae0..ebb8d9db6d47 100644 --- a/packages/contracts-bedrock/justfile +++ b/packages/contracts-bedrock/justfile @@ -22,6 +22,9 @@ test: build-go-ffi test-kontrol: ./test/kontrol/scripts/run-kontrol.sh script +test-medusa: + FOUNDRY_PROFILE=medusa medusa fuzz + test-rerun: build-go-ffi forge test --rerun -vvv diff --git a/packages/contracts-bedrock/medusa.json b/packages/contracts-bedrock/medusa.json new file mode 100644 index 000000000000..76592655ffa1 --- /dev/null +++ b/packages/contracts-bedrock/medusa.json @@ -0,0 +1,82 @@ +{ + "fuzzing": { + "workers": 10, + "workerResetLimit": 50, + "timeout": 0, + "testLimit": 500000, + "callSequenceLength": 100, + "corpusDirectory": "test/properties/medusa/corpus/", + "coverageEnabled": true, + "targetContracts": ["ProtocolAtomicFuzz"], + "targetContractsBalances": [], + "constructorArgs": {}, + "deployerAddress": "0x30000", + "senderAddresses": [ + "0x10000", + "0x20000", + "0x30000" + ], + "blockNumberDelayMax": 60480, + "blockTimestampDelayMax": 604800, + "blockGasLimit": 125000000, + "transactionGasLimit": 12500000, + "testing": { + "stopOnFailedTest": true, + "stopOnFailedContractMatching": false, + "stopOnNoTests": true, + "testAllContracts": false, + "traceAll": true, + "assertionTesting": { + "enabled": true, + "testViewMethods": false, + "panicCodeConfig": { + "failOnCompilerInsertedPanic": false, + "failOnAssertion": true, + "failOnArithmeticUnderflow": false, + "failOnDivideByZero": false, + "failOnEnumTypeConversionOutOfBounds": false, + "failOnIncorrectStorageAccess": false, + "failOnPopEmptyArray": false, + "failOnOutOfBoundsArrayAccess": false, + "failOnAllocateTooMuchMemory": false, + "failOnCallUninitializedVariable": false + } + }, + "propertyTesting": { + "enabled": false, + "testPrefixes": [ + "property_" + ] + }, + "optimizationTesting": { + "enabled": false, + "testPrefixes": [ + "optimize_" + ] + }, + "targetFunctionSignatures": [], + "excludeFunctionSignatures": [] + }, + "chainConfig": { + "codeSizeCheckDisabled": true, + "cheatCodes": { + "cheatCodesEnabled": true, + "enableFFI": false + } + } + }, + "compilation": { + "platform": "crytic-compile", + "platformConfig": { + "target": ".", + "solcVersion": "", + "exportDirectory": "", + "args": ["--foundry-out-directory", "artifacts","--foundry-compile-all"] + } + }, + "logging": { + "level": "info", + "logDirectory": "", + "noColor": false + } +} diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md new file mode 100644 index 000000000000..b3a18514d254 --- /dev/null +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -0,0 +1,71 @@ +# supertoken properties + +legend: +- `[ ]`: property not yet tested +- `**[ ]**`: property not yet tested, dev/research team has asked for extra focus on it +- `[X]`: tested/proven property +- `:(`: property won't be tested due to some limitation + +## Unit test + +| id | description | halmos | medusa | +| --- | --- | --- | --- | +| 0 | supertoken token address does not depend on the executing chain’s chainID | [ ] | [x] | +| 1 | supertoken token address depends on name, remote token, address and decimals | [ ] | [x] | +| 2 | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | [ ] | +| 3 | convert() only allows migrations between tokens representing the same remote asset | [ ] | [ ] | +| 4 | convert() only allows migrations from tokens with the same decimals | [ ] | [ ] | +| 5 | convert() burns the same amount of one token that it mints of the other | [ ] | [ ] | + +## Valid state + +| id | description | halmos | medusa | +| --- | --- | --- | --- | +| 6 | calls to sendERC20 succeed as long as caller has enough balance | [ ] | [ ] | +| 7 | calls to relayERC20 always succeed as long as the cross-domain caller is valid | **[ ]** | [ ] | + +## Variable transition + +| id | description | halmos | medusa | +| --- | --- | --- | --- | +| 8 | sendERC20 with a value of zero does not modify accounting | [ ] | [ ] | +| 9 | relayERC20 with a value of zero does not modify accounting | [ ] | [ ] | +| 10 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [ ] | [ ] | +| 11 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [ ] | [ ] | +| 12 | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [ ] | [ ] | +| 13 | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [ ] | [ ] | +| 14 | supertoken total supply starts at zero | [ ] | [ ] | +| 15 | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | +| 16 | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | + +## High level + +| id | description | halmos | medusa | +| --- | --- | --- | --- | +| 17 | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | [ ] | +| 18 | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | [ ] | +| 19 | sum of total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | +| 20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | [ ] | +| 21 | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [ ] | [ ] | + +## Atomic bridging pseudo-properties + +As another layer of defense, the following properties are defined which assume bridging operations to be atomic (that is, the sequencer and L2Inbox and CrossDomainMessenger contracts are fully abstracted away, `sendERC20` triggering the `relayERC20` call on the same transaction) +It’s worth noting that these properties will not hold for a live system + +| id | description | halmos | echidna | +| --- | --- | --- | --- | +| 20 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [ ] | +| 21 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [ ] | +| 22 | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | + +# Expected external interactions + +- regular ERC20 operations between any accounts on the same chain, provided by [crytic ERC20 properties](https://github.com/crytic/properties?tab=readme-ov-file#erc20-tests) + +# Invariant-breaking candidates (brain dump) + +here we’ll list possible interactions that we intend the fuzzing campaign to support in order to help break invariants + +- [ ] changing the decimals of tokens after deployment +- [ ] `convert()` ing between multiple (3+) representations of the same remote token, by having different names/symbols diff --git a/packages/contracts-bedrock/test/properties/SUMMARY.md b/packages/contracts-bedrock/test/properties/SUMMARY.md new file mode 100644 index 000000000000..ed6c286556fd --- /dev/null +++ b/packages/contracts-bedrock/test/properties/SUMMARY.md @@ -0,0 +1,43 @@ +# SupERC20 advanced testing + +# Overview + +This document defines a set of properties global to the supertoken ecosystem, for which we will: + +- run a [Medusa](https://github.com/crytic/medusa) fuzzing campaign, trying to break system invariants +- formally prove with [Halmos](https://github.com/ethereum-optimism/optimism) whenever possible + +## Where to place the testing campaign + +Given the [OP monorepo](https://github.com/ethereum-optimism/optimism) already has invariant testing provided by foundry, it's not a trivial matter where to place this advanced testing campaign. Two alternatives are proposed: + +- including it in the mainline OP monorepo, in a subdirectory of the existing test contracts such as `test/invariants/medusa/superc20/` +- creating a separate (potentially private) repository for this testing campaign, in which case the deliverable would consist primarily of: + - a summary of the results, extending this document + - PRs with extra unit tests replicating found issues to the main repo where applicable + +## Contracts in scope + +- [ ] [OptimismSuperchainERC20](https://github.com/defi-wonderland/optimism/pull/9/files#diff-810060510a8a9c06dc60cdce6782e5cafd93b638e2557307a68abe694ee86aee) +- [ ] [OptimismMintableERC20Factory](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol) +- [ ] [SuperchsupERC20ainERC20](https://github.com/defi-wonderland/optimism/pull/8/files#diff-603fd7d5a0b2c403c0d1eee21d0ee60fb8eb72430169eaac5ec7081e01de96b8) (not yet merged) +- [ ] [SuperchainERC20Factory](https://github.com/defi-wonderland/optimism/pull/8/files#diff-09838f5703c353d0f7c5ff395acc04c1768ef58becac67404bc17e1fb0018517) (not yet merged) +- [ ] [L2StandardBridgeInterop](https://github.com/defi-wonderland/optimism/pull/10/files#diff-56cf869412631eac0a04a03f7d026596f64a1e00fcffa713bc770d67c6856c2f) (not yet merged) + +## Behavior assumed correct + +- [ ] inclusion of relay transactions +- [ ] sequencer implementation +- [ ] [OptimismMintableERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol) +- [ ] [L2ToL2CrossDomainMessenger](https://www.notion.so/defi-wonderland/src/L2/L2CrossDomainMessenger.sol) +- [ ] [CrossL2Inbox](https://www.notion.so/defi-wonderland/src/L2/CrossL2Inbox.sol) + +## Pain points + +- existing fuzzing tools use the same EVM to run the tested contracts as they do for asserting invariants, tracking ghost variables and everything else necessary to provision a fuzzing campaign. While this is usually very convenient, it means that we can’t assert on the behaviour/state of *different* EVMs from within a fuzzing campaign. This means we will have to walk around the requirement of supertokens having the same address across all chains, and implement a way to mock tokens existing in different chains. We will strive to formally prove it in a unitary fashion to mitigate this in properties 13 and 14 +- a buffer to represent 'in transit' messages should be implemented to assert on invariants relating to the non-atomicity of bridging from one chain to another. It is yet to be determined if it’ll be a FIFO queue (assuming ideal message ordering by sequencers) or it’ll have random-access capability to simulate messages arriving out of order + +## Definitions + +- *legacy token:* an OptimismMintableERC20 or L2StandardERC20 token on the suprechain that has either been deployed by the factory after the liquidity migration upgrade to the latter, or has been deployed before it **but** added to factory’s `deployments` mapping as part of the upgrade. This testing campaign is not concerned with tokens on L1 or not listed in the factory’s `deployments` mapping. +- *supertoken:* a SuperchainERC20 contract deployed on the Superchain diff --git a/packages/contracts-bedrock/test/properties/helpers/Utils.sol b/packages/contracts-bedrock/test/properties/helpers/Utils.sol new file mode 100644 index 000000000000..eabf7b483f18 --- /dev/null +++ b/packages/contracts-bedrock/test/properties/helpers/Utils.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { MockERC20 } from "forge-std/mocks/MockERC20.sol"; + +contract FuzzERC20 is MockERC20 { + function mint(address _to, uint256 _amount) public { + _mint(_to, _amount); + } + + function burn(address _from, uint256 _amount) public { + _burn(_from, _amount); + } +} diff --git a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol new file mode 100644 index 000000000000..55e63b42963e --- /dev/null +++ b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import "forge-std/console.sol"; + +import { Test } from "forge-std/Test.sol"; + +import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { SafeCall } from "src/libraries/SafeCall.sol"; +import { FuzzERC20 } from "../helpers/Utils.sol"; + +contract MockCrossDomainMessenger { + address public crossDomainMessageSender; + address public crossDomainMessageSource; + mapping(uint256 chainId => mapping(bytes32 reayDeployData => address)) internal superTokenAddresses; + mapping(address => bytes32) internal superTokenInitDeploySalts; + // test-specific functions + + function crossChainMessageReceiver(address sender, uint256 destinationChainId) external returns (OptimismSuperchainERC20) { + return OptimismSuperchainERC20(superTokenAddresses[destinationChainId][superTokenInitDeploySalts[sender]]); + } + + function registerSupertoken(bytes32 deploySalt, uint256 chainId, address token) external { + superTokenAddresses[chainId][deploySalt] = token; + superTokenInitDeploySalts[token] = deploySalt; + } + // mocked functions + + function sendMessage(uint256 chainId, address recipient, bytes memory message) external returns (address) { + address crossChainRecipient = superTokenAddresses[chainId][superTokenInitDeploySalts[msg.sender]]; + if (crossChainRecipient == msg.sender) { + require(false, "same chain"); + } + crossDomainMessageSender = crossChainRecipient; + crossDomainMessageSource = msg.sender; + SafeCall.call(crossDomainMessageSender, 0, message); + crossDomainMessageSender = address(0); + } +} + +contract ProtocolAtomicFuzz is Test { + uint8 internal constant MAX_CHAINS = 4; + address internal constant BRIDGE = Predeploys.L2_STANDARD_BRIDGE; + MockCrossDomainMessenger internal constant MESSENGER = + MockCrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + OptimismSuperchainERC20 internal superchainERC20Impl; + string[] internal WORDS = ["FANCY", "TOKENS"]; + uint8[] internal DECIMALS = [0, 6, 18, 36]; + + struct TokenDeployParams { + uint8 remoteTokenIndex; + uint8 name; + uint8 symbol; + uint8 decimals; + } + + address[] internal remoteTokens; + address[] internal allSuperTokens; + mapping(bytes32 => uint256) internal superTokenTotalSupply; + mapping(bytes32 => uint256) internal superTokensTotalSupply; + + constructor() { + vm.etch(address(MESSENGER), address(new MockCrossDomainMessenger()).code); + superchainERC20Impl = new OptimismSuperchainERC20(); + } + + modifier validateTokenDeployParams(TokenDeployParams memory params) { + params.remoteTokenIndex = uint8(bound(params.remoteTokenIndex, 0, remoteTokens.length - 1)); + params.name = uint8(bound(params.name, 0, WORDS.length - 1)); + params.symbol = uint8(bound(params.symbol, 0, WORDS.length - 1)); + params.decimals = uint8(bound(params.decimals, 0, DECIMALS.length - 1)); + _; + } + + function fuzz_DeployNewSupertoken( + TokenDeployParams memory params, + uint256 chainId + ) + external + validateTokenDeployParams(params) + { + chainId = bound(chainId, 0, MAX_CHAINS - 1); + _deploySupertoken( + remoteTokens[params.remoteTokenIndex], + WORDS[params.name], + WORDS[params.symbol], + DECIMALS[params.decimals], + chainId + ); + } + + function fuzz_SelfBridgeSupertoken(uint256 fromIndex, uint256 destinationChainId, uint256 amount) external { + destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); + fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); + OptimismSuperchainERC20 sourceToken = OptimismSuperchainERC20(allSuperTokens[fromIndex]); + OptimismSuperchainERC20 destinationToken = MESSENGER.crossChainMessageReceiver(address(sourceToken), destinationChainId); + // TODO: when implementing non-atomic bridging, allow for the token to + // not yet be deployed and funds be recovered afterwards. + require(address(destinationToken) != address(0)); + uint256 balanceFromBefore = sourceToken.balanceOf(msg.sender); + uint256 balanceToBefore = destinationToken.balanceOf(msg.sender); + vm.prank(msg.sender); + try sourceToken.sendERC20(msg.sender, amount, destinationChainId) { + uint256 balanceFromAfter = sourceToken.balanceOf(msg.sender); + uint256 balanceToAfter = destinationToken.balanceOf(msg.sender); + assert(balanceFromBefore + balanceToBefore == balanceFromAfter + balanceToAfter); + } catch { + assert(balanceFromBefore < amount || address(destinationToken) == address(sourceToken)); + } + } + + // TODO: track total supply for invariant checking + function fuzz_MintSupertoken(uint256 index, uint96 amount) external { + index = bound(index, 0, allSuperTokens.length - 1); + address addr = allSuperTokens[index]; + vm.prank(BRIDGE); + // medusa calls with different senders by default + OptimismSuperchainERC20(addr).mint(msg.sender, amount); + } + + function fuzz_MockNewRemoteToken() external { + // make sure they don't conflict with predeploys/preinstalls/precompiles/other tokens + remoteTokens.push(address(uint160(1000 + remoteTokens.length))); + } + + function _deploySupertoken( + address remoteToken, + string memory name, + string memory symbol, + uint8 decimals, + uint256 chainId + ) + internal + { + bytes32 realSalt = keccak256(abi.encode(remoteToken, name, symbol, decimals)); + bytes32 hackySalt = keccak256(abi.encode(remoteToken, name, symbol, decimals, chainId)); + OptimismSuperchainERC20 localToken = OptimismSuperchainERC20( + address( + // TODO: Use the SuperchainERC20 Beacon Proxy + new ERC1967Proxy{ salt: hackySalt }( + address(superchainERC20Impl), + abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) + ) + ) + ); + MESSENGER.registerSupertoken(realSalt, chainId, address(localToken)); + allSuperTokens.push(address(localToken)); + } +} From 6f386a560b7112954b6105269edd131a360fe57e Mon Sep 17 00:00:00 2001 From: teddy Date: Tue, 13 Aug 2024 17:51:45 -0300 Subject: [PATCH 02/56] fix: delete dead code --- .../test/properties/helpers/Utils.sol | 14 -------------- .../test/properties/medusa/ProtocolAtomic.t.sol | 3 +-- 2 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 packages/contracts-bedrock/test/properties/helpers/Utils.sol diff --git a/packages/contracts-bedrock/test/properties/helpers/Utils.sol b/packages/contracts-bedrock/test/properties/helpers/Utils.sol deleted file mode 100644 index eabf7b483f18..000000000000 --- a/packages/contracts-bedrock/test/properties/helpers/Utils.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -import { MockERC20 } from "forge-std/mocks/MockERC20.sol"; - -contract FuzzERC20 is MockERC20 { - function mint(address _to, uint256 _amount) public { - _mint(_to, _amount); - } - - function burn(address _from, uint256 _amount) public { - _burn(_from, _amount); - } -} diff --git a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol index 55e63b42963e..ef795e3d29aa 100644 --- a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol @@ -9,7 +9,6 @@ import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Pr import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; -import { FuzzERC20 } from "../helpers/Utils.sol"; contract MockCrossDomainMessenger { address public crossDomainMessageSender; @@ -28,7 +27,7 @@ contract MockCrossDomainMessenger { } // mocked functions - function sendMessage(uint256 chainId, address recipient, bytes memory message) external returns (address) { + function sendMessage(uint256 chainId, address /*recipient*/, bytes memory message) external { address crossChainRecipient = superTokenAddresses[chainId][superTokenInitDeploySalts[msg.sender]]; if (crossChainRecipient == msg.sender) { require(false, "same chain"); From e8d42b8a7224b850c44ba4100f0db55e891b91d7 Mon Sep 17 00:00:00 2001 From: teddy Date: Tue, 13 Aug 2024 17:53:39 -0300 Subject: [PATCH 03/56] test: give the fuzzer a head start --- .../properties/medusa/ProtocolAtomic.t.sol | 43 +++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol index ef795e3d29aa..d16b79610737 100644 --- a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol @@ -17,7 +17,13 @@ contract MockCrossDomainMessenger { mapping(address => bytes32) internal superTokenInitDeploySalts; // test-specific functions - function crossChainMessageReceiver(address sender, uint256 destinationChainId) external returns (OptimismSuperchainERC20) { + function crossChainMessageReceiver( + address sender, + uint256 destinationChainId + ) + external + returns (OptimismSuperchainERC20) + { return OptimismSuperchainERC20(superTokenAddresses[destinationChainId][superTokenInitDeploySalts[sender]]); } @@ -27,7 +33,7 @@ contract MockCrossDomainMessenger { } // mocked functions - function sendMessage(uint256 chainId, address /*recipient*/, bytes memory message) external { + function sendMessage(uint256 chainId, address, /*recipient*/ bytes memory message) external { address crossChainRecipient = superTokenAddresses[chainId][superTokenInitDeploySalts[msg.sender]]; if (crossChainRecipient == msg.sender) { require(false, "same chain"); @@ -41,12 +47,16 @@ contract MockCrossDomainMessenger { contract ProtocolAtomicFuzz is Test { uint8 internal constant MAX_CHAINS = 4; + uint8 internal constant INITIAL_TOKENS = 2; + uint8 internal constant INITIAL_SUPERTOKENS = 2; + uint8 internal constant SUPERTOKEN_INITIAL_MINT = 100; address internal constant BRIDGE = Predeploys.L2_STANDARD_BRIDGE; MockCrossDomainMessenger internal constant MESSENGER = MockCrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); OptimismSuperchainERC20 internal superchainERC20Impl; - string[] internal WORDS = ["FANCY", "TOKENS"]; - uint8[] internal DECIMALS = [0, 6, 18, 36]; + // NOTE: having more options for this enables the fuzzer to configure different supertokens for the same + string[] internal WORDS = ["TOKENS"]; + uint8[] internal DECIMALS = [6, 18]; struct TokenDeployParams { uint8 remoteTokenIndex; @@ -63,6 +73,12 @@ contract ProtocolAtomicFuzz is Test { constructor() { vm.etch(address(MESSENGER), address(new MockCrossDomainMessenger()).code); superchainERC20Impl = new OptimismSuperchainERC20(); + for (uint256 i = 0; i < INITIAL_TOKENS; i++) { + _deployRemoteToken(); + for (uint256 j = 0; j < INITIAL_SUPERTOKENS ; j++){ + _deploySupertoken(remoteTokens[i], WORDS[0], WORDS[0], DECIMALS[0], j); + } + } } modifier validateTokenDeployParams(TokenDeployParams memory params) { @@ -94,11 +110,14 @@ contract ProtocolAtomicFuzz is Test { destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); OptimismSuperchainERC20 sourceToken = OptimismSuperchainERC20(allSuperTokens[fromIndex]); - OptimismSuperchainERC20 destinationToken = MESSENGER.crossChainMessageReceiver(address(sourceToken), destinationChainId); + OptimismSuperchainERC20 destinationToken = + MESSENGER.crossChainMessageReceiver(address(sourceToken), destinationChainId); // TODO: when implementing non-atomic bridging, allow for the token to // not yet be deployed and funds be recovered afterwards. require(address(destinationToken) != address(0)); uint256 balanceFromBefore = sourceToken.balanceOf(msg.sender); + // NOTE: lift this requirement to allow one more failure mode + amount = bound(amount, 0, balanceFromBefore); uint256 balanceToBefore = destinationToken.balanceOf(msg.sender); vm.prank(msg.sender); try sourceToken.sendERC20(msg.sender, amount, destinationChainId) { @@ -106,7 +125,7 @@ contract ProtocolAtomicFuzz is Test { uint256 balanceToAfter = destinationToken.balanceOf(msg.sender); assert(balanceFromBefore + balanceToBefore == balanceFromAfter + balanceToAfter); } catch { - assert(balanceFromBefore < amount || address(destinationToken) == address(sourceToken)); + assert(address(destinationToken) == address(sourceToken)); } } @@ -120,6 +139,10 @@ contract ProtocolAtomicFuzz is Test { } function fuzz_MockNewRemoteToken() external { + _deployRemoteToken(); + } + + function _deployRemoteToken() internal { // make sure they don't conflict with predeploys/preinstalls/precompiles/other tokens remoteTokens.push(address(uint160(1000 + remoteTokens.length))); } @@ -135,7 +158,7 @@ contract ProtocolAtomicFuzz is Test { { bytes32 realSalt = keccak256(abi.encode(remoteToken, name, symbol, decimals)); bytes32 hackySalt = keccak256(abi.encode(remoteToken, name, symbol, decimals, chainId)); - OptimismSuperchainERC20 localToken = OptimismSuperchainERC20( + OptimismSuperchainERC20 token = OptimismSuperchainERC20( address( // TODO: Use the SuperchainERC20 Beacon Proxy new ERC1967Proxy{ salt: hackySalt }( @@ -144,7 +167,9 @@ contract ProtocolAtomicFuzz is Test { ) ) ); - MESSENGER.registerSupertoken(realSalt, chainId, address(localToken)); - allSuperTokens.push(address(localToken)); + MESSENGER.registerSupertoken(realSalt, chainId, address(token)); + allSuperTokens.push(address(token)); + vm.prank(BRIDGE); + token.mint(msg.sender, INITIAL_TOKENS * 10 ** decimals); } } From 326366b1d51f3548bbb48f56d82b79ddd52a60de Mon Sep 17 00:00:00 2001 From: teddy Date: Wed, 14 Aug 2024 11:21:20 -0300 Subject: [PATCH 04/56] docs: fix properties order --- packages/contracts-bedrock/test/properties/PROPERTIES.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md index b3a18514d254..152232a8473b 100644 --- a/packages/contracts-bedrock/test/properties/PROPERTIES.md +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -55,9 +55,9 @@ It’s worth noting that these properties will not hold for a live system | id | description | halmos | echidna | | --- | --- | --- | --- | -| 20 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [ ] | -| 21 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [ ] | -| 22 | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | +| 22 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [ ] | +| 23 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [ ] | +| 24 | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | # Expected external interactions From 7a66ae6743d0407709fdfa7676617c4c340949af Mon Sep 17 00:00:00 2001 From: teddy Date: Tue, 13 Aug 2024 18:56:45 -0300 Subject: [PATCH 05/56] test: document & implement assertions 22, 23 and 24 --- .../properties/medusa/ProtocolAtomic.t.sol | 75 ++++++++++++++----- 1 file changed, 57 insertions(+), 18 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol index d16b79610737..e1a84c80c40f 100644 --- a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol @@ -1,11 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; -import "forge-std/console.sol"; - import { Test } from "forge-std/Test.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; +import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; @@ -13,8 +12,8 @@ import { SafeCall } from "src/libraries/SafeCall.sol"; contract MockCrossDomainMessenger { address public crossDomainMessageSender; address public crossDomainMessageSource; - mapping(uint256 chainId => mapping(bytes32 reayDeployData => address)) internal superTokenAddresses; - mapping(address => bytes32) internal superTokenInitDeploySalts; + mapping(address => bytes32) public superTokenInitDeploySalts; + mapping(uint256 chainId => mapping(bytes32 reayDeployData => address)) public superTokenAddresses; // test-specific functions function crossChainMessageReceiver( @@ -46,15 +45,18 @@ contract MockCrossDomainMessenger { } contract ProtocolAtomicFuzz is Test { + using EnumerableMap for EnumerableMap.Bytes32ToUintMap; + uint8 internal constant MAX_CHAINS = 4; - uint8 internal constant INITIAL_TOKENS = 2; - uint8 internal constant INITIAL_SUPERTOKENS = 2; + uint8 internal constant INITIAL_TOKENS = 1; + uint8 internal constant INITIAL_SUPERTOKENS = 1; uint8 internal constant SUPERTOKEN_INITIAL_MINT = 100; address internal constant BRIDGE = Predeploys.L2_STANDARD_BRIDGE; MockCrossDomainMessenger internal constant MESSENGER = MockCrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); OptimismSuperchainERC20 internal superchainERC20Impl; - // NOTE: having more options for this enables the fuzzer to configure different supertokens for the same + // NOTE: having more options for this enables the fuzzer to configure + // different supertokens for the same remote token string[] internal WORDS = ["TOKENS"]; uint8[] internal DECIMALS = [6, 18]; @@ -67,15 +69,16 @@ contract ProtocolAtomicFuzz is Test { address[] internal remoteTokens; address[] internal allSuperTokens; - mapping(bytes32 => uint256) internal superTokenTotalSupply; - mapping(bytes32 => uint256) internal superTokensTotalSupply; + + // deploy salt => total supply sum across chains + EnumerableMap.Bytes32ToUintMap internal ghost_totalSupplyAcrossChains; constructor() { vm.etch(address(MESSENGER), address(new MockCrossDomainMessenger()).code); superchainERC20Impl = new OptimismSuperchainERC20(); for (uint256 i = 0; i < INITIAL_TOKENS; i++) { _deployRemoteToken(); - for (uint256 j = 0; j < INITIAL_SUPERTOKENS ; j++){ + for (uint256 j = 0; j < INITIAL_SUPERTOKENS; j++) { _deploySupertoken(remoteTokens[i], WORDS[0], WORDS[0], DECIMALS[0], j); } } @@ -106,6 +109,8 @@ contract ProtocolAtomicFuzz is Test { ); } + /// @custom:property-id 22 + /// @custom:property-id 23 function fuzz_SelfBridgeSupertoken(uint256 fromIndex, uint256 destinationChainId, uint256 amount) external { destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); @@ -115,27 +120,58 @@ contract ProtocolAtomicFuzz is Test { // TODO: when implementing non-atomic bridging, allow for the token to // not yet be deployed and funds be recovered afterwards. require(address(destinationToken) != address(0)); - uint256 balanceFromBefore = sourceToken.balanceOf(msg.sender); + uint256 sourceBalanceBefore = sourceToken.balanceOf(msg.sender); + uint256 sourceSupplyBefore = sourceToken.totalSupply(); // NOTE: lift this requirement to allow one more failure mode - amount = bound(amount, 0, balanceFromBefore); - uint256 balanceToBefore = destinationToken.balanceOf(msg.sender); + uint256 destinationBalanceBefore = destinationToken.balanceOf(msg.sender); + uint256 destinationSupplyBefore = destinationToken.totalSupply(); + + amount = bound(amount, 0, sourceBalanceBefore); vm.prank(msg.sender); try sourceToken.sendERC20(msg.sender, amount, destinationChainId) { - uint256 balanceFromAfter = sourceToken.balanceOf(msg.sender); - uint256 balanceToAfter = destinationToken.balanceOf(msg.sender); - assert(balanceFromBefore + balanceToBefore == balanceFromAfter + balanceToAfter); + uint256 sourceBalanceAfter = sourceToken.balanceOf(msg.sender); + uint256 destinationBalanceAfter = destinationToken.balanceOf(msg.sender); + // no free mint + assert(sourceBalanceBefore + destinationBalanceBefore == sourceBalanceAfter + destinationBalanceAfter); + // 22 + assert(sourceBalanceBefore - amount == sourceBalanceAfter); + assert(destinationBalanceBefore + amount == destinationBalanceAfter); + uint256 sourceSupplyAfter = sourceToken.totalSupply(); + uint256 destinationSupplyAfter = destinationToken.totalSupply(); + // 23 + assert(sourceSupplyBefore - amount == sourceSupplyAfter); + assert(destinationSupplyBefore + amount == destinationSupplyAfter); } catch { assert(address(destinationToken) == address(sourceToken)); } } - // TODO: track total supply for invariant checking function fuzz_MintSupertoken(uint256 index, uint96 amount) external { index = bound(index, 0, allSuperTokens.length - 1); address addr = allSuperTokens[index]; vm.prank(BRIDGE); // medusa calls with different senders by default OptimismSuperchainERC20(addr).mint(msg.sender, amount); + uint256 currentValue = ghost_totalSupplyAcrossChains.get(MESSENGER.superTokenInitDeploySalts(addr)); + ghost_totalSupplyAcrossChains.set(MESSENGER.superTokenInitDeploySalts(addr), currentValue + amount); + } + + // TODO: will need rework after + // - non-atomic bridge + // - `convert` + /// @custom:property-id 24 + function property_totalSupplyAcrossChainsEqualsMints() external { + for (uint256 i = 0; i < ghost_totalSupplyAcrossChains.length(); i++) { + uint256 totalSupply = 0; + (bytes32 currentSalt, uint256 trackedSupply) = ghost_totalSupplyAcrossChains.at(i); + for (uint256 j = 0; j < MAX_CHAINS; j++) { + address supertoken = MESSENGER.superTokenAddresses(j, currentSalt); + if (supertoken != address(0)) { + totalSupply += OptimismSuperchainERC20(supertoken).totalSupply(); + } + } + assert(trackedSupply == totalSupply); + } } function fuzz_MockNewRemoteToken() external { @@ -169,7 +205,10 @@ contract ProtocolAtomicFuzz is Test { ); MESSENGER.registerSupertoken(realSalt, chainId, address(token)); allSuperTokens.push(address(token)); + uint256 mintAmount = INITIAL_TOKENS * 10 ** decimals; vm.prank(BRIDGE); - token.mint(msg.sender, INITIAL_TOKENS * 10 ** decimals); + token.mint(msg.sender, mintAmount); + (,uint256 curr) = ghost_totalSupplyAcrossChains.tryGet(realSalt); + ghost_totalSupplyAcrossChains.set(realSalt, curr + mintAmount); } } From fa4cf29a5f41b4e334d81fcce1aa5704c9fa7604 Mon Sep 17 00:00:00 2001 From: teddy Date: Wed, 14 Aug 2024 12:26:16 -0300 Subject: [PATCH 06/56] fix: fixes from self-review --- .../test/properties/PROPERTIES.md | 13 ++-- .../test/properties/SUMMARY.md | 8 +- .../helpers/MockCrossDomainMessenger.t.sol | 52 +++++++++++++ .../properties/medusa/ProtocolAtomic.t.sol | 78 ++++++------------- 4 files changed, 88 insertions(+), 63 deletions(-) create mode 100644 packages/contracts-bedrock/test/properties/helpers/MockCrossDomainMessenger.t.sol diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md index 152232a8473b..540d591f77de 100644 --- a/packages/contracts-bedrock/test/properties/PROPERTIES.md +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -4,14 +4,15 @@ legend: - `[ ]`: property not yet tested - `**[ ]**`: property not yet tested, dev/research team has asked for extra focus on it - `[X]`: tested/proven property +- `[~]`: partially tested/proven property - `:(`: property won't be tested due to some limitation ## Unit test | id | description | halmos | medusa | | --- | --- | --- | --- | -| 0 | supertoken token address does not depend on the executing chain’s chainID | [ ] | [x] | -| 1 | supertoken token address depends on name, remote token, address and decimals | [ ] | [x] | +| 0 | supertoken token address does not depend on the executing chain’s chainID | [ ] | [ ] | +| 1 | supertoken token address depends on name, remote token, address and decimals | [ ] | [ ] | | 2 | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | [ ] | | 3 | convert() only allows migrations between tokens representing the same remote asset | [ ] | [ ] | | 4 | convert() only allows migrations from tokens with the same decimals | [ ] | [ ] | @@ -53,11 +54,11 @@ legend: As another layer of defense, the following properties are defined which assume bridging operations to be atomic (that is, the sequencer and L2Inbox and CrossDomainMessenger contracts are fully abstracted away, `sendERC20` triggering the `relayERC20` call on the same transaction) It’s worth noting that these properties will not hold for a live system -| id | description | halmos | echidna | +| id | description | halmos | medusa | | --- | --- | --- | --- | -| 22 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [ ] | -| 23 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [ ] | -| 24 | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | +| 22 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [x] | +| 23 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [x] | +| 24 | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [~] | # Expected external interactions diff --git a/packages/contracts-bedrock/test/properties/SUMMARY.md b/packages/contracts-bedrock/test/properties/SUMMARY.md index ed6c286556fd..cf9c8a93afa5 100644 --- a/packages/contracts-bedrock/test/properties/SUMMARY.md +++ b/packages/contracts-bedrock/test/properties/SUMMARY.md @@ -5,7 +5,7 @@ This document defines a set of properties global to the supertoken ecosystem, for which we will: - run a [Medusa](https://github.com/crytic/medusa) fuzzing campaign, trying to break system invariants -- formally prove with [Halmos](https://github.com/ethereum-optimism/optimism) whenever possible +- formally prove with [Halmos](https://github.com/a16z/halmos) whenever possible ## Where to place the testing campaign @@ -29,12 +29,12 @@ Given the [OP monorepo](https://github.com/ethereum-optimism/optimism) already h - [ ] inclusion of relay transactions - [ ] sequencer implementation - [ ] [OptimismMintableERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol) -- [ ] [L2ToL2CrossDomainMessenger](https://www.notion.so/defi-wonderland/src/L2/L2CrossDomainMessenger.sol) -- [ ] [CrossL2Inbox](https://www.notion.so/defi-wonderland/src/L2/CrossL2Inbox.sol) +- [ ] [L2ToL2CrossDomainMessenger](https://github.com/defi-wonderland/src/L2/L2CrossDomainMessenger.sol) +- [ ] [CrossL2Inbox](https://github.com/defi-wonderland/src/L2/CrossL2Inbox.sol) ## Pain points -- existing fuzzing tools use the same EVM to run the tested contracts as they do for asserting invariants, tracking ghost variables and everything else necessary to provision a fuzzing campaign. While this is usually very convenient, it means that we can’t assert on the behaviour/state of *different* EVMs from within a fuzzing campaign. This means we will have to walk around the requirement of supertokens having the same address across all chains, and implement a way to mock tokens existing in different chains. We will strive to formally prove it in a unitary fashion to mitigate this in properties 13 and 14 +- existing fuzzing tools use the same EVM to run the tested contracts as they do for asserting invariants, tracking ghost variables and everything else necessary to provision a fuzzing campaign. While this is usually very convenient, it means that we can’t assert on the behaviour/state of *different* EVMs from within a fuzzing campaign. This means we will have to walk around the requirement of supertokens having the same address across all chains, and implement a way to mock tokens existing in different chains. We will strive to formally prove it in a unitary fashion to mitigate this in properties 0 and 1 - a buffer to represent 'in transit' messages should be implemented to assert on invariants relating to the non-atomicity of bridging from one chain to another. It is yet to be determined if it’ll be a FIFO queue (assuming ideal message ordering by sequencers) or it’ll have random-access capability to simulate messages arriving out of order ## Definitions diff --git a/packages/contracts-bedrock/test/properties/helpers/MockCrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/properties/helpers/MockCrossDomainMessenger.t.sol new file mode 100644 index 000000000000..4ad4d474b738 --- /dev/null +++ b/packages/contracts-bedrock/test/properties/helpers/MockCrossDomainMessenger.t.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { SafeCall } from "src/libraries/SafeCall.sol"; + +contract MockCrossDomainMessenger { + ///////////////////////////////////////////////////////// + // State vars mocking the L2toL2CrossDomainMessenger // + ///////////////////////////////////////////////////////// + address public crossDomainMessageSender; + address public crossDomainMessageSource; + + /////////////////////////////////////////////////// + // Helpers for cross-chain interaction mocking // + /////////////////////////////////////////////////// + mapping(address => bytes32) public superTokenInitDeploySalts; + mapping(uint256 chainId => mapping(bytes32 reayDeployData => address)) public superTokenAddresses; + + function crossChainMessageReceiver( + address sender, + uint256 destinationChainId + ) + external + returns (OptimismSuperchainERC20) + { + return OptimismSuperchainERC20(superTokenAddresses[destinationChainId][superTokenInitDeploySalts[sender]]); + } + + function registerSupertoken(bytes32 deploySalt, uint256 chainId, address token) external { + superTokenAddresses[chainId][deploySalt] = token; + superTokenInitDeploySalts[token] = deploySalt; + } + + //////////////////////////////////////////////////////// + // Functions mocking the L2toL2CrossDomainMessenger // + //////////////////////////////////////////////////////// + + /// @dev recipient will not be used since in normal execution it's the same + /// address on a different chain, but here we have to compute it to mock + /// cross-chain messaging + function sendMessage(uint256 chainId, address, /*recipient*/ bytes memory message) external { + address crossChainRecipient = superTokenAddresses[chainId][superTokenInitDeploySalts[msg.sender]]; + if (crossChainRecipient == msg.sender) { + require(false, "same chain"); + } + crossDomainMessageSender = crossChainRecipient; + crossDomainMessageSource = msg.sender; + SafeCall.call(crossDomainMessageSender, 0, message); + crossDomainMessageSender = address(0); + } +} diff --git a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol index e1a84c80c40f..a7ffa6229039 100644 --- a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol @@ -7,42 +7,7 @@ import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Pr import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { SafeCall } from "src/libraries/SafeCall.sol"; - -contract MockCrossDomainMessenger { - address public crossDomainMessageSender; - address public crossDomainMessageSource; - mapping(address => bytes32) public superTokenInitDeploySalts; - mapping(uint256 chainId => mapping(bytes32 reayDeployData => address)) public superTokenAddresses; - // test-specific functions - - function crossChainMessageReceiver( - address sender, - uint256 destinationChainId - ) - external - returns (OptimismSuperchainERC20) - { - return OptimismSuperchainERC20(superTokenAddresses[destinationChainId][superTokenInitDeploySalts[sender]]); - } - - function registerSupertoken(bytes32 deploySalt, uint256 chainId, address token) external { - superTokenAddresses[chainId][deploySalt] = token; - superTokenInitDeploySalts[token] = deploySalt; - } - // mocked functions - - function sendMessage(uint256 chainId, address, /*recipient*/ bytes memory message) external { - address crossChainRecipient = superTokenAddresses[chainId][superTokenInitDeploySalts[msg.sender]]; - if (crossChainRecipient == msg.sender) { - require(false, "same chain"); - } - crossDomainMessageSender = crossChainRecipient; - crossDomainMessageSource = msg.sender; - SafeCall.call(crossDomainMessageSender, 0, message); - crossDomainMessageSender = address(0); - } -} +import { MockCrossDomainMessenger } from "../helpers/MockCrossDomainMessenger.t.sol"; contract ProtocolAtomicFuzz is Test { using EnumerableMap for EnumerableMap.Bytes32ToUintMap; @@ -62,15 +27,15 @@ contract ProtocolAtomicFuzz is Test { struct TokenDeployParams { uint8 remoteTokenIndex; - uint8 name; - uint8 symbol; - uint8 decimals; + uint8 nameIndex; + uint8 symbolIndex; + uint8 decimalsIndex; } address[] internal remoteTokens; address[] internal allSuperTokens; - // deploy salt => total supply sum across chains + //@dev 'real' deploy salt => total supply sum across chains EnumerableMap.Bytes32ToUintMap internal ghost_totalSupplyAcrossChains; constructor() { @@ -86,9 +51,9 @@ contract ProtocolAtomicFuzz is Test { modifier validateTokenDeployParams(TokenDeployParams memory params) { params.remoteTokenIndex = uint8(bound(params.remoteTokenIndex, 0, remoteTokens.length - 1)); - params.name = uint8(bound(params.name, 0, WORDS.length - 1)); - params.symbol = uint8(bound(params.symbol, 0, WORDS.length - 1)); - params.decimals = uint8(bound(params.decimals, 0, DECIMALS.length - 1)); + params.nameIndex = uint8(bound(params.nameIndex, 0, WORDS.length - 1)); + params.symbolIndex = uint8(bound(params.symbolIndex, 0, WORDS.length - 1)); + params.decimalsIndex = uint8(bound(params.decimalsIndex, 0, DECIMALS.length - 1)); _; } @@ -102,15 +67,19 @@ contract ProtocolAtomicFuzz is Test { chainId = bound(chainId, 0, MAX_CHAINS - 1); _deploySupertoken( remoteTokens[params.remoteTokenIndex], - WORDS[params.name], - WORDS[params.symbol], - DECIMALS[params.decimals], + WORDS[params.nameIndex], + WORDS[params.symbolIndex], + DECIMALS[params.decimalsIndex], chainId ); } /// @custom:property-id 22 + /// @custom:property sendERC20 decreases sender balance in source chain and increases receiver balance in + /// destination chain exactly by the input amount /// @custom:property-id 23 + /// @custom:property sendERC20 decreases total supply in source chain and increases it in destination chain exactly + /// by the input amount function fuzz_SelfBridgeSupertoken(uint256 fromIndex, uint256 destinationChainId, uint256 amount) external { destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); @@ -122,10 +91,10 @@ contract ProtocolAtomicFuzz is Test { require(address(destinationToken) != address(0)); uint256 sourceBalanceBefore = sourceToken.balanceOf(msg.sender); uint256 sourceSupplyBefore = sourceToken.totalSupply(); - // NOTE: lift this requirement to allow one more failure mode uint256 destinationBalanceBefore = destinationToken.balanceOf(msg.sender); uint256 destinationSupplyBefore = destinationToken.totalSupply(); + // NOTE: lift this requirement to allow one more failure mode amount = bound(amount, 0, sourceBalanceBefore); vm.prank(msg.sender); try sourceToken.sendERC20(msg.sender, amount, destinationChainId) { @@ -160,6 +129,9 @@ contract ProtocolAtomicFuzz is Test { // - non-atomic bridge // - `convert` /// @custom:property-id 24 + /// @custom:property sum of supertoken total supply across all chains is always equal to convert(legacy, super)- + /// convert(super, legacy) + /// @dev deliberately not a view method so medusa runs it but not the view methods defined by Test function property_totalSupplyAcrossChainsEqualsMints() external { for (uint256 i = 0; i < ghost_totalSupplyAcrossChains.length(); i++) { uint256 totalSupply = 0; @@ -185,21 +157,21 @@ contract ProtocolAtomicFuzz is Test { function _deploySupertoken( address remoteToken, - string memory name, - string memory symbol, + string memory nameIndex, + string memory symbolIndex, uint8 decimals, uint256 chainId ) internal { - bytes32 realSalt = keccak256(abi.encode(remoteToken, name, symbol, decimals)); - bytes32 hackySalt = keccak256(abi.encode(remoteToken, name, symbol, decimals, chainId)); + bytes32 realSalt = keccak256(abi.encode(remoteToken, nameIndex, symbolIndex, decimals)); + bytes32 hackySalt = keccak256(abi.encode(remoteToken, nameIndex, symbolIndex, decimals, chainId)); OptimismSuperchainERC20 token = OptimismSuperchainERC20( address( // TODO: Use the SuperchainERC20 Beacon Proxy new ERC1967Proxy{ salt: hackySalt }( address(superchainERC20Impl), - abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) + abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, nameIndex, symbolIndex, decimals)) ) ) ); @@ -208,7 +180,7 @@ contract ProtocolAtomicFuzz is Test { uint256 mintAmount = INITIAL_TOKENS * 10 ** decimals; vm.prank(BRIDGE); token.mint(msg.sender, mintAmount); - (,uint256 curr) = ghost_totalSupplyAcrossChains.tryGet(realSalt); + (, uint256 curr) = ghost_totalSupplyAcrossChains.tryGet(realSalt); ghost_totalSupplyAcrossChains.set(realSalt, curr + mintAmount); } } From 8173ee7515543f1fa726d202a5b64ad4476b944b Mon Sep 17 00:00:00 2001 From: teddy Date: Wed, 14 Aug 2024 12:47:03 -0300 Subject: [PATCH 07/56] test: guide the fuzzer a little bit less previously: initial mint, bound on transfer amount: 146625 calls in 200s now: no initial mint, no bound on transfer amount: 176835 calls in 200s it doesn't seem to slow the fuzzer down --- .../test/properties/medusa/ProtocolAtomic.t.sol | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol index a7ffa6229039..9c3acd1daa21 100644 --- a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol @@ -94,8 +94,6 @@ contract ProtocolAtomicFuzz is Test { uint256 destinationBalanceBefore = destinationToken.balanceOf(msg.sender); uint256 destinationSupplyBefore = destinationToken.totalSupply(); - // NOTE: lift this requirement to allow one more failure mode - amount = bound(amount, 0, sourceBalanceBefore); vm.prank(msg.sender); try sourceToken.sendERC20(msg.sender, amount, destinationChainId) { uint256 sourceBalanceAfter = sourceToken.balanceOf(msg.sender); @@ -111,7 +109,7 @@ contract ProtocolAtomicFuzz is Test { assert(sourceSupplyBefore - amount == sourceSupplyAfter); assert(destinationSupplyBefore + amount == destinationSupplyAfter); } catch { - assert(address(destinationToken) == address(sourceToken)); + assert(address(destinationToken) == address(sourceToken) || sourceBalanceBefore < amount); } } @@ -121,7 +119,8 @@ contract ProtocolAtomicFuzz is Test { vm.prank(BRIDGE); // medusa calls with different senders by default OptimismSuperchainERC20(addr).mint(msg.sender, amount); - uint256 currentValue = ghost_totalSupplyAcrossChains.get(MESSENGER.superTokenInitDeploySalts(addr)); + // currentValue will be zero if key is not present + (,uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(MESSENGER.superTokenInitDeploySalts(addr)); ghost_totalSupplyAcrossChains.set(MESSENGER.superTokenInitDeploySalts(addr), currentValue + amount); } @@ -177,10 +176,5 @@ contract ProtocolAtomicFuzz is Test { ); MESSENGER.registerSupertoken(realSalt, chainId, address(token)); allSuperTokens.push(address(token)); - uint256 mintAmount = INITIAL_TOKENS * 10 ** decimals; - vm.prank(BRIDGE); - token.mint(msg.sender, mintAmount); - (, uint256 curr) = ghost_totalSupplyAcrossChains.tryGet(realSalt); - ghost_totalSupplyAcrossChains.set(realSalt, curr + mintAmount); } } From ec29415b14a53b23d743d143b4f7420528133664 Mon Sep 17 00:00:00 2001 From: teddy Date: Thu, 15 Aug 2024 13:48:38 -0300 Subject: [PATCH 08/56] fix: fixes after lovely feedback by disco --- packages/contracts-bedrock/medusa.json | 2 +- .../test/properties/SUMMARY.md | 7 ++-- ...l => MockL2ToL2CrossDomainMessenger.t.sol} | 9 +++-- .../properties/medusa/ProtocolAtomic.t.sol | 39 ++++++++++++++----- 4 files changed, 38 insertions(+), 19 deletions(-) rename packages/contracts-bedrock/test/properties/helpers/{MockCrossDomainMessenger.t.sol => MockL2ToL2CrossDomainMessenger.t.sol} (85%) diff --git a/packages/contracts-bedrock/medusa.json b/packages/contracts-bedrock/medusa.json index 76592655ffa1..88b940370834 100644 --- a/packages/contracts-bedrock/medusa.json +++ b/packages/contracts-bedrock/medusa.json @@ -18,7 +18,7 @@ ], "blockNumberDelayMax": 60480, "blockTimestampDelayMax": 604800, - "blockGasLimit": 125000000, + "blockGasLimit": 30000000, "transactionGasLimit": 12500000, "testing": { "stopOnFailedTest": true, diff --git a/packages/contracts-bedrock/test/properties/SUMMARY.md b/packages/contracts-bedrock/test/properties/SUMMARY.md index cf9c8a93afa5..31598c1cdd28 100644 --- a/packages/contracts-bedrock/test/properties/SUMMARY.md +++ b/packages/contracts-bedrock/test/properties/SUMMARY.md @@ -18,9 +18,8 @@ Given the [OP monorepo](https://github.com/ethereum-optimism/optimism) already h ## Contracts in scope -- [ ] [OptimismSuperchainERC20](https://github.com/defi-wonderland/optimism/pull/9/files#diff-810060510a8a9c06dc60cdce6782e5cafd93b638e2557307a68abe694ee86aee) -- [ ] [OptimismMintableERC20Factory](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol) -- [ ] [SuperchsupERC20ainERC20](https://github.com/defi-wonderland/optimism/pull/8/files#diff-603fd7d5a0b2c403c0d1eee21d0ee60fb8eb72430169eaac5ec7081e01de96b8) (not yet merged) +- [ ] [OptimismMintableERC20Factory](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol) (modifications to enable `convert` not yet merged) +- [ ] [OptimismSuperchainERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol1) - [ ] [SuperchainERC20Factory](https://github.com/defi-wonderland/optimism/pull/8/files#diff-09838f5703c353d0f7c5ff395acc04c1768ef58becac67404bc17e1fb0018517) (not yet merged) - [ ] [L2StandardBridgeInterop](https://github.com/defi-wonderland/optimism/pull/10/files#diff-56cf869412631eac0a04a03f7d026596f64a1e00fcffa713bc770d67c6856c2f) (not yet merged) @@ -29,7 +28,7 @@ Given the [OP monorepo](https://github.com/ethereum-optimism/optimism) already h - [ ] inclusion of relay transactions - [ ] sequencer implementation - [ ] [OptimismMintableERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol) -- [ ] [L2ToL2CrossDomainMessenger](https://github.com/defi-wonderland/src/L2/L2CrossDomainMessenger.sol) +- [ ] [L2ToL2CrossDomainMessenger](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol) - [ ] [CrossL2Inbox](https://github.com/defi-wonderland/src/L2/CrossL2Inbox.sol) ## Pain points diff --git a/packages/contracts-bedrock/test/properties/helpers/MockCrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/properties/helpers/MockL2ToL2CrossDomainMessenger.t.sol similarity index 85% rename from packages/contracts-bedrock/test/properties/helpers/MockCrossDomainMessenger.t.sol rename to packages/contracts-bedrock/test/properties/helpers/MockL2ToL2CrossDomainMessenger.t.sol index 4ad4d474b738..0e3f819a6f06 100644 --- a/packages/contracts-bedrock/test/properties/helpers/MockCrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/properties/helpers/MockL2ToL2CrossDomainMessenger.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.25; import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; -contract MockCrossDomainMessenger { +contract MockL2ToL2CrossDomainMessenger { ///////////////////////////////////////////////////////// // State vars mocking the L2toL2CrossDomainMessenger // ///////////////////////////////////////////////////////// @@ -14,14 +14,15 @@ contract MockCrossDomainMessenger { /////////////////////////////////////////////////// // Helpers for cross-chain interaction mocking // /////////////////////////////////////////////////// - mapping(address => bytes32) public superTokenInitDeploySalts; - mapping(uint256 chainId => mapping(bytes32 reayDeployData => address)) public superTokenAddresses; + mapping(address supertoken => bytes32 deploySalt) public superTokenInitDeploySalts; + mapping(uint256 chainId => mapping(bytes32 deploySalt => address supertoken)) public superTokenAddresses; function crossChainMessageReceiver( address sender, uint256 destinationChainId ) external + view returns (OptimismSuperchainERC20) { return OptimismSuperchainERC20(superTokenAddresses[destinationChainId][superTokenInitDeploySalts[sender]]); @@ -36,7 +37,7 @@ contract MockCrossDomainMessenger { // Functions mocking the L2toL2CrossDomainMessenger // //////////////////////////////////////////////////////// - /// @dev recipient will not be used since in normal execution it's the same + /// @notice recipient will not be used since in normal execution it's the same /// address on a different chain, but here we have to compute it to mock /// cross-chain messaging function sendMessage(uint256 chainId, address, /*recipient*/ bytes memory message) external { diff --git a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol index 9c3acd1daa21..0368abb5f70f 100644 --- a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol @@ -7,7 +7,7 @@ import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Pr import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { MockCrossDomainMessenger } from "../helpers/MockCrossDomainMessenger.t.sol"; +import { MockL2ToL2CrossDomainMessenger } from "../helpers/MockL2ToL2CrossDomainMessenger.t.sol"; contract ProtocolAtomicFuzz is Test { using EnumerableMap for EnumerableMap.Bytes32ToUintMap; @@ -17,8 +17,8 @@ contract ProtocolAtomicFuzz is Test { uint8 internal constant INITIAL_SUPERTOKENS = 1; uint8 internal constant SUPERTOKEN_INITIAL_MINT = 100; address internal constant BRIDGE = Predeploys.L2_STANDARD_BRIDGE; - MockCrossDomainMessenger internal constant MESSENGER = - MockCrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + MockL2ToL2CrossDomainMessenger internal constant MESSENGER = + MockL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); OptimismSuperchainERC20 internal superchainERC20Impl; // NOTE: having more options for this enables the fuzzer to configure // different supertokens for the same remote token @@ -35,11 +35,11 @@ contract ProtocolAtomicFuzz is Test { address[] internal remoteTokens; address[] internal allSuperTokens; - //@dev 'real' deploy salt => total supply sum across chains + //@notice 'real' deploy salt => total supply sum across chains EnumerableMap.Bytes32ToUintMap internal ghost_totalSupplyAcrossChains; constructor() { - vm.etch(address(MESSENGER), address(new MockCrossDomainMessenger()).code); + vm.etch(address(MESSENGER), address(new MockL2ToL2CrossDomainMessenger()).code); superchainERC20Impl = new OptimismSuperchainERC20(); for (uint256 i = 0; i < INITIAL_TOKENS; i++) { _deployRemoteToken(); @@ -49,6 +49,10 @@ contract ProtocolAtomicFuzz is Test { } } + /// @notice the deploy params are _indexes_ to pick from a pre-defined array of options and limit + /// the amount of supertokens for a given remoteAsset that are incompatible between them, as + /// two supertokens have to share decimals, name, symbol and remoteAsset to be considered + /// the same asset, and therefore bridgable. modifier validateTokenDeployParams(TokenDeployParams memory params) { params.remoteTokenIndex = uint8(bound(params.remoteTokenIndex, 0, remoteTokens.length - 1)); params.nameIndex = uint8(bound(params.nameIndex, 0, WORDS.length - 1)); @@ -57,6 +61,7 @@ contract ProtocolAtomicFuzz is Test { _; } + /// @notice deploy a new supertoken with deploy salt determined by params, to the given (of course mocked) chainId function fuzz_DeployNewSupertoken( TokenDeployParams memory params, uint256 chainId @@ -113,6 +118,9 @@ contract ProtocolAtomicFuzz is Test { } } + /// @notice pick one already-deployed supertoken and mint an arbitrary amount of it + /// necessary so there is something to be bridged :D + /// TODO: will be replaced when testing the factories and `convert()` function fuzz_MintSupertoken(uint256 index, uint96 amount) external { index = bound(index, 0, allSuperTokens.length - 1); address addr = allSuperTokens[index]; @@ -130,13 +138,15 @@ contract ProtocolAtomicFuzz is Test { /// @custom:property-id 24 /// @custom:property sum of supertoken total supply across all chains is always equal to convert(legacy, super)- /// convert(super, legacy) - /// @dev deliberately not a view method so medusa runs it but not the view methods defined by Test + /// @notice deliberately not a view method so medusa runs it but not the view methods defined by Test function property_totalSupplyAcrossChainsEqualsMints() external { - for (uint256 i = 0; i < ghost_totalSupplyAcrossChains.length(); i++) { + // iterate over unique deploy salts aka supertokens that are supposed to be compatible with each other + for (uint256 deploySaltIndex = 0; deploySaltIndex < ghost_totalSupplyAcrossChains.length(); deploySaltIndex++) { uint256 totalSupply = 0; - (bytes32 currentSalt, uint256 trackedSupply) = ghost_totalSupplyAcrossChains.at(i); - for (uint256 j = 0; j < MAX_CHAINS; j++) { - address supertoken = MESSENGER.superTokenAddresses(j, currentSalt); + (bytes32 currentSalt, uint256 trackedSupply) = ghost_totalSupplyAcrossChains.at(deploySaltIndex); + // and then over all the (mocked) chain ids where that supertoken could be deployed + for (uint256 validChainId = 0; validChainId < MAX_CHAINS; validChainId++) { + address supertoken = MESSENGER.superTokenAddresses(validChainId, currentSalt); if (supertoken != address(0)) { totalSupply += OptimismSuperchainERC20(supertoken).totalSupply(); } @@ -149,11 +159,15 @@ contract ProtocolAtomicFuzz is Test { _deployRemoteToken(); } + /// @notice deploy a remote token, that supertokens will be a representation of. They are never called, so there + /// is no need to actually deploy a contract for them function _deployRemoteToken() internal { // make sure they don't conflict with predeploys/preinstalls/precompiles/other tokens remoteTokens.push(address(uint160(1000 + remoteTokens.length))); } + /// @custom:property-id 14 + /// @custom:property supertoken total supply starts at zero function _deploySupertoken( address remoteToken, string memory nameIndex, @@ -163,7 +177,10 @@ contract ProtocolAtomicFuzz is Test { ) internal { + // this salt would be used in production. Tokens sharing it will be bridgable with each other bytes32 realSalt = keccak256(abi.encode(remoteToken, nameIndex, symbolIndex, decimals)); + // what we use in the tests to walk around two contracts needing two different addresses + // tbf we could be using CREATE1, but this feels more verbose bytes32 hackySalt = keccak256(abi.encode(remoteToken, nameIndex, symbolIndex, decimals, chainId)); OptimismSuperchainERC20 token = OptimismSuperchainERC20( address( @@ -174,6 +191,8 @@ contract ProtocolAtomicFuzz is Test { ) ) ); + // 14 + assert(token.totalSupply() == 0); MESSENGER.registerSupertoken(realSalt, chainId, address(token)); allSuperTokens.push(address(token)); } From 75f6977d02fa1000ae6fc4c5ef817fc6f6cbdff9 Mon Sep 17 00:00:00 2001 From: teddy Date: Thu, 15 Aug 2024 16:03:22 -0300 Subject: [PATCH 09/56] docs: merge both documents and categorized properties by their milestone --- .../test/properties/PROPERTIES.md | 125 +++++++++++++----- .../test/properties/SUMMARY.md | 42 ------ 2 files changed, 89 insertions(+), 78 deletions(-) delete mode 100644 packages/contracts-bedrock/test/properties/SUMMARY.md diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md index 540d591f77de..78b9de501962 100644 --- a/packages/contracts-bedrock/test/properties/PROPERTIES.md +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -1,4 +1,57 @@ -# supertoken properties +# Supertoken advanced testing + +## Overview + +This document defines a set of properties global to the supertoken ecosystem, for which we will: + +- run a [Medusa](https://github.com/crytic/medusa) fuzzing campaign, trying to break system invariants +- formally prove with [Halmos](https://github.com/a16z/halmos) whenever possible + +## Milestones + +The supertoken ecosystem consists of not just the supertoken contract, but the required changes to other contracts for liquidity to reach the former. + +Considering only the supertoken contract is merged into the `develop` branch, and work for the other components is still in progress, we define three milestones for the testing campaign: + +- SupERC20: concerned with only the supertoken contract, the first one to be implemented +- Factories: covers the above + the development of `OptimismSuperchainERC20Factory` and required changes to `OptimismMintableERC20Factory` +- Liquidity Migration: includes the `convert` function on the `L2StandardBridgeInterop` to migrate liquidity from legacy tokens into supertokens + +## Where to place the testing campaign + +Given the [OP monorepo](https://github.com/ethereum-optimism/optimism) already has invariant testing provided by foundry, it's not a trivial matter where to place this advanced testing campaign. Two alternatives are proposed: + +- including it in the mainline OP monorepo, in a subdirectory of the existing test contracts such as `test/invariants/medusa/superc20/` +- keep the campaign in wonderland's fork of the repository, in its own feature branch, in which case the deliverable would consist primarily of: + - a summary of the results, extending this document + - PRs with extra unit tests replicating found issues to the main repo where applicable + +## Contracts in scope + +- [ ] [OptimismMintableERC20Factory](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol) (modifications to enable `convert` not yet merged) +- [ ] [OptimismSuperchainERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol1) +- [ ] [SuperchainERC20Factory](https://github.com/defi-wonderland/optimism/pull/8/files#diff-09838f5703c353d0f7c5ff395acc04c1768ef58becac67404bc17e1fb0018517) (not yet merged) +- [ ] [L2StandardBridgeInterop](https://github.com/defi-wonderland/optimism/pull/10/files#diff-56cf869412631eac0a04a03f7d026596f64a1e00fcffa713bc770d67c6856c2f) (not yet merged) + +## Behavior assumed correct + +- [ ] inclusion of relay transactions +- [ ] sequencer implementation +- [ ] [OptimismMintableERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol) +- [ ] [L2ToL2CrossDomainMessenger](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol) +- [ ] [CrossL2Inbox](https://github.com/defi-wonderland/src/L2/CrossL2Inbox.sol) + +## Pain points + +- existing fuzzing tools use the same EVM to run the tested contracts as they do for asserting invariants, tracking ghost variables and everything else necessary to provision a fuzzing campaign. While this is usually very convenient, it means that we can’t assert on the behaviour/state of *different* EVMs from within a fuzzing campaign. This means we will have to walk around the requirement of supertokens having the same address across all chains, and implement a way to mock tokens existing in different chains. We will strive to formally prove it in a unitary fashion to mitigate this in properties 0 and 1 +- a buffer to represent 'in transit' messages should be implemented to assert on invariants relating to the non-atomicity of bridging from one chain to another. It is yet to be determined if it’ll be a FIFO queue (assuming ideal message ordering by sequencers) or it’ll have random-access capability to simulate messages arriving out of order + +## Definitions + +- *legacy token:* an OptimismMintableERC20 or L2StandardERC20 token on the suprechain that has either been deployed by the factory after the liquidity migration upgrade to the latter, or has been deployed before it **but** added to factory’s `deployments` mapping as part of the upgrade. This testing campaign is not concerned with tokens on L1 or not listed in the factory’s `deployments` mapping. +- *supertoken:* a SuperchainERC20 contract deployed on the Superchain + +# Ecosystem properties legend: - `[ ]`: property not yet tested @@ -9,56 +62,56 @@ legend: ## Unit test -| id | description | halmos | medusa | -| --- | --- | --- | --- | -| 0 | supertoken token address does not depend on the executing chain’s chainID | [ ] | [ ] | -| 1 | supertoken token address depends on name, remote token, address and decimals | [ ] | [ ] | -| 2 | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | [ ] | -| 3 | convert() only allows migrations between tokens representing the same remote asset | [ ] | [ ] | -| 4 | convert() only allows migrations from tokens with the same decimals | [ ] | [ ] | -| 5 | convert() burns the same amount of one token that it mints of the other | [ ] | [ ] | +| id | milestone | description | halmos | medusa | +| --- | --- | --- | --- | --- | +| 0 | Factories | supertoken token address does not depend on the executing chain’s chainID | [ ] | [ ] | +| 1 | Factories | supertoken token address depends on name, remote token, address and decimals | [ ] | [ ] | +| 2 | Liquidity Migration | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | [ ] | +| 3 | Liquidity Migration | convert() only allows migrations between tokens representing the same remote asset | [ ] | [ ] | +| 4 | Liquidity Migration | convert() only allows migrations from tokens with the same decimals | [ ] | [ ] | +| 5 | Liquidity Migration | convert() burns the same amount of one token that it mints of the other | [ ] | [ ] | ## Valid state -| id | description | halmos | medusa | -| --- | --- | --- | --- | -| 6 | calls to sendERC20 succeed as long as caller has enough balance | [ ] | [ ] | -| 7 | calls to relayERC20 always succeed as long as the cross-domain caller is valid | **[ ]** | [ ] | +| id | milestone | description | halmos | medusa | +| --- | --- | --- | --- | --- | +| 6 | SupERC20 | calls to sendERC20 succeed as long as caller has enough balance | [ ] | [ ] | +| 7 | SupERC20 | calls to relayERC20 always succeed as long as the cross-domain caller is valid | **[ ]** | [ ] | ## Variable transition -| id | description | halmos | medusa | -| --- | --- | --- | --- | -| 8 | sendERC20 with a value of zero does not modify accounting | [ ] | [ ] | -| 9 | relayERC20 with a value of zero does not modify accounting | [ ] | [ ] | -| 10 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [ ] | [ ] | -| 11 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [ ] | [ ] | -| 12 | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [ ] | [ ] | -| 13 | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [ ] | [ ] | -| 14 | supertoken total supply starts at zero | [ ] | [ ] | -| 15 | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | -| 16 | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | +| id | milestone | description | halmos | medusa | +| --- | --- | --- | --- | --- | +| 8 | SupERC20 | sendERC20 with a value of zero does not modify accounting | [ ] | [ ] | +| 9 | SupERC20 | relayERC20 with a value of zero does not modify accounting | [ ] | [ ] | +| 10 | SupERC20 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [ ] | [ ] | +| 11 | SupERC20 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [ ] | [ ] | +| 12 | Liquidity Migration | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [ ] | [ ] | +| 13 | Liquidity Migration | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [ ] | [ ] | +| 14 | SupERC20 | supertoken total supply starts at zero | [ ] | [ ] | +| 15 | Factories | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | +| 16 | Factories | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | ## High level -| id | description | halmos | medusa | -| --- | --- | --- | --- | -| 17 | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | [ ] | -| 18 | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | [ ] | -| 19 | sum of total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | -| 20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | [ ] | -| 21 | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [ ] | [ ] | +| id | milestone | description | halmos | medusa | +| --- | --- | --- | --- | --- | +| 17 | Liquidity Migration | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | [ ] | +| 18 | Liquidity Migration | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | [ ] | +| 19 | Liquidity Migration | sum of total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | +| 20 | SupERC20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | [ ] | +| 21 | Liquidity Migration | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [ ] | [ ] | ## Atomic bridging pseudo-properties As another layer of defense, the following properties are defined which assume bridging operations to be atomic (that is, the sequencer and L2Inbox and CrossDomainMessenger contracts are fully abstracted away, `sendERC20` triggering the `relayERC20` call on the same transaction) It’s worth noting that these properties will not hold for a live system -| id | description | halmos | medusa | -| --- | --- | --- | --- | -| 22 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [x] | -| 23 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [x] | -| 24 | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [~] | +| id | milestone | description | halmos | medusa | +| --- | --- | --- | --- | --- | +| 22 | SupERC20 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [x] | +| 23 | SupERC20 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [x] | +| 24 | Liquidity Migration | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [~] | # Expected external interactions diff --git a/packages/contracts-bedrock/test/properties/SUMMARY.md b/packages/contracts-bedrock/test/properties/SUMMARY.md deleted file mode 100644 index 31598c1cdd28..000000000000 --- a/packages/contracts-bedrock/test/properties/SUMMARY.md +++ /dev/null @@ -1,42 +0,0 @@ -# SupERC20 advanced testing - -# Overview - -This document defines a set of properties global to the supertoken ecosystem, for which we will: - -- run a [Medusa](https://github.com/crytic/medusa) fuzzing campaign, trying to break system invariants -- formally prove with [Halmos](https://github.com/a16z/halmos) whenever possible - -## Where to place the testing campaign - -Given the [OP monorepo](https://github.com/ethereum-optimism/optimism) already has invariant testing provided by foundry, it's not a trivial matter where to place this advanced testing campaign. Two alternatives are proposed: - -- including it in the mainline OP monorepo, in a subdirectory of the existing test contracts such as `test/invariants/medusa/superc20/` -- creating a separate (potentially private) repository for this testing campaign, in which case the deliverable would consist primarily of: - - a summary of the results, extending this document - - PRs with extra unit tests replicating found issues to the main repo where applicable - -## Contracts in scope - -- [ ] [OptimismMintableERC20Factory](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol) (modifications to enable `convert` not yet merged) -- [ ] [OptimismSuperchainERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol1) -- [ ] [SuperchainERC20Factory](https://github.com/defi-wonderland/optimism/pull/8/files#diff-09838f5703c353d0f7c5ff395acc04c1768ef58becac67404bc17e1fb0018517) (not yet merged) -- [ ] [L2StandardBridgeInterop](https://github.com/defi-wonderland/optimism/pull/10/files#diff-56cf869412631eac0a04a03f7d026596f64a1e00fcffa713bc770d67c6856c2f) (not yet merged) - -## Behavior assumed correct - -- [ ] inclusion of relay transactions -- [ ] sequencer implementation -- [ ] [OptimismMintableERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol) -- [ ] [L2ToL2CrossDomainMessenger](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol) -- [ ] [CrossL2Inbox](https://github.com/defi-wonderland/src/L2/CrossL2Inbox.sol) - -## Pain points - -- existing fuzzing tools use the same EVM to run the tested contracts as they do for asserting invariants, tracking ghost variables and everything else necessary to provision a fuzzing campaign. While this is usually very convenient, it means that we can’t assert on the behaviour/state of *different* EVMs from within a fuzzing campaign. This means we will have to walk around the requirement of supertokens having the same address across all chains, and implement a way to mock tokens existing in different chains. We will strive to formally prove it in a unitary fashion to mitigate this in properties 0 and 1 -- a buffer to represent 'in transit' messages should be implemented to assert on invariants relating to the non-atomicity of bridging from one chain to another. It is yet to be determined if it’ll be a FIFO queue (assuming ideal message ordering by sequencers) or it’ll have random-access capability to simulate messages arriving out of order - -## Definitions - -- *legacy token:* an OptimismMintableERC20 or L2StandardERC20 token on the suprechain that has either been deployed by the factory after the liquidity migration upgrade to the latter, or has been deployed before it **but** added to factory’s `deployments` mapping as part of the upgrade. This testing campaign is not concerned with tokens on L1 or not listed in the factory’s `deployments` mapping. -- *supertoken:* a SuperchainERC20 contract deployed on the Superchain From d761fa9f4fd4ead0781abfa961bb9c26af136c10 Mon Sep 17 00:00:00 2001 From: teddy Date: Thu, 15 Aug 2024 16:45:05 -0300 Subject: [PATCH 10/56] fix: fixes from parti's review --- .../test/properties/PROPERTIES.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md index 78b9de501962..0262ecd23b52 100644 --- a/packages/contracts-bedrock/test/properties/PROPERTIES.md +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -30,7 +30,7 @@ Given the [OP monorepo](https://github.com/ethereum-optimism/optimism) already h - [ ] [OptimismMintableERC20Factory](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol) (modifications to enable `convert` not yet merged) - [ ] [OptimismSuperchainERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol1) -- [ ] [SuperchainERC20Factory](https://github.com/defi-wonderland/optimism/pull/8/files#diff-09838f5703c353d0f7c5ff395acc04c1768ef58becac67404bc17e1fb0018517) (not yet merged) +- [ ] [OptimismSuperchainERC20Factory](https://github.com/defi-wonderland/optimism/pull/8/files#diff-09838f5703c353d0f7c5ff395acc04c1768ef58becac67404bc17e1fb0018517) (not yet merged) - [ ] [L2StandardBridgeInterop](https://github.com/defi-wonderland/optimism/pull/10/files#diff-56cf869412631eac0a04a03f7d026596f64a1e00fcffa713bc770d67c6856c2f) (not yet merged) ## Behavior assumed correct @@ -49,7 +49,7 @@ Given the [OP monorepo](https://github.com/ethereum-optimism/optimism) already h ## Definitions - *legacy token:* an OptimismMintableERC20 or L2StandardERC20 token on the suprechain that has either been deployed by the factory after the liquidity migration upgrade to the latter, or has been deployed before it **but** added to factory’s `deployments` mapping as part of the upgrade. This testing campaign is not concerned with tokens on L1 or not listed in the factory’s `deployments` mapping. -- *supertoken:* a SuperchainERC20 contract deployed on the Superchain +- *supertoken:* a SuperchainERC20 contract deployed by the `OptimismSuperchainERC20Factory` # Ecosystem properties @@ -62,14 +62,14 @@ legend: ## Unit test -| id | milestone | description | halmos | medusa | -| --- | --- | --- | --- | --- | -| 0 | Factories | supertoken token address does not depend on the executing chain’s chainID | [ ] | [ ] | -| 1 | Factories | supertoken token address depends on name, remote token, address and decimals | [ ] | [ ] | -| 2 | Liquidity Migration | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | [ ] | -| 3 | Liquidity Migration | convert() only allows migrations between tokens representing the same remote asset | [ ] | [ ] | -| 4 | Liquidity Migration | convert() only allows migrations from tokens with the same decimals | [ ] | [ ] | -| 5 | Liquidity Migration | convert() burns the same amount of one token that it mints of the other | [ ] | [ ] | +| id | milestone | description | halmos | medusa | +| --- | --- | --- | --- | --- | +| 0 | Factories | supertoken token address does not depend on the executing chain’s chainID | [ ] | [ ] | +| 1 | Factories | supertoken token address depends on remote token, name, symbol and decimals | [ ] | [ ] | +| 2 | Liquidity Migration | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | [ ] | +| 3 | Liquidity Migration | convert() only allows migrations between tokens representing the same remote asset | [ ] | [ ] | +| 4 | Liquidity Migration | convert() only allows migrations from tokens with the same decimals | [ ] | [ ] | +| 5 | Liquidity Migration | convert() burns the same amount of legacy token that it mints of supertoken, and viceversa | [ ] | [ ] | ## Valid state @@ -98,7 +98,7 @@ legend: | --- | --- | --- | --- | --- | | 17 | Liquidity Migration | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | [ ] | | 18 | Liquidity Migration | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | [ ] | -| 19 | Liquidity Migration | sum of total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | +| 19 | Liquidity Migration | sum of supertoken total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | | 20 | SupERC20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | [ ] | | 21 | Liquidity Migration | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [ ] | [ ] | From 51a72e3d7276b4ae7818c0afa9df49ae2e05fedc Mon Sep 17 00:00:00 2001 From: teddy Date: Fri, 16 Aug 2024 15:24:08 -0300 Subject: [PATCH 11/56] fix: feedback from disco --- .../properties/medusa/ProtocolAtomic.t.sol | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol index 0368abb5f70f..b4f44d2bcf67 100644 --- a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol @@ -41,10 +41,10 @@ contract ProtocolAtomicFuzz is Test { constructor() { vm.etch(address(MESSENGER), address(new MockL2ToL2CrossDomainMessenger()).code); superchainERC20Impl = new OptimismSuperchainERC20(); - for (uint256 i = 0; i < INITIAL_TOKENS; i++) { + for (uint256 remoteTokenIndex = 0; remoteTokenIndex < INITIAL_TOKENS; remoteTokenIndex++) { _deployRemoteToken(); - for (uint256 j = 0; j < INITIAL_SUPERTOKENS; j++) { - _deploySupertoken(remoteTokens[i], WORDS[0], WORDS[0], DECIMALS[0], j); + for (uint256 supertokenChainId = 0; supertokenChainId < INITIAL_SUPERTOKENS; supertokenChainId++) { + _deploySupertoken(remoteTokens[remoteTokenIndex], WORDS[0], WORDS[0], DECIMALS[0], supertokenChainId); } } } @@ -62,6 +62,8 @@ contract ProtocolAtomicFuzz is Test { } /// @notice deploy a new supertoken with deploy salt determined by params, to the given (of course mocked) chainId + /// @custom:property-id 14 + /// @custom:property supertoken total supply starts at zero function fuzz_DeployNewSupertoken( TokenDeployParams memory params, uint256 chainId @@ -70,13 +72,15 @@ contract ProtocolAtomicFuzz is Test { validateTokenDeployParams(params) { chainId = bound(chainId, 0, MAX_CHAINS - 1); - _deploySupertoken( + OptimismSuperchainERC20 supertoken = _deploySupertoken( remoteTokens[params.remoteTokenIndex], WORDS[params.nameIndex], WORDS[params.symbolIndex], DECIMALS[params.decimalsIndex], chainId ); + // 14 + assert(supertoken.totalSupply() == 0); } /// @custom:property-id 22 @@ -166,34 +170,36 @@ contract ProtocolAtomicFuzz is Test { remoteTokens.push(address(uint160(1000 + remoteTokens.length))); } - /// @custom:property-id 14 - /// @custom:property supertoken total supply starts at zero + /// @notice deploy a new supertoken representing remoteToken + /// remoteToken, name, symbol and decimals determine the 'real' deploy salt + /// and supertokens sharing it are interoperable between them + /// we however use the chainId as part of the deploy salt to mock the ability of + /// supertokens to exist on different chains on a single EVM. function _deploySupertoken( address remoteToken, - string memory nameIndex, - string memory symbolIndex, + string memory name, + string memory symbol, uint8 decimals, uint256 chainId ) internal + returns(OptimismSuperchainERC20 supertoken) { // this salt would be used in production. Tokens sharing it will be bridgable with each other - bytes32 realSalt = keccak256(abi.encode(remoteToken, nameIndex, symbolIndex, decimals)); + bytes32 realSalt = keccak256(abi.encode(remoteToken, name, symbol, decimals)); // what we use in the tests to walk around two contracts needing two different addresses // tbf we could be using CREATE1, but this feels more verbose - bytes32 hackySalt = keccak256(abi.encode(remoteToken, nameIndex, symbolIndex, decimals, chainId)); - OptimismSuperchainERC20 token = OptimismSuperchainERC20( + bytes32 hackySalt = keccak256(abi.encode(remoteToken, name, symbol, decimals, chainId)); + supertoken = OptimismSuperchainERC20( address( // TODO: Use the SuperchainERC20 Beacon Proxy new ERC1967Proxy{ salt: hackySalt }( address(superchainERC20Impl), - abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, nameIndex, symbolIndex, decimals)) + abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) ) ) ); - // 14 - assert(token.totalSupply() == 0); - MESSENGER.registerSupertoken(realSalt, chainId, address(token)); - allSuperTokens.push(address(token)); + MESSENGER.registerSupertoken(realSalt, chainId, address(supertoken)); + allSuperTokens.push(address(supertoken)); } } From 745dcbc90b8940b97492b5fba2eb400cba507051 Mon Sep 17 00:00:00 2001 From: teddy Date: Fri, 16 Aug 2024 16:58:58 -0300 Subject: [PATCH 12/56] fix: feedback from doc --- packages/contracts-bedrock/test/properties/PROPERTIES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md index 0262ecd23b52..4bf542771307 100644 --- a/packages/contracts-bedrock/test/properties/PROPERTIES.md +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -43,7 +43,7 @@ Given the [OP monorepo](https://github.com/ethereum-optimism/optimism) already h ## Pain points -- existing fuzzing tools use the same EVM to run the tested contracts as they do for asserting invariants, tracking ghost variables and everything else necessary to provision a fuzzing campaign. While this is usually very convenient, it means that we can’t assert on the behaviour/state of *different* EVMs from within a fuzzing campaign. This means we will have to walk around the requirement of supertokens having the same address across all chains, and implement a way to mock tokens existing in different chains. We will strive to formally prove it in a unitary fashion to mitigate this in properties 0 and 1 +- existing fuzzing tools use the same EVM to run the tested contracts as they do for asserting invariants, tracking ghost variables and everything else necessary to provision a fuzzing campaign. While this is usually very convenient, it means that we can’t assert on the behaviour/state of *different* chains from within a fuzzing campaign. This means we will have to walk around the requirement of supertokens having the same address across all chains, and implement a way to mock tokens existing in different chains. We will strive to formally prove it in a unitary fashion to mitigate this in properties 0 and 1 - a buffer to represent 'in transit' messages should be implemented to assert on invariants relating to the non-atomicity of bridging from one chain to another. It is yet to be determined if it’ll be a FIFO queue (assuming ideal message ordering by sequencers) or it’ll have random-access capability to simulate messages arriving out of order ## Definitions From 07ca17ec5dc36395379943e79e0e93d3ee2a9ea9 Mon Sep 17 00:00:00 2001 From: teddy Date: Mon, 19 Aug 2024 13:12:19 -0300 Subject: [PATCH 13/56] refactor: separate state transitions from pure properties --- packages/contracts-bedrock/medusa.json | 4 +-- .../medusa/Protocol.properties.t.sol | 35 +++++++++++++++++++ .../Protocol.handler.t.sol} | 31 +++------------- 3 files changed, 41 insertions(+), 29 deletions(-) create mode 100644 packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol rename packages/contracts-bedrock/test/properties/medusa/{ProtocolAtomic.t.sol => handlers/Protocol.handler.t.sol} (84%) diff --git a/packages/contracts-bedrock/medusa.json b/packages/contracts-bedrock/medusa.json index 88b940370834..c91f69be607e 100644 --- a/packages/contracts-bedrock/medusa.json +++ b/packages/contracts-bedrock/medusa.json @@ -7,7 +7,7 @@ "callSequenceLength": 100, "corpusDirectory": "test/properties/medusa/corpus/", "coverageEnabled": true, - "targetContracts": ["ProtocolAtomicFuzz"], + "targetContracts": ["ProtocolProperties"], "targetContractsBalances": [], "constructorArgs": {}, "deployerAddress": "0x30000", @@ -43,7 +43,7 @@ } }, "propertyTesting": { - "enabled": false, + "enabled": true, "testPrefixes": [ "property_" ] diff --git a/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol b/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol new file mode 100644 index 000000000000..a6ed77dc6c6e --- /dev/null +++ b/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { ProtocolHandler } from "./handlers/Protocol.handler.t.sol"; +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; + +contract ProtocolProperties is ProtocolHandler { + using EnumerableMap for EnumerableMap.Bytes32ToUintMap; + // TODO: will need rework after + // - non-atomic bridge + // - `convert` + /// @custom:property-id 24 + /// @custom:property sum of supertoken total supply across all chains is always equal to convert(legacy, super)- + /// convert(super, legacy) + + function property_totalSupplyAcrossChainsEqualsMints() external view returns (bool success) { + // iterate over unique deploy salts aka supertokens that are supposed to be compatible with each other + for (uint256 deploySaltIndex = 0; deploySaltIndex < ghost_totalSupplyAcrossChains.length(); deploySaltIndex++) { + uint256 totalSupply = 0; + (bytes32 currentSalt, uint256 trackedSupply) = ghost_totalSupplyAcrossChains.at(deploySaltIndex); + // and then over all the (mocked) chain ids where that supertoken could be deployed + for (uint256 validChainId = 0; validChainId < MAX_CHAINS; validChainId++) { + address supertoken = MESSENGER.superTokenAddresses(validChainId, currentSalt); + if (supertoken != address(0)) { + totalSupply += OptimismSuperchainERC20(supertoken).totalSupply(); + } + } + if (trackedSupply != totalSupply) { + return false; + } + } + return true; + } +} diff --git a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol b/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol similarity index 84% rename from packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol rename to packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol index b4f44d2bcf67..6d6209aca11b 100644 --- a/packages/contracts-bedrock/test/properties/medusa/ProtocolAtomic.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol @@ -7,9 +7,9 @@ import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Pr import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { MockL2ToL2CrossDomainMessenger } from "../helpers/MockL2ToL2CrossDomainMessenger.t.sol"; +import { MockL2ToL2CrossDomainMessenger } from "../../helpers/MockL2ToL2CrossDomainMessenger.t.sol"; -contract ProtocolAtomicFuzz is Test { +contract ProtocolHandler is Test { using EnumerableMap for EnumerableMap.Bytes32ToUintMap; uint8 internal constant MAX_CHAINS = 4; @@ -132,33 +132,10 @@ contract ProtocolAtomicFuzz is Test { // medusa calls with different senders by default OptimismSuperchainERC20(addr).mint(msg.sender, amount); // currentValue will be zero if key is not present - (,uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(MESSENGER.superTokenInitDeploySalts(addr)); + (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(MESSENGER.superTokenInitDeploySalts(addr)); ghost_totalSupplyAcrossChains.set(MESSENGER.superTokenInitDeploySalts(addr), currentValue + amount); } - // TODO: will need rework after - // - non-atomic bridge - // - `convert` - /// @custom:property-id 24 - /// @custom:property sum of supertoken total supply across all chains is always equal to convert(legacy, super)- - /// convert(super, legacy) - /// @notice deliberately not a view method so medusa runs it but not the view methods defined by Test - function property_totalSupplyAcrossChainsEqualsMints() external { - // iterate over unique deploy salts aka supertokens that are supposed to be compatible with each other - for (uint256 deploySaltIndex = 0; deploySaltIndex < ghost_totalSupplyAcrossChains.length(); deploySaltIndex++) { - uint256 totalSupply = 0; - (bytes32 currentSalt, uint256 trackedSupply) = ghost_totalSupplyAcrossChains.at(deploySaltIndex); - // and then over all the (mocked) chain ids where that supertoken could be deployed - for (uint256 validChainId = 0; validChainId < MAX_CHAINS; validChainId++) { - address supertoken = MESSENGER.superTokenAddresses(validChainId, currentSalt); - if (supertoken != address(0)) { - totalSupply += OptimismSuperchainERC20(supertoken).totalSupply(); - } - } - assert(trackedSupply == totalSupply); - } - } - function fuzz_MockNewRemoteToken() external { _deployRemoteToken(); } @@ -183,7 +160,7 @@ contract ProtocolAtomicFuzz is Test { uint256 chainId ) internal - returns(OptimismSuperchainERC20 supertoken) + returns (OptimismSuperchainERC20 supertoken) { // this salt would be used in production. Tokens sharing it will be bridgable with each other bytes32 realSalt = keccak256(abi.encode(remoteToken, name, symbol, decimals)); From f23d8ff482ffa74086e2813b7d891c3d20be2d57 Mon Sep 17 00:00:00 2001 From: teddy Date: Mon, 19 Aug 2024 13:16:13 -0300 Subject: [PATCH 14/56] docs: update tested properties --- packages/contracts-bedrock/test/properties/PROPERTIES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md index 4bf542771307..36b7b330ab0b 100644 --- a/packages/contracts-bedrock/test/properties/PROPERTIES.md +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -86,9 +86,9 @@ legend: | 9 | SupERC20 | relayERC20 with a value of zero does not modify accounting | [ ] | [ ] | | 10 | SupERC20 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [ ] | [ ] | | 11 | SupERC20 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [ ] | [ ] | -| 12 | Liquidity Migration | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [ ] | [ ] | +| 12 | Liquidity Migration | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [ ] | [~] | | 13 | Liquidity Migration | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [ ] | [ ] | -| 14 | SupERC20 | supertoken total supply starts at zero | [ ] | [ ] | +| 14 | SupERC20 | supertoken total supply starts at zero | [ ] | [x] | | 15 | Factories | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | | 16 | Factories | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | From 590a3ba550a5462b28a2ec2bfbef4286e1454174 Mon Sep 17 00:00:00 2001 From: teddy Date: Mon, 19 Aug 2024 15:33:20 -0300 Subject: [PATCH 15/56] refactor: move all assertions into properties contract --- .../medusa/Protocol.properties.t.sol | 77 ++++++++++++++++++- .../medusa/handlers/Protocol.handler.t.sol | 75 ------------------ 2 files changed, 76 insertions(+), 76 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol b/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol index a6ed77dc6c6e..36a696f6c442 100644 --- a/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol @@ -7,13 +7,13 @@ import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableM contract ProtocolProperties is ProtocolHandler { using EnumerableMap for EnumerableMap.Bytes32ToUintMap; + // TODO: will need rework after // - non-atomic bridge // - `convert` /// @custom:property-id 24 /// @custom:property sum of supertoken total supply across all chains is always equal to convert(legacy, super)- /// convert(super, legacy) - function property_totalSupplyAcrossChainsEqualsMints() external view returns (bool success) { // iterate over unique deploy salts aka supertokens that are supposed to be compatible with each other for (uint256 deploySaltIndex = 0; deploySaltIndex < ghost_totalSupplyAcrossChains.length(); deploySaltIndex++) { @@ -32,4 +32,79 @@ contract ProtocolProperties is ProtocolHandler { } return true; } + + /// @notice deploy a new supertoken with deploy salt determined by params, to the given (of course mocked) chainId + /// @custom:property-id 14 + /// @custom:property supertoken total supply starts at zero + function fuzz_DeployNewSupertoken( + TokenDeployParams memory params, + uint256 chainId + ) + external + validateTokenDeployParams(params) + { + chainId = bound(chainId, 0, MAX_CHAINS - 1); + OptimismSuperchainERC20 supertoken = _deploySupertoken( + remoteTokens[params.remoteTokenIndex], + WORDS[params.nameIndex], + WORDS[params.symbolIndex], + DECIMALS[params.decimalsIndex], + chainId + ); + // 14 + assert(supertoken.totalSupply() == 0); + } + + /// @custom:property-id 22 + /// @custom:property sendERC20 decreases sender balance in source chain and increases receiver balance in + /// destination chain exactly by the input amount + /// @custom:property-id 23 + /// @custom:property sendERC20 decreases total supply in source chain and increases it in destination chain exactly + /// by the input amount + function fuzz_SelfBridgeSupertoken(uint256 fromIndex, uint256 destinationChainId, uint256 amount) external { + destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); + fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); + OptimismSuperchainERC20 sourceToken = OptimismSuperchainERC20(allSuperTokens[fromIndex]); + OptimismSuperchainERC20 destinationToken = + MESSENGER.crossChainMessageReceiver(address(sourceToken), destinationChainId); + // TODO: when implementing non-atomic bridging, allow for the token to + // not yet be deployed and funds be recovered afterwards. + require(address(destinationToken) != address(0)); + uint256 sourceBalanceBefore = sourceToken.balanceOf(msg.sender); + uint256 sourceSupplyBefore = sourceToken.totalSupply(); + uint256 destinationBalanceBefore = destinationToken.balanceOf(msg.sender); + uint256 destinationSupplyBefore = destinationToken.totalSupply(); + + vm.prank(msg.sender); + try sourceToken.sendERC20(msg.sender, amount, destinationChainId) { + uint256 sourceBalanceAfter = sourceToken.balanceOf(msg.sender); + uint256 destinationBalanceAfter = destinationToken.balanceOf(msg.sender); + // no free mint + assert(sourceBalanceBefore + destinationBalanceBefore == sourceBalanceAfter + destinationBalanceAfter); + // 22 + assert(sourceBalanceBefore - amount == sourceBalanceAfter); + assert(destinationBalanceBefore + amount == destinationBalanceAfter); + uint256 sourceSupplyAfter = sourceToken.totalSupply(); + uint256 destinationSupplyAfter = destinationToken.totalSupply(); + // 23 + assert(sourceSupplyBefore - amount == sourceSupplyAfter); + assert(destinationSupplyBefore + amount == destinationSupplyAfter); + } catch { + assert(address(destinationToken) == address(sourceToken) || sourceBalanceBefore < amount); + } + } + + /// @notice pick one already-deployed supertoken and mint an arbitrary amount of it + /// necessary so there is something to be bridged :D + /// TODO: will be replaced when testing the factories and `convert()` + function fuzz_MintSupertoken(uint256 index, uint96 amount) external { + index = bound(index, 0, allSuperTokens.length - 1); + address addr = allSuperTokens[index]; + vm.prank(BRIDGE); + // medusa calls with different senders by default + OptimismSuperchainERC20(addr).mint(msg.sender, amount); + // currentValue will be zero if key is not present + (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(MESSENGER.superTokenInitDeploySalts(addr)); + ghost_totalSupplyAcrossChains.set(MESSENGER.superTokenInitDeploySalts(addr), currentValue + amount); + } } diff --git a/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol b/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol index 6d6209aca11b..523f67801edf 100644 --- a/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol @@ -61,81 +61,6 @@ contract ProtocolHandler is Test { _; } - /// @notice deploy a new supertoken with deploy salt determined by params, to the given (of course mocked) chainId - /// @custom:property-id 14 - /// @custom:property supertoken total supply starts at zero - function fuzz_DeployNewSupertoken( - TokenDeployParams memory params, - uint256 chainId - ) - external - validateTokenDeployParams(params) - { - chainId = bound(chainId, 0, MAX_CHAINS - 1); - OptimismSuperchainERC20 supertoken = _deploySupertoken( - remoteTokens[params.remoteTokenIndex], - WORDS[params.nameIndex], - WORDS[params.symbolIndex], - DECIMALS[params.decimalsIndex], - chainId - ); - // 14 - assert(supertoken.totalSupply() == 0); - } - - /// @custom:property-id 22 - /// @custom:property sendERC20 decreases sender balance in source chain and increases receiver balance in - /// destination chain exactly by the input amount - /// @custom:property-id 23 - /// @custom:property sendERC20 decreases total supply in source chain and increases it in destination chain exactly - /// by the input amount - function fuzz_SelfBridgeSupertoken(uint256 fromIndex, uint256 destinationChainId, uint256 amount) external { - destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); - fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); - OptimismSuperchainERC20 sourceToken = OptimismSuperchainERC20(allSuperTokens[fromIndex]); - OptimismSuperchainERC20 destinationToken = - MESSENGER.crossChainMessageReceiver(address(sourceToken), destinationChainId); - // TODO: when implementing non-atomic bridging, allow for the token to - // not yet be deployed and funds be recovered afterwards. - require(address(destinationToken) != address(0)); - uint256 sourceBalanceBefore = sourceToken.balanceOf(msg.sender); - uint256 sourceSupplyBefore = sourceToken.totalSupply(); - uint256 destinationBalanceBefore = destinationToken.balanceOf(msg.sender); - uint256 destinationSupplyBefore = destinationToken.totalSupply(); - - vm.prank(msg.sender); - try sourceToken.sendERC20(msg.sender, amount, destinationChainId) { - uint256 sourceBalanceAfter = sourceToken.balanceOf(msg.sender); - uint256 destinationBalanceAfter = destinationToken.balanceOf(msg.sender); - // no free mint - assert(sourceBalanceBefore + destinationBalanceBefore == sourceBalanceAfter + destinationBalanceAfter); - // 22 - assert(sourceBalanceBefore - amount == sourceBalanceAfter); - assert(destinationBalanceBefore + amount == destinationBalanceAfter); - uint256 sourceSupplyAfter = sourceToken.totalSupply(); - uint256 destinationSupplyAfter = destinationToken.totalSupply(); - // 23 - assert(sourceSupplyBefore - amount == sourceSupplyAfter); - assert(destinationSupplyBefore + amount == destinationSupplyAfter); - } catch { - assert(address(destinationToken) == address(sourceToken) || sourceBalanceBefore < amount); - } - } - - /// @notice pick one already-deployed supertoken and mint an arbitrary amount of it - /// necessary so there is something to be bridged :D - /// TODO: will be replaced when testing the factories and `convert()` - function fuzz_MintSupertoken(uint256 index, uint96 amount) external { - index = bound(index, 0, allSuperTokens.length - 1); - address addr = allSuperTokens[index]; - vm.prank(BRIDGE); - // medusa calls with different senders by default - OptimismSuperchainERC20(addr).mint(msg.sender, amount); - // currentValue will be zero if key is not present - (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(MESSENGER.superTokenInitDeploySalts(addr)); - ghost_totalSupplyAcrossChains.set(MESSENGER.superTokenInitDeploySalts(addr), currentValue + amount); - } - function fuzz_MockNewRemoteToken() external { _deployRemoteToken(); } From 51bf7fdc58653d4bab135aeeaff5cea49b02210e Mon Sep 17 00:00:00 2001 From: teddy Date: Mon, 19 Aug 2024 16:07:17 -0300 Subject: [PATCH 16/56] fix: move function without assertions back into handler --- .../properties/medusa/Protocol.properties.t.sol | 14 -------------- .../medusa/handlers/Protocol.handler.t.sol | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol b/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol index 36a696f6c442..5b7090d6dc87 100644 --- a/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol @@ -93,18 +93,4 @@ contract ProtocolProperties is ProtocolHandler { assert(address(destinationToken) == address(sourceToken) || sourceBalanceBefore < amount); } } - - /// @notice pick one already-deployed supertoken and mint an arbitrary amount of it - /// necessary so there is something to be bridged :D - /// TODO: will be replaced when testing the factories and `convert()` - function fuzz_MintSupertoken(uint256 index, uint96 amount) external { - index = bound(index, 0, allSuperTokens.length - 1); - address addr = allSuperTokens[index]; - vm.prank(BRIDGE); - // medusa calls with different senders by default - OptimismSuperchainERC20(addr).mint(msg.sender, amount); - // currentValue will be zero if key is not present - (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(MESSENGER.superTokenInitDeploySalts(addr)); - ghost_totalSupplyAcrossChains.set(MESSENGER.superTokenInitDeploySalts(addr), currentValue + amount); - } } diff --git a/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol b/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol index 523f67801edf..db126425ab36 100644 --- a/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol @@ -65,6 +65,20 @@ contract ProtocolHandler is Test { _deployRemoteToken(); } + /// @notice pick one already-deployed supertoken and mint an arbitrary amount of it + /// necessary so there is something to be bridged :D + /// TODO: will be replaced when testing the factories and `convert()` + function fuzz_MintSupertoken(uint256 index, uint96 amount) external { + index = bound(index, 0, allSuperTokens.length - 1); + address addr = allSuperTokens[index]; + vm.prank(BRIDGE); + // medusa calls with different senders by default + OptimismSuperchainERC20(addr).mint(msg.sender, amount); + // currentValue will be zero if key is not present + (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(MESSENGER.superTokenInitDeploySalts(addr)); + ghost_totalSupplyAcrossChains.set(MESSENGER.superTokenInitDeploySalts(addr), currentValue + amount); + } + /// @notice deploy a remote token, that supertokens will be a representation of. They are never called, so there /// is no need to actually deploy a contract for them function _deployRemoteToken() internal { From 79bf5e54d03877647b1769c8077e0937b057ff26 Mon Sep 17 00:00:00 2001 From: teddy Date: Tue, 20 Aug 2024 15:26:28 -0300 Subject: [PATCH 17/56] test: only use assertion mode --- packages/contracts-bedrock/medusa.json | 4 ++-- .../test/properties/medusa/Protocol.properties.t.sol | 11 ++++------- .../properties/medusa/handlers/Protocol.handler.t.sol | 9 +++++---- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/packages/contracts-bedrock/medusa.json b/packages/contracts-bedrock/medusa.json index c91f69be607e..cb4737956fea 100644 --- a/packages/contracts-bedrock/medusa.json +++ b/packages/contracts-bedrock/medusa.json @@ -28,7 +28,7 @@ "traceAll": true, "assertionTesting": { "enabled": true, - "testViewMethods": false, + "testViewMethods": true, "panicCodeConfig": { "failOnCompilerInsertedPanic": false, "failOnAssertion": true, @@ -43,7 +43,7 @@ } }, "propertyTesting": { - "enabled": true, + "enabled": false, "testPrefixes": [ "property_" ] diff --git a/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol b/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol index 5b7090d6dc87..dd169dc5748d 100644 --- a/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol @@ -14,7 +14,7 @@ contract ProtocolProperties is ProtocolHandler { /// @custom:property-id 24 /// @custom:property sum of supertoken total supply across all chains is always equal to convert(legacy, super)- /// convert(super, legacy) - function property_totalSupplyAcrossChainsEqualsMints() external view returns (bool success) { + function property_totalSupplyAcrossChainsEqualsMints() external view { // iterate over unique deploy salts aka supertokens that are supposed to be compatible with each other for (uint256 deploySaltIndex = 0; deploySaltIndex < ghost_totalSupplyAcrossChains.length(); deploySaltIndex++) { uint256 totalSupply = 0; @@ -26,17 +26,14 @@ contract ProtocolProperties is ProtocolHandler { totalSupply += OptimismSuperchainERC20(supertoken).totalSupply(); } } - if (trackedSupply != totalSupply) { - return false; - } + assert(trackedSupply == totalSupply); } - return true; } /// @notice deploy a new supertoken with deploy salt determined by params, to the given (of course mocked) chainId /// @custom:property-id 14 /// @custom:property supertoken total supply starts at zero - function fuzz_DeployNewSupertoken( + function property_DeployNewSupertoken( TokenDeployParams memory params, uint256 chainId ) @@ -61,7 +58,7 @@ contract ProtocolProperties is ProtocolHandler { /// @custom:property-id 23 /// @custom:property sendERC20 decreases total supply in source chain and increases it in destination chain exactly /// by the input amount - function fuzz_SelfBridgeSupertoken(uint256 fromIndex, uint256 destinationChainId, uint256 amount) external { + function property_SelfBridgeSupertoken(uint256 fromIndex, uint256 destinationChainId, uint256 amount) external { destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); OptimismSuperchainERC20 sourceToken = OptimismSuperchainERC20(allSuperTokens[fromIndex]); diff --git a/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol b/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol index db126425ab36..266650486e34 100644 --- a/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol +++ b/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.25; -import { Test } from "forge-std/Test.sol"; +import { TestBase } from "forge-std/Base.sol"; +import { StdUtils } from "forge-std/StdUtils.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; @@ -9,7 +10,7 @@ import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { MockL2ToL2CrossDomainMessenger } from "../../helpers/MockL2ToL2CrossDomainMessenger.t.sol"; -contract ProtocolHandler is Test { +contract ProtocolHandler is TestBase, StdUtils { using EnumerableMap for EnumerableMap.Bytes32ToUintMap; uint8 internal constant MAX_CHAINS = 4; @@ -61,14 +62,14 @@ contract ProtocolHandler is Test { _; } - function fuzz_MockNewRemoteToken() external { + function handler_MockNewRemoteToken() external { _deployRemoteToken(); } /// @notice pick one already-deployed supertoken and mint an arbitrary amount of it /// necessary so there is something to be bridged :D /// TODO: will be replaced when testing the factories and `convert()` - function fuzz_MintSupertoken(uint256 index, uint96 amount) external { + function handler_MintSupertoken(uint256 index, uint96 amount) external { index = bound(index, 0, allSuperTokens.length - 1); address addr = allSuperTokens[index]; vm.prank(BRIDGE); From 6e13fd227f1a5348adc308268845796c2c8fecf9 Mon Sep 17 00:00:00 2001 From: teddy Date: Tue, 20 Aug 2024 15:26:53 -0300 Subject: [PATCH 18/56] fix: improve justfile recipie for medusa --- packages/contracts-bedrock/justfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/contracts-bedrock/justfile b/packages/contracts-bedrock/justfile index ebb8d9db6d47..290f01574ead 100644 --- a/packages/contracts-bedrock/justfile +++ b/packages/contracts-bedrock/justfile @@ -22,8 +22,8 @@ test: build-go-ffi test-kontrol: ./test/kontrol/scripts/run-kontrol.sh script -test-medusa: - FOUNDRY_PROFILE=medusa medusa fuzz +test-medusa timeout='100': + FOUNDRY_PROFILE=medusa medusa fuzz --timeout {{timeout}} test-rerun: build-go-ffi forge test --rerun -vvv From 7e6fdbc7eabeea9f41ab9517d85401a6861cc0e6 Mon Sep 17 00:00:00 2001 From: Disco <131301107+0xDiscotech@users.noreply.github.com> Date: Fri, 23 Aug 2024 13:22:01 -0300 Subject: [PATCH 19/56] feat: halmos symbolic tests (#21) * feat: introduce OptimismSuperchainERC20 * fix: contract fixes * feat: add snapshots and semver * test: add supports interface tests * test: add invariant test * feat: add parameters to the RelayERC20 event * fix: typo * fix: from param description * fix: event signature and interface pragma * feat: add initializer * feat: use unstructured storage and OZ v5 * feat: update superchain erc20 interfaces * fix: adapt storage to ERC7201 * test: add initializable OZ v5 test * fix: invariant docs * fix: ERC165 implementation * test: improve superc20 invariant (#11) * fix: gas snapshot * chore: configure medusa with basic supERC20 self-bridging - used --foundry-compile-all to ensure the test contract under `test/properties` is compiled (otherwise it is not compiled and medusa crashes when it can't find it's compiled representation) - set src,test,script to test/properties/medusa to not waste time compiling contracts that are not required for the medusa campaign - used an atomic bridge, which doesnt allow for testing of several of the proposed invariants * fix: delete dead code * test: give the fuzzer a head start * feat: create suite for sybolic tests with halmos * test: setup and 3 properties with symbolic tests * chore: remove todo comment * docs: fix properties order * test: document & implement assertions 22, 23 and 24 * fix: fixes from self-review * test: guide the fuzzer a little bit less previously: initial mint, bound on transfer amount: 146625 calls in 200s now: no initial mint, no bound on transfer amount: 176835 calls in 200s it doesn't seem to slow the fuzzer down * feat: add property for burn * refactor: remove symbolic address on mint property * refactor: order the tests based on the property id * feat: checkpoint * chore: set xdomain sender on failing test * chore: enhance mocks * Revert "Merge branch 'chore/setup-medusa' into feat/halmos-symbolic-tests" This reverts commit 945d6b6ad265ea5e3790d7ac9c5bf4d6586eb533, reversing changes made to 5dcb3a89252e9e8fa9b54ba9012e714f7cc96395. * refactor: remove symbolic addresses to make all of the test work * chore: remove console logs * feat: add properties file * chore: polish * refactor: enhance test on property 7 using direct try catch (now works) * fix: review comments * refactor: add symbolic addresses on test functions * feat: create halmos toml * chore: polish test contract and mock * chore: update property * refactor: move symbolic folder into properties one * feat: create advanced tests helper contract * refactor: enhance tests using symbolic addresses instead of concrete ones * chore: remove 0 property natspec * feat: add halmos profile and just script * chore: rename symbolic folder to halmos * feat: add halmos commands to justfile * chore: reorder assertions on one test * refactor: complete test property seven * chore: mark properties as completed * chore: add halmos-cheatcodes dependency * chore: rename advancedtest->halmosbase * chore: minimize mocked messenger * chore: delete empty halmos file * chore: revert changes to medusa.json * docs: update changes to PROPERTIES.md from base branch * test: sendERC20 destination fix * chore: natspec fixes --------- Co-authored-by: agusduha Co-authored-by: 0xng Co-authored-by: teddy --- .gitmodules | 3 + packages/contracts-bedrock/foundry.toml | 8 +- packages/contracts-bedrock/halmos.toml | 15 ++ packages/contracts-bedrock/justfile | 7 + .../contracts-bedrock/lib/halmos-cheatcodes | 1 + .../test/invariants/PROPERTIES.md | 73 ++++++ .../test/properties/PROPERTIES.md | 23 +- .../properties/halmos/MockL2ToL2Messenger.sol | 25 ++ .../halmos/OptimismSuperchainERC20.t.sol | 237 ++++++++++++++++++ .../test/properties/helpers/HalmosBase.sol | 18 ++ 10 files changed, 398 insertions(+), 12 deletions(-) create mode 100644 packages/contracts-bedrock/halmos.toml create mode 160000 packages/contracts-bedrock/lib/halmos-cheatcodes create mode 100644 packages/contracts-bedrock/test/invariants/PROPERTIES.md create mode 100644 packages/contracts-bedrock/test/properties/halmos/MockL2ToL2Messenger.sol create mode 100644 packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol create mode 100644 packages/contracts-bedrock/test/properties/helpers/HalmosBase.sol diff --git a/.gitmodules b/.gitmodules index 21ecaedbb77a..222d45be7ccc 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,3 +29,6 @@ [submodule "packages/contracts-bedrock/lib/openzeppelin-contracts-v5"] path = packages/contracts-bedrock/lib/openzeppelin-contracts-v5 url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "packages/contracts-bedrock/lib/halmos-cheatcodes"] + path = packages/contracts-bedrock/lib/halmos-cheatcodes + url = https://github.com/a16z/halmos-cheatcodes diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 3b69c67412f6..69b1fde5c5eb 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -21,7 +21,8 @@ remappings = [ 'ds-test/=lib/forge-std/lib/ds-test/src', 'safe-contracts/=lib/safe-contracts/contracts', 'kontrol-cheatcodes/=lib/kontrol-cheatcodes/src', - 'gelato/=lib/automate/contracts' + 'gelato/=lib/automate/contracts', + 'halmos-cheatcodes/=lib/halmos-cheatcodes/' ] extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout'] bytecode_hash = 'none' @@ -101,3 +102,8 @@ script = 'test/kontrol/proofs' src = 'test/properties/medusa/' test = 'test/properties/medusa/' script = 'test/properties/medusa/' + +[profile.halmos] +src = 'test/properties/halmos/' +test = 'test/properties/halmos/' +script = 'test/properties/halmos/' diff --git a/packages/contracts-bedrock/halmos.toml b/packages/contracts-bedrock/halmos.toml new file mode 100644 index 000000000000..c431c6c3a532 --- /dev/null +++ b/packages/contracts-bedrock/halmos.toml @@ -0,0 +1,15 @@ +# Halmos configuration file + +## The version needed is `halmos 0.1.15.dev2+gc3f45dd` +## Just running `halmos` will run the tests with the default configuration + +[global] +# Contract to test +match-contract = "SymTest_" + +# Path to the Forge artifacts directory +forge_build_out = "./forge-artifacts" + + +# Storage layout +storage_layout = "generic" \ No newline at end of file diff --git a/packages/contracts-bedrock/justfile b/packages/contracts-bedrock/justfile index 290f01574ead..a003558bb91e 100644 --- a/packages/contracts-bedrock/justfile +++ b/packages/contracts-bedrock/justfile @@ -25,6 +25,13 @@ test-kontrol: test-medusa timeout='100': FOUNDRY_PROFILE=medusa medusa fuzz --timeout {{timeout}} + +test-halmos-all VERBOSE="-v": + FOUNDRY_PROFILE=halmos halmos {{VERBOSE}} + +test-halmos TEST VERBOSE="-v": + FOUNDRY_PROFILE=halmos halmos --function {{TEST}} {{VERBOSE}} + test-rerun: build-go-ffi forge test --rerun -vvv diff --git a/packages/contracts-bedrock/lib/halmos-cheatcodes b/packages/contracts-bedrock/lib/halmos-cheatcodes new file mode 160000 index 000000000000..c0d865508c0f --- /dev/null +++ b/packages/contracts-bedrock/lib/halmos-cheatcodes @@ -0,0 +1 @@ +Subproject commit c0d865508c0fee0a11b97732c5e90f9cad6b65a5 diff --git a/packages/contracts-bedrock/test/invariants/PROPERTIES.md b/packages/contracts-bedrock/test/invariants/PROPERTIES.md new file mode 100644 index 000000000000..5a5cc71d73b5 --- /dev/null +++ b/packages/contracts-bedrock/test/invariants/PROPERTIES.md @@ -0,0 +1,73 @@ +# supertoken properties + +legend: + +- `[ ]`: property not yet tested +- `**[ ]**`: property not yet tested, dev/research team has asked for extra focus on it +- `[X]`: tested/proven property +- `[~]`: partially tested/proven property +- `:(`: property won't be tested due to some limitation + +## Unit test + +| id | description | halmos | medusa | +| --- | ---------------------------------------------------------------------------------- | ------ | ------ | +| 0 | supertoken token address does not depend on the executing chain’s chainID | [ ] | [ ] | +| 1 | supertoken token address depends on name, remote token, address and decimals | [ ] | [ ] | +| 2 | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | [ ] | +| 3 | convert() only allows migrations between tokens representing the same remote asset | [ ] | [ ] | +| 4 | convert() only allows migrations from tokens with the same decimals | [ ] | [ ] | +| 5 | convert() burns the same amount of one token that it mints of the other | [ ] | [ ] | + +## Valid state + +| id | description | halmos | medusa | +| --- | ------------------------------------------------------------------------------------------ | ------- | ------ | +| 6 | calls to sendERC20 succeed as long as caller has enough balance | [x] | [ ] | +| 7 | calls to relayERC20 always succeed as long as the sender and cross-domain caller are valid | **[~]** | [ ] | + +## Variable transition + +| id | description | halmos | medusa | +| --- | ------------------------------------------------------------------------------------------------- | ------ | ------ | +| 8 | sendERC20 with a value of zero does not modify accounting | [x] | [ ] | +| 9 | relayERC20 with a value of zero does not modify accounting | [x] | [ ] | +| 10 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | [ ] | +| 11 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [x] | [ ] | +| 12 | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [x] | [ ] | +| 13 | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [x] | [ ] | +| 14 | supertoken total supply starts at zero | [x] | [ ] | +| 15 | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | +| 16 | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | + +## High level + +| id | description | halmos | medusa | +| --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ------ | +| 17 | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | [ ] | +| 18 | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | [ ] | +| 19 | sum of total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | +| 20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | [ ] | +| 21 | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [ ] | [ ] | + +## Atomic bridging pseudo-properties + +As another layer of defense, the following properties are defined which assume bridging operations to be atomic (that is, the sequencer and L2Inbox and CrossDomainMessenger contracts are fully abstracted away, `sendERC20` triggering the `relayERC20` call on the same transaction) +It’s worth noting that these properties will not hold for a live system + +| id | description | halmos | medusa | +| --- | ---------------------------------------------------------------------------------------------------------------------------------- | ------ | ------ | +| 22 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [x] | +| 23 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [x] | +| 24 | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [~] | + +# Expected external interactions + +- regular ERC20 operations between any accounts on the same chain, provided by [crytic ERC20 properties](https://github.com/crytic/properties?tab=readme-ov-file#erc20-tests) + +# Invariant-breaking candidates (brain dump) + +here we’ll list possible interactions that we intend the fuzzing campaign to support in order to help break invariants + +- [ ] changing the decimals of tokens after deployment +- [ ] `convert()` ing between multiple (3+) representations of the same remote token, by having different names/symbols diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md index 36b7b330ab0b..25dc9b036d3b 100644 --- a/packages/contracts-bedrock/test/properties/PROPERTIES.md +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -54,6 +54,7 @@ Given the [OP monorepo](https://github.com/ethereum-optimism/optimism) already h # Ecosystem properties legend: + - `[ ]`: property not yet tested - `**[ ]**`: property not yet tested, dev/research team has asked for extra focus on it - `[X]`: tested/proven property @@ -73,22 +74,22 @@ legend: ## Valid state -| id | milestone | description | halmos | medusa | -| --- | --- | --- | --- | --- | -| 6 | SupERC20 | calls to sendERC20 succeed as long as caller has enough balance | [ ] | [ ] | -| 7 | SupERC20 | calls to relayERC20 always succeed as long as the cross-domain caller is valid | **[ ]** | [ ] | +| id | milestone | description | halmos | medusa | +| --- | --- | --- | --- | --- | +| 6 | SupERC20 | calls to sendERC20 succeed as long as caller has enough balance | [x] | [ ] | +| 7 | SupERC20 | calls to relayERC20 always succeed as long as the sender and cross-domain caller are valid | **[~]** | [ ] | ## Variable transition | id | milestone | description | halmos | medusa | | --- | --- | --- | --- | --- | -| 8 | SupERC20 | sendERC20 with a value of zero does not modify accounting | [ ] | [ ] | -| 9 | SupERC20 | relayERC20 with a value of zero does not modify accounting | [ ] | [ ] | -| 10 | SupERC20 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [ ] | [ ] | -| 11 | SupERC20 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [ ] | [ ] | -| 12 | Liquidity Migration | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [ ] | [~] | -| 13 | Liquidity Migration | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [ ] | [ ] | -| 14 | SupERC20 | supertoken total supply starts at zero | [ ] | [x] | +| 8 | SupERC20 | sendERC20 with a value of zero does not modify accounting | [x] | [ ] | +| 9 | SupERC20 | relayERC20 with a value of zero does not modify accounting | [x] | [ ] | +| 10 | SupERC20 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | [ ] | +| 11 | SupERC20 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [x] | [ ] | +| 12 | Liquidity Migration | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [x] | [~] | +| 13 | Liquidity Migration | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [x] | [ ] | +| 14 | SupERC20 | supertoken total supply starts at zero | [x] | [x] | | 15 | Factories | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | | 16 | Factories | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | diff --git a/packages/contracts-bedrock/test/properties/halmos/MockL2ToL2Messenger.sol b/packages/contracts-bedrock/test/properties/halmos/MockL2ToL2Messenger.sol new file mode 100644 index 000000000000..fb8732f384f8 --- /dev/null +++ b/packages/contracts-bedrock/test/properties/halmos/MockL2ToL2Messenger.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + + +// TODO: Try to merge to a single mocked contract used by fuzzing and symbolic invariant tests - only if possible +// and low priorty +contract MockL2ToL2Messenger { + // Setting the current cross domain sender for the check of sender address equals the supertoken address + address internal immutable CROSS_DOMAIN_SENDER; + + constructor(address _xDomainSender) { + CROSS_DOMAIN_SENDER = _xDomainSender; + } + + function sendMessage(uint256 , address , bytes calldata) external payable { + } + + function crossDomainMessageSource() external view returns (uint256 _source) { + _source = block.chainid + 1; + } + + function crossDomainMessageSender() external view returns (address _sender) { + _sender = CROSS_DOMAIN_SENDER; + } +} diff --git a/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol b/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol new file mode 100644 index 000000000000..a6285ac58e08 --- /dev/null +++ b/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { SymTest } from "halmos-cheatcodes/src/SymTest.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; +import { MockL2ToL2Messenger } from "./MockL2ToL2Messenger.sol"; +import { HalmosBase } from "../helpers/HalmosBase.sol"; + +contract SymTest_OptimismSuperchainERC20 is SymTest, HalmosBase { + MockL2ToL2Messenger internal constant MESSENGER = MockL2ToL2Messenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + + OptimismSuperchainERC20 public superchainERC20Impl; + OptimismSuperchainERC20 internal optimismSuperchainERC20; + + function setUp() public { + // Deploy the OptimismSuperchainERC20 contract implementation and the proxy to be used + superchainERC20Impl = new OptimismSuperchainERC20(); + optimismSuperchainERC20 = OptimismSuperchainERC20( + address( + // TODO: Update to beacon proxy + new ERC1967Proxy( + address(superchainERC20Impl), + abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) + ) + ) + ); + + // Etch the mocked L2 to L2 Messenger since the messenger logic is out of scope for these test suite. Also, we + // avoid issues such as `TSTORE` opcode not being supported, or issues with `encodeVersionedNonce()` + address _mockL2ToL2CrossDomainMessenger = address(new MockL2ToL2Messenger(address(optimismSuperchainERC20))); + vm.etch(address(MESSENGER), _mockL2ToL2CrossDomainMessenger.code); + // NOTE: We need to set the crossDomainMessageSender as an immutable or otherwise storage vars and not taken + // into account when etching on halmos. Setting a constant slot with setters and getters didn't work neither. + } + + /// @notice Check setup works as expected + function check_setup() public view { + assert(optimismSuperchainERC20.remoteToken() == remoteToken); + assert(eqStrings(optimismSuperchainERC20.name(), name)); + assert(eqStrings(optimismSuperchainERC20.symbol(), symbol)); + assert(optimismSuperchainERC20.decimals() == decimals); + assert(MESSENGER.crossDomainMessageSender() == address(optimismSuperchainERC20)); + } + + /// @custom:property-id 6 + /// @custom:property Calls to sendERC20 succeed as long as caller has enough balance + function check_sendERC20SucceedsOnlyIfEnoughBalance( + uint256 _initialBalance, + address _from, + uint256 _amount, + address _to, + uint256 _chainId + ) + public + { + /* Preconditions */ + vm.assume(_chainId != CURRENT_CHAIN_ID); + vm.assume(_to != address(0)); + vm.assume(_from != address(0)); + + // Can't deal to unsupported cheatcode + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + optimismSuperchainERC20.mint(_from, _initialBalance); + + vm.prank(_from); + /* Action */ + try optimismSuperchainERC20.sendERC20(_to, _amount, _chainId) { + /* Postcondition */ + assert(_initialBalance >= _amount); + } catch { + assert(_initialBalance < _amount); + } + } + + /// @custom:property-id 7 + /// @custom:property Calls to relayERC20 always succeed as long as the sender the cross-domain caller are valid + function check_relayERC20OnlyFromL2ToL2Messenger( + address _crossDomainSender, + address _sender, + address _from, + address _to, + uint256 _amount + ) + public + { + /* Precondition */ + vm.assume(_to != address(0)); + // Deploying a new messenger because of an issue of not being able to etch the storage layout of the mock + // contract. So needed to a new one setting the symbolic immutable variable for the crossDomainSender. + vm.etch(address(MESSENGER), address(new MockL2ToL2Messenger(_crossDomainSender)).code); + + vm.prank(_sender); + /* Action */ + try optimismSuperchainERC20.relayERC20(_from, _to, _amount) { + /* Postconditions */ + assert( + _sender == address(MESSENGER) + && MESSENGER.crossDomainMessageSender() == address(optimismSuperchainERC20) + ); + } catch { + assert( + _sender != address(MESSENGER) + || MESSENGER.crossDomainMessageSender() != address(optimismSuperchainERC20) + ); + } + } + + /// @custom:property-id 8 + /// @custom:property `sendERC20` with a value of zero does not modify accounting + function check_sendERC20ZeroCall(address _from, address _to, uint256 _chainId) public { + /* Preconditions */ + vm.assume(_to != address(0)); + vm.assume(_chainId != CURRENT_CHAIN_ID); + vm.assume(_to != address(Predeploys.CROSS_L2_INBOX) && _to != address(MESSENGER)); + + uint256 _totalSupplyBefore = optimismSuperchainERC20.totalSupply(); + uint256 _fromBalanceBefore = optimismSuperchainERC20.balanceOf(_from); + + vm.startPrank(_from); + /* Action */ + optimismSuperchainERC20.sendERC20(_to, ZERO_AMOUNT, _chainId); + + /* Postcondition */ + assert(optimismSuperchainERC20.totalSupply() == _totalSupplyBefore); + assert(optimismSuperchainERC20.balanceOf(_from) == _fromBalanceBefore); + } + + /// @custom:property-id 9 + /// @custom:property `relayERC20` with a value of zero does not modify accounting + function check_relayERC20ZeroCall(address _from, address _to) public { + uint256 _totalSupplyBefore = optimismSuperchainERC20.totalSupply(); + /* Preconditions */ + uint256 _fromBalanceBefore = optimismSuperchainERC20.balanceOf(_from); + uint256 _toBalanceBefore = optimismSuperchainERC20.balanceOf(_to); + vm.prank(address(MESSENGER)); + + /* Action */ + optimismSuperchainERC20.relayERC20(_from, _to, ZERO_AMOUNT); + + /* Postconditions */ + assert(optimismSuperchainERC20.totalSupply() == _totalSupplyBefore); + assert(optimismSuperchainERC20.balanceOf(_from) == _fromBalanceBefore); + assert(optimismSuperchainERC20.balanceOf(_to) == _toBalanceBefore); + } + + /// @custom:property-id 10 + /// @custom:property `sendERC20` decreases the token's totalSupply in the source chain exactly by the input amount + function check_sendERC20DecreasesTotalSupply( + address _sender, + address _to, + uint256 _amount, + uint256 _chainId + ) + public + { + /* Preconditions */ + vm.assume(_to != address(0)); + vm.assume(_chainId != CURRENT_CHAIN_ID); + + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + optimismSuperchainERC20.mint(_sender, _amount); + + uint256 _totalSupplyBefore = optimismSuperchainERC20.totalSupply(); + uint256 _balanceBefore = optimismSuperchainERC20.balanceOf(_sender); + + vm.prank(_sender); + /* Action */ + optimismSuperchainERC20.sendERC20(_to, _amount, _chainId); + + /* Postconditions */ + assert(optimismSuperchainERC20.totalSupply() == _totalSupplyBefore - _amount); + assert(optimismSuperchainERC20.balanceOf(_sender) == _balanceBefore - _amount); + } + + /// @custom:property-id 11 + /// @custom:property `relayERC20` increases the token's totalSupply in the destination chain exactly by the input + /// amount + function check_relayERC20IncreasesTotalSupply(address _from, address _to, uint256 _amount) public { + vm.assume(_to != address(0)); + + /* Preconditions */ + uint256 _totalSupplyBefore = optimismSuperchainERC20.totalSupply(); + uint256 _toBalanceBefore = optimismSuperchainERC20.balanceOf(_to); + + vm.prank(address(MESSENGER)); + /* Action */ + optimismSuperchainERC20.relayERC20(_from, _to, _amount); + + /* Postconditions */ + assert(optimismSuperchainERC20.totalSupply() == _totalSupplyBefore + _amount); + assert(optimismSuperchainERC20.balanceOf(_to) == _toBalanceBefore + _amount); + } + + /// @custom:property-id 12 + /// @custom:property Increases the total supply on the amount minted by the bridge + function check_mint(address _from, uint256 _amount) public { + /* Preconditions */ + uint256 _totalSupplyBefore = optimismSuperchainERC20.totalSupply(); + uint256 _balanceBefore = optimismSuperchainERC20.balanceOf(_from); + + vm.startPrank(Predeploys.L2_STANDARD_BRIDGE); + /* Action */ + optimismSuperchainERC20.mint(_from, _amount); + + /* Postconditions */ + assert(optimismSuperchainERC20.totalSupply() == _totalSupplyBefore + _amount); + assert(optimismSuperchainERC20.balanceOf(_from) == _balanceBefore + _amount); + } + + /// @custom:property-id 13 + /// @custom:property Supertoken total supply only decreases on the amount burned by the bridge + function check_burn(address _from, uint256 _amount) public { + /* Preconditions */ + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + optimismSuperchainERC20.mint(_from, _amount); + + uint256 _totalSupplyBefore = optimismSuperchainERC20.totalSupply(); + uint256 _balanceBefore = optimismSuperchainERC20.balanceOf(_from); + + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + /* Action */ + optimismSuperchainERC20.burn(_from, _amount); + + /* Postconditions */ + assert(optimismSuperchainERC20.totalSupply() == _totalSupplyBefore - _amount); + assert(optimismSuperchainERC20.balanceOf(_from) == _balanceBefore - _amount); + } + + /// @custom:property-id 14 + /// @custom:property Supertoken total supply starts at zero + function check_totalSupplyStartsAtZero() public view { + /* Postconditions */ + assert(optimismSuperchainERC20.totalSupply() == 0); + } +} diff --git a/packages/contracts-bedrock/test/properties/helpers/HalmosBase.sol b/packages/contracts-bedrock/test/properties/helpers/HalmosBase.sol new file mode 100644 index 000000000000..75bfe2f7c9e1 --- /dev/null +++ b/packages/contracts-bedrock/test/properties/helpers/HalmosBase.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { Test } from "forge-std/Test.sol"; + +contract HalmosBase is Test { + uint256 internal constant CURRENT_CHAIN_ID = 1; + uint256 internal constant ZERO_AMOUNT = 0; + + address internal remoteToken = address(bytes20(keccak256("remoteToken"))); + string internal name = "SuperchainERC20"; + string internal symbol = "SUPER"; + uint8 internal decimals = 18; + + function eqStrings(string memory a, string memory b) internal pure returns (bool) { + return keccak256(abi.encode(a)) == keccak256(abi.encode(b)); + } +} From 773a1d85ec170359fb39b481923b051c24320919 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Fri, 16 Aug 2024 23:00:53 -0300 Subject: [PATCH 20/56] feat: test properties 22 and 23 * refactor: allow for atomicity on mock messenger * refactor: cross domain sender logic on mock messenger * refactor: l2 to l2 caller and messenge sender logic * chore: remove assumes for removed checks on mock messenger --- .../properties/halmos/MockL2ToL2Messenger.sol | 56 +++++- .../halmos/OptimismSuperchainERC20.t.sol | 184 ++++++++++++------ .../test/properties/helpers/HalmosBase.sol | 1 + 3 files changed, 174 insertions(+), 67 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/halmos/MockL2ToL2Messenger.sol b/packages/contracts-bedrock/test/properties/halmos/MockL2ToL2Messenger.sol index fb8732f384f8..5f7aa3b301e7 100644 --- a/packages/contracts-bedrock/test/properties/halmos/MockL2ToL2Messenger.sol +++ b/packages/contracts-bedrock/test/properties/halmos/MockL2ToL2Messenger.sol @@ -1,25 +1,65 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.25; +import "src/L2/L2ToL2CrossDomainMessenger.sol"; +import { SafeCall } from "src/libraries/SafeCall.sol"; // TODO: Try to merge to a single mocked contract used by fuzzing and symbolic invariant tests - only if possible -// and low priorty -contract MockL2ToL2Messenger { - // Setting the current cross domain sender for the check of sender address equals the supertoken address - address internal immutable CROSS_DOMAIN_SENDER; +// and is a low priorty +contract MockL2ToL2Messenger is IL2ToL2CrossDomainMessenger { + /// NOTE: Setting everything as immutable bc the storage layour is ignored when etching. + address internal immutable SOURCE_TOKEN; + address internal immutable DESTINATION_TOKEN; + uint256 public immutable DESTINATION_CHAIN_ID; + // Custom cross domain sender to be used when neither the source nor destination token are the callers + address internal immutable CUSTOM_CROSS_DOMAIN_SENDER; - constructor(address _xDomainSender) { - CROSS_DOMAIN_SENDER = _xDomainSender; + constructor( + address _sourceToken, + address _destinationToken, + uint256 _destinationChainId, + address _customCrossDomainSender + ) { + SOURCE_TOKEN = _sourceToken; + DESTINATION_TOKEN = _destinationToken; + DESTINATION_CHAIN_ID = _destinationChainId; + CUSTOM_CROSS_DOMAIN_SENDER = _customCrossDomainSender; } - function sendMessage(uint256 , address , bytes calldata) external payable { + function sendMessage(uint256 _destination, address, bytes calldata _message) external payable { + // Mocking the environment to allow atomicity by executing the message call + if (_destination == DESTINATION_CHAIN_ID) { + (bool _success) = SafeCall.call(DESTINATION_TOKEN, 0, _message); + if (!_success) revert("MockL2ToL2Messenger: sendMessage failed"); + } + } + + function relayMessage( + uint256, + uint256, + uint256, + address, + address _target, + bytes calldata _message + ) + external + payable + { + (bool succ, bytes memory ret) = _target.call{ value: msg.value }(_message); + if (!succ) revert(string(ret)); + + // TODO: Add more logic? Like replacing the (unsupported) `TSTORE` updates with `SSTORE` - or add the checks } function crossDomainMessageSource() external view returns (uint256 _source) { _source = block.chainid + 1; } + // Mock this function so it just always returns the expected if called by the supertoken, or otherwise defaults to + // the custom cross domain sender function crossDomainMessageSender() external view returns (address _sender) { - _sender = CROSS_DOMAIN_SENDER; + if (msg.sender == SOURCE_TOKEN) _sender = SOURCE_TOKEN; + else if (msg.sender == DESTINATION_TOKEN) _sender = DESTINATION_TOKEN; + else _sender = CUSTOM_CROSS_DOMAIN_SENDER; } } diff --git a/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol b/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol index a6285ac58e08..cdbae879d0ff 100644 --- a/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol +++ b/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol @@ -12,12 +12,23 @@ contract SymTest_OptimismSuperchainERC20 is SymTest, HalmosBase { MockL2ToL2Messenger internal constant MESSENGER = MockL2ToL2Messenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); OptimismSuperchainERC20 public superchainERC20Impl; - OptimismSuperchainERC20 internal optimismSuperchainERC20; + OptimismSuperchainERC20 internal sourceToken; + OptimismSuperchainERC20 internal destToken; function setUp() public { // Deploy the OptimismSuperchainERC20 contract implementation and the proxy to be used superchainERC20Impl = new OptimismSuperchainERC20(); - optimismSuperchainERC20 = OptimismSuperchainERC20( + sourceToken = OptimismSuperchainERC20( + address( + // TODO: Update to beacon proxy + new ERC1967Proxy( + address(superchainERC20Impl), + abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) + ) + ) + ); + + destToken = OptimismSuperchainERC20( address( // TODO: Update to beacon proxy new ERC1967Proxy( @@ -29,19 +40,34 @@ contract SymTest_OptimismSuperchainERC20 is SymTest, HalmosBase { // Etch the mocked L2 to L2 Messenger since the messenger logic is out of scope for these test suite. Also, we // avoid issues such as `TSTORE` opcode not being supported, or issues with `encodeVersionedNonce()` - address _mockL2ToL2CrossDomainMessenger = address(new MockL2ToL2Messenger(address(optimismSuperchainERC20))); + address _mockL2ToL2CrossDomainMessenger = + address(new MockL2ToL2Messenger(address(sourceToken), address(destToken), DESTINATION_CHAIN_ID, address(0))); vm.etch(address(MESSENGER), _mockL2ToL2CrossDomainMessenger.code); // NOTE: We need to set the crossDomainMessageSender as an immutable or otherwise storage vars and not taken // into account when etching on halmos. Setting a constant slot with setters and getters didn't work neither. } /// @notice Check setup works as expected - function check_setup() public view { - assert(optimismSuperchainERC20.remoteToken() == remoteToken); - assert(eqStrings(optimismSuperchainERC20.name(), name)); - assert(eqStrings(optimismSuperchainERC20.symbol(), symbol)); - assert(optimismSuperchainERC20.decimals() == decimals); - assert(MESSENGER.crossDomainMessageSender() == address(optimismSuperchainERC20)); + function check_setup() public { + // Source token + assert(sourceToken.remoteToken() == remoteToken); + assert(eqStrings(sourceToken.name(), name)); + assert(eqStrings(sourceToken.symbol(), symbol)); + assert(sourceToken.decimals() == decimals); + vm.prank(address(sourceToken)); + assert(MESSENGER.crossDomainMessageSender() == address(sourceToken)); + + // Destination token + assert(destToken.remoteToken() == remoteToken); + assert(eqStrings(destToken.name(), name)); + assert(eqStrings(destToken.symbol(), symbol)); + assert(destToken.decimals() == decimals); + assert(MESSENGER.DESTINATION_CHAIN_ID() == DESTINATION_CHAIN_ID); + vm.prank(address(destToken)); + assert(MESSENGER.crossDomainMessageSender() == address(destToken)); + + // Custom cross domain sender + assert(MESSENGER.crossDomainMessageSender() == address(0)); } /// @custom:property-id 6 @@ -56,17 +82,16 @@ contract SymTest_OptimismSuperchainERC20 is SymTest, HalmosBase { public { /* Preconditions */ - vm.assume(_chainId != CURRENT_CHAIN_ID); vm.assume(_to != address(0)); vm.assume(_from != address(0)); // Can't deal to unsupported cheatcode vm.prank(Predeploys.L2_STANDARD_BRIDGE); - optimismSuperchainERC20.mint(_from, _initialBalance); + sourceToken.mint(_from, _initialBalance); vm.prank(_from); /* Action */ - try optimismSuperchainERC20.sendERC20(_to, _amount, _chainId) { + try sourceToken.sendERC20(_to, _amount, _chainId) { /* Postcondition */ assert(_initialBalance >= _amount); } catch { @@ -89,21 +114,18 @@ contract SymTest_OptimismSuperchainERC20 is SymTest, HalmosBase { vm.assume(_to != address(0)); // Deploying a new messenger because of an issue of not being able to etch the storage layout of the mock // contract. So needed to a new one setting the symbolic immutable variable for the crossDomainSender. - vm.etch(address(MESSENGER), address(new MockL2ToL2Messenger(_crossDomainSender)).code); + // Used 0 address on source token so when the `soureToken` calls it if returns the symbolic `_crossDomainSender` + vm.etch( + address(MESSENGER), address(new MockL2ToL2Messenger(address(0), address(0), 0, _crossDomainSender)).code + ); vm.prank(_sender); /* Action */ - try optimismSuperchainERC20.relayERC20(_from, _to, _amount) { + try sourceToken.relayERC20(_from, _to, _amount) { /* Postconditions */ - assert( - _sender == address(MESSENGER) - && MESSENGER.crossDomainMessageSender() == address(optimismSuperchainERC20) - ); + assert(_sender == address(MESSENGER) && MESSENGER.crossDomainMessageSender() == address(sourceToken)); } catch { - assert( - _sender != address(MESSENGER) - || MESSENGER.crossDomainMessageSender() != address(optimismSuperchainERC20) - ); + assert(_sender != address(MESSENGER) || MESSENGER.crossDomainMessageSender() != address(sourceToken)); } } @@ -112,37 +134,38 @@ contract SymTest_OptimismSuperchainERC20 is SymTest, HalmosBase { function check_sendERC20ZeroCall(address _from, address _to, uint256 _chainId) public { /* Preconditions */ vm.assume(_to != address(0)); - vm.assume(_chainId != CURRENT_CHAIN_ID); vm.assume(_to != address(Predeploys.CROSS_L2_INBOX) && _to != address(MESSENGER)); - uint256 _totalSupplyBefore = optimismSuperchainERC20.totalSupply(); - uint256 _fromBalanceBefore = optimismSuperchainERC20.balanceOf(_from); + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); + uint256 _toBalanceBefore = sourceToken.balanceOf(_to); vm.startPrank(_from); /* Action */ - optimismSuperchainERC20.sendERC20(_to, ZERO_AMOUNT, _chainId); + sourceToken.sendERC20(_to, ZERO_AMOUNT, _chainId); /* Postcondition */ - assert(optimismSuperchainERC20.totalSupply() == _totalSupplyBefore); - assert(optimismSuperchainERC20.balanceOf(_from) == _fromBalanceBefore); + assert(sourceToken.totalSupply() == _totalSupplyBefore); + assert(sourceToken.balanceOf(_from) == _fromBalanceBefore); + assert(sourceToken.balanceOf(_to) == _toBalanceBefore); } /// @custom:property-id 9 /// @custom:property `relayERC20` with a value of zero does not modify accounting function check_relayERC20ZeroCall(address _from, address _to) public { - uint256 _totalSupplyBefore = optimismSuperchainERC20.totalSupply(); + uint256 _totalSupplyBefore = sourceToken.totalSupply(); /* Preconditions */ - uint256 _fromBalanceBefore = optimismSuperchainERC20.balanceOf(_from); - uint256 _toBalanceBefore = optimismSuperchainERC20.balanceOf(_to); + uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); + uint256 _toBalanceBefore = sourceToken.balanceOf(_to); vm.prank(address(MESSENGER)); /* Action */ - optimismSuperchainERC20.relayERC20(_from, _to, ZERO_AMOUNT); + sourceToken.relayERC20(_from, _to, ZERO_AMOUNT); /* Postconditions */ - assert(optimismSuperchainERC20.totalSupply() == _totalSupplyBefore); - assert(optimismSuperchainERC20.balanceOf(_from) == _fromBalanceBefore); - assert(optimismSuperchainERC20.balanceOf(_to) == _toBalanceBefore); + assert(sourceToken.totalSupply() == _totalSupplyBefore); + assert(sourceToken.balanceOf(_from) == _fromBalanceBefore); + assert(sourceToken.balanceOf(_to) == _toBalanceBefore); } /// @custom:property-id 10 @@ -157,21 +180,20 @@ contract SymTest_OptimismSuperchainERC20 is SymTest, HalmosBase { { /* Preconditions */ vm.assume(_to != address(0)); - vm.assume(_chainId != CURRENT_CHAIN_ID); vm.prank(Predeploys.L2_STANDARD_BRIDGE); - optimismSuperchainERC20.mint(_sender, _amount); + sourceToken.mint(_sender, _amount); - uint256 _totalSupplyBefore = optimismSuperchainERC20.totalSupply(); - uint256 _balanceBefore = optimismSuperchainERC20.balanceOf(_sender); + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + uint256 _balanceBefore = sourceToken.balanceOf(_sender); vm.prank(_sender); /* Action */ - optimismSuperchainERC20.sendERC20(_to, _amount, _chainId); + sourceToken.sendERC20(Predeploys.CROSS_L2_INBOX, _amount, _chainId); /* Postconditions */ - assert(optimismSuperchainERC20.totalSupply() == _totalSupplyBefore - _amount); - assert(optimismSuperchainERC20.balanceOf(_sender) == _balanceBefore - _amount); + assert(sourceToken.totalSupply() == _totalSupplyBefore - _amount); + assert(sourceToken.balanceOf(_sender) == _balanceBefore - _amount); } /// @custom:property-id 11 @@ -181,32 +203,32 @@ contract SymTest_OptimismSuperchainERC20 is SymTest, HalmosBase { vm.assume(_to != address(0)); /* Preconditions */ - uint256 _totalSupplyBefore = optimismSuperchainERC20.totalSupply(); - uint256 _toBalanceBefore = optimismSuperchainERC20.balanceOf(_to); + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + uint256 _toBalanceBefore = sourceToken.balanceOf(_to); vm.prank(address(MESSENGER)); /* Action */ - optimismSuperchainERC20.relayERC20(_from, _to, _amount); + sourceToken.relayERC20(_from, _to, _amount); /* Postconditions */ - assert(optimismSuperchainERC20.totalSupply() == _totalSupplyBefore + _amount); - assert(optimismSuperchainERC20.balanceOf(_to) == _toBalanceBefore + _amount); + assert(sourceToken.totalSupply() == _totalSupplyBefore + _amount); + assert(sourceToken.balanceOf(_to) == _toBalanceBefore + _amount); } /// @custom:property-id 12 /// @custom:property Increases the total supply on the amount minted by the bridge function check_mint(address _from, uint256 _amount) public { /* Preconditions */ - uint256 _totalSupplyBefore = optimismSuperchainERC20.totalSupply(); - uint256 _balanceBefore = optimismSuperchainERC20.balanceOf(_from); + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + uint256 _balanceBefore = sourceToken.balanceOf(_from); vm.startPrank(Predeploys.L2_STANDARD_BRIDGE); /* Action */ - optimismSuperchainERC20.mint(_from, _amount); + sourceToken.mint(_from, _amount); /* Postconditions */ - assert(optimismSuperchainERC20.totalSupply() == _totalSupplyBefore + _amount); - assert(optimismSuperchainERC20.balanceOf(_from) == _balanceBefore + _amount); + assert(sourceToken.totalSupply() == _totalSupplyBefore + _amount); + assert(sourceToken.balanceOf(_from) == _balanceBefore + _amount); } /// @custom:property-id 13 @@ -214,24 +236,68 @@ contract SymTest_OptimismSuperchainERC20 is SymTest, HalmosBase { function check_burn(address _from, uint256 _amount) public { /* Preconditions */ vm.prank(Predeploys.L2_STANDARD_BRIDGE); - optimismSuperchainERC20.mint(_from, _amount); + sourceToken.mint(_from, _amount); - uint256 _totalSupplyBefore = optimismSuperchainERC20.totalSupply(); - uint256 _balanceBefore = optimismSuperchainERC20.balanceOf(_from); + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + uint256 _balanceBefore = sourceToken.balanceOf(_from); vm.prank(Predeploys.L2_STANDARD_BRIDGE); /* Action */ - optimismSuperchainERC20.burn(_from, _amount); + sourceToken.burn(_from, _amount); /* Postconditions */ - assert(optimismSuperchainERC20.totalSupply() == _totalSupplyBefore - _amount); - assert(optimismSuperchainERC20.balanceOf(_from) == _balanceBefore - _amount); + assert(sourceToken.totalSupply() == _totalSupplyBefore - _amount); + assert(sourceToken.balanceOf(_from) == _balanceBefore - _amount); } /// @custom:property-id 14 /// @custom:property Supertoken total supply starts at zero function check_totalSupplyStartsAtZero() public view { /* Postconditions */ - assert(optimismSuperchainERC20.totalSupply() == 0); + assert(sourceToken.totalSupply() == 0); + } + + /// @custom:property-id 22 + /// @custom:property `sendERC20` decreases sender balance in source chain and increases receiver balance in + /// destination chain exactly by the input amount + /// @custom:property-id 23 + /// @custom:property `sendERC20` decreases total supply in source chain and increases it in destination chain + /// exactly by the input amount + function check_crossChainMintAndBurn(address _from, address _to, uint256 _amount, uint256 _chainId) public { + /* Preconditions */ + vm.assume(_to != address(0)); + vm.assume(_from != address(0)); + + // Mint the amount to send + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + sourceToken.mint(_from, _amount); + + uint256 fromBalanceBefore = sourceToken.balanceOf(_from); + uint256 toBalanceBefore = destToken.balanceOf(_to); + uint256 sourceTotalSupplyBefore = sourceToken.totalSupply(); + uint256 destTotalSupplyBefore = destToken.totalSupply(); + + vm.prank(_from); + /* Action */ + try sourceToken.sendERC20(_to, _amount, _chainId) { + /* Postconditions */ + // Source + assert(sourceToken.balanceOf(_from) == fromBalanceBefore - _amount); + assert(sourceToken.totalSupply() == sourceTotalSupplyBefore - _amount); + + // Destination + if (_chainId == DESTINATION_CHAIN_ID) { + // If the destination chain matches the one of the dest token, check that the amount was minted + assert(destToken.balanceOf(_to) == toBalanceBefore + _amount); + assert(destToken.totalSupply() == destTotalSupplyBefore + _amount); + } else { + // Otherwise the balances should remain the same + assert(destToken.balanceOf(_to) == toBalanceBefore); + assert(destToken.totalSupply() == destTotalSupplyBefore); + } + } catch { + // Shouldn't fail + assert(false); + } } } diff --git a/packages/contracts-bedrock/test/properties/helpers/HalmosBase.sol b/packages/contracts-bedrock/test/properties/helpers/HalmosBase.sol index 75bfe2f7c9e1..5ffac1050d14 100644 --- a/packages/contracts-bedrock/test/properties/helpers/HalmosBase.sol +++ b/packages/contracts-bedrock/test/properties/helpers/HalmosBase.sol @@ -5,6 +5,7 @@ import { Test } from "forge-std/Test.sol"; contract HalmosBase is Test { uint256 internal constant CURRENT_CHAIN_ID = 1; + uint256 internal constant DESTINATION_CHAIN_ID = 2; uint256 internal constant ZERO_AMOUNT = 0; address internal remoteToken = address(bytes20(keccak256("remoteToken"))); From 8c4e7c672b1a3be43b36a942add8f1738424c0bf Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Thu, 29 Aug 2024 11:41:36 -0300 Subject: [PATCH 21/56] feat: checkpoint of superc20 kontrol tests --- .../kontrol/proofs/OptimismSuperchain.k.sol | 303 ++++++++++++++++++ .../test/kontrol/scripts/run-kontrol.sh | 3 +- 2 files changed, 305 insertions(+), 1 deletion(-) create mode 100644 packages/contracts-bedrock/test/kontrol/proofs/OptimismSuperchain.k.sol diff --git a/packages/contracts-bedrock/test/kontrol/proofs/OptimismSuperchain.k.sol b/packages/contracts-bedrock/test/kontrol/proofs/OptimismSuperchain.k.sol new file mode 100644 index 000000000000..1e78fb4e7c90 --- /dev/null +++ b/packages/contracts-bedrock/test/kontrol/proofs/OptimismSuperchain.k.sol @@ -0,0 +1,303 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { SymTest } from "halmos-cheatcodes/src/SymTest.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; +import { MockL2ToL2Messenger } from "test/properties/halmos/MockL2ToL2Messenger.sol"; +import { HalmosBase } from "test/properties/helpers/HalmosBase.sol"; + +contract OptimismSuperchainERC20Kontrol is SymTest, HalmosBase { + MockL2ToL2Messenger internal constant MESSENGER = MockL2ToL2Messenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + + OptimismSuperchainERC20 public superchainERC20Impl; + OptimismSuperchainERC20 internal sourceToken; + OptimismSuperchainERC20 internal destToken; + + function setUp() public { + // Deploy the OptimismSuperchainERC20 contract implementation and the proxy to be used + superchainERC20Impl = new OptimismSuperchainERC20(); + sourceToken = OptimismSuperchainERC20( + address( + // TODO: Update to beacon proxy + new ERC1967Proxy( + address(superchainERC20Impl), + abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) + ) + ) + ); + + destToken = OptimismSuperchainERC20( + address( + // TODO: Update to beacon proxy + new ERC1967Proxy( + address(superchainERC20Impl), + abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) + ) + ) + ); + + // Etch the mocked L2 to L2 Messenger since the messenger logic is out of scope for these test suite. Also, we + // avoid issues such as `TSTORE` opcode not being supported, or issues with `encodeVersionedNonce()` + address _mockL2ToL2CrossDomainMessenger = + address(new MockL2ToL2Messenger(address(sourceToken), address(destToken), DESTINATION_CHAIN_ID, address(0))); + vm.etch(address(MESSENGER), _mockL2ToL2CrossDomainMessenger.code); + // NOTE: We need to set the crossDomainMessageSender as an immutable or otherwise storage vars and not taken + // into account when etching on halmos. Setting a constant slot with setters and getters didn't work neither. + } + + /// @notice Check setup works as expected + function prove_setup() public { + // Source token + assert(sourceToken.remoteToken() == remoteToken); + assert(eqStrings(sourceToken.name(), name)); + assert(eqStrings(sourceToken.symbol(), symbol)); + assert(sourceToken.decimals() == decimals); + vm.prank(address(sourceToken)); + assert(MESSENGER.crossDomainMessageSender() == address(sourceToken)); + + // Destination token + assert(destToken.remoteToken() == remoteToken); + assert(eqStrings(destToken.name(), name)); + assert(eqStrings(destToken.symbol(), symbol)); + assert(destToken.decimals() == decimals); + assert(MESSENGER.DESTINATION_CHAIN_ID() == DESTINATION_CHAIN_ID); + vm.prank(address(destToken)); + assert(MESSENGER.crossDomainMessageSender() == address(destToken)); + + // Custom cross domain sender + assert(MESSENGER.crossDomainMessageSender() == address(0)); + } + + /// @custom:property-id 6 + /// @custom:property Calls to sendERC20 succeed as long as caller has enough balance + function prove_sendERC20SucceedsOnlyIfEnoughBalance( + uint256 _initialBalance, + address _from, + uint256 _amount, + address _to, + uint256 _chainId + ) + public + { + /* Preconditions */ + vm.assume(_to != address(0)); + vm.assume(_from != address(0)); + + // Can't deal to unsupported cheatcode + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + sourceToken.mint(_from, _initialBalance); + + vm.prank(_from); + /* Action */ + try sourceToken.sendERC20(_to, _amount, _chainId) { + /* Postcondition */ + assert(_initialBalance >= _amount); + } catch { + assert(_initialBalance < _amount); + } + } + + /// @custom:property-id 7 + /// @custom:property Calls to relayERC20 always succeed as long as the sender the cross-domain caller are valid + function prove_relayERC20OnlyFromL2ToL2Messenger( + address _crossDomainSender, + address _sender, + address _from, + address _to, + uint256 _amount + ) + public + { + /* Precondition */ + vm.assume(_to != address(0)); + // Deploying a new messenger because of an issue of not being able to etch the storage layout of the mock + // contract. So needed to a new one setting the symbolic immutable variable for the crossDomainSender. + // Used 0 address on source token so when the `soureToken` calls it if returns the symbolic `_crossDomainSender` + vm.etch( + address(MESSENGER), address(new MockL2ToL2Messenger(address(0), address(0), 0, _crossDomainSender)).code + ); + + vm.prank(_sender); + /* Action */ + try sourceToken.relayERC20(_from, _to, _amount) { + /* Postconditions */ + assert(_sender == address(MESSENGER) && MESSENGER.crossDomainMessageSender() == address(sourceToken)); + } catch { + assert(_sender != address(MESSENGER) || MESSENGER.crossDomainMessageSender() != address(sourceToken)); + } + } + + /// @custom:property-id 8 + /// @custom:property `sendERC20` with a value of zero does not modify accounting + function prove_sendERC20ZeroCall(address _from, address _to, uint256 _chainId) public { + /* Preconditions */ + vm.assume(_to != address(0)); + vm.assume(_to != address(Predeploys.CROSS_L2_INBOX) && _to != address(MESSENGER)); + + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); + uint256 _toBalanceBefore = sourceToken.balanceOf(_to); + + vm.startPrank(_from); + /* Action */ + sourceToken.sendERC20(_to, ZERO_AMOUNT, _chainId); + + /* Postcondition */ + assert(sourceToken.totalSupply() == _totalSupplyBefore); + assert(sourceToken.balanceOf(_from) == _fromBalanceBefore); + assert(sourceToken.balanceOf(_to) == _toBalanceBefore); + } + + /// @custom:property-id 9 + /// @custom:property `relayERC20` with a value of zero does not modify accounting + function prove_relayERC20ZeroCall(address _from, address _to) public { + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + /* Preconditions */ + uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); + uint256 _toBalanceBefore = sourceToken.balanceOf(_to); + vm.prank(address(MESSENGER)); + + /* Action */ + sourceToken.relayERC20(_from, _to, ZERO_AMOUNT); + + /* Postconditions */ + assert(sourceToken.totalSupply() == _totalSupplyBefore); + assert(sourceToken.balanceOf(_from) == _fromBalanceBefore); + assert(sourceToken.balanceOf(_to) == _toBalanceBefore); + } + + /// @custom:property-id 10 + /// @custom:property `sendERC20` decreases the token's totalSupply in the source chain exactly by the input amount + function prove_sendERC20DecreasesTotalSupply( + address _sender, + address _to, + uint256 _amount, + uint256 _chainId + ) + public + { + /* Preconditions */ + vm.assume(_to != address(0)); + + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + sourceToken.mint(_sender, _amount); + + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + uint256 _balanceBefore = sourceToken.balanceOf(_sender); + + vm.prank(_sender); + /* Action */ + sourceToken.sendERC20(Predeploys.CROSS_L2_INBOX, _amount, _chainId); + + /* Postconditions */ + assert(sourceToken.totalSupply() == _totalSupplyBefore - _amount); + assert(sourceToken.balanceOf(_sender) == _balanceBefore - _amount); + } + + /// @custom:property-id 11 + /// @custom:property `relayERC20` increases the token's totalSupply in the destination chain exactly by the input + /// amount + function prove_relayERC20IncreasesTotalSupply(address _from, address _to, uint256 _amount) public { + vm.assume(_to != address(0)); + + /* Preconditions */ + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + uint256 _toBalanceBefore = sourceToken.balanceOf(_to); + + vm.prank(address(MESSENGER)); + /* Action */ + sourceToken.relayERC20(_from, _to, _amount); + + /* Postconditions */ + assert(sourceToken.totalSupply() == _totalSupplyBefore + _amount); + assert(sourceToken.balanceOf(_to) == _toBalanceBefore + _amount); + } + + /// @custom:property-id 12 + /// @custom:property Increases the total supply on the amount minted by the bridge + function prove_mint(address _from, uint256 _amount) public { + /* Preconditions */ + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + uint256 _balanceBefore = sourceToken.balanceOf(_from); + + vm.startPrank(Predeploys.L2_STANDARD_BRIDGE); + /* Action */ + sourceToken.mint(_from, _amount); + + /* Postconditions */ + assert(sourceToken.totalSupply() == _totalSupplyBefore + _amount); + assert(sourceToken.balanceOf(_from) == _balanceBefore + _amount); + } + + /// @custom:property-id 13 + /// @custom:property Supertoken total supply only decreases on the amount burned by the bridge + function prove_burn(address _from, uint256 _amount) public { + /* Preconditions */ + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + sourceToken.mint(_from, _amount); + + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + uint256 _balanceBefore = sourceToken.balanceOf(_from); + + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + /* Action */ + sourceToken.burn(_from, _amount); + + /* Postconditions */ + assert(sourceToken.totalSupply() == _totalSupplyBefore - _amount); + assert(sourceToken.balanceOf(_from) == _balanceBefore - _amount); + } + + /// @custom:property-id 14 + /// @custom:property Supertoken total supply starts at zero + function prove_totalSupplyStartsAtZero() public view { + /* Postconditions */ + assert(sourceToken.totalSupply() == 0); + } + + /// @custom:property-id 22 + /// @custom:property `sendERC20` decreases sender balance in source chain and increases receiver balance in + /// destination chain exactly by the input amount + /// @custom:property-id 23 + /// @custom:property `sendERC20` decreases total supply in source chain and increases it in destination chain + /// exactly by the input amount + function prove_crossChainMintAndBurn(address _from, address _to, uint256 _amount, uint256 _chainId) public { + /* Preconditions */ + vm.assume(_to != address(0)); + vm.assume(_from != address(0)); + + // Mint the amount to send + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + sourceToken.mint(_from, _amount); + + uint256 fromBalanceBefore = sourceToken.balanceOf(_from); + uint256 toBalanceBefore = destToken.balanceOf(_to); + uint256 sourceTotalSupplyBefore = sourceToken.totalSupply(); + uint256 destTotalSupplyBefore = destToken.totalSupply(); + + vm.prank(_from); + /* Action */ + try sourceToken.sendERC20(_to, _amount, _chainId) { + /* Postconditions */ + // Source + assert(sourceToken.balanceOf(_from) == fromBalanceBefore - _amount); + assert(sourceToken.totalSupply() == sourceTotalSupplyBefore - _amount); + + // Destination + if (_chainId == DESTINATION_CHAIN_ID) { + // If the destination chain matches the one of the dest token, check that the amount was minted + assert(destToken.balanceOf(_to) == toBalanceBefore + _amount); + assert(destToken.totalSupply() == destTotalSupplyBefore + _amount); + } else { + // Otherwise the balances should remain the same + assert(destToken.balanceOf(_to) == toBalanceBefore); + assert(destToken.totalSupply() == destTotalSupplyBefore); + } + } catch { + // Shouldn't fail + assert(false); + } + } +} diff --git a/packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh b/packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh index eeda15b92293..e87527086aeb 100755 --- a/packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh +++ b/packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh @@ -140,7 +140,8 @@ if [ "$SCRIPT_TESTS" == true ]; then "L1StandardBridgeKontrol.prove_finalizeBridgeERC20_paused" \ "L1StandardBridgeKontrol.prove_finalizeBridgeETH_paused" \ "L1ERC721BridgeKontrol.prove_finalizeBridgeERC721_paused" \ - "L1CrossDomainMessengerKontrol.prove_relayMessage_paused" + "L1CrossDomainMessengerKontrol.prove_relayMessage_paused" \ + "OptimismSuperchainERC20Kontrol.prove_setup" ) elif [ "$CUSTOM_TESTS" != 0 ]; then test_list=( "${@:${CUSTOM_TESTS}}" ) From 8b379dc8cb82bddf37974ef7da7d9ad97c027b88 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Thu, 29 Aug 2024 13:20:42 -0300 Subject: [PATCH 22/56] feat: setup kontrol --- packages/contracts-bedrock/.gitignore | 1 + packages/contracts-bedrock/foundry.toml | 6 ++++++ .../proofs => properties/kontrol}/OptimismSuperchain.k.sol | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) rename packages/contracts-bedrock/test/{kontrol/proofs => properties/kontrol}/OptimismSuperchain.k.sol (98%) diff --git a/packages/contracts-bedrock/.gitignore b/packages/contracts-bedrock/.gitignore index 396c03d4458d..6ecdd53bc7b6 100644 --- a/packages/contracts-bedrock/.gitignore +++ b/packages/contracts-bedrock/.gitignore @@ -7,6 +7,7 @@ kout-deployment kout-proofs test/kontrol/logs test/properties/medusa/corpus/ +out/ # Metrics coverage.out diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 69b1fde5c5eb..0c82189413ce 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -107,3 +107,9 @@ script = 'test/properties/medusa/' src = 'test/properties/halmos/' test = 'test/properties/halmos/' script = 'test/properties/halmos/' + +[profile.kontrol-properties] +src = "test/properties/kontrol" +test = "test/properties/kontrol" +script = "test/properties/kontrol" +out = 'out' \ No newline at end of file diff --git a/packages/contracts-bedrock/test/kontrol/proofs/OptimismSuperchain.k.sol b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchain.k.sol similarity index 98% rename from packages/contracts-bedrock/test/kontrol/proofs/OptimismSuperchain.k.sol rename to packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchain.k.sol index 1e78fb4e7c90..94116cf536e2 100644 --- a/packages/contracts-bedrock/test/kontrol/proofs/OptimismSuperchain.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchain.k.sol @@ -2,13 +2,13 @@ pragma solidity 0.8.25; import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; -import { SymTest } from "halmos-cheatcodes/src/SymTest.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; import { MockL2ToL2Messenger } from "test/properties/halmos/MockL2ToL2Messenger.sol"; import { HalmosBase } from "test/properties/helpers/HalmosBase.sol"; +import { KontrolCheats } from "kontrol-cheatcodes/KontrolCheats.sol"; -contract OptimismSuperchainERC20Kontrol is SymTest, HalmosBase { +contract OptimismSuperchainERC20Kontrol is KontrolCheats, HalmosBase { MockL2ToL2Messenger internal constant MESSENGER = MockL2ToL2Messenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); OptimismSuperchainERC20 public superchainERC20Impl; From c29990e01457bd1d1d25b9e006635efa5cef1566 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Sun, 1 Sep 2024 14:06:21 -0300 Subject: [PATCH 23/56] feat: external computation diff state wip --- packages/contracts-bedrock/.gitignore | 3 + packages/contracts-bedrock/foundry.toml | 8 +- .../supererc20-state-diff/AddressNames.json | 6 + .../supererc20-state-diff/StateDiff.json | 585 ++++++++++++++++++ .../test/properties/kontrol/KontrolBase.sol | 65 ++ ...in.k.sol => OptimismSuperchainERC20.k.sol} | 62 +- .../kontrol/deployments/InitialState.sol | 90 +++ .../kontrol/deployments/InitialStateCode.sol | 15 + .../kontrol/helpers/LibStateDiff.sol | 136 ++++ .../kontrol/helpers/RecordStateDiff.sol | 74 +++ .../kontrol/optimism-superchain-lemmas.md | 33 + .../kontrol/utils/record-state-diff.sh | 55 ++ 12 files changed, 1090 insertions(+), 42 deletions(-) create mode 100644 packages/contracts-bedrock/supererc20-state-diff/AddressNames.json create mode 100644 packages/contracts-bedrock/supererc20-state-diff/StateDiff.json create mode 100644 packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol rename packages/contracts-bedrock/test/properties/kontrol/{OptimismSuperchain.k.sol => OptimismSuperchainERC20.k.sol} (82%) create mode 100644 packages/contracts-bedrock/test/properties/kontrol/deployments/InitialState.sol create mode 100644 packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol create mode 100644 packages/contracts-bedrock/test/properties/kontrol/helpers/LibStateDiff.sol create mode 100644 packages/contracts-bedrock/test/properties/kontrol/helpers/RecordStateDiff.sol create mode 100644 packages/contracts-bedrock/test/properties/kontrol/optimism-superchain-lemmas.md create mode 100644 packages/contracts-bedrock/test/properties/kontrol/utils/record-state-diff.sh diff --git a/packages/contracts-bedrock/.gitignore b/packages/contracts-bedrock/.gitignore index 6ecdd53bc7b6..e0676cfa0fd5 100644 --- a/packages/contracts-bedrock/.gitignore +++ b/packages/contracts-bedrock/.gitignore @@ -42,3 +42,6 @@ deploy-config/devnetL1.json # Getting Started guide deploy config deploy-config/getting-started.json + +# Supererc20 kontrol +out-kontrol-properties/ \ No newline at end of file diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 0c82189413ce..db14a7f6bb8b 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -112,4 +112,10 @@ script = 'test/properties/halmos/' src = "test/properties/kontrol" test = "test/properties/kontrol" script = "test/properties/kontrol" -out = 'out' \ No newline at end of file +out = 'out-kontrol-properties' +# Make sure to export the variables $STATE_DIFF_DIR and $STATE_DIFF_NAME in your shell +fs_permissions = [ + { access = 'read', path = './supererc20-state-diff' }, + { access = 'read-write', path = './supererc20-state-diff/StateDiff.json' }, + { access = 'read-write', path = './supererc20-state-diff/AddressNames.json' } +] \ No newline at end of file diff --git a/packages/contracts-bedrock/supererc20-state-diff/AddressNames.json b/packages/contracts-bedrock/supererc20-state-diff/AddressNames.json new file mode 100644 index 000000000000..d94c12b6939f --- /dev/null +++ b/packages/contracts-bedrock/supererc20-state-diff/AddressNames.json @@ -0,0 +1,6 @@ +{ + "0x2e234DAe75C793f67A35089C9d99245E1C58470b": "sourceToken", + "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f": "superchainERC20Impl", + "0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9": "mockL2ToL2Messenger", + "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a": "destToken" +} \ No newline at end of file diff --git a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json new file mode 100644 index 000000000000..f1dba0541bbf --- /dev/null +++ b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json @@ -0,0 +1,585 @@ +{ + "accountAccesses": [ + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x6080604052348015600e575f80fd5b5060156019565b60c9565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff161560685760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b039081161460c65780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b6117bd806100d65f395ff3fe608060405234801561000f575f80fd5b5060043610610163575f3560e01c806378a3727b116100c7578063d505accf1161007d578063d9f5004611610063578063d9f5004614610356578063dd62ed3e14610369578063f6d2ee8614610391575f80fd5b8063d505accf146102fc578063d6c0b2c41461030f575f80fd5b806395d89b41116100ad57806395d89b41146102ce5780639dc29fac146102d6578063a9059cbb146102e9575f80fd5b806378a3727b146102965780637ecebe00146102a9575f80fd5b8063313ce5671161011c57806340c10f191161010257806340c10f191461022057806354fd4d501461023557806370a0823114610271575f80fd5b8063313ce567146101e45780633644e51514610218575f80fd5b8063095ea7b31161014c578063095ea7b3146101a457806318160ddd146101b757806323b872dd146101d1575f80fd5b806301ffc9a71461016757806306fdde031461018f575b5f80fd5b61017a610175366004611201565b6103a4565b60405190151581526020015b60405180910390f35b61019761043c565b6040516101869190611293565b61017a6101b23660046112c9565b6104ee565b6805345cdf77eb68f44c545b604051908152602001610186565b61017a6101df3660046112f3565b61053d565b7f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb035460405160ff9091168152602001610186565b6101c36105f7565b61023361022e3660046112c9565b610673565b005b6101976040518060400160405280600c81526020017f312e302e302d626574612e31000000000000000000000000000000000000000081525081565b6101c361027f366004611331565b6387a211a2600c9081525f91909152602090205490565b6102336102a436600461134c565b61076b565b6101c36102b7366004611331565b6338377508600c9081525f91909152602090205490565b610197610923565b6102336102e43660046112c9565b610954565b61017a6102f73660046112c9565b610a40565b61023361030a366004611393565b610ab7565b7f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610186565b6102336103643660046112f3565b610c4a565b6101c36103773660046113fc565b602052637f5e9f20600c9081525f91909152603490205490565b61023361039f366004611507565b610ebf565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f0bc3227100000000000000000000000000000000000000000000000000000000148061043657507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60607f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00600101805461046d90611589565b80601f016020809104026020016040519081016040528092919081815260200182805461049990611589565b80156104e45780601f106104bb576101008083540402835291602001916104e4565b820191905f5260205f20905b8154815290600101906020018083116104c757829003601f168201915b5050505050905090565b5f82602052637f5e9f20600c52335f52816034600c2055815f52602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560205fa350600192915050565b5f8360601b33602052637f5e9f208117600c526034600c208054600181011561057b5780851115610575576313be252b5f526004601cfd5b84810382555b50506387a211a28117600c526020600c208054808511156105a35763f4d678b85f526004601cfd5b84810382555050835f526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3505060019392505050565b5f8061060161043c565b8051906020012090506040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81528160208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015260a081209250505090565b33734200000000000000000000000000000000000010146106c0576040517f38da3b1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821661070d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107178282611104565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161075f91815260200190565b60405180910390a25050565b73ffffffffffffffffffffffffffffffffffffffff83166107b8576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107c23383611180565b6040805133602482015273ffffffffffffffffffffffffffffffffffffffff85166044820152606480820185905282518083039091018152608490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd9f500460000000000000000000000000000000000000000000000000000000017905290517f7056f41f00000000000000000000000000000000000000000000000000000000815273420000000000000000000000000000000000002390637056f41f9061089c908590309086906004016115da565b5f604051808303815f87803b1580156108b3575f80fd5b505af11580156108c5573d5f803e3d5ffd5b5050604080518681526020810186905273ffffffffffffffffffffffffffffffffffffffff881693503392507ffcea3600a13c757f2758710b089cc9752781c35d2a9d6804370ed18cd82f0bb691015b60405180910390a350505050565b60607f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00600201805461046d90611589565b33734200000000000000000000000000000000000010146109a1576040517f38da3b1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166109ee576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109f88282611180565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161075f91815260200190565b5f6387a211a2600c52335f526020600c20805480841115610a685763f4d678b85f526004601cfd5b83810382555050825f526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350600192915050565b5f610ac061043c565b80519060200120905084421115610ade57631a15a3cc5f526004601cfd5b6040518860601b60601c98508760601b60601c975065383775081901600e52885f526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83528360208401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528a60208401528960408401528860608401528060808401528760a084015260c08320604e526042602c205f528660ff16602052856040528460605260208060805f60015afa8b3d5114610be65763ddafbaef5f526004601cfd5b019055777f5e9f20000000000000000000000000000000000000000088176040526034602c2087905587897f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a360405250505f606052505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216610c97576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373420000000000000000000000000000000000002314610ce4576040517f065d515000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff1673420000000000000000000000000000000000002373ffffffffffffffffffffffffffffffffffffffff166338ffde186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d7c9190611617565b73ffffffffffffffffffffffffffffffffffffffff1614610dc9576040517fbc22e2aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73420000000000000000000000000000000000002373ffffffffffffffffffffffffffffffffffffffff1663247944626040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e27573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e4b9190611632565b9050610e578383611104565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc75e22a0b57fb7740dbfc0caa5c6b7a82a2139964e7f1b7be7ac4e8be0f719ba8484604051610915929190918252602082015260400190565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610f095750825b90505f8267ffffffffffffffff166001148015610f255750303b155b905081158015610f33575080155b15610f6a576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610fcb5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b7f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb0080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8b161781557f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb016110558a82611694565b50600281016110648982611694565b5060030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff881617905583156110f45784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b505050565b6805345cdf77eb68f44c54818101818110156111275763e5cfe9575f526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52815f526020600c208181540181555080602052600c5160601c5f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a35050565b6387a211a2600c52815f526020600c208054808311156111a75763f4d678b85f526004601cfd5b82900390556805345cdf77eb68f44c805482900390555f81815273ffffffffffffffffffffffffffffffffffffffff83167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602083a35050565b5f60208284031215611211575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611240575f80fd5b9392505050565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f6112406020830184611247565b73ffffffffffffffffffffffffffffffffffffffff811681146112c6575f80fd5b50565b5f80604083850312156112da575f80fd5b82356112e5816112a5565b946020939093013593505050565b5f805f60608486031215611305575f80fd5b8335611310816112a5565b92506020840135611320816112a5565b929592945050506040919091013590565b5f60208284031215611341575f80fd5b8135611240816112a5565b5f805f6060848603121561135e575f80fd5b8335611369816112a5565b95602085013595506040909401359392505050565b803560ff8116811461138e575f80fd5b919050565b5f805f805f805f60e0888a0312156113a9575f80fd5b87356113b4816112a5565b965060208801356113c4816112a5565b955060408801359450606088013593506113e06080890161137e565b925060a0880135915060c0880135905092959891949750929550565b5f806040838503121561140d575f80fd5b8235611418816112a5565b91506020830135611428816112a5565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f83011261146f575f80fd5b813567ffffffffffffffff8082111561148a5761148a611433565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156114d0576114d0611433565b816040528381528660208588010111156114e8575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f806080858703121561151a575f80fd5b8435611525816112a5565b9350602085013567ffffffffffffffff80821115611541575f80fd5b61154d88838901611460565b94506040870135915080821115611562575f80fd5b5061156f87828801611460565b92505061157e6060860161137e565b905092959194509250565b600181811c9082168061159d57607f821691505b6020821081036115d4577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b83815273ffffffffffffffffffffffffffffffffffffffff83166020820152606060408201525f61160e6060830184611247565b95945050505050565b5f60208284031215611627575f80fd5b8151611240816112a5565b5f60208284031215611642575f80fd5b5051919050565b601f8211156110ff57805f5260205f20601f840160051c8101602085101561166e5750805b601f840160051c820191505b8181101561168d575f815560010161167a565b5050505050565b815167ffffffffffffffff8111156116ae576116ae611433565b6116c2816116bc8454611589565b84611649565b602080601f831160018114611714575f84156116de5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556117a8565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561176057888601518255948401946001909101908401611741565b508582101561179c57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b505060018460011b0185555b50505050505056fea164736f6c6343000819000a", + "deployedCode": "0x608060405234801561000f575f80fd5b5060043610610163575f3560e01c806378a3727b116100c7578063d505accf1161007d578063d9f5004611610063578063d9f5004614610356578063dd62ed3e14610369578063f6d2ee8614610391575f80fd5b8063d505accf146102fc578063d6c0b2c41461030f575f80fd5b806395d89b41116100ad57806395d89b41146102ce5780639dc29fac146102d6578063a9059cbb146102e9575f80fd5b806378a3727b146102965780637ecebe00146102a9575f80fd5b8063313ce5671161011c57806340c10f191161010257806340c10f191461022057806354fd4d501461023557806370a0823114610271575f80fd5b8063313ce567146101e45780633644e51514610218575f80fd5b8063095ea7b31161014c578063095ea7b3146101a457806318160ddd146101b757806323b872dd146101d1575f80fd5b806301ffc9a71461016757806306fdde031461018f575b5f80fd5b61017a610175366004611201565b6103a4565b60405190151581526020015b60405180910390f35b61019761043c565b6040516101869190611293565b61017a6101b23660046112c9565b6104ee565b6805345cdf77eb68f44c545b604051908152602001610186565b61017a6101df3660046112f3565b61053d565b7f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb035460405160ff9091168152602001610186565b6101c36105f7565b61023361022e3660046112c9565b610673565b005b6101976040518060400160405280600c81526020017f312e302e302d626574612e31000000000000000000000000000000000000000081525081565b6101c361027f366004611331565b6387a211a2600c9081525f91909152602090205490565b6102336102a436600461134c565b61076b565b6101c36102b7366004611331565b6338377508600c9081525f91909152602090205490565b610197610923565b6102336102e43660046112c9565b610954565b61017a6102f73660046112c9565b610a40565b61023361030a366004611393565b610ab7565b7f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610186565b6102336103643660046112f3565b610c4a565b6101c36103773660046113fc565b602052637f5e9f20600c9081525f91909152603490205490565b61023361039f366004611507565b610ebf565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f0bc3227100000000000000000000000000000000000000000000000000000000148061043657507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60607f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00600101805461046d90611589565b80601f016020809104026020016040519081016040528092919081815260200182805461049990611589565b80156104e45780601f106104bb576101008083540402835291602001916104e4565b820191905f5260205f20905b8154815290600101906020018083116104c757829003601f168201915b5050505050905090565b5f82602052637f5e9f20600c52335f52816034600c2055815f52602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560205fa350600192915050565b5f8360601b33602052637f5e9f208117600c526034600c208054600181011561057b5780851115610575576313be252b5f526004601cfd5b84810382555b50506387a211a28117600c526020600c208054808511156105a35763f4d678b85f526004601cfd5b84810382555050835f526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3505060019392505050565b5f8061060161043c565b8051906020012090506040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81528160208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015260a081209250505090565b33734200000000000000000000000000000000000010146106c0576040517f38da3b1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821661070d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107178282611104565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161075f91815260200190565b60405180910390a25050565b73ffffffffffffffffffffffffffffffffffffffff83166107b8576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107c23383611180565b6040805133602482015273ffffffffffffffffffffffffffffffffffffffff85166044820152606480820185905282518083039091018152608490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd9f500460000000000000000000000000000000000000000000000000000000017905290517f7056f41f00000000000000000000000000000000000000000000000000000000815273420000000000000000000000000000000000002390637056f41f9061089c908590309086906004016115da565b5f604051808303815f87803b1580156108b3575f80fd5b505af11580156108c5573d5f803e3d5ffd5b5050604080518681526020810186905273ffffffffffffffffffffffffffffffffffffffff881693503392507ffcea3600a13c757f2758710b089cc9752781c35d2a9d6804370ed18cd82f0bb691015b60405180910390a350505050565b60607f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00600201805461046d90611589565b33734200000000000000000000000000000000000010146109a1576040517f38da3b1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166109ee576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109f88282611180565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161075f91815260200190565b5f6387a211a2600c52335f526020600c20805480841115610a685763f4d678b85f526004601cfd5b83810382555050825f526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350600192915050565b5f610ac061043c565b80519060200120905084421115610ade57631a15a3cc5f526004601cfd5b6040518860601b60601c98508760601b60601c975065383775081901600e52885f526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83528360208401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528a60208401528960408401528860608401528060808401528760a084015260c08320604e526042602c205f528660ff16602052856040528460605260208060805f60015afa8b3d5114610be65763ddafbaef5f526004601cfd5b019055777f5e9f20000000000000000000000000000000000000000088176040526034602c2087905587897f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a360405250505f606052505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216610c97576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373420000000000000000000000000000000000002314610ce4576040517f065d515000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff1673420000000000000000000000000000000000002373ffffffffffffffffffffffffffffffffffffffff166338ffde186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d7c9190611617565b73ffffffffffffffffffffffffffffffffffffffff1614610dc9576040517fbc22e2aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73420000000000000000000000000000000000002373ffffffffffffffffffffffffffffffffffffffff1663247944626040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e27573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e4b9190611632565b9050610e578383611104565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc75e22a0b57fb7740dbfc0caa5c6b7a82a2139964e7f1b7be7ac4e8be0f719ba8484604051610915929190918252602082015260400190565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610f095750825b90505f8267ffffffffffffffff166001148015610f255750303b155b905081158015610f33575080155b15610f6a576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610fcb5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b7f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb0080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8b161781557f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb016110558a82611694565b50600281016110648982611694565b5060030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff881617905583156110f45784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b505050565b6805345cdf77eb68f44c54818101818110156111275763e5cfe9575f526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52815f526020600c208181540181555080602052600c5160601c5f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a35050565b6387a211a2600c52815f526020600c208054808311156111a75763f4d678b85f526004601cfd5b82900390556805345cdf77eb68f44c805482900390555f81815273ffffffffffffffffffffffffffffffffffffffff83167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602083a35050565b5f60208284031215611211575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611240575f80fd5b9392505050565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f6112406020830184611247565b73ffffffffffffffffffffffffffffffffffffffff811681146112c6575f80fd5b50565b5f80604083850312156112da575f80fd5b82356112e5816112a5565b946020939093013593505050565b5f805f60608486031215611305575f80fd5b8335611310816112a5565b92506020840135611320816112a5565b929592945050506040919091013590565b5f60208284031215611341575f80fd5b8135611240816112a5565b5f805f6060848603121561135e575f80fd5b8335611369816112a5565b95602085013595506040909401359392505050565b803560ff8116811461138e575f80fd5b919050565b5f805f805f805f60e0888a0312156113a9575f80fd5b87356113b4816112a5565b965060208801356113c4816112a5565b955060408801359450606088013593506113e06080890161137e565b925060a0880135915060c0880135905092959891949750929550565b5f806040838503121561140d575f80fd5b8235611418816112a5565b91506020830135611428816112a5565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f83011261146f575f80fd5b813567ffffffffffffffff8082111561148a5761148a611433565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156114d0576114d0611433565b816040528381528660208588010111156114e8575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f806080858703121561151a575f80fd5b8435611525816112a5565b9350602085013567ffffffffffffffff80821115611541575f80fd5b61154d88838901611460565b94506040870135915080821115611562575f80fd5b5061156f87828801611460565b92505061157e6060860161137e565b905092959194509250565b600181811c9082168061159d57607f821691505b6020821081036115d4577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b83815273ffffffffffffffffffffffffffffffffffffffff83166020820152606060408201525f61160e6060830184611247565b95945050505050565b5f60208284031215611627575f80fd5b8151611240816112a5565b5f60208284031215611642575f80fd5b5051919050565b601f8211156110ff57805f5260205f20601f840160051c8101602085101561166e5750805b601f840160051c820191505b8181101561168d575f815560010161167a565b5050505050565b815167ffffffffffffffff8111156116ae576116ae611433565b6116c2816116bc8454611589565b84611649565b602080601f831160018114611714575f84156116de5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556117a8565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561176057888601518255948401946001909101908401611741565b508582101561179c57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b505060018460011b0185555b50505050505056fea164736f6c6343000819000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", + "isWrite": true, + "newValue": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x60806040526040516103ae3803806103ae8339810160408190526100229161023c565b61002c8282610033565b505061031b565b61003c82610091565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561008557610080828261010c565b505050565b61008d61017f565b5050565b806001600160a01b03163b5f036100cb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516101289190610305565b5f60405180830381855af49150503d805f8114610160576040519150601f19603f3d011682016040523d82523d5f602084013e610165565b606091505b5090925090506101768583836101a0565b95945050505050565b341561019e5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b5576101b0826101ff565b6101f8565b81511580156101cc57506001600160a01b0384163b155b156101f557604051639996b31560e01b81526001600160a01b03851660048201526024016100c2565b50805b9392505050565b80511561020f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561024d575f80fd5b82516001600160a01b0381168114610263575f80fd5b60208401519092506001600160401b038082111561027f575f80fd5b818501915085601f830112610292575f80fd5b8151818111156102a4576102a4610228565b604051601f8201601f19908116603f011681019083821181831017156102cc576102cc610228565b816040528281528860208487010111156102e4575f80fd5b8260208601602083015e5f6020848301015280955050505050509250929050565b5f82518060208501845e5f920191825250919050565b6087806103275f395ff3fe6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000104f6d2ee86000000000000000000000000237a66474b7b934b22574359500212977b656d9f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e455243323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005535550455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": true, + "newValue": "0x0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf6d2ee86000000000000000000000000237a66474b7b934b22574359500212977b656d9f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e4552433230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055355504552000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000010000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": true, + "newValue": "0x000000000000000000000000237a66474b7b934b22574359500212977b656d9f", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb01" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": true, + "newValue": "0x5375706572636861696e4552433230000000000000000000000000000000001e", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb01" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb02" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": true, + "newValue": "0x535550455200000000000000000000000000000000000000000000000000000a", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb02" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb03" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000012", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb03" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000010000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000010000000000000001", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000010000000000000001", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + } + ], + "value": 0 + }, + { + "accessor": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", + "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x60806040526040516103ae3803806103ae8339810160408190526100229161023c565b61002c8282610033565b505061031b565b61003c82610091565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561008557610080828261010c565b505050565b61008d61017f565b5050565b806001600160a01b03163b5f036100cb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516101289190610305565b5f60405180830381855af49150503d805f8114610160576040519150601f19603f3d011682016040523d82523d5f602084013e610165565b606091505b5090925090506101768583836101a0565b95945050505050565b341561019e5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b5576101b0826101ff565b6101f8565b81511580156101cc57506001600160a01b0384163b155b156101f557604051639996b31560e01b81526001600160a01b03851660048201526024016100c2565b50805b9392505050565b80511561020f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561024d575f80fd5b82516001600160a01b0381168114610263575f80fd5b60208401519092506001600160401b038082111561027f575f80fd5b818501915085601f830112610292575f80fd5b8151818111156102a4576102a4610228565b604051601f8201601f19908116603f011681019083821181831017156102cc576102cc610228565b816040528281528860208487010111156102e4575f80fd5b8260208601602083015e5f6020848301015280955050505050509250929050565b5f82518060208501845e5f920191825250919050565b6087806103275f395ff3fe6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000104f6d2ee86000000000000000000000000237a66474b7b934b22574359500212977b656d9f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e455243323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005535550455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": true, + "newValue": "0x0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" + } + ], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0xf6d2ee86000000000000000000000000237a66474b7b934b22574359500212977b656d9f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e4552433230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055355504552000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x", + "initialized": true, + "kind": "DelegateCall", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [ + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000010000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": true, + "newValue": "0x000000000000000000000000237a66474b7b934b22574359500212977b656d9f", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb01" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": true, + "newValue": "0x5375706572636861696e4552433230000000000000000000000000000000001e", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb01" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb02" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": true, + "newValue": "0x535550455200000000000000000000000000000000000000000000000000000a", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb02" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb03" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000012", + "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", + "reverted": false, + "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb03" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": false, + "newValue": "0x0000000000000000000000000000000000000000000000010000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000010000000000000001", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + }, + { + "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "isWrite": true, + "newValue": "0x0000000000000000000000000000000000000000000000000000000000000001", + "previousValue": "0x0000000000000000000000000000000000000000000000010000000000000001", + "reverted": false, + "slot": "0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00" + } + ], + "value": 0 + }, + { + "accessor": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", + "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x610100604052348015610010575f80fd5b5060405161070538038061070583398101604081905261002f9161006a565b6001600160a01b0393841660805291831660a05260c0521660e0526100b4565b80516001600160a01b0381168114610065575f80fd5b919050565b5f805f806080858703121561007d575f80fd5b6100868561004f565b93506100946020860161004f565b9250604085015191506100a96060860161004f565b905092959194509250565b60805160a05160c05160e0516106036101025f395f6102ab01525f818160a901526102cf01525f818161025d0152818161028601526102fa01525f81816101fb015261022401526106035ff3fe608060405260043610610058575f3560e01c80632ea02369116100415780632ea023691461009857806338ffde18146100cb5780637056f41f14610104575f80fd5b80631ecd26f21461005c5780632479446214610071575b5f80fd5b61006f61006a366004610484565b610117565b005b34801561007c575f80fd5b506100856101d2565b6040519081526020015b60405180910390f35b3480156100a3575f80fd5b506100857f000000000000000000000000000000000000000000000000000000000000000081565b3480156100d6575f80fd5b506100df6101e3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008f565b61006f610112366004610500565b6102cd565b5f808473ffffffffffffffffffffffffffffffffffffffff16348585604051610141929190610556565b5f6040518083038185875af1925050503d805f811461017b576040519150601f19603f3d011682016040523d82523d5f602084013e610180565b606091505b5091509150816101c757806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101be9190610565565b60405180910390fd5b505050505050505050565b5f6101de4660016105b8565b905090565b5f73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361024657507f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036102a857507f000000000000000000000000000000000000000000000000000000000000000090565b507f000000000000000000000000000000000000000000000000000000000000000090565b7f000000000000000000000000000000000000000000000000000000000000000084036103e6575f6103557f00000000000000000000000000000000000000000000000000000000000000005f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506103ec92505050565b9050806103e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016101be565b505b50505050565b5f6103f9845a8585610401565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461043a575f80fd5b919050565b5f8083601f84011261044f575f80fd5b50813567ffffffffffffffff811115610466575f80fd5b60208301915083602082850101111561047d575f80fd5b9250929050565b5f805f805f805f60c0888a03121561049a575f80fd5b8735965060208801359550604088013594506104b860608901610417565b93506104c660808901610417565b925060a088013567ffffffffffffffff8111156104e1575f80fd5b6104ed8a828b0161043f565b989b979a50959850939692959293505050565b5f805f8060608587031215610513575f80fd5b8435935061052360208601610417565b9250604085013567ffffffffffffffff81111561053e575f80fd5b61054a8782880161043f565b95989497509550505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b808201808211156105f0577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9291505056fea164736f6c6343000819000a0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000", + "deployedCode": "0x608060405260043610610058575f3560e01c80632ea02369116100415780632ea023691461009857806338ffde18146100cb5780637056f41f14610104575f80fd5b80631ecd26f21461005c5780632479446214610071575b5f80fd5b61006f61006a366004610484565b610117565b005b34801561007c575f80fd5b506100856101d2565b6040519081526020015b60405180910390f35b3480156100a3575f80fd5b506100857f000000000000000000000000000000000000000000000000000000000000000281565b3480156100d6575f80fd5b506100df6101e3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008f565b61006f610112366004610500565b6102cd565b5f808473ffffffffffffffffffffffffffffffffffffffff16348585604051610141929190610556565b5f6040518083038185875af1925050503d805f811461017b576040519150601f19603f3d011682016040523d82523d5f602084013e610180565b606091505b5091509150816101c757806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101be9190610565565b60405180910390fd5b505050505050505050565b5f6101de4660016105b8565b905090565b5f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361024657507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036102a857507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a90565b507f000000000000000000000000000000000000000000000000000000000000000090565b7f000000000000000000000000000000000000000000000000000000000000000284036103e6575f6103557f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506103ec92505050565b9050806103e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016101be565b505b50505050565b5f6103f9845a8585610401565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461043a575f80fd5b919050565b5f8083601f84011261044f575f80fd5b50813567ffffffffffffffff811115610466575f80fd5b60208301915083602082850101111561047d575f80fd5b9250929050565b5f805f805f805f60c0888a03121561049a575f80fd5b8735965060208801359550604088013594506104b860608901610417565b93506104c660808901610417565b925060a088013567ffffffffffffffff8111156104e1575f80fd5b6104ed8a828b0161043f565b989b979a50959850939692959293505050565b5f805f8060608587031215610513575f80fd5b8435935061052360208601610417565b9250604085013567ffffffffffffffff81111561053e575f80fd5b61054a8782880161043f565b95989497509550505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b808201808211156105f0577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9291505056fea164736f6c6343000819000a", + "initialized": true, + "kind": "Create", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + } + ] +} \ No newline at end of file diff --git a/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol b/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol new file mode 100644 index 000000000000..283c4e639113 --- /dev/null +++ b/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; +import { MockL2ToL2Messenger } from "test/properties/halmos/MockL2ToL2Messenger.sol"; +import { KontrolCheats } from "kontrol-cheatcodes/KontrolCheats.sol"; +import { RecordStateDiff } from "./helpers/RecordStateDiff.sol"; +import { Test } from "forge-std/Test.sol"; + +contract KontrolBase is Test, KontrolCheats, RecordStateDiff { + uint256 internal constant CURRENT_CHAIN_ID = 1; + uint256 internal constant DESTINATION_CHAIN_ID = 2; + uint256 internal constant ZERO_AMOUNT = 0; + + MockL2ToL2Messenger internal constant MESSENGER = MockL2ToL2Messenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); + + address internal remoteToken = address(bytes20(keccak256("remoteToken"))); + string internal name = "SuperchainERC20"; + string internal symbol = "SUPER"; + uint8 internal decimals = 18; + + OptimismSuperchainERC20 public superchainERC20Impl; + OptimismSuperchainERC20 internal sourceToken; + OptimismSuperchainERC20 internal destToken; + MockL2ToL2Messenger internal mockL2ToL2Messenger; + + // The second function to get the state diff saving the addresses with their names + function setUpNamed() public virtual recordStateDiff { + // Deploy the OptimismSuperchainERC20 contract implementation and the proxy to be used + superchainERC20Impl = new OptimismSuperchainERC20(); + sourceToken = OptimismSuperchainERC20( + address( + // TODO: Update to beacon proxy + new ERC1967Proxy( + address(superchainERC20Impl), + abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) + ) + ) + ); + + destToken = OptimismSuperchainERC20( + address( + // TODO: Update to beacon proxy + new ERC1967Proxy( + address(superchainERC20Impl), + abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) + ) + ) + ); + + mockL2ToL2Messenger = + new MockL2ToL2Messenger(address(sourceToken), address(destToken), DESTINATION_CHAIN_ID, address(0)); + + save_address(address(superchainERC20Impl), "superchainERC20Impl"); + save_address(address(sourceToken), "sourceToken"); + save_address(address(destToken), "destToken"); + save_address(address(mockL2ToL2Messenger), "mockL2ToL2Messenger"); + } + + function eqStrings(string memory a, string memory b) internal pure returns (bool) { + return keccak256(abi.encode(a)) == keccak256(abi.encode(b)); + } +} diff --git a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchain.k.sol b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol similarity index 82% rename from packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchain.k.sol rename to packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol index 94116cf536e2..ca73d5586123 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchain.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol @@ -3,52 +3,22 @@ pragma solidity 0.8.25; import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; import { MockL2ToL2Messenger } from "test/properties/halmos/MockL2ToL2Messenger.sol"; -import { HalmosBase } from "test/properties/helpers/HalmosBase.sol"; -import { KontrolCheats } from "kontrol-cheatcodes/KontrolCheats.sol"; - -contract OptimismSuperchainERC20Kontrol is KontrolCheats, HalmosBase { - MockL2ToL2Messenger internal constant MESSENGER = MockL2ToL2Messenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); - - OptimismSuperchainERC20 public superchainERC20Impl; - OptimismSuperchainERC20 internal sourceToken; - OptimismSuperchainERC20 internal destToken; - - function setUp() public { - // Deploy the OptimismSuperchainERC20 contract implementation and the proxy to be used - superchainERC20Impl = new OptimismSuperchainERC20(); - sourceToken = OptimismSuperchainERC20( - address( - // TODO: Update to beacon proxy - new ERC1967Proxy( - address(superchainERC20Impl), - abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) - ) - ) - ); - - destToken = OptimismSuperchainERC20( - address( - // TODO: Update to beacon proxy - new ERC1967Proxy( - address(superchainERC20Impl), - abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) - ) - ) - ); - - // Etch the mocked L2 to L2 Messenger since the messenger logic is out of scope for these test suite. Also, we - // avoid issues such as `TSTORE` opcode not being supported, or issues with `encodeVersionedNonce()` - address _mockL2ToL2CrossDomainMessenger = - address(new MockL2ToL2Messenger(address(sourceToken), address(destToken), DESTINATION_CHAIN_ID, address(0))); - vm.etch(address(MESSENGER), _mockL2ToL2CrossDomainMessenger.code); - // NOTE: We need to set the crossDomainMessageSender as an immutable or otherwise storage vars and not taken - // into account when etching on halmos. Setting a constant slot with setters and getters didn't work neither. +import { KontrolBase } from "test/properties/kontrol/KontrolBase.sol"; +import { InitialState } from "./deployments/InitialState.sol"; + +contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { + function setUpInlined() public { + superchainERC20Impl = OptimismSuperchainERC20(superchainERC20ImplAddress); + sourceToken = OptimismSuperchainERC20(sourceTokenAddress); + destToken = OptimismSuperchainERC20(destTokenAddress); + vm.etch(address(MESSENGER), mockL2ToL2MessengerAddress.code); } /// @notice Check setup works as expected function prove_setup() public { + setUpInlined(); + // Source token assert(sourceToken.remoteToken() == remoteToken); assert(eqStrings(sourceToken.name(), name)); @@ -68,6 +38,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolCheats, HalmosBase { // Custom cross domain sender assert(MESSENGER.crossDomainMessageSender() == address(0)); + + assert(block.chainid >= 0); } /// @custom:property-id 6 @@ -81,10 +53,15 @@ contract OptimismSuperchainERC20Kontrol is KontrolCheats, HalmosBase { ) public { + setUpInlined(); + /* Preconditions */ vm.assume(_to != address(0)); vm.assume(_from != address(0)); + notBuiltinAddress(_from); + notBuiltinAddress(_to); + // Can't deal to unsupported cheatcode vm.prank(Predeploys.L2_STANDARD_BRIDGE); sourceToken.mint(_from, _initialBalance); @@ -136,6 +113,9 @@ contract OptimismSuperchainERC20Kontrol is KontrolCheats, HalmosBase { vm.assume(_to != address(0)); vm.assume(_to != address(Predeploys.CROSS_L2_INBOX) && _to != address(MESSENGER)); + notBuiltinAddress(_from); + notBuiltinAddress(_to); + uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); uint256 _toBalanceBefore = sourceToken.balanceOf(_to); diff --git a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialState.sol b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialState.sol new file mode 100644 index 000000000000..cb47c362f4f6 --- /dev/null +++ b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialState.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: UNLICENSED +// This file was autogenerated by running `kontrol load-state`. Do not edit this file manually. + +pragma solidity ^0.8.13; + +import { Vm } from "forge-std/Vm.sol"; + +import { InitialStateCode } from "./InitialStateCode.sol"; + +contract InitialState is InitialStateCode { + // Test contract address, 0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496 + address private constant FOUNDRY_TEST_ADDRESS = 0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496; + // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D + address private constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); + Vm private constant vm = Vm(VM_ADDRESS); + + address internal constant sourceTokenAddress = 0x2e234DAe75C793f67A35089C9d99245E1C58470b; + address internal constant superchainERC20ImplAddress = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f; + address internal constant mockL2ToL2MessengerAddress = 0x5991A2dF15A8F6A256D3Ec51E99254Cd3fb576A9; + address internal constant destTokenAddress = 0xF62849F9A0B5Bf2913b396098F7c7019b51A820a; + + function recreateState() public { + bytes32 slot; + bytes32 value; + vm.etch(superchainERC20ImplAddress, superchainERC20ImplCode); + slot = hex"f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00"; + value = hex"000000000000000000000000000000000000000000000000ffffffffffffffff"; + vm.store(superchainERC20ImplAddress, slot, value); + vm.etch(sourceTokenAddress, sourceTokenCode); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; + value = hex"0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f"; + vm.store(sourceTokenAddress, slot, value); + slot = hex"f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; + vm.store(sourceTokenAddress, slot, value); + slot = hex"f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00"; + value = hex"0000000000000000000000000000000000000000000000010000000000000001"; + vm.store(sourceTokenAddress, slot, value); + slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00"; + value = hex"000000000000000000000000237a66474b7b934b22574359500212977b656d9f"; + vm.store(sourceTokenAddress, slot, value); + slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb01"; + value = hex"5375706572636861696e4552433230000000000000000000000000000000001e"; + vm.store(sourceTokenAddress, slot, value); + slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb02"; + value = hex"535550455200000000000000000000000000000000000000000000000000000a"; + vm.store(sourceTokenAddress, slot, value); + slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb03"; + value = hex"0000000000000000000000000000000000000000000000000000000000000012"; + vm.store(sourceTokenAddress, slot, value); + slot = hex"f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; + vm.store(sourceTokenAddress, slot, value); + vm.etch(destTokenAddress, destTokenCode); + slot = hex"360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; + value = hex"0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f"; + vm.store(destTokenAddress, slot, value); + slot = hex"f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; + vm.store(destTokenAddress, slot, value); + slot = hex"f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00"; + value = hex"0000000000000000000000000000000000000000000000010000000000000001"; + vm.store(destTokenAddress, slot, value); + slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00"; + value = hex"000000000000000000000000237a66474b7b934b22574359500212977b656d9f"; + vm.store(destTokenAddress, slot, value); + slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb01"; + value = hex"5375706572636861696e4552433230000000000000000000000000000000001e"; + vm.store(destTokenAddress, slot, value); + slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb02"; + value = hex"535550455200000000000000000000000000000000000000000000000000000a"; + vm.store(destTokenAddress, slot, value); + slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb03"; + value = hex"0000000000000000000000000000000000000000000000000000000000000012"; + vm.store(destTokenAddress, slot, value); + slot = hex"f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00"; + value = hex"0000000000000000000000000000000000000000000000000000000000000001"; + vm.store(destTokenAddress, slot, value); + vm.etch(mockL2ToL2MessengerAddress, mockL2ToL2MessengerCode); + } + + function _notExternalAddress(address user) public pure { + vm.assume(user != FOUNDRY_TEST_ADDRESS); + vm.assume(user != VM_ADDRESS); + vm.assume(user != sourceTokenAddress); + vm.assume(user != superchainERC20ImplAddress); + vm.assume(user != mockL2ToL2MessengerAddress); + vm.assume(user != destTokenAddress); + } +} diff --git a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol new file mode 100644 index 000000000000..e4c80facdabf --- /dev/null +++ b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: UNLICENSED +// This file was autogenerated by running `kontrol load-state`. Do not edit this file manually. + +pragma solidity ^0.8.13; + +contract InitialStateCode { + bytes internal constant superchainERC20ImplCode = + hex"608060405234801561000f575f80fd5b5060043610610163575f3560e01c806378a3727b116100c7578063d505accf1161007d578063d9f5004611610063578063d9f5004614610356578063dd62ed3e14610369578063f6d2ee8614610391575f80fd5b8063d505accf146102fc578063d6c0b2c41461030f575f80fd5b806395d89b41116100ad57806395d89b41146102ce5780639dc29fac146102d6578063a9059cbb146102e9575f80fd5b806378a3727b146102965780637ecebe00146102a9575f80fd5b8063313ce5671161011c57806340c10f191161010257806340c10f191461022057806354fd4d501461023557806370a0823114610271575f80fd5b8063313ce567146101e45780633644e51514610218575f80fd5b8063095ea7b31161014c578063095ea7b3146101a457806318160ddd146101b757806323b872dd146101d1575f80fd5b806301ffc9a71461016757806306fdde031461018f575b5f80fd5b61017a610175366004611201565b6103a4565b60405190151581526020015b60405180910390f35b61019761043c565b6040516101869190611293565b61017a6101b23660046112c9565b6104ee565b6805345cdf77eb68f44c545b604051908152602001610186565b61017a6101df3660046112f3565b61053d565b7f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb035460405160ff9091168152602001610186565b6101c36105f7565b61023361022e3660046112c9565b610673565b005b6101976040518060400160405280600c81526020017f312e302e302d626574612e31000000000000000000000000000000000000000081525081565b6101c361027f366004611331565b6387a211a2600c9081525f91909152602090205490565b6102336102a436600461134c565b61076b565b6101c36102b7366004611331565b6338377508600c9081525f91909152602090205490565b610197610923565b6102336102e43660046112c9565b610954565b61017a6102f73660046112c9565b610a40565b61023361030a366004611393565b610ab7565b7f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610186565b6102336103643660046112f3565b610c4a565b6101c36103773660046113fc565b602052637f5e9f20600c9081525f91909152603490205490565b61023361039f366004611507565b610ebf565b5f7fffffffff0000000000000000000000000000000000000000000000000000000082167f0bc3227100000000000000000000000000000000000000000000000000000000148061043657507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60607f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00600101805461046d90611589565b80601f016020809104026020016040519081016040528092919081815260200182805461049990611589565b80156104e45780601f106104bb576101008083540402835291602001916104e4565b820191905f5260205f20905b8154815290600101906020018083116104c757829003601f168201915b5050505050905090565b5f82602052637f5e9f20600c52335f52816034600c2055815f52602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560205fa350600192915050565b5f8360601b33602052637f5e9f208117600c526034600c208054600181011561057b5780851115610575576313be252b5f526004601cfd5b84810382555b50506387a211a28117600c526020600c208054808511156105a35763f4d678b85f526004601cfd5b84810382555050835f526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3505060019392505050565b5f8061060161043c565b8051906020012090506040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81528160208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015260a081209250505090565b33734200000000000000000000000000000000000010146106c0576040517f38da3b1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821661070d576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107178282611104565b8173ffffffffffffffffffffffffffffffffffffffff167f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968858260405161075f91815260200190565b60405180910390a25050565b73ffffffffffffffffffffffffffffffffffffffff83166107b8576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6107c23383611180565b6040805133602482015273ffffffffffffffffffffffffffffffffffffffff85166044820152606480820185905282518083039091018152608490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fd9f500460000000000000000000000000000000000000000000000000000000017905290517f7056f41f00000000000000000000000000000000000000000000000000000000815273420000000000000000000000000000000000002390637056f41f9061089c908590309086906004016115da565b5f604051808303815f87803b1580156108b3575f80fd5b505af11580156108c5573d5f803e3d5ffd5b5050604080518681526020810186905273ffffffffffffffffffffffffffffffffffffffff881693503392507ffcea3600a13c757f2758710b089cc9752781c35d2a9d6804370ed18cd82f0bb691015b60405180910390a350505050565b60607f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00600201805461046d90611589565b33734200000000000000000000000000000000000010146109a1576040517f38da3b1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166109ee576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109f88282611180565b8173ffffffffffffffffffffffffffffffffffffffff167fcc16f5dbb4873280815c1ee09dbd06736cffcc184412cf7a71a0fdb75d397ca58260405161075f91815260200190565b5f6387a211a2600c52335f526020600c20805480841115610a685763f4d678b85f526004601cfd5b83810382555050825f526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350600192915050565b5f610ac061043c565b80519060200120905084421115610ade57631a15a3cc5f526004601cfd5b6040518860601b60601c98508760601b60601c975065383775081901600e52885f526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83528360208401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528a60208401528960408401528860608401528060808401528760a084015260c08320604e526042602c205f528660ff16602052856040528460605260208060805f60015afa8b3d5114610be65763ddafbaef5f526004601cfd5b019055777f5e9f20000000000000000000000000000000000000000088176040526034602c2087905587897f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a360405250505f606052505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216610c97576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373420000000000000000000000000000000000002314610ce4576040517f065d515000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff1673420000000000000000000000000000000000002373ffffffffffffffffffffffffffffffffffffffff166338ffde186040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d58573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d7c9190611617565b73ffffffffffffffffffffffffffffffffffffffff1614610dc9576040517fbc22e2aa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f73420000000000000000000000000000000000002373ffffffffffffffffffffffffffffffffffffffff1663247944626040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e27573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e4b9190611632565b9050610e578383611104565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fc75e22a0b57fb7740dbfc0caa5c6b7a82a2139964e7f1b7be7ac4e8be0f719ba8484604051610915929190918252602082015260400190565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff165f81158015610f095750825b90505f8267ffffffffffffffff166001148015610f255750303b155b905081158015610f33575080155b15610f6a576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610fcb5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b7f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb0080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8b161781557f07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb016110558a82611694565b50600281016110648982611694565b5060030180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff881617905583156110f45784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050505050565b505050565b6805345cdf77eb68f44c54818101818110156111275763e5cfe9575f526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52815f526020600c208181540181555080602052600c5160601c5f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a35050565b6387a211a2600c52815f526020600c208054808311156111a75763f4d678b85f526004601cfd5b82900390556805345cdf77eb68f44c805482900390555f81815273ffffffffffffffffffffffffffffffffffffffff83167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602083a35050565b5f60208284031215611211575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611240575f80fd5b9392505050565b5f81518084528060208401602086015e5f6020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081525f6112406020830184611247565b73ffffffffffffffffffffffffffffffffffffffff811681146112c6575f80fd5b50565b5f80604083850312156112da575f80fd5b82356112e5816112a5565b946020939093013593505050565b5f805f60608486031215611305575f80fd5b8335611310816112a5565b92506020840135611320816112a5565b929592945050506040919091013590565b5f60208284031215611341575f80fd5b8135611240816112a5565b5f805f6060848603121561135e575f80fd5b8335611369816112a5565b95602085013595506040909401359392505050565b803560ff8116811461138e575f80fd5b919050565b5f805f805f805f60e0888a0312156113a9575f80fd5b87356113b4816112a5565b965060208801356113c4816112a5565b955060408801359450606088013593506113e06080890161137e565b925060a0880135915060c0880135905092959891949750929550565b5f806040838503121561140d575f80fd5b8235611418816112a5565b91506020830135611428816112a5565b809150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f82601f83011261146f575f80fd5b813567ffffffffffffffff8082111561148a5761148a611433565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019082821181831017156114d0576114d0611433565b816040528381528660208588010111156114e8575f80fd5b836020870160208301375f602085830101528094505050505092915050565b5f805f806080858703121561151a575f80fd5b8435611525816112a5565b9350602085013567ffffffffffffffff80821115611541575f80fd5b61154d88838901611460565b94506040870135915080821115611562575f80fd5b5061156f87828801611460565b92505061157e6060860161137e565b905092959194509250565b600181811c9082168061159d57607f821691505b6020821081036115d4577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b83815273ffffffffffffffffffffffffffffffffffffffff83166020820152606060408201525f61160e6060830184611247565b95945050505050565b5f60208284031215611627575f80fd5b8151611240816112a5565b5f60208284031215611642575f80fd5b5051919050565b601f8211156110ff57805f5260205f20601f840160051c8101602085101561166e5750805b601f840160051c820191505b8181101561168d575f815560010161167a565b5050505050565b815167ffffffffffffffff8111156116ae576116ae611433565b6116c2816116bc8454611589565b84611649565b602080601f831160018114611714575f84156116de5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556117a8565b5f858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561176057888601518255948401946001909101908401611741565b508582101561179c57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b505060018460011b0185555b50505050505056fea164736f6c6343000819000a"; + bytes internal constant sourceTokenCode = + hex"6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a"; + bytes internal constant destTokenCode = + hex"6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a"; + bytes internal constant mockL2ToL2MessengerCode = + hex"608060405260043610610058575f3560e01c80632ea02369116100415780632ea023691461009857806338ffde18146100cb5780637056f41f14610104575f80fd5b80631ecd26f21461005c5780632479446214610071575b5f80fd5b61006f61006a366004610484565b610117565b005b34801561007c575f80fd5b506100856101d2565b6040519081526020015b60405180910390f35b3480156100a3575f80fd5b506100857f000000000000000000000000000000000000000000000000000000000000000281565b3480156100d6575f80fd5b506100df6101e3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008f565b61006f610112366004610500565b6102cd565b5f808473ffffffffffffffffffffffffffffffffffffffff16348585604051610141929190610556565b5f6040518083038185875af1925050503d805f811461017b576040519150601f19603f3d011682016040523d82523d5f602084013e610180565b606091505b5091509150816101c757806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101be9190610565565b60405180910390fd5b505050505050505050565b5f6101de4660016105b8565b905090565b5f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361024657507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036102a857507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a90565b507f000000000000000000000000000000000000000000000000000000000000000090565b7f000000000000000000000000000000000000000000000000000000000000000284036103e6575f6103557f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506103ec92505050565b9050806103e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016101be565b505b50505050565b5f6103f9845a8585610401565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461043a575f80fd5b919050565b5f8083601f84011261044f575f80fd5b50813567ffffffffffffffff811115610466575f80fd5b60208301915083602082850101111561047d575f80fd5b9250929050565b5f805f805f805f60c0888a03121561049a575f80fd5b8735965060208801359550604088013594506104b860608901610417565b93506104c660808901610417565b925060a088013567ffffffffffffffff8111156104e1575f80fd5b6104ed8a828b0161043f565b989b979a50959850939692959293505050565b5f805f8060608587031215610513575f80fd5b8435935061052360208601610417565b9250604085013567ffffffffffffffff81111561053e575f80fd5b61054a8782880161043f565b95989497509550505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b808201808211156105f0577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9291505056fea164736f6c6343000819000a"; +} diff --git a/packages/contracts-bedrock/test/properties/kontrol/helpers/LibStateDiff.sol b/packages/contracts-bedrock/test/properties/kontrol/helpers/LibStateDiff.sol new file mode 100644 index 000000000000..d5269b082604 --- /dev/null +++ b/packages/contracts-bedrock/test/properties/kontrol/helpers/LibStateDiff.sol @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: MIT +// (The MIT License) + +// Copyright 2020-2024 Optimism + +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: + +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +pragma solidity 0.8.25; + +import { stdJson } from "forge-std/StdJson.sol"; +import { VmSafe } from "forge-std/Vm.sol"; + +/// @title LibStateDiff +/// @author refcell +/// @notice Library to write StateDiff output to json. +library LibStateDiff { + /// @notice Accepts an array of AccountAccess structs from the Vm and encodes them as a json string. + /// @param _accountAccesses Array of AccountAccess structs. + /// @return serialized_ string + function encodeAccountAccesses(VmSafe.AccountAccess[] memory _accountAccesses) + internal + returns (string memory serialized_) + { + string[] memory accountAccesses = new string[](_accountAccesses.length); + for (uint256 i = 0; i < _accountAccesses.length; i++) { + accountAccesses[i] = serializeAccountAccess(_accountAccesses[i]); + } + serialized_ = stdJson.serialize("accountAccessElem", "accountAccesses", accountAccesses); + } + + /// @notice Turns an AccountAccess into a json serialized string + /// @param _accountAccess The AccountAccess to serialize + /// @return serialized_ The json serialized string + function serializeAccountAccess(VmSafe.AccountAccess memory _accountAccess) + internal + returns (string memory serialized_) + { + string memory json = "foo"; + json = stdJson.serialize("accountAccess", "chainInfo", serializeChainInfo(_accountAccess.chainInfo)); + json = stdJson.serialize("accountAccess", "kind", serializeAccountAccessKind(_accountAccess.kind)); + json = stdJson.serialize("accountAccess", "account", _accountAccess.account); + json = stdJson.serialize("accountAccess", "accessor", _accountAccess.accessor); + json = stdJson.serialize("accountAccess", "initialized", _accountAccess.initialized); + json = stdJson.serialize("accountAccess", "oldBalance", _accountAccess.oldBalance); + json = stdJson.serialize("accountAccess", "newBalance", _accountAccess.newBalance); + json = stdJson.serialize("accountAccess", "deployedCode", _accountAccess.deployedCode); + json = stdJson.serialize("accountAccess", "value", _accountAccess.value); + json = stdJson.serialize("accountAccess", "data", _accountAccess.data); + json = stdJson.serialize("accountAccess", "reverted", _accountAccess.reverted); + json = stdJson.serialize( + "accountAccess", "storageAccesses", serializeStorageAccesses(_accountAccess.storageAccesses) + ); + serialized_ = json; + } + + /// @notice Accepts a VmSafe.ChainInfo struct and encodes it as a json string. + /// @param _chainInfo The ChainInfo struct to serialize + /// @return serialized_ string + function serializeChainInfo(VmSafe.ChainInfo memory _chainInfo) internal returns (string memory serialized_) { + string memory json = ""; + json = stdJson.serialize("chainInfo", "forkId", _chainInfo.forkId); + json = stdJson.serialize("chainInfo", "chainId", _chainInfo.chainId); + serialized_ = json; + } + + /// @notice Turns an AccountAccessKind into a string. + /// @param _kind The AccountAccessKind to serialize + /// @return serialized_ The string representation of the AccountAccessKind + function serializeAccountAccessKind(VmSafe.AccountAccessKind _kind) + internal + pure + returns (string memory serialized_) + { + if (_kind == VmSafe.AccountAccessKind.Call) { + serialized_ = "Call"; + } else if (_kind == VmSafe.AccountAccessKind.DelegateCall) { + serialized_ = "DelegateCall"; + } else if (_kind == VmSafe.AccountAccessKind.CallCode) { + serialized_ = "CallCode"; + } else if (_kind == VmSafe.AccountAccessKind.StaticCall) { + serialized_ = "StaticCall"; + } else if (_kind == VmSafe.AccountAccessKind.Create) { + serialized_ = "Create"; + } else if (_kind == VmSafe.AccountAccessKind.SelfDestruct) { + serialized_ = "SelfDestruct"; + } else { + serialized_ = "Resume"; + } + } + + /// @notice Accepts an array of StorageAccess structs from the Vm and encodes each as a json string. + /// @param _storageAccesses Array of StorageAccess structs. + /// @return serialized_ The list of json serialized StorageAccess structs. + function serializeStorageAccesses(VmSafe.StorageAccess[] memory _storageAccesses) + internal + returns (string[] memory serialized_) + { + serialized_ = new string[](_storageAccesses.length); + for (uint256 i = 0; i < _storageAccesses.length; i++) { + serialized_[i] = serializeStorageAccess(_storageAccesses[i]); + } + } + + /// @notice Turns a StorageAccess into a json serialized string + /// @param _storageAccess The StorageAccess to serialize + /// @return serialized_ The json serialized string + function serializeStorageAccess(VmSafe.StorageAccess memory _storageAccess) + internal + returns (string memory serialized_) + { + string memory json = ""; + json = stdJson.serialize("storageAccess", "account", _storageAccess.account); + json = stdJson.serialize("storageAccess", "slot", _storageAccess.slot); + json = stdJson.serialize("storageAccess", "isWrite", _storageAccess.isWrite); + json = stdJson.serialize("storageAccess", "previousValue", _storageAccess.previousValue); + json = stdJson.serialize("storageAccess", "newValue", _storageAccess.newValue); + json = stdJson.serialize("storageAccess", "reverted", _storageAccess.reverted); + serialized_ = json; + } +} diff --git a/packages/contracts-bedrock/test/properties/kontrol/helpers/RecordStateDiff.sol b/packages/contracts-bedrock/test/properties/kontrol/helpers/RecordStateDiff.sol new file mode 100644 index 000000000000..a49cb41b6545 --- /dev/null +++ b/packages/contracts-bedrock/test/properties/kontrol/helpers/RecordStateDiff.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import { console2 as console } from "forge-std/console2.sol"; +import { stdJson } from "forge-std/StdJson.sol"; +import { Vm } from "forge-std/Vm.sol"; +import { VmSafe } from "forge-std/Vm.sol"; +import { LibStateDiff } from "./LibStateDiff.sol"; + +struct Contract { + string contractName; + address contractAddress; +} + +abstract contract RecordStateDiff { + Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + /// @notice Executes a function recording its state updates and saves it to the + /// the file $STATE_DIFF_DIR/$STATE_DIFF_FILE + /// @dev STATE_DIFF_DIR env var with file folder relative to the foundry root dir + /// @dev STATE_DIFF_NAME env var with state diff file name + modifier recordStateDiff() { + // Check if the specified JSON file exists and create it if not + string memory statediffFile = check_file(vm.envString("STATE_DIFF_DIR"), vm.envString("STATE_DIFF_NAME")); + vm.startStateDiffRecording(); + _; + VmSafe.AccountAccess[] memory accesses = vm.stopAndReturnStateDiff(); + string memory json = LibStateDiff.encodeAccountAccesses(accesses); + vm.writeJson({ json: json, path: statediffFile }); + } + + /// @notice Saves a an address with a name to $STATE_DIFF_DIR/$STATE_DIFF_NAMES + /// @dev STATE_DIFF_DIR env var with file folder relative to the foundry root dir + /// @dev ADDR_NAMES env var with named addresses file name + /// TODO: Investigate/fix why the resulting order of the strings in the json seems to not preseve the order + /// in which `save_address` is called when saving multiple addresses + function save_address(address addr, string memory name) public { + string memory address_names_file = check_file(vm.envString("STATE_DIFF_DIR"), vm.envString("ADDR_NAMES")); + vm.writeJson({ json: vm.serializeString("", vm.toString(addr), name), path: address_names_file }); + } + + /// @notice Checks if dir_name/file_name exists and creates it if not + function check_file(string memory dir_name, string memory file_name) public returns (string memory) { + string memory dirname = string.concat(vm.projectRoot(), "/", dir_name); + string memory filename = string.concat(vm.projectRoot(), "/", dir_name, "/", file_name); + if (vm.exists(filename)) return filename; + if (!vm.isDir(dirname)) ffi_two_arg("mkdir", "-p", dirname); // Create directory if doesn't exist + ffi_one_arg("touch", filename); // Create file. Might be redundant, but better make sure + return filename; + } + + /// @notice Execute one bash command with one argument + /// @dev Will revert if the command returns any output + /// TODO: abstract number of arguments per function + function ffi_one_arg(string memory command, string memory arg) public { + string[] memory inputs = new string[](2); + inputs[0] = command; + inputs[1] = arg; + bytes memory res = vm.ffi(inputs); + require(res.length == 0, "RecordStateDiff: Command execution failed"); + } + + /// @notice Execute one bash command with one argument + /// @dev Will revert if the command returns any output + /// TODO: abstract number of arguments per function + function ffi_two_arg(string memory command, string memory arg1, string memory arg2) public { + string[] memory inputs = new string[](3); + inputs[0] = command; + inputs[1] = arg1; + inputs[2] = arg2; + bytes memory res = vm.ffi(inputs); + require(res.length == 0, "RecordStateDiff: Command execution failed"); + } +} diff --git a/packages/contracts-bedrock/test/properties/kontrol/optimism-superchain-lemmas.md b/packages/contracts-bedrock/test/properties/kontrol/optimism-superchain-lemmas.md new file mode 100644 index 000000000000..6cb29280402f --- /dev/null +++ b/packages/contracts-bedrock/test/properties/kontrol/optimism-superchain-lemmas.md @@ -0,0 +1,33 @@ +```k +requires "foundry.md" + +module OPTIMISM-SUPERCHAIN-LEMMAS + imports BOOL + imports FOUNDRY + imports INT-SYMBOLIC + + // Convert booleans to their word equivalents + rule bool2Word(true) => 1 + rule bool2Word(false) => 0 + + // Associativity and Commutativity Rules: + rule A +Int (B +Int C) => (A +Int B) +Int C + rule A *Int B => B *Int A + + // Comparison Normalization: + rule A +Int B A A false requires 0 <=Int B + rule A false requires 0 <=Int B + + rule A -Int A => 0 + rule 0 +Int A => A + rule A +Int 0 => A + rule A -Int 0 => A + + rule chop(I) => I requires #rangeUInt(256, I) + rule chop (chop (X:Int) +Int Y:Int) => chop (X +Int Y) + rule chop (X:Int +Int chop (Y:Int)) => chop (X +Int Y) +endmodule +``` diff --git a/packages/contracts-bedrock/test/properties/kontrol/utils/record-state-diff.sh b/packages/contracts-bedrock/test/properties/kontrol/utils/record-state-diff.sh new file mode 100644 index 000000000000..f2e242e913ea --- /dev/null +++ b/packages/contracts-bedrock/test/properties/kontrol/utils/record-state-diff.sh @@ -0,0 +1,55 @@ +#!/bin/bash +set -euo pipefail + +################################################################################ +# WARNING: This script is meant to be run from the foundry root directory # +# bash ./test/properties/kontrol/utils/record-state-diff.sh to run it # +################################################################################ + +########################## +# ENVIRNONMENT VARIABLES # +########################## + +# JSON-related variables +export STATE_DIFF_DIR=supererc20-state-diff # Relative to the Foundry root directory +export STATE_DIFF_NAME=StateDiff.json +export ADDR_NAMES=AddressNames.json +CLEAN_JSON_PATH=test/kontrol/scripts/json/clean_json.py + +# Where the contract and function that produces the jsons live +RECORDING_CONTRACT_DIR=test/properties/kontrol # Relative to the Foundry root directory +RECORDING_CONTRACT_FILE=KontrolBase.sol # Name of the Solidity file +RECORDING_CONTRACT_NAME=KontrolBase # Name of the actual contract +RECORDING_CONTRACT_FUNCTION=setUpNamed # Name of the function with the recordStateDiff modifier + +RECORDING_CONTRACT_PATH="$RECORDING_CONTRACT_DIR/$RECORDING_CONTRACT_FILE:$RECORDING_CONTRACT_NAME" + +# Kontrol-related variables +GENERATED_CONTRACT_NAME=InitialState +GENERATED_CONTRACT_DIR=test/properties/kontrol/deployments # Relative to the Foundry root directory +GENERATED_CONTRACT_LICENSE=UNLICENSED + +#################### +# RECORD EXECUTION # +#################### + +# Run the function with the recordStateDiff modifier +forge script $RECORDING_CONTRACT_PATH --sig "$RECORDING_CONTRACT_FUNCTION" --ffi -vv +# state diff JSON comes out scaped from the last command +# We execute this script to unscape it so that it can be fed to Kontrol +python3 "$CLEAN_JSON_PATH" "$STATE_DIFF_DIR/$STATE_DIFF_NAME" + +############################### +# GENERATE SOLIDITY CONTRACTS # +############################### + +# Give the appropriate files to Kontrol to create the contracts +kontrol load-state "$GENERATED_CONTRACT_NAME" "$STATE_DIFF_DIR/$STATE_DIFF_NAME" \ + --contract-names "$STATE_DIFF_DIR/$ADDR_NAMES" \ + --output-dir "$GENERATED_CONTRACT_DIR" \ + --license "$GENERATED_CONTRACT_LICENSE" \ + --from-state-diff + +# Format the code to ensure compatibility with any CI checks +forge fmt "$GENERATED_CONTRACT_DIR/$GENERATED_CONTRACT_NAME.sol" +forge fmt "$GENERATED_CONTRACT_DIR/${GENERATED_CONTRACT_NAME}Code.sol" \ No newline at end of file From 293423808f2c484269f1895861a6f78679fd1413 Mon Sep 17 00:00:00 2001 From: drgorillamd <83670532+drgorillamd@users.noreply.github.com> Date: Mon, 2 Sep 2024 16:28:19 +0200 Subject: [PATCH 24/56] fix(test): init glob var in state diff generator --- .../supererc20-state-diff/StateDiff.json | 29 +++++++++++++++---- .../test/properties/kontrol/KontrolBase.sol | 13 ++++++--- .../kontrol/OptimismSuperchainERC20.k.sol | 1 + .../kontrol/deployments/InitialState.sol | 4 +-- 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json index f1dba0541bbf..4b083086ffa9 100644 --- a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json +++ b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json @@ -1,5 +1,22 @@ { "accountAccesses": [ + { + "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", + "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", + "chainInfo": { + "chainId": 31337, + "forkId": 0 + }, + "data": "0x", + "deployedCode": "0x", + "initialized": true, + "kind": "Resume", + "newBalance": 0, + "oldBalance": 0, + "reverted": false, + "storageAccesses": [], + "value": 0 + }, { "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", @@ -57,7 +74,7 @@ "chainId": 31337, "forkId": 0 }, - "data": "0x60806040526040516103ae3803806103ae8339810160408190526100229161023c565b61002c8282610033565b505061031b565b61003c82610091565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561008557610080828261010c565b505050565b61008d61017f565b5050565b806001600160a01b03163b5f036100cb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516101289190610305565b5f60405180830381855af49150503d805f8114610160576040519150601f19603f3d011682016040523d82523d5f602084013e610165565b606091505b5090925090506101768583836101a0565b95945050505050565b341561019e5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b5576101b0826101ff565b6101f8565b81511580156101cc57506001600160a01b0384163b155b156101f557604051639996b31560e01b81526001600160a01b03851660048201526024016100c2565b50805b9392505050565b80511561020f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561024d575f80fd5b82516001600160a01b0381168114610263575f80fd5b60208401519092506001600160401b038082111561027f575f80fd5b818501915085601f830112610292575f80fd5b8151818111156102a4576102a4610228565b604051601f8201601f19908116603f011681019083821181831017156102cc576102cc610228565b816040528281528860208487010111156102e4575f80fd5b8260208601602083015e5f6020848301015280955050505050509250929050565b5f82518060208501845e5f920191825250919050565b6087806103275f395ff3fe6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000104f6d2ee86000000000000000000000000237a66474b7b934b22574359500212977b656d9f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e455243323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005535550455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "data": "0x60806040526040516103ae3803806103ae8339810160408190526100229161023c565b61002c8282610033565b505061031b565b61003c82610091565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561008557610080828261010c565b505050565b61008d61017f565b5050565b806001600160a01b03163b5f036100cb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516101289190610305565b5f60405180830381855af49150503d805f8114610160576040519150601f19603f3d011682016040523d82523d5f602084013e610165565b606091505b5090925090506101768583836101a0565b95945050505050565b341561019e5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b5576101b0826101ff565b6101f8565b81511580156101cc57506001600160a01b0384163b155b156101f557604051639996b31560e01b81526001600160a01b03851660048201526024016100c2565b50805b9392505050565b80511561020f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561024d575f80fd5b82516001600160a01b0381168114610263575f80fd5b60208401519092506001600160401b038082111561027f575f80fd5b818501915085601f830112610292575f80fd5b8151818111156102a4576102a4610228565b604051601f8201601f19908116603f011681019083821181831017156102cc576102cc610228565b816040528281528860208487010111156102e4575f80fd5b8260208601602083015e5f6020848301015280955050505050509250929050565b5f82518060208501845e5f920191825250919050565b6087806103275f395ff3fe6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000104f6d2ee86000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e455243323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005535550455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "deployedCode": "0x6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a", "initialized": true, "kind": "Create", @@ -125,7 +142,7 @@ "chainId": 31337, "forkId": 0 }, - "data": "0xf6d2ee86000000000000000000000000237a66474b7b934b22574359500212977b656d9f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e4552433230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055355504552000000000000000000000000000000000000000000000000000000", + "data": "0xf6d2ee86000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e4552433230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055355504552000000000000000000000000000000000000000000000000000000", "deployedCode": "0x", "initialized": true, "kind": "DelegateCall", @@ -184,7 +201,7 @@ { "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", "isWrite": true, - "newValue": "0x000000000000000000000000237a66474b7b934b22574359500212977b656d9f", + "newValue": "0x000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d", "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", "reverted": false, "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00" @@ -280,7 +297,7 @@ "chainId": 31337, "forkId": 0 }, - "data": "0x60806040526040516103ae3803806103ae8339810160408190526100229161023c565b61002c8282610033565b505061031b565b61003c82610091565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561008557610080828261010c565b505050565b61008d61017f565b5050565b806001600160a01b03163b5f036100cb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516101289190610305565b5f60405180830381855af49150503d805f8114610160576040519150601f19603f3d011682016040523d82523d5f602084013e610165565b606091505b5090925090506101768583836101a0565b95945050505050565b341561019e5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b5576101b0826101ff565b6101f8565b81511580156101cc57506001600160a01b0384163b155b156101f557604051639996b31560e01b81526001600160a01b03851660048201526024016100c2565b50805b9392505050565b80511561020f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561024d575f80fd5b82516001600160a01b0381168114610263575f80fd5b60208401519092506001600160401b038082111561027f575f80fd5b818501915085601f830112610292575f80fd5b8151818111156102a4576102a4610228565b604051601f8201601f19908116603f011681019083821181831017156102cc576102cc610228565b816040528281528860208487010111156102e4575f80fd5b8260208601602083015e5f6020848301015280955050505050509250929050565b5f82518060208501845e5f920191825250919050565b6087806103275f395ff3fe6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000104f6d2ee86000000000000000000000000237a66474b7b934b22574359500212977b656d9f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e455243323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005535550455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "data": "0x60806040526040516103ae3803806103ae8339810160408190526100229161023c565b61002c8282610033565b505061031b565b61003c82610091565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561008557610080828261010c565b505050565b61008d61017f565b5050565b806001600160a01b03163b5f036100cb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516101289190610305565b5f60405180830381855af49150503d805f8114610160576040519150601f19603f3d011682016040523d82523d5f602084013e610165565b606091505b5090925090506101768583836101a0565b95945050505050565b341561019e5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b5576101b0826101ff565b6101f8565b81511580156101cc57506001600160a01b0384163b155b156101f557604051639996b31560e01b81526001600160a01b03851660048201526024016100c2565b50805b9392505050565b80511561020f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561024d575f80fd5b82516001600160a01b0381168114610263575f80fd5b60208401519092506001600160401b038082111561027f575f80fd5b818501915085601f830112610292575f80fd5b8151818111156102a4576102a4610228565b604051601f8201601f19908116603f011681019083821181831017156102cc576102cc610228565b816040528281528860208487010111156102e4575f80fd5b8260208601602083015e5f6020848301015280955050505050509250929050565b5f82518060208501845e5f920191825250919050565b6087806103275f395ff3fe6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000104f6d2ee86000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e455243323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005535550455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "deployedCode": "0x6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a", "initialized": true, "kind": "Create", @@ -348,7 +365,7 @@ "chainId": 31337, "forkId": 0 }, - "data": "0xf6d2ee86000000000000000000000000237a66474b7b934b22574359500212977b656d9f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e4552433230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055355504552000000000000000000000000000000000000000000000000000000", + "data": "0xf6d2ee86000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e4552433230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055355504552000000000000000000000000000000000000000000000000000000", "deployedCode": "0x", "initialized": true, "kind": "DelegateCall", @@ -407,7 +424,7 @@ { "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", "isWrite": true, - "newValue": "0x000000000000000000000000237a66474b7b934b22574359500212977b656d9f", + "newValue": "0x000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d", "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", "reverted": false, "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00" diff --git a/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol b/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol index 283c4e639113..9f39bb54f8b1 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol @@ -16,10 +16,10 @@ contract KontrolBase is Test, KontrolCheats, RecordStateDiff { MockL2ToL2Messenger internal constant MESSENGER = MockL2ToL2Messenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); - address internal remoteToken = address(bytes20(keccak256("remoteToken"))); - string internal name = "SuperchainERC20"; - string internal symbol = "SUPER"; - uint8 internal decimals = 18; + address internal remoteToken; + string internal name; + string internal symbol; + uint8 internal decimals; OptimismSuperchainERC20 public superchainERC20Impl; OptimismSuperchainERC20 internal sourceToken; @@ -28,6 +28,11 @@ contract KontrolBase is Test, KontrolCheats, RecordStateDiff { // The second function to get the state diff saving the addresses with their names function setUpNamed() public virtual recordStateDiff { + remoteToken = makeAddr("remoteToken"); + name = "SuperchainERC20"; + symbol = "SUPER"; + decimals = 18; + // Deploy the OptimismSuperchainERC20 contract implementation and the proxy to be used superchainERC20Impl = new OptimismSuperchainERC20(); sourceToken = OptimismSuperchainERC20( diff --git a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol index ca73d5586123..f0ca6954ae82 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol @@ -20,6 +20,7 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { setUpInlined(); // Source token + assert(remoteToken != address(0)); assert(sourceToken.remoteToken() == remoteToken); assert(eqStrings(sourceToken.name(), name)); assert(eqStrings(sourceToken.symbol(), symbol)); diff --git a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialState.sol b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialState.sol index cb47c362f4f6..990c69510c6c 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialState.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialState.sol @@ -37,7 +37,7 @@ contract InitialState is InitialStateCode { value = hex"0000000000000000000000000000000000000000000000010000000000000001"; vm.store(sourceTokenAddress, slot, value); slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00"; - value = hex"000000000000000000000000237a66474b7b934b22574359500212977b656d9f"; + value = hex"000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d"; vm.store(sourceTokenAddress, slot, value); slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb01"; value = hex"5375706572636861696e4552433230000000000000000000000000000000001e"; @@ -62,7 +62,7 @@ contract InitialState is InitialStateCode { value = hex"0000000000000000000000000000000000000000000000010000000000000001"; vm.store(destTokenAddress, slot, value); slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00"; - value = hex"000000000000000000000000237a66474b7b934b22574359500212977b656d9f"; + value = hex"000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d"; vm.store(destTokenAddress, slot, value); slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb01"; value = hex"5375706572636861696e4552433230000000000000000000000000000000001e"; From 98e443a2a3af7c8d31764f09b25ce2b86cc4d86f Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Mon, 2 Sep 2024 20:53:15 -0300 Subject: [PATCH 25/56] Revert "fix(test): init glob var in state diff generator" The changes are no longer needed since with the constructor args flag it works This reverts commit 293423808f2c484269f1895861a6f78679fd1413. --- .../supererc20-state-diff/StateDiff.json | 29 ++++--------------- .../test/properties/kontrol/KontrolBase.sol | 13 +++------ .../kontrol/OptimismSuperchainERC20.k.sol | 1 - .../kontrol/deployments/InitialState.sol | 4 +-- 4 files changed, 12 insertions(+), 35 deletions(-) diff --git a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json index 4b083086ffa9..f1dba0541bbf 100644 --- a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json +++ b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json @@ -1,22 +1,5 @@ { "accountAccesses": [ - { - "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", - "account": "0x7109709ECfa91a80626fF3989D68f67F5b1DD12D", - "chainInfo": { - "chainId": 31337, - "forkId": 0 - }, - "data": "0x", - "deployedCode": "0x", - "initialized": true, - "kind": "Resume", - "newBalance": 0, - "oldBalance": 0, - "reverted": false, - "storageAccesses": [], - "value": 0 - }, { "accessor": "0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496", "account": "0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f", @@ -74,7 +57,7 @@ "chainId": 31337, "forkId": 0 }, - "data": "0x60806040526040516103ae3803806103ae8339810160408190526100229161023c565b61002c8282610033565b505061031b565b61003c82610091565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561008557610080828261010c565b505050565b61008d61017f565b5050565b806001600160a01b03163b5f036100cb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516101289190610305565b5f60405180830381855af49150503d805f8114610160576040519150601f19603f3d011682016040523d82523d5f602084013e610165565b606091505b5090925090506101768583836101a0565b95945050505050565b341561019e5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b5576101b0826101ff565b6101f8565b81511580156101cc57506001600160a01b0384163b155b156101f557604051639996b31560e01b81526001600160a01b03851660048201526024016100c2565b50805b9392505050565b80511561020f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561024d575f80fd5b82516001600160a01b0381168114610263575f80fd5b60208401519092506001600160401b038082111561027f575f80fd5b818501915085601f830112610292575f80fd5b8151818111156102a4576102a4610228565b604051601f8201601f19908116603f011681019083821181831017156102cc576102cc610228565b816040528281528860208487010111156102e4575f80fd5b8260208601602083015e5f6020848301015280955050505050509250929050565b5f82518060208501845e5f920191825250919050565b6087806103275f395ff3fe6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000104f6d2ee86000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e455243323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005535550455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "data": "0x60806040526040516103ae3803806103ae8339810160408190526100229161023c565b61002c8282610033565b505061031b565b61003c82610091565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561008557610080828261010c565b505050565b61008d61017f565b5050565b806001600160a01b03163b5f036100cb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516101289190610305565b5f60405180830381855af49150503d805f8114610160576040519150601f19603f3d011682016040523d82523d5f602084013e610165565b606091505b5090925090506101768583836101a0565b95945050505050565b341561019e5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b5576101b0826101ff565b6101f8565b81511580156101cc57506001600160a01b0384163b155b156101f557604051639996b31560e01b81526001600160a01b03851660048201526024016100c2565b50805b9392505050565b80511561020f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561024d575f80fd5b82516001600160a01b0381168114610263575f80fd5b60208401519092506001600160401b038082111561027f575f80fd5b818501915085601f830112610292575f80fd5b8151818111156102a4576102a4610228565b604051601f8201601f19908116603f011681019083821181831017156102cc576102cc610228565b816040528281528860208487010111156102e4575f80fd5b8260208601602083015e5f6020848301015280955050505050509250929050565b5f82518060208501845e5f920191825250919050565b6087806103275f395ff3fe6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000104f6d2ee86000000000000000000000000237a66474b7b934b22574359500212977b656d9f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e455243323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005535550455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "deployedCode": "0x6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a", "initialized": true, "kind": "Create", @@ -142,7 +125,7 @@ "chainId": 31337, "forkId": 0 }, - "data": "0xf6d2ee86000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e4552433230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055355504552000000000000000000000000000000000000000000000000000000", + "data": "0xf6d2ee86000000000000000000000000237a66474b7b934b22574359500212977b656d9f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e4552433230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055355504552000000000000000000000000000000000000000000000000000000", "deployedCode": "0x", "initialized": true, "kind": "DelegateCall", @@ -201,7 +184,7 @@ { "account": "0x2e234DAe75C793f67A35089C9d99245E1C58470b", "isWrite": true, - "newValue": "0x000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d", + "newValue": "0x000000000000000000000000237a66474b7b934b22574359500212977b656d9f", "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", "reverted": false, "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00" @@ -297,7 +280,7 @@ "chainId": 31337, "forkId": 0 }, - "data": "0x60806040526040516103ae3803806103ae8339810160408190526100229161023c565b61002c8282610033565b505061031b565b61003c82610091565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561008557610080828261010c565b505050565b61008d61017f565b5050565b806001600160a01b03163b5f036100cb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516101289190610305565b5f60405180830381855af49150503d805f8114610160576040519150601f19603f3d011682016040523d82523d5f602084013e610165565b606091505b5090925090506101768583836101a0565b95945050505050565b341561019e5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b5576101b0826101ff565b6101f8565b81511580156101cc57506001600160a01b0384163b155b156101f557604051639996b31560e01b81526001600160a01b03851660048201526024016100c2565b50805b9392505050565b80511561020f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561024d575f80fd5b82516001600160a01b0381168114610263575f80fd5b60208401519092506001600160401b038082111561027f575f80fd5b818501915085601f830112610292575f80fd5b8151818111156102a4576102a4610228565b604051601f8201601f19908116603f011681019083821181831017156102cc576102cc610228565b816040528281528860208487010111156102e4575f80fd5b8260208601602083015e5f6020848301015280955050505050509250929050565b5f82518060208501845e5f920191825250919050565b6087806103275f395ff3fe6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000104f6d2ee86000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e455243323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005535550455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "data": "0x60806040526040516103ae3803806103ae8339810160408190526100229161023c565b61002c8282610033565b505061031b565b61003c82610091565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561008557610080828261010c565b505050565b61008d61017f565b5050565b806001600160a01b03163b5f036100cb57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516101289190610305565b5f60405180830381855af49150503d805f8114610160576040519150601f19603f3d011682016040523d82523d5f602084013e610165565b606091505b5090925090506101768583836101a0565b95945050505050565b341561019e5760405163b398979f60e01b815260040160405180910390fd5b565b6060826101b5576101b0826101ff565b6101f8565b81511580156101cc57506001600160a01b0384163b155b156101f557604051639996b31560e01b81526001600160a01b03851660048201526024016100c2565b50805b9392505050565b80511561020f5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b634e487b7160e01b5f52604160045260245ffd5b5f806040838503121561024d575f80fd5b82516001600160a01b0381168114610263575f80fd5b60208401519092506001600160401b038082111561027f575f80fd5b818501915085601f830112610292575f80fd5b8151818111156102a4576102a4610228565b604051601f8201601f19908116603f011681019083821181831017156102cc576102cc610228565b816040528281528860208487010111156102e4575f80fd5b8260208601602083015e5f6020848301015280955050505050509250929050565b5f82518060208501845e5f920191825250919050565b6087806103275f395ff3fe6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a0000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000104f6d2ee86000000000000000000000000237a66474b7b934b22574359500212977b656d9f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e455243323000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005535550455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "deployedCode": "0x6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a", "initialized": true, "kind": "Create", @@ -365,7 +348,7 @@ "chainId": 31337, "forkId": 0 }, - "data": "0xf6d2ee86000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e4552433230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055355504552000000000000000000000000000000000000000000000000000000", + "data": "0xf6d2ee86000000000000000000000000237a66474b7b934b22574359500212977b656d9f000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000f5375706572636861696e4552433230000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055355504552000000000000000000000000000000000000000000000000000000", "deployedCode": "0x", "initialized": true, "kind": "DelegateCall", @@ -424,7 +407,7 @@ { "account": "0xF62849F9A0B5Bf2913b396098F7c7019b51A820a", "isWrite": true, - "newValue": "0x000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d", + "newValue": "0x000000000000000000000000237a66474b7b934b22574359500212977b656d9f", "previousValue": "0x0000000000000000000000000000000000000000000000000000000000000000", "reverted": false, "slot": "0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00" diff --git a/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol b/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol index 9f39bb54f8b1..283c4e639113 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol @@ -16,10 +16,10 @@ contract KontrolBase is Test, KontrolCheats, RecordStateDiff { MockL2ToL2Messenger internal constant MESSENGER = MockL2ToL2Messenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); - address internal remoteToken; - string internal name; - string internal symbol; - uint8 internal decimals; + address internal remoteToken = address(bytes20(keccak256("remoteToken"))); + string internal name = "SuperchainERC20"; + string internal symbol = "SUPER"; + uint8 internal decimals = 18; OptimismSuperchainERC20 public superchainERC20Impl; OptimismSuperchainERC20 internal sourceToken; @@ -28,11 +28,6 @@ contract KontrolBase is Test, KontrolCheats, RecordStateDiff { // The second function to get the state diff saving the addresses with their names function setUpNamed() public virtual recordStateDiff { - remoteToken = makeAddr("remoteToken"); - name = "SuperchainERC20"; - symbol = "SUPER"; - decimals = 18; - // Deploy the OptimismSuperchainERC20 contract implementation and the proxy to be used superchainERC20Impl = new OptimismSuperchainERC20(); sourceToken = OptimismSuperchainERC20( diff --git a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol index f0ca6954ae82..ca73d5586123 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol @@ -20,7 +20,6 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { setUpInlined(); // Source token - assert(remoteToken != address(0)); assert(sourceToken.remoteToken() == remoteToken); assert(eqStrings(sourceToken.name(), name)); assert(eqStrings(sourceToken.symbol(), symbol)); diff --git a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialState.sol b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialState.sol index 990c69510c6c..cb47c362f4f6 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialState.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialState.sol @@ -37,7 +37,7 @@ contract InitialState is InitialStateCode { value = hex"0000000000000000000000000000000000000000000000010000000000000001"; vm.store(sourceTokenAddress, slot, value); slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00"; - value = hex"000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d"; + value = hex"000000000000000000000000237a66474b7b934b22574359500212977b656d9f"; vm.store(sourceTokenAddress, slot, value); slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb01"; value = hex"5375706572636861696e4552433230000000000000000000000000000000001e"; @@ -62,7 +62,7 @@ contract InitialState is InitialStateCode { value = hex"0000000000000000000000000000000000000000000000010000000000000001"; vm.store(destTokenAddress, slot, value); slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00"; - value = hex"000000000000000000000000857a393dd324e79ff1c0a1ec826a66072e3a881d"; + value = hex"000000000000000000000000237a66474b7b934b22574359500212977b656d9f"; vm.store(destTokenAddress, slot, value); slot = hex"07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb01"; value = hex"5375706572636861696e4552433230000000000000000000000000000000001e"; From 830753625dcf7302a56f857bd9f741fb0c709416 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:10:20 -0300 Subject: [PATCH 26/56] chore: update setup on kontrol tests and add assumes * feat: create temporary file to debug symoblic tests with foundry --- .../kontrol/FoundryDebugSymbolic.t.sol | 141 ++++++++++++++++++ .../kontrol/OptimismSuperchainERC20.k.sol | 56 +++++-- 2 files changed, 187 insertions(+), 10 deletions(-) create mode 100644 packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol diff --git a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol new file mode 100644 index 000000000000..dd82f69dc6af --- /dev/null +++ b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { MockL2ToL2Messenger } from "test/properties/halmos/MockL2ToL2Messenger.sol"; +import { KontrolBase } from "test/properties/kontrol/KontrolBase.sol"; +import { InitialState } from "./deployments/InitialState.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; + +import "forge-std/Test.sol"; + +// TODO: File to debug faster with foundry replicating scenarios where the proof failed, needs removal afterwards. +contract FoundryDebugTests is KontrolBase { + function setUp() public { + // Deploy the OptimismSuperchainERC20 contract implementation and the proxy to be used + superchainERC20Impl = new OptimismSuperchainERC20(); + sourceToken = OptimismSuperchainERC20( + address( + // TODO: Update to beacon proxy + new ERC1967Proxy( + address(superchainERC20Impl), + abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) + ) + ) + ); + + destToken = OptimismSuperchainERC20( + address( + // TODO: Update to beacon proxy + new ERC1967Proxy( + address(superchainERC20Impl), + abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) + ) + ) + ); + + mockL2ToL2Messenger = + new MockL2ToL2Messenger(address(sourceToken), address(destToken), DESTINATION_CHAIN_ID, address(0)); + vm.etch(address(MESSENGER), address(mockL2ToL2Messenger).code); + } + + /// @notice Check setup works as expected + function test_proveSetup() public { + // Source token + assert(sourceToken.remoteToken() == remoteToken); + assert(eqStrings(sourceToken.name(), name)); + assert(eqStrings(sourceToken.symbol(), symbol)); + assert(sourceToken.decimals() == decimals); + vm.prank(address(sourceToken)); + assert(MESSENGER.crossDomainMessageSender() == address(sourceToken)); + + // Destination token + assert(destToken.remoteToken() == remoteToken); + assert(eqStrings(destToken.name(), name)); + assert(eqStrings(destToken.symbol(), symbol)); + assert(destToken.decimals() == decimals); + assert(MESSENGER.DESTINATION_CHAIN_ID() == DESTINATION_CHAIN_ID); + vm.prank(address(destToken)); + assert(MESSENGER.crossDomainMessageSender() == address(destToken)); + + // Custom cross domain sender + assert(MESSENGER.crossDomainMessageSender() == address(0)); + } + + /// @custom:property-id 7 + /// @custom:property Calls to relayERC20 always succeed as long as the sender the cross-domain caller are valid + function test_proveRelayERC20OnlyFromL2ToL2Messenger() public { + address _crossDomainSender = address(0); + address _sender = address(0); + address _from = address(645326474426547203313410069153905908525362434350); + address _to = address(728815563385977040452943777879061427756277306519); + uint256 _amount = 0; + + /* Precondition */ + vm.assume(_to != address(0)); + // Deploying a new messenger because of an issue of not being able to etch the storage layout of the mock + // contract. So needed to a new one setting the symbolic immutable variable for the crossDomainSender. + // Used 0 address on source token so when the `soureToken` calls it if returns the symbolic `_crossDomainSender` + vm.etch( + address(MESSENGER), address(new MockL2ToL2Messenger(address(0), address(0), 0, _crossDomainSender)).code + ); + + vm.prank(_sender); + /* Action */ + try sourceToken.relayERC20(_from, _to, _amount) { + /* Postconditions */ + assert(_sender == address(MESSENGER) && MESSENGER.crossDomainMessageSender() == address(sourceToken)); + } catch { + assert(_sender != address(MESSENGER) || MESSENGER.crossDomainMessageSender() != address(sourceToken)); + } + } + + /// @custom:property-id 8 + /// @custom:property `sendERC20` with a value of zero does not modify accounting + function test_proveSendERC20ZeroCall() public { + /* Preconditions */ + // 0x4200000000000000000000000000000000000024 + address _from = address(376793390874373408599387495934666716005045108772); + // 0x7Fa9385Be102aC3eac297483DD6233d62B3e1497 + address _to = address(728815563385977040452943777879061427756277306519); + uint256 _chainId = 0; + + console.log("from : ", _from); + console.log("to : ", _to); + + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); + uint256 _toBalanceBefore = sourceToken.balanceOf(_to); + + vm.startPrank(_from); + /* Action */ + sourceToken.sendERC20(_to, ZERO_AMOUNT, _chainId); + + /* Postcondition */ + assert(sourceToken.totalSupply() == _totalSupplyBefore); + assert(sourceToken.balanceOf(_from) == _fromBalanceBefore); + assert(sourceToken.balanceOf(_to) == _toBalanceBefore); + } + + /// @custom:property-id 9 + /// @custom:property `relayERC20` with a value of zero does not modify accounting + function test_proveRelayERC20ZeroCall() public { + /* Preconditions */ + address _from = address(0); + address _to = address(1); + + uint256 _totalSupplyBefore = sourceToken.totalSupply(); + uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); + uint256 _toBalanceBefore = sourceToken.balanceOf(_to); + + vm.prank(address(MESSENGER)); + /* Action */ + sourceToken.relayERC20(_from, _to, ZERO_AMOUNT); + + /* Postconditions */ + assert(sourceToken.totalSupply() == _totalSupplyBefore); + assert(sourceToken.balanceOf(_from) == _fromBalanceBefore); + assert(sourceToken.balanceOf(_to) == _toBalanceBefore); + } +} diff --git a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol index ca73d5586123..e805b26c0aa3 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol @@ -38,8 +38,6 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { // Custom cross domain sender assert(MESSENGER.crossDomainMessageSender() == address(0)); - - assert(block.chainid >= 0); } /// @custom:property-id 6 @@ -59,8 +57,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(_to != address(0)); vm.assume(_from != address(0)); - notBuiltinAddress(_from); - notBuiltinAddress(_to); + vm.assume(notBuiltinAddress(_from)); + vm.assume(notBuiltinAddress(_to)); // Can't deal to unsupported cheatcode vm.prank(Predeploys.L2_STANDARD_BRIDGE); @@ -87,6 +85,11 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { ) public { + setUpInlined(); + + vm.assume(notBuiltinAddress(_from)); + vm.assume(notBuiltinAddress(_to)); + /* Precondition */ vm.assume(_to != address(0)); // Deploying a new messenger because of an issue of not being able to etch the storage layout of the mock @@ -109,12 +112,14 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /// @custom:property-id 8 /// @custom:property `sendERC20` with a value of zero does not modify accounting function prove_sendERC20ZeroCall(address _from, address _to, uint256 _chainId) public { + setUpInlined(); + /* Preconditions */ vm.assume(_to != address(0)); vm.assume(_to != address(Predeploys.CROSS_L2_INBOX) && _to != address(MESSENGER)); - notBuiltinAddress(_from); - notBuiltinAddress(_to); + vm.assume(notBuiltinAddress(_from)); + vm.assume(notBuiltinAddress(_to)); uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); @@ -133,12 +138,16 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /// @custom:property-id 9 /// @custom:property `relayERC20` with a value of zero does not modify accounting function prove_relayERC20ZeroCall(address _from, address _to) public { - uint256 _totalSupplyBefore = sourceToken.totalSupply(); + setUpInlined(); + /* Preconditions */ + vm.assume(_to != address(0)); + + uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); uint256 _toBalanceBefore = sourceToken.balanceOf(_to); - vm.prank(address(MESSENGER)); + vm.prank(address(MESSENGER)); /* Action */ sourceToken.relayERC20(_from, _to, ZERO_AMOUNT); @@ -158,7 +167,13 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { ) public { + setUpInlined(); + /* Preconditions */ + vm.assume(notBuiltinAddress(_sender)); + vm.assume(notBuiltinAddress(_to)); + + vm.assume(_sender != address(0)); vm.assume(_to != address(0)); vm.prank(Predeploys.L2_STANDARD_BRIDGE); @@ -180,9 +195,13 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /// @custom:property `relayERC20` increases the token's totalSupply in the destination chain exactly by the input /// amount function prove_relayERC20IncreasesTotalSupply(address _from, address _to, uint256 _amount) public { - vm.assume(_to != address(0)); + setUpInlined(); /* Preconditions */ + vm.assume(_to != address(0)); + vm.assume(notBuiltinAddress(_from)); + vm.assume(notBuiltinAddress(_to)); + uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _toBalanceBefore = sourceToken.balanceOf(_to); @@ -198,7 +217,12 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /// @custom:property-id 12 /// @custom:property Increases the total supply on the amount minted by the bridge function prove_mint(address _from, uint256 _amount) public { + setUpInlined(); + /* Preconditions */ + vm.assume(_from != address(0)); + vm.assume(notBuiltinAddress(_from)); + uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _balanceBefore = sourceToken.balanceOf(_from); @@ -214,7 +238,12 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /// @custom:property-id 13 /// @custom:property Supertoken total supply only decreases on the amount burned by the bridge function prove_burn(address _from, uint256 _amount) public { + setUpInlined(); + /* Preconditions */ + vm.assume(_from != address(0)); + vm.assume(notBuiltinAddress(_from)); + vm.prank(Predeploys.L2_STANDARD_BRIDGE); sourceToken.mint(_from, _amount); @@ -232,7 +261,9 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /// @custom:property-id 14 /// @custom:property Supertoken total supply starts at zero - function prove_totalSupplyStartsAtZero() public view { + function prove_totalSupplyStartsAtZero() public { + setUpInlined(); + /* Postconditions */ assert(sourceToken.totalSupply() == 0); } @@ -244,6 +275,11 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /// @custom:property `sendERC20` decreases total supply in source chain and increases it in destination chain /// exactly by the input amount function prove_crossChainMintAndBurn(address _from, address _to, uint256 _amount, uint256 _chainId) public { + setUpInlined(); + + vm.assume(notBuiltinAddress(_from)); + vm.assume(notBuiltinAddress(_to)); + /* Preconditions */ vm.assume(_to != address(0)); vm.assume(_from != address(0)); From e40c1c1327e36461cef04e157555c43c34a8c0e0 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Tue, 3 Sep 2024 15:12:19 -0300 Subject: [PATCH 27/56] refactor: mock messenger storage layout wip due failing tests --- .../supererc20-state-diff/StateDiff.json | 4 +- .../halmos/OptimismSuperchainERC20.t.sol | 3 +- .../kontrol/FoundryDebugSymbolic.t.sol | 62 +++++++++-------- .../test/properties/kontrol/KontrolBase.sol | 5 +- .../kontrol/OptimismSuperchainERC20.k.sol | 28 +++++--- .../kontrol/deployments/InitialStateCode.sol | 2 +- .../kontrol/helpers/MockL2ToL2Messenger.sol | 67 +++++++++++++++++++ 7 files changed, 124 insertions(+), 47 deletions(-) create mode 100644 packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol diff --git a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json index f1dba0541bbf..27e9fa3c0c13 100644 --- a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json +++ b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json @@ -503,8 +503,8 @@ "chainId": 31337, "forkId": 0 }, - "data": "0x610100604052348015610010575f80fd5b5060405161070538038061070583398101604081905261002f9161006a565b6001600160a01b0393841660805291831660a05260c0521660e0526100b4565b80516001600160a01b0381168114610065575f80fd5b919050565b5f805f806080858703121561007d575f80fd5b6100868561004f565b93506100946020860161004f565b9250604085015191506100a96060860161004f565b905092959194509250565b60805160a05160c05160e0516106036101025f395f6102ab01525f818160a901526102cf01525f818161025d0152818161028601526102fa01525f81816101fb015261022401526106035ff3fe608060405260043610610058575f3560e01c80632ea02369116100415780632ea023691461009857806338ffde18146100cb5780637056f41f14610104575f80fd5b80631ecd26f21461005c5780632479446214610071575b5f80fd5b61006f61006a366004610484565b610117565b005b34801561007c575f80fd5b506100856101d2565b6040519081526020015b60405180910390f35b3480156100a3575f80fd5b506100857f000000000000000000000000000000000000000000000000000000000000000081565b3480156100d6575f80fd5b506100df6101e3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008f565b61006f610112366004610500565b6102cd565b5f808473ffffffffffffffffffffffffffffffffffffffff16348585604051610141929190610556565b5f6040518083038185875af1925050503d805f811461017b576040519150601f19603f3d011682016040523d82523d5f602084013e610180565b606091505b5091509150816101c757806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101be9190610565565b60405180910390fd5b505050505050505050565b5f6101de4660016105b8565b905090565b5f73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361024657507f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036102a857507f000000000000000000000000000000000000000000000000000000000000000090565b507f000000000000000000000000000000000000000000000000000000000000000090565b7f000000000000000000000000000000000000000000000000000000000000000084036103e6575f6103557f00000000000000000000000000000000000000000000000000000000000000005f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506103ec92505050565b9050806103e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016101be565b505b50505050565b5f6103f9845a8585610401565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461043a575f80fd5b919050565b5f8083601f84011261044f575f80fd5b50813567ffffffffffffffff811115610466575f80fd5b60208301915083602082850101111561047d575f80fd5b9250929050565b5f805f805f805f60c0888a03121561049a575f80fd5b8735965060208801359550604088013594506104b860608901610417565b93506104c660808901610417565b925060a088013567ffffffffffffffff8111156104e1575f80fd5b6104ed8a828b0161043f565b989b979a50959850939692959293505050565b5f805f8060608587031215610513575f80fd5b8435935061052360208601610417565b9250604085013567ffffffffffffffff81111561053e575f80fd5b61054a8782880161043f565b95989497509550505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b808201808211156105f0577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9291505056fea164736f6c6343000819000a0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000", - "deployedCode": "0x608060405260043610610058575f3560e01c80632ea02369116100415780632ea023691461009857806338ffde18146100cb5780637056f41f14610104575f80fd5b80631ecd26f21461005c5780632479446214610071575b5f80fd5b61006f61006a366004610484565b610117565b005b34801561007c575f80fd5b506100856101d2565b6040519081526020015b60405180910390f35b3480156100a3575f80fd5b506100857f000000000000000000000000000000000000000000000000000000000000000281565b3480156100d6575f80fd5b506100df6101e3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008f565b61006f610112366004610500565b6102cd565b5f808473ffffffffffffffffffffffffffffffffffffffff16348585604051610141929190610556565b5f6040518083038185875af1925050503d805f811461017b576040519150601f19603f3d011682016040523d82523d5f602084013e610180565b606091505b5091509150816101c757806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101be9190610565565b60405180910390fd5b505050505050505050565b5f6101de4660016105b8565b905090565b5f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361024657507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036102a857507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a90565b507f000000000000000000000000000000000000000000000000000000000000000090565b7f000000000000000000000000000000000000000000000000000000000000000284036103e6575f6103557f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506103ec92505050565b9050806103e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016101be565b505b50505050565b5f6103f9845a8585610401565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461043a575f80fd5b919050565b5f8083601f84011261044f575f80fd5b50813567ffffffffffffffff811115610466575f80fd5b60208301915083602082850101111561047d575f80fd5b9250929050565b5f805f805f805f60c0888a03121561049a575f80fd5b8735965060208801359550604088013594506104b860608901610417565b93506104c660808901610417565b925060a088013567ffffffffffffffff8111156104e1575f80fd5b6104ed8a828b0161043f565b989b979a50959850939692959293505050565b5f805f8060608587031215610513575f80fd5b8435935061052360208601610417565b9250604085013567ffffffffffffffff81111561053e575f80fd5b61054a8782880161043f565b95989497509550505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b808201808211156105f0577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9291505056fea164736f6c6343000819000a", + "data": "0x610100604052348015610010575f80fd5b5060405161078f38038061078f83398101604081905261002f9161006d565b6001600160a01b039384166080529190921660a05260c09190915260e0526100ad565b80516001600160a01b0381168114610068575f80fd5b919050565b5f805f8060808587031215610080575f80fd5b61008985610052565b935061009760208601610052565b6040860151606090960151949790965092505050565b60805160a05160c05160e05161068e6101015f395f8181609501526101b801525f818160d9015261037801525f818161030f0152818161033801526103a301525f81816102ad01526102d6015261068e5ff3fe60806040526004361061006e575f3560e01c806338ffde181161004c57806338ffde18146100fb5780637056f41f14610134578063722c2a4d14610147578063f230b4c2146101a7575f80fd5b80631ecd26f21461007257806324794462146100875780632ea02369146100c8575b5f80fd5b61008561008036600461052d565b6101da565b005b348015610092575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b3480156100d3575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000081565b348015610106575f80fd5b5061010f610295565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bf565b6100856101423660046105a9565b610376565b348015610152575f80fd5b506100856101613660046105ff565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101b2575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000081565b5f808473ffffffffffffffffffffffffffffffffffffffff1634858560405161020492919061061f565b5f6040518083038185875af1925050503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b50915091508161028a57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610281919061062e565b60405180910390fd5b505050505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036102f857507f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361035a57507f000000000000000000000000000000000000000000000000000000000000000090565b505f5473ffffffffffffffffffffffffffffffffffffffff1690565b7f0000000000000000000000000000000000000000000000000000000000000000840361048f575f6103fe7f00000000000000000000000000000000000000000000000000000000000000005f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061049592505050565b90508061048d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152608401610281565b505b50505050565b5f6104a2845a85856104aa565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104e3575f80fd5b919050565b5f8083601f8401126104f8575f80fd5b50813567ffffffffffffffff81111561050f575f80fd5b602083019150836020828501011115610526575f80fd5b9250929050565b5f805f805f805f60c0888a031215610543575f80fd5b873596506020880135955060408801359450610561606089016104c0565b935061056f608089016104c0565b925060a088013567ffffffffffffffff81111561058a575f80fd5b6105968a828b016104e8565b989b979a50959850939692959293505050565b5f805f80606085870312156105bc575f80fd5b843593506105cc602086016104c0565b9250604085013567ffffffffffffffff8111156105e7575f80fd5b6105f3878288016104e8565b95989497509550505050565b5f6020828403121561060f575f80fd5b610618826104c0565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", + "deployedCode": "0x60806040526004361061006e575f3560e01c806338ffde181161004c57806338ffde18146100fb5780637056f41f14610134578063722c2a4d14610147578063f230b4c2146101a7575f80fd5b80631ecd26f21461007257806324794462146100875780632ea02369146100c8575b5f80fd5b61008561008036600461052d565b6101da565b005b348015610092575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100d3575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000281565b348015610106575f80fd5b5061010f610295565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bf565b6100856101423660046105a9565b610376565b348015610152575f80fd5b506100856101613660046105ff565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101b2575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff1634858560405161020492919061061f565b5f6040518083038185875af1925050503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b50915091508161028a57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610281919061062e565b60405180910390fd5b505050505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b1633036102f857507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a16330361035a57507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a90565b505f5473ffffffffffffffffffffffffffffffffffffffff1690565b7f0000000000000000000000000000000000000000000000000000000000000002840361048f575f6103fe7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061049592505050565b90508061048d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152608401610281565b505b50505050565b5f6104a2845a85856104aa565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104e3575f80fd5b919050565b5f8083601f8401126104f8575f80fd5b50813567ffffffffffffffff81111561050f575f80fd5b602083019150836020828501011115610526575f80fd5b9250929050565b5f805f805f805f60c0888a031215610543575f80fd5b873596506020880135955060408801359450610561606089016104c0565b935061056f608089016104c0565b925060a088013567ffffffffffffffff81111561058a575f80fd5b6105968a828b016104e8565b989b979a50959850939692959293505050565b5f805f80606085870312156105bc575f80fd5b843593506105cc602086016104c0565b9250604085013567ffffffffffffffff8111156105e7575f80fd5b6105f3878288016104e8565b95989497509550505050565b5f6020828403121561060f575f80fd5b610618826104c0565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a", "initialized": true, "kind": "Create", "newBalance": 0, diff --git a/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol b/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol index cdbae879d0ff..37c591f24a63 100644 --- a/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol +++ b/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol @@ -50,6 +50,7 @@ contract SymTest_OptimismSuperchainERC20 is SymTest, HalmosBase { /// @notice Check setup works as expected function check_setup() public { // Source token + assert(remoteToken != address(0)); assert(sourceToken.remoteToken() == remoteToken); assert(eqStrings(sourceToken.name(), name)); assert(eqStrings(sourceToken.symbol(), symbol)); @@ -200,8 +201,6 @@ contract SymTest_OptimismSuperchainERC20 is SymTest, HalmosBase { /// @custom:property `relayERC20` increases the token's totalSupply in the destination chain exactly by the input /// amount function check_relayERC20IncreasesTotalSupply(address _from, address _to, uint256 _amount) public { - vm.assume(_to != address(0)); - /* Preconditions */ uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _toBalanceBefore = sourceToken.balanceOf(_to); diff --git a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol index dd82f69dc6af..e6fd0b5ac8d9 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.25; import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { MockL2ToL2Messenger } from "test/properties/halmos/MockL2ToL2Messenger.sol"; +import { MockL2ToL2Messenger } from "test/properties/kontrol/helpers/MockL2ToL2Messenger.sol"; import { KontrolBase } from "test/properties/kontrol/KontrolBase.sol"; import { InitialState } from "./deployments/InitialState.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; @@ -36,13 +36,14 @@ contract FoundryDebugTests is KontrolBase { ); mockL2ToL2Messenger = - new MockL2ToL2Messenger(address(sourceToken), address(destToken), DESTINATION_CHAIN_ID, address(0)); + new MockL2ToL2Messenger(address(sourceToken), address(destToken), DESTINATION_CHAIN_ID, SOURCE); vm.etch(address(MESSENGER), address(mockL2ToL2Messenger).code); } /// @notice Check setup works as expected function test_proveSetup() public { // Source token + assert(remoteToken != address(0)); assert(sourceToken.remoteToken() == remoteToken); assert(eqStrings(sourceToken.name(), name)); assert(eqStrings(sourceToken.symbol(), symbol)); @@ -65,40 +66,43 @@ contract FoundryDebugTests is KontrolBase { /// @custom:property-id 7 /// @custom:property Calls to relayERC20 always succeed as long as the sender the cross-domain caller are valid - function test_proveRelayERC20OnlyFromL2ToL2Messenger() public { - address _crossDomainSender = address(0); - address _sender = address(0); - address _from = address(645326474426547203313410069153905908525362434350); - address _to = address(728815563385977040452943777879061427756277306519); - uint256 _amount = 0; - - /* Precondition */ - vm.assume(_to != address(0)); - // Deploying a new messenger because of an issue of not being able to etch the storage layout of the mock - // contract. So needed to a new one setting the symbolic immutable variable for the crossDomainSender. - // Used 0 address on source token so when the `soureToken` calls it if returns the symbolic `_crossDomainSender` - vm.etch( - address(MESSENGER), address(new MockL2ToL2Messenger(address(0), address(0), 0, _crossDomainSender)).code - ); - - vm.prank(_sender); - /* Action */ - try sourceToken.relayERC20(_from, _to, _amount) { - /* Postconditions */ - assert(_sender == address(MESSENGER) && MESSENGER.crossDomainMessageSender() == address(sourceToken)); - } catch { - assert(_sender != address(MESSENGER) || MESSENGER.crossDomainMessageSender() != address(sourceToken)); - } - } + // function test_proveRelayERC20OnlyFromL2ToL2Messenger() public { + // address _crossDomainSender = address(0); + // address _sender = address(0); + // address _from = address(645326474426547203313410069153905908525362434350); + // address _to = address(728815563385977040452943777879061427756277306519); + // uint256 _amount = 0; + + // /* Precondition */ + // vm.assume(_to != address(0)); + // // Deploying a new messenger because of an issue of not being able to etch the storage layout of the mock + // // contract. So needed to a new one setting the symbolic immutable variable for the crossDomainSender. + // // Used 0 address on source token so when the `soureToken` calls it if returns the symbolic + // `_crossDomainSender` + // vm.etch( + // address(MESSENGER), address(new MockL2ToL2Messenger(address(0), address(0), 0, _crossDomainSender)).code + // ); + + // vm.prank(_sender); + // /* Action */ + // try sourceToken.relayERC20(_from, _to, _amount) { + // /* Postconditions */ + // assert(_sender == address(MESSENGER) && MESSENGER.crossDomainMessageSender() == address(sourceToken)); + // } catch { + // assert(_sender != address(MESSENGER) || MESSENGER.crossDomainMessageSender() != address(sourceToken)); + // } + // } /// @custom:property-id 8 /// @custom:property `sendERC20` with a value of zero does not modify accounting function test_proveSendERC20ZeroCall() public { /* Preconditions */ // 0x4200000000000000000000000000000000000024 - address _from = address(376793390874373408599387495934666716005045108772); + // address _from = address(376793390874373408599387495934666716005045108772); // // 0x7Fa9385Be102aC3eac297483DD6233d62B3e1497 - address _to = address(728815563385977040452943777879061427756277306519); + // address _to = address(728815563385977040452943777879061427756277306519); // + address _from = address(263400868551549723330807389252719309078400616204); // 0x2e234dAE75c793F67a35089C9D99245e1C58470c + address _to = address(1); uint256 _chainId = 0; console.log("from : ", _from); diff --git a/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol b/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol index 283c4e639113..467b8c225540 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/KontrolBase.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.25; import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; -import { MockL2ToL2Messenger } from "test/properties/halmos/MockL2ToL2Messenger.sol"; +import { MockL2ToL2Messenger } from "test/properties/kontrol/helpers/MockL2ToL2Messenger.sol"; import { KontrolCheats } from "kontrol-cheatcodes/KontrolCheats.sol"; import { RecordStateDiff } from "./helpers/RecordStateDiff.sol"; import { Test } from "forge-std/Test.sol"; @@ -12,6 +12,7 @@ import { Test } from "forge-std/Test.sol"; contract KontrolBase is Test, KontrolCheats, RecordStateDiff { uint256 internal constant CURRENT_CHAIN_ID = 1; uint256 internal constant DESTINATION_CHAIN_ID = 2; + uint256 internal constant SOURCE = 3; uint256 internal constant ZERO_AMOUNT = 0; MockL2ToL2Messenger internal constant MESSENGER = MockL2ToL2Messenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); @@ -51,7 +52,7 @@ contract KontrolBase is Test, KontrolCheats, RecordStateDiff { ); mockL2ToL2Messenger = - new MockL2ToL2Messenger(address(sourceToken), address(destToken), DESTINATION_CHAIN_ID, address(0)); + new MockL2ToL2Messenger(address(sourceToken), address(destToken), DESTINATION_CHAIN_ID, SOURCE); save_address(address(superchainERC20Impl), "superchainERC20Impl"); save_address(address(sourceToken), "sourceToken"); diff --git a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol index e805b26c0aa3..1a1a83ec3c22 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.25; import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { MockL2ToL2Messenger } from "test/properties/halmos/MockL2ToL2Messenger.sol"; +import { MockL2ToL2Messenger } from "test/properties/kontrol/helpers/MockL2ToL2Messenger.sol"; import { KontrolBase } from "test/properties/kontrol/KontrolBase.sol"; import { InitialState } from "./deployments/InitialState.sol"; @@ -36,8 +36,12 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.prank(address(destToken)); assert(MESSENGER.crossDomainMessageSender() == address(destToken)); - // Custom cross domain sender + // Messenger + assert(MESSENGER.SOURCE() == SOURCE); assert(MESSENGER.crossDomainMessageSender() == address(0)); + // Check the setter works properly + MESSENGER.forTest_setCustomCrossDomainSender(address(420)); + assert(MESSENGER.crossDomainMessageSender() == address(420)); } /// @custom:property-id 6 @@ -87,17 +91,13 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { { setUpInlined(); + /* Preconditions */ + vm.assume(_to != address(0)); vm.assume(notBuiltinAddress(_from)); vm.assume(notBuiltinAddress(_to)); + vm.assume(notBuiltinAddress(_sender)); - /* Precondition */ - vm.assume(_to != address(0)); - // Deploying a new messenger because of an issue of not being able to etch the storage layout of the mock - // contract. So needed to a new one setting the symbolic immutable variable for the crossDomainSender. - // Used 0 address on source token so when the `soureToken` calls it if returns the symbolic `_crossDomainSender` - vm.etch( - address(MESSENGER), address(new MockL2ToL2Messenger(address(0), address(0), 0, _crossDomainSender)).code - ); + MESSENGER.forTest_setCustomCrossDomainSender(_crossDomainSender); vm.prank(_sender); /* Action */ @@ -117,6 +117,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /* Preconditions */ vm.assume(_to != address(0)); vm.assume(_to != address(Predeploys.CROSS_L2_INBOX) && _to != address(MESSENGER)); + // TODO + vm.assume(_from != address(0)); vm.assume(notBuiltinAddress(_from)); vm.assume(notBuiltinAddress(_to)); @@ -142,6 +144,10 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /* Preconditions */ vm.assume(_to != address(0)); + vm.assume(notBuiltinAddress(_from)); + vm.assume(notBuiltinAddress(_to)); + // TODO + vm.assume(_to != address(1)); uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); @@ -274,7 +280,7 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /// @custom:property-id 23 /// @custom:property `sendERC20` decreases total supply in source chain and increases it in destination chain /// exactly by the input amount - function prove_crossChainMintAndBurn(address _from, address _to, uint256 _amount, uint256 _chainId) public { + function prove_crossChainSendERC20(address _from, address _to, uint256 _amount, uint256 _chainId) public { setUpInlined(); vm.assume(notBuiltinAddress(_from)); diff --git a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol index e4c80facdabf..87eb904359d4 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol @@ -11,5 +11,5 @@ contract InitialStateCode { bytes internal constant destTokenCode = hex"6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a"; bytes internal constant mockL2ToL2MessengerCode = - hex"608060405260043610610058575f3560e01c80632ea02369116100415780632ea023691461009857806338ffde18146100cb5780637056f41f14610104575f80fd5b80631ecd26f21461005c5780632479446214610071575b5f80fd5b61006f61006a366004610484565b610117565b005b34801561007c575f80fd5b506100856101d2565b6040519081526020015b60405180910390f35b3480156100a3575f80fd5b506100857f000000000000000000000000000000000000000000000000000000000000000281565b3480156100d6575f80fd5b506100df6101e3565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161008f565b61006f610112366004610500565b6102cd565b5f808473ffffffffffffffffffffffffffffffffffffffff16348585604051610141929190610556565b5f6040518083038185875af1925050503d805f811461017b576040519150601f19603f3d011682016040523d82523d5f602084013e610180565b606091505b5091509150816101c757806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101be9190610565565b60405180910390fd5b505050505050505050565b5f6101de4660016105b8565b905090565b5f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361024657507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036102a857507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a90565b507f000000000000000000000000000000000000000000000000000000000000000090565b7f000000000000000000000000000000000000000000000000000000000000000284036103e6575f6103557f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506103ec92505050565b9050806103e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016101be565b505b50505050565b5f6103f9845a8585610401565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461043a575f80fd5b919050565b5f8083601f84011261044f575f80fd5b50813567ffffffffffffffff811115610466575f80fd5b60208301915083602082850101111561047d575f80fd5b9250929050565b5f805f805f805f60c0888a03121561049a575f80fd5b8735965060208801359550604088013594506104b860608901610417565b93506104c660808901610417565b925060a088013567ffffffffffffffff8111156104e1575f80fd5b6104ed8a828b0161043f565b989b979a50959850939692959293505050565b5f805f8060608587031215610513575f80fd5b8435935061052360208601610417565b9250604085013567ffffffffffffffff81111561053e575f80fd5b61054a8782880161043f565b95989497509550505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b808201808211156105f0577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9291505056fea164736f6c6343000819000a"; + hex"60806040526004361061006e575f3560e01c806338ffde181161004c57806338ffde18146100fb5780637056f41f14610134578063722c2a4d14610147578063f230b4c2146101a7575f80fd5b80631ecd26f21461007257806324794462146100875780632ea02369146100c8575b5f80fd5b61008561008036600461052d565b6101da565b005b348015610092575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100d3575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000281565b348015610106575f80fd5b5061010f610295565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bf565b6100856101423660046105a9565b610376565b348015610152575f80fd5b506100856101613660046105ff565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101b2575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff1634858560405161020492919061061f565b5f6040518083038185875af1925050503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b50915091508161028a57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610281919061062e565b60405180910390fd5b505050505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b1633036102f857507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a16330361035a57507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a90565b505f5473ffffffffffffffffffffffffffffffffffffffff1690565b7f0000000000000000000000000000000000000000000000000000000000000002840361048f575f6103fe7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061049592505050565b90508061048d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152608401610281565b505b50505050565b5f6104a2845a85856104aa565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104e3575f80fd5b919050565b5f8083601f8401126104f8575f80fd5b50813567ffffffffffffffff81111561050f575f80fd5b602083019150836020828501011115610526575f80fd5b9250929050565b5f805f805f805f60c0888a031215610543575f80fd5b873596506020880135955060408801359450610561606089016104c0565b935061056f608089016104c0565b925060a088013567ffffffffffffffff81111561058a575f80fd5b6105968a828b016104e8565b989b979a50959850939692959293505050565b5f805f80606085870312156105bc575f80fd5b843593506105cc602086016104c0565b9250604085013567ffffffffffffffff8111156105e7575f80fd5b6105f3878288016104e8565b95989497509550505050565b5f6020828403121561060f575f80fd5b610618826104c0565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a"; } diff --git a/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol b/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol new file mode 100644 index 000000000000..78898c42ea31 --- /dev/null +++ b/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.25; + +import "src/L2/L2ToL2CrossDomainMessenger.sol"; +import { SafeCall } from "src/libraries/SafeCall.sol"; + +// TODO: Try to merge to a single mocked contract used by fuzzing and symbolic invariant tests - only if possible +// and is a low priorty +contract MockL2ToL2Messenger is IL2ToL2CrossDomainMessenger { + address internal immutable SOURCE_TOKEN; + address internal immutable DESTINATION_TOKEN; + uint256 public immutable DESTINATION_CHAIN_ID; + uint256 public immutable SOURCE; + + // Custom cross domain sender to be used when neither the source nor destination token are the callers + address internal customCrossDomainSender; + + constructor(address _sourceToken, address _destinationToken, uint256 _destinationChainId, uint256 _source) { + SOURCE_TOKEN = _sourceToken; + DESTINATION_TOKEN = _destinationToken; + DESTINATION_CHAIN_ID = _destinationChainId; + SOURCE = _source; + } + + // Mock the sendMessage function to execute the message call and simulate an atomic environmanet if the destination + // chain id matches the defined one + function sendMessage(uint256 _destination, address, bytes calldata _message) external payable { + // Mocking the environment to allow atomicity by executing the message call + if (_destination == DESTINATION_CHAIN_ID) { + (bool _success) = SafeCall.call(DESTINATION_TOKEN, 0, _message); + if (!_success) revert("MockL2ToL2Messenger: sendMessage failed"); + } + } + + // Mock the relay message function to just call the target address with the input message + function relayMessage( + uint256, + uint256, + uint256, + address, + address _target, + bytes calldata _message + ) + external + payable + { + (bool succ, bytes memory ret) = _target.call{ value: msg.value }(_message); + if (!succ) revert(string(ret)); + } + + function crossDomainMessageSource() external view returns (uint256 _source) { + _source = SOURCE; + } + + // Mock this function so it just always returns the expected if called by the supertoken to pass throgh the + // `address(this)` checks, or otherwise defaults to the custom cross domain sender + function crossDomainMessageSender() external view returns (address _sender) { + if (msg.sender == SOURCE_TOKEN) _sender = SOURCE_TOKEN; + else if (msg.sender == DESTINATION_TOKEN) _sender = DESTINATION_TOKEN; + else _sender = customCrossDomainSender; + } + + /// Setter function for the customCrossDomainSender + function forTest_setCustomCrossDomainSender(address _customCrossDomainSender) external { + customCrossDomainSender = _customCrossDomainSender; + } +} From 342f33fc046c21ae8c55571a74f183d1ef3a07f4 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Wed, 4 Sep 2024 13:41:48 -0300 Subject: [PATCH 28/56] chore: replicate new scenarios on foundry debug --- .../kontrol/FoundryDebugSymbolic.t.sol | 88 +++++++++++-------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol index e6fd0b5ac8d9..22bf6c9e9c0e 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol @@ -66,48 +66,48 @@ contract FoundryDebugTests is KontrolBase { /// @custom:property-id 7 /// @custom:property Calls to relayERC20 always succeed as long as the sender the cross-domain caller are valid - // function test_proveRelayERC20OnlyFromL2ToL2Messenger() public { - // address _crossDomainSender = address(0); - // address _sender = address(0); - // address _from = address(645326474426547203313410069153905908525362434350); - // address _to = address(728815563385977040452943777879061427756277306519); - // uint256 _amount = 0; - - // /* Precondition */ - // vm.assume(_to != address(0)); - // // Deploying a new messenger because of an issue of not being able to etch the storage layout of the mock - // // contract. So needed to a new one setting the symbolic immutable variable for the crossDomainSender. - // // Used 0 address on source token so when the `soureToken` calls it if returns the symbolic - // `_crossDomainSender` - // vm.etch( - // address(MESSENGER), address(new MockL2ToL2Messenger(address(0), address(0), 0, _crossDomainSender)).code - // ); - - // vm.prank(_sender); - // /* Action */ - // try sourceToken.relayERC20(_from, _to, _amount) { - // /* Postconditions */ - // assert(_sender == address(MESSENGER) && MESSENGER.crossDomainMessageSender() == address(sourceToken)); - // } catch { - // assert(_sender != address(MESSENGER) || MESSENGER.crossDomainMessageSender() != address(sourceToken)); - // } - // } + function test_proveRelayERC20OnlyFromL2ToL2Messenger() public { + address _crossDomainSender = address(263400868551549723330807389252719309078400616202); + address _sender = address(376793390874373408599387495934666716005045108771); + address _from = address(645326474426547203313410069153905908525362434350); + address _to = address(728815563385977040452943777879061427756277306519); + uint256 _amount = 0; + + /* Precondition */ + MESSENGER.forTest_setCustomCrossDomainSender(_crossDomainSender); + + vm.prank(_sender); + /* Action */ + try sourceToken.relayERC20(_from, _to, _amount) { + /* Postconditions */ + console.log("here 1"); + console.log("sender", _sender); + console.log("crossDomainSender", MESSENGER.crossDomainMessageSender()); + console.log("sourceToken", address(sourceToken)); + assert(_sender == address(MESSENGER) && MESSENGER.crossDomainMessageSender() == address(sourceToken)); + } catch { + console.log("here 2"); + assert(_sender != address(MESSENGER) || MESSENGER.crossDomainMessageSender() != address(sourceToken)); + } + } + // NUMBER_CELL = 16777217 + // VV2__from_114b9705 = 645326474426547203313410069153905908525362434350 + // CALLER_ID = 645326474426547203313410069153905908525362434350 + // TIMESTAMP_CELL = 1073741825 + // ORIGIN_ID = 645326474426547203313410069153905908525362434350 + // VV3__to_114b9705 = 728815563385977040452943777879061427756277306519 + // VV0__crossDomainSender_114b9705 = 263400868551549723330807389252719309078400616202 + // VV4__amount_114b9705 = 0 + // VV1__sender_114b9705 = 376793390874373408599387495934666716005045108771 /// @custom:property-id 8 /// @custom:property `sendERC20` with a value of zero does not modify accounting function test_proveSendERC20ZeroCall() public { /* Preconditions */ - // 0x4200000000000000000000000000000000000024 - // address _from = address(376793390874373408599387495934666716005045108772); // - // 0x7Fa9385Be102aC3eac297483DD6233d62B3e1497 - // address _to = address(728815563385977040452943777879061427756277306519); // - address _from = address(263400868551549723330807389252719309078400616204); // 0x2e234dAE75c793F67a35089C9D99245e1C58470c - address _to = address(1); + address _from = address(376793390874373408599387495934666716005045108772); // 0x4200000000000000000000000000000000000024 + address _to = address(728815563385977040452943777879061427756277306519); // 0x7Fa9385Be102aC3eac297483DD6233d62B3e1497 uint256 _chainId = 0; - console.log("from : ", _from); - console.log("to : ", _to); - uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); uint256 _toBalanceBefore = sourceToken.balanceOf(_to); @@ -122,12 +122,20 @@ contract FoundryDebugTests is KontrolBase { assert(sourceToken.balanceOf(_to) == _toBalanceBefore); } + // VV2__chainId_114b9705 = 0 + // VV0__from_114b9705 = 376793390874373408599387495934666716005045108772 + // NUMBER_CELL = 16777217 + // VV1__to_114b9705 = 728815563385977040452943777879061427756277306519 + // CALLER_ID = 645326474426547203313410069153905908525362434350 + // TIMESTAMP_CELL = 1073741825 + // ORIGIN_ID = 645326474426547203313410069153905908525362434350 + /// @custom:property-id 9 /// @custom:property `relayERC20` with a value of zero does not modify accounting function test_proveRelayERC20ZeroCall() public { /* Preconditions */ - address _from = address(0); - address _to = address(1); + address _from = address(728815563385977040452943777879061427756277306519); + address _to = address(728815563385977040452943777879061427756277306519); uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); @@ -142,4 +150,10 @@ contract FoundryDebugTests is KontrolBase { assert(sourceToken.balanceOf(_from) == _fromBalanceBefore); assert(sourceToken.balanceOf(_to) == _toBalanceBefore); } + // NUMBER_CELL = 16777217 + // VV1__to_114b9705 = 728815563385977040452943777879061427756277306519 + // CALLER_ID = 645326474426547203313410069153905908525362434350 + // TIMESTAMP_CELL = 1073741825 + // ORIGIN_ID = 645326474426547203313410069153905908525362434350 + // VV0__from_114b9705 = 728815563385977040452943777879061427756277306519 } From 79158b84a5ac993665f0dbd0f8e6ef1782c551b5 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Thu, 5 Sep 2024 01:36:29 -0300 Subject: [PATCH 29/56] refactor: cross domain sender logic on mock messenger --- .../supererc20-state-diff/StateDiff.json | 4 +- .../kontrol/FoundryDebugSymbolic.t.sol | 83 +++++++++++++++---- .../kontrol/OptimismSuperchainERC20.k.sol | 12 ++- .../kontrol/deployments/InitialStateCode.sol | 2 +- .../kontrol/helpers/MockL2ToL2Messenger.sol | 19 +++-- 5 files changed, 95 insertions(+), 25 deletions(-) diff --git a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json index 27e9fa3c0c13..bf720166938b 100644 --- a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json +++ b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json @@ -503,8 +503,8 @@ "chainId": 31337, "forkId": 0 }, - "data": "0x610100604052348015610010575f80fd5b5060405161078f38038061078f83398101604081905261002f9161006d565b6001600160a01b039384166080529190921660a05260c09190915260e0526100ad565b80516001600160a01b0381168114610068575f80fd5b919050565b5f805f8060808587031215610080575f80fd5b61008985610052565b935061009760208601610052565b6040860151606090960151949790965092505050565b60805160a05160c05160e05161068e6101015f395f8181609501526101b801525f818160d9015261037801525f818161030f0152818161033801526103a301525f81816102ad01526102d6015261068e5ff3fe60806040526004361061006e575f3560e01c806338ffde181161004c57806338ffde18146100fb5780637056f41f14610134578063722c2a4d14610147578063f230b4c2146101a7575f80fd5b80631ecd26f21461007257806324794462146100875780632ea02369146100c8575b5f80fd5b61008561008036600461052d565b6101da565b005b348015610092575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b3480156100d3575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000081565b348015610106575f80fd5b5061010f610295565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bf565b6100856101423660046105a9565b610376565b348015610152575f80fd5b506100856101613660046105ff565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101b2575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000081565b5f808473ffffffffffffffffffffffffffffffffffffffff1634858560405161020492919061061f565b5f6040518083038185875af1925050503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b50915091508161028a57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610281919061062e565b60405180910390fd5b505050505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036102f857507f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361035a57507f000000000000000000000000000000000000000000000000000000000000000090565b505f5473ffffffffffffffffffffffffffffffffffffffff1690565b7f0000000000000000000000000000000000000000000000000000000000000000840361048f575f6103fe7f00000000000000000000000000000000000000000000000000000000000000005f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061049592505050565b90508061048d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152608401610281565b505b50505050565b5f6104a2845a85856104aa565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104e3575f80fd5b919050565b5f8083601f8401126104f8575f80fd5b50813567ffffffffffffffff81111561050f575f80fd5b602083019150836020828501011115610526575f80fd5b9250929050565b5f805f805f805f60c0888a031215610543575f80fd5b873596506020880135955060408801359450610561606089016104c0565b935061056f608089016104c0565b925060a088013567ffffffffffffffff81111561058a575f80fd5b6105968a828b016104e8565b989b979a50959850939692959293505050565b5f805f80606085870312156105bc575f80fd5b843593506105cc602086016104c0565b9250604085013567ffffffffffffffff8111156105e7575f80fd5b6105f3878288016104e8565b95989497509550505050565b5f6020828403121561060f575f80fd5b610618826104c0565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", - "deployedCode": "0x60806040526004361061006e575f3560e01c806338ffde181161004c57806338ffde18146100fb5780637056f41f14610134578063722c2a4d14610147578063f230b4c2146101a7575f80fd5b80631ecd26f21461007257806324794462146100875780632ea02369146100c8575b5f80fd5b61008561008036600461052d565b6101da565b005b348015610092575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100d3575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000281565b348015610106575f80fd5b5061010f610295565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bf565b6100856101423660046105a9565b610376565b348015610152575f80fd5b506100856101613660046105ff565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101b2575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff1634858560405161020492919061061f565b5f6040518083038185875af1925050503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b50915091508161028a57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610281919061062e565b60405180910390fd5b505050505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b1633036102f857507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a16330361035a57507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a90565b505f5473ffffffffffffffffffffffffffffffffffffffff1690565b7f0000000000000000000000000000000000000000000000000000000000000002840361048f575f6103fe7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061049592505050565b90508061048d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152608401610281565b505b50505050565b5f6104a2845a85856104aa565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104e3575f80fd5b919050565b5f8083601f8401126104f8575f80fd5b50813567ffffffffffffffff81111561050f575f80fd5b602083019150836020828501011115610526575f80fd5b9250929050565b5f805f805f805f60c0888a031215610543575f80fd5b873596506020880135955060408801359450610561606089016104c0565b935061056f608089016104c0565b925060a088013567ffffffffffffffff81111561058a575f80fd5b6105968a828b016104e8565b989b979a50959850939692959293505050565b5f805f80606085870312156105bc575f80fd5b843593506105cc602086016104c0565b9250604085013567ffffffffffffffff8111156105e7575f80fd5b6105f3878288016104e8565b95989497509550505050565b5f6020828403121561060f575f80fd5b610618826104c0565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a", + "data": "0x610100604052348015610010575f80fd5b5060405161082d38038061082d83398101604081905261002f9161006d565b6001600160a01b039384166080529190921660a05260c09190915260e0526100ad565b80516001600160a01b0381168114610068575f80fd5b919050565b5f805f8060808587031215610080575f80fd5b61008985610052565b935061009760208601610052565b6040860151606090960151949790965092505050565b60805160a05160c05160e05161072c6101015f395f818160a001526101ed01525f818160e4015261041601525f8181610381015281816103aa015261044101525f818161031d0152610346015261072c5ff3fe608060405260043610610079575f3560e01c80637056f41f1161004c5780637056f41f1461013f578063722c2a4d1461015257806391db7f49146101b2578063f230b4c2146101dc575f80fd5b80631ecd26f21461007d57806324794462146100925780632ea02369146100d357806338ffde1814610106575b5f80fd5b61009061008b3660046105cb565b61020f565b005b34801561009d575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b3480156100de575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000081565b348015610111575f80fd5b5061011a6102ca565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ca565b61009061014d366004610647565b610414565b34801561015d575f80fd5b5061009061016c36600461069d565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101bd575f80fd5b5060015473ffffffffffffffffffffffffffffffffffffffff1661011a565b3480156101e7575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000081565b5f808473ffffffffffffffffffffffffffffffffffffffff163485856040516102399291906106bd565b5f6040518083038185875af1925050503d805f8114610273576040519150601f19603f3d011682016040523d82523d5f602084013e610278565b606091505b5091509150816102bf57806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102b691906106cc565b60405180910390fd5b505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff161561030657505f5473ffffffffffffffffffffffffffffffffffffffff166103d1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361036a57507f00000000000000000000000000000000000000000000000000000000000000006103d1565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036103ce57507f00000000000000000000000000000000000000000000000000000000000000006103d1565b505f5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831617905590565b7f0000000000000000000000000000000000000000000000000000000000000000840361052d575f61049c7f00000000000000000000000000000000000000000000000000000000000000005f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061053392505050565b90508061052b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016102b6565b505b50505050565b5f610540845a8585610548565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610581575f80fd5b919050565b5f8083601f840112610596575f80fd5b50813567ffffffffffffffff8111156105ad575f80fd5b6020830191508360208285010111156105c4575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105e1575f80fd5b8735965060208801359550604088013594506105ff6060890161055e565b935061060d6080890161055e565b925060a088013567ffffffffffffffff811115610628575f80fd5b6106348a828b01610586565b989b979a50959850939692959293505050565b5f805f806060858703121561065a575f80fd5b8435935061066a6020860161055e565b9250604085013567ffffffffffffffff811115610685575f80fd5b61069187828801610586565b95989497509550505050565b5f602082840312156106ad575f80fd5b6106b68261055e565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", + "deployedCode": "0x608060405260043610610079575f3560e01c80637056f41f1161004c5780637056f41f1461013f578063722c2a4d1461015257806391db7f49146101b2578063f230b4c2146101dc575f80fd5b80631ecd26f21461007d57806324794462146100925780632ea02369146100d357806338ffde1814610106575b5f80fd5b61009061008b3660046105cb565b61020f565b005b34801561009d575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100de575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000281565b348015610111575f80fd5b5061011a6102ca565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ca565b61009061014d366004610647565b610414565b34801561015d575f80fd5b5061009061016c36600461069d565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101bd575f80fd5b5060015473ffffffffffffffffffffffffffffffffffffffff1661011a565b3480156101e7575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff163485856040516102399291906106bd565b5f6040518083038185875af1925050503d805f8114610273576040519150601f19603f3d011682016040523d82523d5f602084013e610278565b606091505b5091509150816102bf57806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102b691906106cc565b60405180910390fd5b505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff161561030657505f5473ffffffffffffffffffffffffffffffffffffffff166103d1565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361036a57507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b6103d1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036103ce57507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a6103d1565b505f5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831617905590565b7f0000000000000000000000000000000000000000000000000000000000000002840361052d575f61049c7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061053392505050565b90508061052b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016102b6565b505b50505050565b5f610540845a8585610548565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610581575f80fd5b919050565b5f8083601f840112610596575f80fd5b50813567ffffffffffffffff8111156105ad575f80fd5b6020830191508360208285010111156105c4575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105e1575f80fd5b8735965060208801359550604088013594506105ff6060890161055e565b935061060d6080890161055e565b925060a088013567ffffffffffffffff811115610628575f80fd5b6106348a828b01610586565b989b979a50959850939692959293505050565b5f805f806060858703121561065a575f80fd5b8435935061066a6020860161055e565b9250604085013567ffffffffffffffff811115610685575f80fd5b61069187828801610586565b95989497509550505050565b5f602082840312156106ad575f80fd5b6106b68261055e565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a", "initialized": true, "kind": "Create", "newBalance": 0, diff --git a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol index 22bf6c9e9c0e..e43e0bf96178 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol @@ -12,6 +12,8 @@ import "forge-std/Test.sol"; // TODO: File to debug faster with foundry replicating scenarios where the proof failed, needs removal afterwards. contract FoundryDebugTests is KontrolBase { + event CrossDomainMessageSender(address _sender); + function setUp() public { // Deploy the OptimismSuperchainERC20 contract implementation and the proxy to be used superchainERC20Impl = new OptimismSuperchainERC20(); @@ -66,8 +68,15 @@ contract FoundryDebugTests is KontrolBase { /// @custom:property-id 7 /// @custom:property Calls to relayERC20 always succeed as long as the sender the cross-domain caller are valid - function test_proveRelayERC20OnlyFromL2ToL2Messenger() public { - address _crossDomainSender = address(263400868551549723330807389252719309078400616202); + function test_proveRelayERC20OnlyFromL2ToL2Messenger() + // address _crossDomainSender, + // address _sender, + // address _from, + // address _to, + // uint256 _amount + public + { + address _crossDomainSender = address(0); address _sender = address(376793390874373408599387495934666716005045108771); address _from = address(645326474426547203313410069153905908525362434350); address _to = address(728815563385977040452943777879061427756277306519); @@ -76,29 +85,30 @@ contract FoundryDebugTests is KontrolBase { /* Precondition */ MESSENGER.forTest_setCustomCrossDomainSender(_crossDomainSender); + // Expect the cross domain sender to be emitted so after confirming it matches, we can use it for checks + vm.expectEmit(true, true, true, true); + emit CrossDomainMessageSender(_crossDomainSender); + vm.prank(_sender); /* Action */ try sourceToken.relayERC20(_from, _to, _amount) { /* Postconditions */ - console.log("here 1"); - console.log("sender", _sender); - console.log("crossDomainSender", MESSENGER.crossDomainMessageSender()); - console.log("sourceToken", address(sourceToken)); - assert(_sender == address(MESSENGER) && MESSENGER.crossDomainMessageSender() == address(sourceToken)); + assert(_sender == address(MESSENGER) && _crossDomainSender == address(sourceToken)); } catch { - console.log("here 2"); - assert(_sender != address(MESSENGER) || MESSENGER.crossDomainMessageSender() != address(sourceToken)); + // Emit to bypass the check when the call fails + emit CrossDomainMessageSender(_crossDomainSender); + assert(_sender != address(MESSENGER) || _crossDomainSender != address(sourceToken)); } } - // NUMBER_CELL = 16777217 - // VV2__from_114b9705 = 645326474426547203313410069153905908525362434350 - // CALLER_ID = 645326474426547203313410069153905908525362434350 - // TIMESTAMP_CELL = 1073741825 // ORIGIN_ID = 645326474426547203313410069153905908525362434350 - // VV3__to_114b9705 = 728815563385977040452943777879061427756277306519 - // VV0__crossDomainSender_114b9705 = 263400868551549723330807389252719309078400616202 // VV4__amount_114b9705 = 0 // VV1__sender_114b9705 = 376793390874373408599387495934666716005045108771 + // CALLER_ID = 645326474426547203313410069153905908525362434350 + // NUMBER_CELL = 16777217 + // VV2__from_114b9705 = 645326474426547203313410069153905908525362434350 + // VV0__crossDomainSender_114b9705 = 0 + // VV3__to_114b9705 = 728815563385977040452943777879061427756277306519 + // TIMESTAMP_CELL = 1073741825 /// @custom:property-id 8 /// @custom:property `sendERC20` with a value of zero does not modify accounting @@ -156,4 +166,47 @@ contract FoundryDebugTests is KontrolBase { // TIMESTAMP_CELL = 1073741825 // ORIGIN_ID = 645326474426547203313410069153905908525362434350 // VV0__from_114b9705 = 728815563385977040452943777879061427756277306519 + + function test_proveCrossChainSendERC20() public { + /* Preconditions */ + address _from = address(376793390874373408599387495934666716005045108752); + address _to = address(728815563385977040452943777879061427756277306519); + uint256 _amount = 0; + uint256 _chainId = 2; + // Mint the amount to send + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + sourceToken.mint(_from, _amount); + + uint256 fromBalanceBefore = sourceToken.balanceOf(_from); + uint256 toBalanceBefore = destToken.balanceOf(_to); + uint256 sourceTotalSupplyBefore = sourceToken.totalSupply(); + uint256 destTotalSupplyBefore = destToken.totalSupply(); + + vm.prank(_from); + /* Action */ + try sourceToken.sendERC20(_to, _amount, _chainId) { + /* Postconditions */ + // Source + assert(sourceToken.balanceOf(_from) == fromBalanceBefore - _amount); + assert(sourceToken.totalSupply() == sourceTotalSupplyBefore - _amount); + + // Destination + if (_chainId == DESTINATION_CHAIN_ID) { + // If the destination chain matches the one of the dest token, check that the amount was minted + assert(destToken.balanceOf(_to) == toBalanceBefore + _amount); + assert(destToken.totalSupply() == destTotalSupplyBefore + _amount); + } else { + // Otherwise the balances should remain the same + assert(destToken.balanceOf(_to) == toBalanceBefore); + assert(destToken.totalSupply() == destTotalSupplyBefore); + } + } catch { + // Shouldn't fail + assert(false); + } + } + // VV1__to_114b9705 = 728815563385977040452943777879061427756277306519 + // VV0__from_114b9705 = 376793390874373408599387495934666716005045108752 + // VV2__amount_114b9705 = 0 + // VV3__chainId_114b9705 = 2 } diff --git a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol index 1a1a83ec3c22..30a9d5540411 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol @@ -8,6 +8,8 @@ import { KontrolBase } from "test/properties/kontrol/KontrolBase.sol"; import { InitialState } from "./deployments/InitialState.sol"; contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { + event CrossDomainMessageSender(address _sender); + function setUpInlined() public { superchainERC20Impl = OptimismSuperchainERC20(superchainERC20ImplAddress); sourceToken = OptimismSuperchainERC20(sourceTokenAddress); @@ -99,13 +101,19 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { MESSENGER.forTest_setCustomCrossDomainSender(_crossDomainSender); + // Expect the cross domain sender to be emitted so after confirming it matches, we can use it for checks + vm.expectEmit(true, true, true, true); + emit CrossDomainMessageSender(_crossDomainSender); + vm.prank(_sender); /* Action */ try sourceToken.relayERC20(_from, _to, _amount) { /* Postconditions */ - assert(_sender == address(MESSENGER) && MESSENGER.crossDomainMessageSender() == address(sourceToken)); + assert(_sender == address(MESSENGER) && _crossDomainSender == address(sourceToken)); } catch { - assert(_sender != address(MESSENGER) || MESSENGER.crossDomainMessageSender() != address(sourceToken)); + // Emit to bypass the check when the call fails + emit CrossDomainMessageSender(_crossDomainSender); + assert(_sender != address(MESSENGER) || _crossDomainSender != address(sourceToken)); } } diff --git a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol index 87eb904359d4..cb5574e45706 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol @@ -11,5 +11,5 @@ contract InitialStateCode { bytes internal constant destTokenCode = hex"6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a"; bytes internal constant mockL2ToL2MessengerCode = - hex"60806040526004361061006e575f3560e01c806338ffde181161004c57806338ffde18146100fb5780637056f41f14610134578063722c2a4d14610147578063f230b4c2146101a7575f80fd5b80631ecd26f21461007257806324794462146100875780632ea02369146100c8575b5f80fd5b61008561008036600461052d565b6101da565b005b348015610092575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100d3575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000281565b348015610106575f80fd5b5061010f610295565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bf565b6100856101423660046105a9565b610376565b348015610152575f80fd5b506100856101613660046105ff565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101b2575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff1634858560405161020492919061061f565b5f6040518083038185875af1925050503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b50915091508161028a57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610281919061062e565b60405180910390fd5b505050505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b1633036102f857507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a16330361035a57507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a90565b505f5473ffffffffffffffffffffffffffffffffffffffff1690565b7f0000000000000000000000000000000000000000000000000000000000000002840361048f575f6103fe7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061049592505050565b90508061048d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152608401610281565b505b50505050565b5f6104a2845a85856104aa565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104e3575f80fd5b919050565b5f8083601f8401126104f8575f80fd5b50813567ffffffffffffffff81111561050f575f80fd5b602083019150836020828501011115610526575f80fd5b9250929050565b5f805f805f805f60c0888a031215610543575f80fd5b873596506020880135955060408801359450610561606089016104c0565b935061056f608089016104c0565b925060a088013567ffffffffffffffff81111561058a575f80fd5b6105968a828b016104e8565b989b979a50959850939692959293505050565b5f805f80606085870312156105bc575f80fd5b843593506105cc602086016104c0565b9250604085013567ffffffffffffffff8111156105e7575f80fd5b6105f3878288016104e8565b95989497509550505050565b5f6020828403121561060f575f80fd5b610618826104c0565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a"; + hex"608060405260043610610079575f3560e01c80637056f41f1161004c5780637056f41f1461013f578063722c2a4d1461015257806391db7f49146101b2578063f230b4c2146101dc575f80fd5b80631ecd26f21461007d57806324794462146100925780632ea02369146100d357806338ffde1814610106575b5f80fd5b61009061008b3660046105cb565b61020f565b005b34801561009d575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100de575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000281565b348015610111575f80fd5b5061011a6102ca565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ca565b61009061014d366004610647565b610414565b34801561015d575f80fd5b5061009061016c36600461069d565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101bd575f80fd5b5060015473ffffffffffffffffffffffffffffffffffffffff1661011a565b3480156101e7575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff163485856040516102399291906106bd565b5f6040518083038185875af1925050503d805f8114610273576040519150601f19603f3d011682016040523d82523d5f602084013e610278565b606091505b5091509150816102bf57806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102b691906106cc565b60405180910390fd5b505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff161561030657505f5473ffffffffffffffffffffffffffffffffffffffff166103d1565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361036a57507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b6103d1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036103ce57507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a6103d1565b505f5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831617905590565b7f0000000000000000000000000000000000000000000000000000000000000002840361052d575f61049c7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061053392505050565b90508061052b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016102b6565b505b50505050565b5f610540845a8585610548565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610581575f80fd5b919050565b5f8083601f840112610596575f80fd5b50813567ffffffffffffffff8111156105ad575f80fd5b6020830191508360208285010111156105c4575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105e1575f80fd5b8735965060208801359550604088013594506105ff6060890161055e565b935061060d6080890161055e565b925060a088013567ffffffffffffffff811115610628575f80fd5b6106348a828b01610586565b989b979a50959850939692959293505050565b5f805f806060858703121561065a575f80fd5b8435935061066a6020860161055e565b9250604085013567ffffffffffffffff811115610685575f80fd5b61069187828801610586565b95989497509550505050565b5f602082840312156106ad575f80fd5b6106b68261055e565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a"; } diff --git a/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol b/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol index 78898c42ea31..f382064fe092 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol @@ -3,10 +3,13 @@ pragma solidity 0.8.25; import "src/L2/L2ToL2CrossDomainMessenger.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; +import "forge-std/Test.sol"; // TODO: Try to merge to a single mocked contract used by fuzzing and symbolic invariant tests - only if possible // and is a low priorty -contract MockL2ToL2Messenger is IL2ToL2CrossDomainMessenger { +contract MockL2ToL2Messenger { + event CrossDomainMessageSender(address _sender); + address internal immutable SOURCE_TOKEN; address internal immutable DESTINATION_TOKEN; uint256 public immutable DESTINATION_CHAIN_ID; @@ -14,6 +17,7 @@ contract MockL2ToL2Messenger is IL2ToL2CrossDomainMessenger { // Custom cross domain sender to be used when neither the source nor destination token are the callers address internal customCrossDomainSender; + address internal lastCrossDomainSender; constructor(address _sourceToken, address _destinationToken, uint256 _destinationChainId, uint256 _source) { SOURCE_TOKEN = _sourceToken; @@ -46,18 +50,23 @@ contract MockL2ToL2Messenger is IL2ToL2CrossDomainMessenger { { (bool succ, bytes memory ret) = _target.call{ value: msg.value }(_message); if (!succ) revert(string(ret)); + + // Emit an event to access to the last cross domain sender, can't be stored in storage due to view + // restriction + emit CrossDomainMessageSender(customCrossDomainSender); } function crossDomainMessageSource() external view returns (uint256 _source) { _source = SOURCE; } - // Mock this function so it just always returns the expected if called by the supertoken to pass throgh the - // `address(this)` checks, or otherwise defaults to the custom cross domain sender + // Mock this function so it defaults to the custom domain sender if set, otherwise it defaults to the address of the + // token that called the function - reverts if neither are met function crossDomainMessageSender() external view returns (address _sender) { - if (msg.sender == SOURCE_TOKEN) _sender = SOURCE_TOKEN; + if (customCrossDomainSender != address(0)) _sender = customCrossDomainSender; + else if (msg.sender == SOURCE_TOKEN) _sender = SOURCE_TOKEN; else if (msg.sender == DESTINATION_TOKEN) _sender = DESTINATION_TOKEN; - else _sender = customCrossDomainSender; + else _sender = address(0); } /// Setter function for the customCrossDomainSender From dc0c2c4dd9219d08f2389a5499308dbd252b014b Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Thu, 5 Sep 2024 09:55:41 -0300 Subject: [PATCH 30/56] chore: remove event, add a boolean and update cross domain sender visibility on mock messenger --- .../supererc20-state-diff/StateDiff.json | 4 ++-- .../kontrol/FoundryDebugSymbolic.t.sol | 23 ++++++++----------- .../kontrol/deployments/InitialStateCode.sol | 2 +- .../kontrol/helpers/MockL2ToL2Messenger.sol | 11 ++++----- 4 files changed, 17 insertions(+), 23 deletions(-) diff --git a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json index bf720166938b..ef187ae5be04 100644 --- a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json +++ b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json @@ -503,8 +503,8 @@ "chainId": 31337, "forkId": 0 }, - "data": "0x610100604052348015610010575f80fd5b5060405161082d38038061082d83398101604081905261002f9161006d565b6001600160a01b039384166080529190921660a05260c09190915260e0526100ad565b80516001600160a01b0381168114610068575f80fd5b919050565b5f805f8060808587031215610080575f80fd5b61008985610052565b935061009760208601610052565b6040860151606090960151949790965092505050565b60805160a05160c05160e05161072c6101015f395f818160a001526101ed01525f818160e4015261041601525f8181610381015281816103aa015261044101525f818161031d0152610346015261072c5ff3fe608060405260043610610079575f3560e01c80637056f41f1161004c5780637056f41f1461013f578063722c2a4d1461015257806391db7f49146101b2578063f230b4c2146101dc575f80fd5b80631ecd26f21461007d57806324794462146100925780632ea02369146100d357806338ffde1814610106575b5f80fd5b61009061008b3660046105cb565b61020f565b005b34801561009d575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b3480156100de575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000081565b348015610111575f80fd5b5061011a6102ca565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ca565b61009061014d366004610647565b610414565b34801561015d575f80fd5b5061009061016c36600461069d565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101bd575f80fd5b5060015473ffffffffffffffffffffffffffffffffffffffff1661011a565b3480156101e7575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000081565b5f808473ffffffffffffffffffffffffffffffffffffffff163485856040516102399291906106bd565b5f6040518083038185875af1925050503d805f8114610273576040519150601f19603f3d011682016040523d82523d5f602084013e610278565b606091505b5091509150816102bf57806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102b691906106cc565b60405180910390fd5b505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff161561030657505f5473ffffffffffffffffffffffffffffffffffffffff166103d1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361036a57507f00000000000000000000000000000000000000000000000000000000000000006103d1565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036103ce57507f00000000000000000000000000000000000000000000000000000000000000006103d1565b505f5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831617905590565b7f0000000000000000000000000000000000000000000000000000000000000000840361052d575f61049c7f00000000000000000000000000000000000000000000000000000000000000005f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061053392505050565b90508061052b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016102b6565b505b50505050565b5f610540845a8585610548565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610581575f80fd5b919050565b5f8083601f840112610596575f80fd5b50813567ffffffffffffffff8111156105ad575f80fd5b6020830191508360208285010111156105c4575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105e1575f80fd5b8735965060208801359550604088013594506105ff6060890161055e565b935061060d6080890161055e565b925060a088013567ffffffffffffffff811115610628575f80fd5b6106348a828b01610586565b989b979a50959850939692959293505050565b5f805f806060858703121561065a575f80fd5b8435935061066a6020860161055e565b9250604085013567ffffffffffffffff811115610685575f80fd5b61069187828801610586565b95989497509550505050565b5f602082840312156106ad575f80fd5b6106b68261055e565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", - "deployedCode": "0x608060405260043610610079575f3560e01c80637056f41f1161004c5780637056f41f1461013f578063722c2a4d1461015257806391db7f49146101b2578063f230b4c2146101dc575f80fd5b80631ecd26f21461007d57806324794462146100925780632ea02369146100d357806338ffde1814610106575b5f80fd5b61009061008b3660046105cb565b61020f565b005b34801561009d575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100de575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000281565b348015610111575f80fd5b5061011a6102ca565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ca565b61009061014d366004610647565b610414565b34801561015d575f80fd5b5061009061016c36600461069d565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101bd575f80fd5b5060015473ffffffffffffffffffffffffffffffffffffffff1661011a565b3480156101e7575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff163485856040516102399291906106bd565b5f6040518083038185875af1925050503d805f8114610273576040519150601f19603f3d011682016040523d82523d5f602084013e610278565b606091505b5091509150816102bf57806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102b691906106cc565b60405180910390fd5b505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff161561030657505f5473ffffffffffffffffffffffffffffffffffffffff166103d1565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361036a57507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b6103d1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036103ce57507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a6103d1565b505f5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831617905590565b7f0000000000000000000000000000000000000000000000000000000000000002840361052d575f61049c7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061053392505050565b90508061052b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016102b6565b505b50505050565b5f610540845a8585610548565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610581575f80fd5b919050565b5f8083601f840112610596575f80fd5b50813567ffffffffffffffff8111156105ad575f80fd5b6020830191508360208285010111156105c4575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105e1575f80fd5b8735965060208801359550604088013594506105ff6060890161055e565b935061060d6080890161055e565b925060a088013567ffffffffffffffff811115610628575f80fd5b6106348a828b01610586565b989b979a50959850939692959293505050565b5f805f806060858703121561065a575f80fd5b8435935061066a6020860161055e565b9250604085013567ffffffffffffffff811115610685575f80fd5b61069187828801610586565b95989497509550505050565b5f602082840312156106ad575f80fd5b6106b68261055e565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a", + "data": "0x610100604052348015610010575f80fd5b506040516107fd3803806107fd83398101604081905261002f9161006d565b6001600160a01b039384166080529190921660a05260c09190915260e0526100ad565b80516001600160a01b0381168114610068575f80fd5b919050565b5f805f8060808587031215610080575f80fd5b61008985610052565b935061009760208601610052565b6040860151606090960151949790965092505050565b60805160a05160c05160e0516106fc6101015f395f8181609501526101b801525f818160d901526103e601525f8181610394015281816103bd015261041101525f8181610332015261035b01526106fc5ff3fe60806040526004361061006e575f3560e01c806338ffde181161004c57806338ffde18146100fb5780637056f41f14610134578063722c2a4d14610147578063f230b4c2146101a7575f80fd5b80631ecd26f21461007257806324794462146100875780632ea02369146100c8575b5f80fd5b61008561008036600461059b565b6101da565b005b348015610092575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b3480156100d3575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000081565b348015610106575f80fd5b5061010f6102e1565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bf565b610085610142366004610617565b6103e4565b348015610152575f80fd5b5061008561016136600461066d565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101b2575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000081565b5f808473ffffffffffffffffffffffffffffffffffffffff1634858560405161020492919061068d565b5f6040518083038185875af1925050503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b50915091508161028a57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610281919061069c565b60405180910390fd5b5f5460405173ffffffffffffffffffffffffffffffffffffffff90911681527fa0a4943ae409d8e364a5a387db7729ebd60cddcf3b9f3bcffa12108e6499daae9060200160405180910390a1505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff161561031b57505f5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361037d57507f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036103df57507f000000000000000000000000000000000000000000000000000000000000000090565b505f90565b7f000000000000000000000000000000000000000000000000000000000000000084036104fd575f61046c7f00000000000000000000000000000000000000000000000000000000000000005f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061050392505050565b9050806104fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152608401610281565b505b50505050565b5f610510845a8585610518565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610551575f80fd5b919050565b5f8083601f840112610566575f80fd5b50813567ffffffffffffffff81111561057d575f80fd5b602083019150836020828501011115610594575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105b1575f80fd5b8735965060208801359550604088013594506105cf6060890161052e565b93506105dd6080890161052e565b925060a088013567ffffffffffffffff8111156105f8575f80fd5b6106048a828b01610556565b989b979a50959850939692959293505050565b5f805f806060858703121561062a575f80fd5b8435935061063a6020860161052e565b9250604085013567ffffffffffffffff811115610655575f80fd5b61066187828801610556565b95989497509550505050565b5f6020828403121561067d575f80fd5b6106868261052e565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", + "deployedCode": "0x60806040526004361061006e575f3560e01c806338ffde181161004c57806338ffde18146100fb5780637056f41f14610134578063722c2a4d14610147578063f230b4c2146101a7575f80fd5b80631ecd26f21461007257806324794462146100875780632ea02369146100c8575b5f80fd5b61008561008036600461059b565b6101da565b005b348015610092575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100d3575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000281565b348015610106575f80fd5b5061010f6102e1565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bf565b610085610142366004610617565b6103e4565b348015610152575f80fd5b5061008561016136600461066d565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101b2575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff1634858560405161020492919061068d565b5f6040518083038185875af1925050503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b50915091508161028a57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610281919061069c565b60405180910390fd5b5f5460405173ffffffffffffffffffffffffffffffffffffffff90911681527fa0a4943ae409d8e364a5a387db7729ebd60cddcf3b9f3bcffa12108e6499daae9060200160405180910390a1505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff161561031b57505f5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361037d57507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036103df57507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a90565b505f90565b7f000000000000000000000000000000000000000000000000000000000000000284036104fd575f61046c7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061050392505050565b9050806104fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152608401610281565b505b50505050565b5f610510845a8585610518565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610551575f80fd5b919050565b5f8083601f840112610566575f80fd5b50813567ffffffffffffffff81111561057d575f80fd5b602083019150836020828501011115610594575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105b1575f80fd5b8735965060208801359550604088013594506105cf6060890161052e565b93506105dd6080890161052e565b925060a088013567ffffffffffffffff8111156105f8575f80fd5b6106048a828b01610556565b989b979a50959850939692959293505050565b5f805f806060858703121561062a575f80fd5b8435935061063a6020860161052e565b9250604085013567ffffffffffffffff811115610655575f80fd5b61066187828801610556565b95989497509550505050565b5f6020828403121561067d575f80fd5b6106868261052e565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a", "initialized": true, "kind": "Create", "newBalance": 0, diff --git a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol index e43e0bf96178..4d8e3fd9f2be 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol @@ -86,29 +86,26 @@ contract FoundryDebugTests is KontrolBase { MESSENGER.forTest_setCustomCrossDomainSender(_crossDomainSender); // Expect the cross domain sender to be emitted so after confirming it matches, we can use it for checks - vm.expectEmit(true, true, true, true); - emit CrossDomainMessageSender(_crossDomainSender); vm.prank(_sender); /* Action */ try sourceToken.relayERC20(_from, _to, _amount) { /* Postconditions */ - assert(_sender == address(MESSENGER) && _crossDomainSender == address(sourceToken)); + assert(_sender == address(MESSENGER) && MESSENGER.customCrossDomainSender() == address(sourceToken)); } catch { // Emit to bypass the check when the call fails - emit CrossDomainMessageSender(_crossDomainSender); - assert(_sender != address(MESSENGER) || _crossDomainSender != address(sourceToken)); + assert(_sender != address(MESSENGER) || MESSENGER.customCrossDomainSender() != address(sourceToken)); } } - // ORIGIN_ID = 645326474426547203313410069153905908525362434350 // VV4__amount_114b9705 = 0 - // VV1__sender_114b9705 = 376793390874373408599387495934666716005045108771 - // CALLER_ID = 645326474426547203313410069153905908525362434350 - // NUMBER_CELL = 16777217 - // VV2__from_114b9705 = 645326474426547203313410069153905908525362434350 - // VV0__crossDomainSender_114b9705 = 0 - // VV3__to_114b9705 = 728815563385977040452943777879061427756277306519 - // TIMESTAMP_CELL = 1073741825 + // ORIGIN_ID = 645326474426547203313410069153905908525362434350 + // TIMESTAMP_CELL = 1073741825 + // VV1__sender_114b9705 = 376793390874373408599387495934666716005045108771 + // NUMBER_CELL = 16777217 + // VV3__to_114b9705 = 728815563385977040452943777879061427756277306519 + // VV2__from_114b9705 = 645326474426547203313410069153905908525362434350 + // CALLER_ID = 645326474426547203313410069153905908525362434350 + // VV0__crossDomainSender_114b9705 = 0 /// @custom:property-id 8 /// @custom:property `sendERC20` with a value of zero does not modify accounting diff --git a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol index cb5574e45706..29fa901e36a6 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol @@ -11,5 +11,5 @@ contract InitialStateCode { bytes internal constant destTokenCode = hex"6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a"; bytes internal constant mockL2ToL2MessengerCode = - hex"608060405260043610610079575f3560e01c80637056f41f1161004c5780637056f41f1461013f578063722c2a4d1461015257806391db7f49146101b2578063f230b4c2146101dc575f80fd5b80631ecd26f21461007d57806324794462146100925780632ea02369146100d357806338ffde1814610106575b5f80fd5b61009061008b3660046105cb565b61020f565b005b34801561009d575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100de575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000281565b348015610111575f80fd5b5061011a6102ca565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ca565b61009061014d366004610647565b610414565b34801561015d575f80fd5b5061009061016c36600461069d565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101bd575f80fd5b5060015473ffffffffffffffffffffffffffffffffffffffff1661011a565b3480156101e7575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff163485856040516102399291906106bd565b5f6040518083038185875af1925050503d805f8114610273576040519150601f19603f3d011682016040523d82523d5f602084013e610278565b606091505b5091509150816102bf57806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102b691906106cc565b60405180910390fd5b505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff161561030657505f5473ffffffffffffffffffffffffffffffffffffffff166103d1565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361036a57507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b6103d1565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036103ce57507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a6103d1565b505f5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831617905590565b7f0000000000000000000000000000000000000000000000000000000000000002840361052d575f61049c7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061053392505050565b90508061052b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016102b6565b505b50505050565b5f610540845a8585610548565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610581575f80fd5b919050565b5f8083601f840112610596575f80fd5b50813567ffffffffffffffff8111156105ad575f80fd5b6020830191508360208285010111156105c4575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105e1575f80fd5b8735965060208801359550604088013594506105ff6060890161055e565b935061060d6080890161055e565b925060a088013567ffffffffffffffff811115610628575f80fd5b6106348a828b01610586565b989b979a50959850939692959293505050565b5f805f806060858703121561065a575f80fd5b8435935061066a6020860161055e565b9250604085013567ffffffffffffffff811115610685575f80fd5b61069187828801610586565b95989497509550505050565b5f602082840312156106ad575f80fd5b6106b68261055e565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a"; + hex"60806040526004361061006e575f3560e01c806338ffde181161004c57806338ffde18146100fb5780637056f41f14610134578063722c2a4d14610147578063f230b4c2146101a7575f80fd5b80631ecd26f21461007257806324794462146100875780632ea02369146100c8575b5f80fd5b61008561008036600461059b565b6101da565b005b348015610092575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100d3575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000281565b348015610106575f80fd5b5061010f6102e1565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bf565b610085610142366004610617565b6103e4565b348015610152575f80fd5b5061008561016136600461066d565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101b2575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff1634858560405161020492919061068d565b5f6040518083038185875af1925050503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b50915091508161028a57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610281919061069c565b60405180910390fd5b5f5460405173ffffffffffffffffffffffffffffffffffffffff90911681527fa0a4943ae409d8e364a5a387db7729ebd60cddcf3b9f3bcffa12108e6499daae9060200160405180910390a1505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff161561031b57505f5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361037d57507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036103df57507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a90565b505f90565b7f000000000000000000000000000000000000000000000000000000000000000284036104fd575f61046c7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061050392505050565b9050806104fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152608401610281565b505b50505050565b5f610510845a8585610518565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610551575f80fd5b919050565b5f8083601f840112610566575f80fd5b50813567ffffffffffffffff81111561057d575f80fd5b602083019150836020828501011115610594575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105b1575f80fd5b8735965060208801359550604088013594506105cf6060890161052e565b93506105dd6080890161052e565b925060a088013567ffffffffffffffff8111156105f8575f80fd5b6106048a828b01610556565b989b979a50959850939692959293505050565b5f805f806060858703121561062a575f80fd5b8435935061063a6020860161052e565b9250604085013567ffffffffffffffff811115610655575f80fd5b61066187828801610556565b95989497509550505050565b5f6020828403121561067d575f80fd5b6106868261052e565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a"; } diff --git a/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol b/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol index f382064fe092..a3f4b5a7fe5c 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol @@ -16,8 +16,8 @@ contract MockL2ToL2Messenger { uint256 public immutable SOURCE; // Custom cross domain sender to be used when neither the source nor destination token are the callers - address internal customCrossDomainSender; - address internal lastCrossDomainSender; + address public customCrossDomainSender; + bool internal crossDomainSenderSet; constructor(address _sourceToken, address _destinationToken, uint256 _destinationChainId, uint256 _source) { SOURCE_TOKEN = _sourceToken; @@ -50,10 +50,6 @@ contract MockL2ToL2Messenger { { (bool succ, bytes memory ret) = _target.call{ value: msg.value }(_message); if (!succ) revert(string(ret)); - - // Emit an event to access to the last cross domain sender, can't be stored in storage due to view - // restriction - emit CrossDomainMessageSender(customCrossDomainSender); } function crossDomainMessageSource() external view returns (uint256 _source) { @@ -63,7 +59,7 @@ contract MockL2ToL2Messenger { // Mock this function so it defaults to the custom domain sender if set, otherwise it defaults to the address of the // token that called the function - reverts if neither are met function crossDomainMessageSender() external view returns (address _sender) { - if (customCrossDomainSender != address(0)) _sender = customCrossDomainSender; + if (crossDomainSenderSet) _sender = customCrossDomainSender; else if (msg.sender == SOURCE_TOKEN) _sender = SOURCE_TOKEN; else if (msg.sender == DESTINATION_TOKEN) _sender = DESTINATION_TOKEN; else _sender = address(0); @@ -71,6 +67,7 @@ contract MockL2ToL2Messenger { /// Setter function for the customCrossDomainSender function forTest_setCustomCrossDomainSender(address _customCrossDomainSender) external { + crossDomainSenderSet = true; customCrossDomainSender = _customCrossDomainSender; } } From befba99c102091cec53be08199e316da0575116a Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Thu, 5 Sep 2024 09:57:32 -0300 Subject: [PATCH 31/56] chore: unnecessary remove 0 address asingment --- .../contracts-bedrock/supererc20-state-diff/StateDiff.json | 4 ++-- .../test/properties/kontrol/deployments/InitialStateCode.sol | 2 +- .../test/properties/kontrol/helpers/MockL2ToL2Messenger.sol | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json index ef187ae5be04..f87791116f3c 100644 --- a/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json +++ b/packages/contracts-bedrock/supererc20-state-diff/StateDiff.json @@ -503,8 +503,8 @@ "chainId": 31337, "forkId": 0 }, - "data": "0x610100604052348015610010575f80fd5b506040516107fd3803806107fd83398101604081905261002f9161006d565b6001600160a01b039384166080529190921660a05260c09190915260e0526100ad565b80516001600160a01b0381168114610068575f80fd5b919050565b5f805f8060808587031215610080575f80fd5b61008985610052565b935061009760208601610052565b6040860151606090960151949790965092505050565b60805160a05160c05160e0516106fc6101015f395f8181609501526101b801525f818160d901526103e601525f8181610394015281816103bd015261041101525f8181610332015261035b01526106fc5ff3fe60806040526004361061006e575f3560e01c806338ffde181161004c57806338ffde18146100fb5780637056f41f14610134578063722c2a4d14610147578063f230b4c2146101a7575f80fd5b80631ecd26f21461007257806324794462146100875780632ea02369146100c8575b5f80fd5b61008561008036600461059b565b6101da565b005b348015610092575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b3480156100d3575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000081565b348015610106575f80fd5b5061010f6102e1565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bf565b610085610142366004610617565b6103e4565b348015610152575f80fd5b5061008561016136600461066d565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101b2575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000081565b5f808473ffffffffffffffffffffffffffffffffffffffff1634858560405161020492919061068d565b5f6040518083038185875af1925050503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b50915091508161028a57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610281919061069c565b60405180910390fd5b5f5460405173ffffffffffffffffffffffffffffffffffffffff90911681527fa0a4943ae409d8e364a5a387db7729ebd60cddcf3b9f3bcffa12108e6499daae9060200160405180910390a1505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff161561031b57505f5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361037d57507f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036103df57507f000000000000000000000000000000000000000000000000000000000000000090565b505f90565b7f000000000000000000000000000000000000000000000000000000000000000084036104fd575f61046c7f00000000000000000000000000000000000000000000000000000000000000005f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061050392505050565b9050806104fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152608401610281565b505b50505050565b5f610510845a8585610518565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610551575f80fd5b919050565b5f8083601f840112610566575f80fd5b50813567ffffffffffffffff81111561057d575f80fd5b602083019150836020828501011115610594575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105b1575f80fd5b8735965060208801359550604088013594506105cf6060890161052e565b93506105dd6080890161052e565b925060a088013567ffffffffffffffff8111156105f8575f80fd5b6106048a828b01610556565b989b979a50959850939692959293505050565b5f805f806060858703121561062a575f80fd5b8435935061063a6020860161052e565b9250604085013567ffffffffffffffff811115610655575f80fd5b61066187828801610556565b95989497509550505050565b5f6020828403121561067d575f80fd5b6106868261052e565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", - "deployedCode": "0x60806040526004361061006e575f3560e01c806338ffde181161004c57806338ffde18146100fb5780637056f41f14610134578063722c2a4d14610147578063f230b4c2146101a7575f80fd5b80631ecd26f21461007257806324794462146100875780632ea02369146100c8575b5f80fd5b61008561008036600461059b565b6101da565b005b348015610092575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100d3575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000281565b348015610106575f80fd5b5061010f6102e1565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bf565b610085610142366004610617565b6103e4565b348015610152575f80fd5b5061008561016136600461066d565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101b2575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff1634858560405161020492919061068d565b5f6040518083038185875af1925050503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b50915091508161028a57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610281919061069c565b60405180910390fd5b5f5460405173ffffffffffffffffffffffffffffffffffffffff90911681527fa0a4943ae409d8e364a5a387db7729ebd60cddcf3b9f3bcffa12108e6499daae9060200160405180910390a1505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff161561031b57505f5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361037d57507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036103df57507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a90565b505f90565b7f000000000000000000000000000000000000000000000000000000000000000284036104fd575f61046c7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061050392505050565b9050806104fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152608401610281565b505b50505050565b5f610510845a8585610518565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610551575f80fd5b919050565b5f8083601f840112610566575f80fd5b50813567ffffffffffffffff81111561057d575f80fd5b602083019150836020828501011115610594575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105b1575f80fd5b8735965060208801359550604088013594506105cf6060890161052e565b93506105dd6080890161052e565b925060a088013567ffffffffffffffff8111156105f8575f80fd5b6106048a828b01610556565b989b979a50959850939692959293505050565b5f805f806060858703121561062a575f80fd5b8435935061063a6020860161052e565b9250604085013567ffffffffffffffff811115610655575f80fd5b61066187828801610556565b95989497509550505050565b5f6020828403121561067d575f80fd5b6106868261052e565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a", + "data": "0x610100604052348015610010575f80fd5b5060405161080038038061080083398101604081905261002f9161006d565b6001600160a01b039384166080529190921660a05260c09190915260e0526100ad565b80516001600160a01b0381168114610068575f80fd5b919050565b5f805f8060808587031215610080575f80fd5b61008985610052565b935061009760208601610052565b6040860151606090960151949790965092505050565b60805160a05160c05160e0516106ff6101015f395f818160a0015261020601525f818160e401526103e901525f818161039b015281816103c4015261041401525f8181610339015261036201526106ff5ff3fe608060405260043610610079575f3560e01c80637056f41f1161004c5780637056f41f1461013f578063722c2a4d1461015257806382dc9c8b146101ca578063f230b4c2146101f5575f80fd5b80631ecd26f21461007d57806324794462146100925780632ea02369146100d357806338ffde1814610106575b5f80fd5b61009061008b36600461059e565b610228565b005b34801561009d575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040519081526020015b60405180910390f35b3480156100de575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000081565b348015610111575f80fd5b5061011a6102e3565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ca565b61009061014d36600461061a565b6103e7565b34801561015d575f80fd5b5061009061016c366004610670565b5f805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffff0000000000000000000000000000000000000000009092169190911774010000000000000000000000000000000000000000179055565b3480156101d5575f80fd5b505f5461011a9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610200575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000081565b5f808473ffffffffffffffffffffffffffffffffffffffff16348585604051610252929190610690565b5f6040518083038185875af1925050503d805f811461028c576040519150601f19603f3d011682016040523d82523d5f602084013e610291565b606091505b5091509150816102d857806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102cf919061069f565b60405180910390fd5b505050505050505050565b5f805474010000000000000000000000000000000000000000900460ff161561032257505f5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361038457507f000000000000000000000000000000000000000000000000000000000000000090565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633036103e457507f00000000000000000000000000000000000000000000000000000000000000005b90565b7f00000000000000000000000000000000000000000000000000000000000000008403610500575f61046f7f00000000000000000000000000000000000000000000000000000000000000005f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061050692505050565b9050806104fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016102cf565b505b50505050565b5f610513845a858561051b565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610554575f80fd5b919050565b5f8083601f840112610569575f80fd5b50813567ffffffffffffffff811115610580575f80fd5b602083019150836020828501011115610597575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105b4575f80fd5b8735965060208801359550604088013594506105d260608901610531565b93506105e060808901610531565b925060a088013567ffffffffffffffff8111156105fb575f80fd5b6106078a828b01610559565b989b979a50959850939692959293505050565b5f805f806060858703121561062d575f80fd5b8435935061063d60208601610531565b9250604085013567ffffffffffffffff811115610658575f80fd5b61066487828801610559565b95989497509550505050565b5f60208284031215610680575f80fd5b61068982610531565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003", + "deployedCode": "0x608060405260043610610079575f3560e01c80637056f41f1161004c5780637056f41f1461013f578063722c2a4d1461015257806382dc9c8b146101ca578063f230b4c2146101f5575f80fd5b80631ecd26f21461007d57806324794462146100925780632ea02369146100d357806338ffde1814610106575b5f80fd5b61009061008b36600461059e565b610228565b005b34801561009d575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100de575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000281565b348015610111575f80fd5b5061011a6102e3565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ca565b61009061014d36600461061a565b6103e7565b34801561015d575f80fd5b5061009061016c366004610670565b5f805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffff0000000000000000000000000000000000000000009092169190911774010000000000000000000000000000000000000000179055565b3480156101d5575f80fd5b505f5461011a9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610200575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff16348585604051610252929190610690565b5f6040518083038185875af1925050503d805f811461028c576040519150601f19603f3d011682016040523d82523d5f602084013e610291565b606091505b5091509150816102d857806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102cf919061069f565b60405180910390fd5b505050505050505050565b5f805474010000000000000000000000000000000000000000900460ff161561032257505f5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361038457507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036103e457507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5b90565b7f00000000000000000000000000000000000000000000000000000000000000028403610500575f61046f7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061050692505050565b9050806104fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016102cf565b505b50505050565b5f610513845a858561051b565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610554575f80fd5b919050565b5f8083601f840112610569575f80fd5b50813567ffffffffffffffff811115610580575f80fd5b602083019150836020828501011115610597575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105b4575f80fd5b8735965060208801359550604088013594506105d260608901610531565b93506105e060808901610531565b925060a088013567ffffffffffffffff8111156105fb575f80fd5b6106078a828b01610559565b989b979a50959850939692959293505050565b5f805f806060858703121561062d575f80fd5b8435935061063d60208601610531565b9250604085013567ffffffffffffffff811115610658575f80fd5b61066487828801610559565b95989497509550505050565b5f60208284031215610680575f80fd5b61068982610531565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a", "initialized": true, "kind": "Create", "newBalance": 0, diff --git a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol index 29fa901e36a6..fa587471be8b 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/deployments/InitialStateCode.sol @@ -11,5 +11,5 @@ contract InitialStateCode { bytes internal constant destTokenCode = hex"6080604052600a600c565b005b60186014601a565b605d565b565b5f60587f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b365f80375f80365f845af43d5f803e8080156076573d5ff35b3d5ffdfea164736f6c6343000819000a"; bytes internal constant mockL2ToL2MessengerCode = - hex"60806040526004361061006e575f3560e01c806338ffde181161004c57806338ffde18146100fb5780637056f41f14610134578063722c2a4d14610147578063f230b4c2146101a7575f80fd5b80631ecd26f21461007257806324794462146100875780632ea02369146100c8575b5f80fd5b61008561008036600461059b565b6101da565b005b348015610092575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100d3575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000281565b348015610106575f80fd5b5061010f6102e1565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100bf565b610085610142366004610617565b6103e4565b348015610152575f80fd5b5061008561016136600461066d565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3480156101b2575f80fd5b506100b57f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff1634858560405161020492919061068d565b5f6040518083038185875af1925050503d805f811461023e576040519150601f19603f3d011682016040523d82523d5f602084013e610243565b606091505b50915091508161028a57806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610281919061069c565b60405180910390fd5b5f5460405173ffffffffffffffffffffffffffffffffffffffff90911681527fa0a4943ae409d8e364a5a387db7729ebd60cddcf3b9f3bcffa12108e6499daae9060200160405180910390a1505050505050505050565b5f805473ffffffffffffffffffffffffffffffffffffffff161561031b57505f5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361037d57507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036103df57507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a90565b505f90565b7f000000000000000000000000000000000000000000000000000000000000000284036104fd575f61046c7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061050392505050565b9050806104fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c6564000000000000000000000000000000000000000000000000006064820152608401610281565b505b50505050565b5f610510845a8585610518565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610551575f80fd5b919050565b5f8083601f840112610566575f80fd5b50813567ffffffffffffffff81111561057d575f80fd5b602083019150836020828501011115610594575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105b1575f80fd5b8735965060208801359550604088013594506105cf6060890161052e565b93506105dd6080890161052e565b925060a088013567ffffffffffffffff8111156105f8575f80fd5b6106048a828b01610556565b989b979a50959850939692959293505050565b5f805f806060858703121561062a575f80fd5b8435935061063a6020860161052e565b9250604085013567ffffffffffffffff811115610655575f80fd5b61066187828801610556565b95989497509550505050565b5f6020828403121561067d575f80fd5b6106868261052e565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a"; + hex"608060405260043610610079575f3560e01c80637056f41f1161004c5780637056f41f1461013f578063722c2a4d1461015257806382dc9c8b146101ca578063f230b4c2146101f5575f80fd5b80631ecd26f21461007d57806324794462146100925780632ea02369146100d357806338ffde1814610106575b5f80fd5b61009061008b36600461059e565b610228565b005b34801561009d575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000035b6040519081526020015b60405180910390f35b3480156100de575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000281565b348015610111575f80fd5b5061011a6102e3565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ca565b61009061014d36600461061a565b6103e7565b34801561015d575f80fd5b5061009061016c366004610670565b5f805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffff0000000000000000000000000000000000000000009092169190911774010000000000000000000000000000000000000000179055565b3480156101d5575f80fd5b505f5461011a9073ffffffffffffffffffffffffffffffffffffffff1681565b348015610200575f80fd5b506100c07f000000000000000000000000000000000000000000000000000000000000000381565b5f808473ffffffffffffffffffffffffffffffffffffffff16348585604051610252929190610690565b5f6040518083038185875af1925050503d805f811461028c576040519150601f19603f3d011682016040523d82523d5f602084013e610291565b606091505b5091509150816102d857806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102cf919061069f565b60405180910390fd5b505050505050505050565b5f805474010000000000000000000000000000000000000000900460ff161561032257505f5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b16330361038457507f0000000000000000000000002e234dae75c793f67a35089c9d99245e1c58470b90565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a1633036103e457507f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5b90565b7f00000000000000000000000000000000000000000000000000000000000000028403610500575f61046f7f000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a5f85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061050692505050565b9050806104fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4d6f636b4c32546f4c324d657373656e6765723a2073656e644d65737361676560448201527f206661696c65640000000000000000000000000000000000000000000000000060648201526084016102cf565b505b50505050565b5f610513845a858561051b565b949350505050565b5f805f835160208501868989f195945050505050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610554575f80fd5b919050565b5f8083601f840112610569575f80fd5b50813567ffffffffffffffff811115610580575f80fd5b602083019150836020828501011115610597575f80fd5b9250929050565b5f805f805f805f60c0888a0312156105b4575f80fd5b8735965060208801359550604088013594506105d260608901610531565b93506105e060808901610531565b925060a088013567ffffffffffffffff8111156105fb575f80fd5b6106078a828b01610559565b989b979a50959850939692959293505050565b5f805f806060858703121561062d575f80fd5b8435935061063d60208601610531565b9250604085013567ffffffffffffffff811115610658575f80fd5b61066487828801610559565b95989497509550505050565b5f60208284031215610680575f80fd5b61068982610531565b9392505050565b818382375f9101908152919050565b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150509291505056fea164736f6c6343000819000a"; } diff --git a/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol b/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol index a3f4b5a7fe5c..dc4af91bca30 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol @@ -61,8 +61,8 @@ contract MockL2ToL2Messenger { function crossDomainMessageSender() external view returns (address _sender) { if (crossDomainSenderSet) _sender = customCrossDomainSender; else if (msg.sender == SOURCE_TOKEN) _sender = SOURCE_TOKEN; + // Leaving the `if` here for clarity else if (msg.sender == DESTINATION_TOKEN) _sender = DESTINATION_TOKEN; - else _sender = address(0); } /// Setter function for the customCrossDomainSender From 498f85fda2add8689dd2f02918bad254dcc30e20 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Thu, 5 Sep 2024 10:08:15 -0300 Subject: [PATCH 32/56] chore: update failing scenario on foundry debug tests --- .../kontrol/FoundryDebugSymbolic.t.sol | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol index 4d8e3fd9f2be..fe442d9c9363 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol @@ -76,7 +76,7 @@ contract FoundryDebugTests is KontrolBase { // uint256 _amount public { - address _crossDomainSender = address(0); + address _crossDomainSender = address(263400868551549723330807389252719309078400616203); address _sender = address(376793390874373408599387495934666716005045108771); address _from = address(645326474426547203313410069153905908525362434350); address _to = address(728815563385977040452943777879061427756277306519); @@ -97,15 +97,13 @@ contract FoundryDebugTests is KontrolBase { assert(_sender != address(MESSENGER) || MESSENGER.customCrossDomainSender() != address(sourceToken)); } } + // VV1__sender_114b9705 = 376793390874373408599387495934666716005045108771 + // VV3__to_114b9705 = 728815563385977040452943777879061427756277306519 + // VV0__crossDomainSender_114b9705 = 263400868551549723330807389252719309078400616203 + // ORIGIN_ID = 645326474426547203313410069153905908525362434350 + // CALLER_ID = 645326474426547203313410069153905908525362434350 // VV4__amount_114b9705 = 0 - // ORIGIN_ID = 645326474426547203313410069153905908525362434350 - // TIMESTAMP_CELL = 1073741825 - // VV1__sender_114b9705 = 376793390874373408599387495934666716005045108771 - // NUMBER_CELL = 16777217 - // VV3__to_114b9705 = 728815563385977040452943777879061427756277306519 - // VV2__from_114b9705 = 645326474426547203313410069153905908525362434350 - // CALLER_ID = 645326474426547203313410069153905908525362434350 - // VV0__crossDomainSender_114b9705 = 0 + // VV2__from_114b9705 = 645326474426547203313410069153905908525362434350 /// @custom:property-id 8 /// @custom:property `sendERC20` with a value of zero does not modify accounting From 51efcda731e1c902172072392b6faac9b65dcf2b Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Fri, 6 Sep 2024 14:23:06 -0300 Subject: [PATCH 33/56] refactor: use symoblic storage cheatcode --- packages/contracts-bedrock/kontrol.toml | 44 +++++++++++++++++++ .../kontrol/FoundryDebugSymbolic.t.sol | 8 ++-- .../kontrol/OptimismSuperchainERC20.k.sol | 20 ++++----- 3 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 packages/contracts-bedrock/kontrol.toml diff --git a/packages/contracts-bedrock/kontrol.toml b/packages/contracts-bedrock/kontrol.toml new file mode 100644 index 000000000000..cfdc385ff02a --- /dev/null +++ b/packages/contracts-bedrock/kontrol.toml @@ -0,0 +1,44 @@ +[build.default] +foundry-project-root = '.' +regen = false +rekompile = false +verbose = false +debug = false +auxiliary-lemmas = true + +# require = 'lemmas.k' +# module-import = 'TestBase:KONTROL-LEMMAS' + +[prove.default] +foundry-project-root = '.' +verbose = false +debug = false +max-depth = 25000 +reinit = false +cse = false +workers = 1 +failure-information = true +counterexample-information = true +minimize-proofs = false +fail-fast = true +smt-timeout = 1000 +break-every-step = false +break-on-jumpi = false +break-on-calls = false +break-on-storage = false +break-on-basic-blocks = false +break-on-cheatcodes = false +run-constructor = true +symbolic-immutables = false +schedule = CANCUN +init-node-from = supererc20-state-diff/StateDiff.json + +[show.default] +foundry-project-root = '.' +verbose = false +debug = false +use-hex-encoding = false + +[view-kcfg.default] +foundry-project-root = '.' +use-hex-encoding = false \ No newline at end of file diff --git a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol index fe442d9c9363..fb7e2157bf8e 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol @@ -164,10 +164,10 @@ contract FoundryDebugTests is KontrolBase { function test_proveCrossChainSendERC20() public { /* Preconditions */ - address _from = address(376793390874373408599387495934666716005045108752); + address _from = address(728815563385977040452943777879061427756277306519); address _to = address(728815563385977040452943777879061427756277306519); uint256 _amount = 0; - uint256 _chainId = 2; + uint256 _chainId = 0; // Mint the amount to send vm.prank(Predeploys.L2_STANDARD_BRIDGE); sourceToken.mint(_from, _amount); @@ -201,7 +201,7 @@ contract FoundryDebugTests is KontrolBase { } } // VV1__to_114b9705 = 728815563385977040452943777879061427756277306519 - // VV0__from_114b9705 = 376793390874373408599387495934666716005045108752 + // VV0__from_114b9705 = 728815563385977040452943777879061427756277306519 // VV2__amount_114b9705 = 0 - // VV3__chainId_114b9705 = 2 + // VV3__chainId_114b9705 = 0 } diff --git a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol index 30a9d5540411..cd648791ad21 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol @@ -92,6 +92,7 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { public { setUpInlined(); + kevm.symbolicStorage(address(MESSENGER)); /* Preconditions */ vm.assume(_to != address(0)); @@ -99,7 +100,7 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(notBuiltinAddress(_to)); vm.assume(notBuiltinAddress(_sender)); - MESSENGER.forTest_setCustomCrossDomainSender(_crossDomainSender); + // MESSENGER.forTest_setCustomCrossDomainSender(_crossDomainSender); // Expect the cross domain sender to be emitted so after confirming it matches, we can use it for checks vm.expectEmit(true, true, true, true); @@ -109,7 +110,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /* Action */ try sourceToken.relayERC20(_from, _to, _amount) { /* Postconditions */ - assert(_sender == address(MESSENGER) && _crossDomainSender == address(sourceToken)); + assert(_sender == address(MESSENGER)); + assert(_crossDomainSender == address(sourceToken)); } catch { // Emit to bypass the check when the call fails emit CrossDomainMessageSender(_crossDomainSender); @@ -125,8 +127,6 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /* Preconditions */ vm.assume(_to != address(0)); vm.assume(_to != address(Predeploys.CROSS_L2_INBOX) && _to != address(MESSENGER)); - // TODO - vm.assume(_from != address(0)); vm.assume(notBuiltinAddress(_from)); vm.assume(notBuiltinAddress(_to)); @@ -254,12 +254,14 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { function prove_burn(address _from, uint256 _amount) public { setUpInlined(); + kevm.symbolicStorage(address(sourceToken)); + /* Preconditions */ vm.assume(_from != address(0)); vm.assume(notBuiltinAddress(_from)); - vm.prank(Predeploys.L2_STANDARD_BRIDGE); - sourceToken.mint(_from, _amount); + // vm.prank(Predeploys.L2_STANDARD_BRIDGE); + // sourceToken.mint(_from, _amount); uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _balanceBefore = sourceToken.balanceOf(_from); @@ -291,6 +293,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { function prove_crossChainSendERC20(address _from, address _to, uint256 _amount, uint256 _chainId) public { setUpInlined(); + kevm.symbolicStorage(address(sourceToken)); + vm.assume(notBuiltinAddress(_from)); vm.assume(notBuiltinAddress(_to)); @@ -298,10 +302,6 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(_to != address(0)); vm.assume(_from != address(0)); - // Mint the amount to send - vm.prank(Predeploys.L2_STANDARD_BRIDGE); - sourceToken.mint(_from, _amount); - uint256 fromBalanceBefore = sourceToken.balanceOf(_from); uint256 toBalanceBefore = destToken.balanceOf(_to); uint256 sourceTotalSupplyBefore = sourceToken.totalSupply(); From d89717f75fcb823b846fbca3c34f374e7b31bffd Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Fri, 6 Sep 2024 19:01:57 -0300 Subject: [PATCH 34/56] chore: optimize tests and apply symbolic storage everywhere possible --- packages/contracts-bedrock/kontrol.toml | 70 +++++++++---------- .../{kontrol => }/FoundryDebugSymbolic.t.sol | 1 - .../kontrol/OptimismSuperchainERC20.k.sol | 28 ++++---- .../kontrol/helpers/MockL2ToL2Messenger.sol | 1 - 4 files changed, 48 insertions(+), 52 deletions(-) rename packages/contracts-bedrock/test/properties/{kontrol => }/FoundryDebugSymbolic.t.sol (99%) diff --git a/packages/contracts-bedrock/kontrol.toml b/packages/contracts-bedrock/kontrol.toml index cfdc385ff02a..dcd4d584e2af 100644 --- a/packages/contracts-bedrock/kontrol.toml +++ b/packages/contracts-bedrock/kontrol.toml @@ -1,44 +1,44 @@ [build.default] -foundry-project-root = '.' -regen = false -rekompile = false -verbose = false -debug = false -auxiliary-lemmas = true +foundry-project-root = './' +regen = false +rekompile = false +verbose = false +debug = false +auxiliary-lemmas = true -# require = 'lemmas.k' -# module-import = 'TestBase:KONTROL-LEMMAS' +# require = 'lemmas.k' +# module-import = 'TestBase:KONTROL-LEMMAS' [prove.default] -foundry-project-root = '.' -verbose = false -debug = false -max-depth = 25000 -reinit = false -cse = false -workers = 1 -failure-information = true +foundry-project-root = '.' +verbose = false +debug = false +max-depth = 25000 +reinit = false +cse = false +workers = 1 +failure-information = true counterexample-information = true -minimize-proofs = false -fail-fast = true -smt-timeout = 1000 -break-every-step = false -break-on-jumpi = false -break-on-calls = false -break-on-storage = false -break-on-basic-blocks = false -break-on-cheatcodes = false -run-constructor = true -symbolic-immutables = false -schedule = CANCUN -init-node-from = supererc20-state-diff/StateDiff.json +minimize-proofs = false +fail-fast = true +smt-timeout = 1000 +break-every-step = false +break-on-jumpi = false +break-on-calls = false +break-on-storage = false +break-on-basic-blocks = false +break-on-cheatcodes = false +run-constructor = true +symbolic-immutables = false +schedule = CANCUN +init-node-from = supererc20-state-diff/StateDiff.json [show.default] -foundry-project-root = '.' -verbose = false -debug = false -use-hex-encoding = false +foundry-project-root = '.' +verbose = false +debug = false +use-hex-encoding = false [view-kcfg.default] -foundry-project-root = '.' -use-hex-encoding = false \ No newline at end of file +foundry-project-root = '.' +use-hex-encoding = false diff --git a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol b/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol similarity index 99% rename from packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol rename to packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol index fb7e2157bf8e..f8895c57e3f7 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/FoundryDebugSymbolic.t.sol +++ b/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol @@ -5,7 +5,6 @@ import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { MockL2ToL2Messenger } from "test/properties/kontrol/helpers/MockL2ToL2Messenger.sol"; import { KontrolBase } from "test/properties/kontrol/KontrolBase.sol"; -import { InitialState } from "./deployments/InitialState.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; import "forge-std/Test.sol"; diff --git a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol index cd648791ad21..8abad75d6fef 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol @@ -49,7 +49,6 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /// @custom:property-id 6 /// @custom:property Calls to sendERC20 succeed as long as caller has enough balance function prove_sendERC20SucceedsOnlyIfEnoughBalance( - uint256 _initialBalance, address _from, uint256 _amount, address _to, @@ -59,6 +58,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { { setUpInlined(); + kevm.symbolicStorage(address(sourceToken)); + /* Preconditions */ vm.assume(_to != address(0)); vm.assume(_from != address(0)); @@ -67,8 +68,10 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(notBuiltinAddress(_to)); // Can't deal to unsupported cheatcode - vm.prank(Predeploys.L2_STANDARD_BRIDGE); - sourceToken.mint(_from, _initialBalance); + // vm.prank(Predeploys.L2_STANDARD_BRIDGE); + // sourceToken.mint(_from, _initialBalance); + + uint256 _initialBalance = sourceToken.balanceOf(_from); vm.prank(_from); /* Action */ @@ -92,7 +95,6 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { public { setUpInlined(); - kevm.symbolicStorage(address(MESSENGER)); /* Preconditions */ vm.assume(_to != address(0)); @@ -100,12 +102,9 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(notBuiltinAddress(_to)); vm.assume(notBuiltinAddress(_sender)); + kevm.symbolicStorage(address(MESSENGER)); // MESSENGER.forTest_setCustomCrossDomainSender(_crossDomainSender); - // Expect the cross domain sender to be emitted so after confirming it matches, we can use it for checks - vm.expectEmit(true, true, true, true); - emit CrossDomainMessageSender(_crossDomainSender); - vm.prank(_sender); /* Action */ try sourceToken.relayERC20(_from, _to, _amount) { @@ -126,7 +125,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /* Preconditions */ vm.assume(_to != address(0)); - vm.assume(_to != address(Predeploys.CROSS_L2_INBOX) && _to != address(MESSENGER)); + vm.assume(_to != address(Predeploys.CROSS_L2_INBOX)); + vm.assume(_to != address(MESSENGER)); vm.assume(notBuiltinAddress(_from)); vm.assume(notBuiltinAddress(_to)); @@ -154,8 +154,6 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(_to != address(0)); vm.assume(notBuiltinAddress(_from)); vm.assume(notBuiltinAddress(_to)); - // TODO - vm.assume(_to != address(1)); uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); @@ -254,8 +252,6 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { function prove_burn(address _from, uint256 _amount) public { setUpInlined(); - kevm.symbolicStorage(address(sourceToken)); - /* Preconditions */ vm.assume(_from != address(0)); vm.assume(notBuiltinAddress(_from)); @@ -263,6 +259,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { // vm.prank(Predeploys.L2_STANDARD_BRIDGE); // sourceToken.mint(_from, _amount); + kevm.symbolicStorage(address(sourceToken)); + uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _balanceBefore = sourceToken.balanceOf(_from); @@ -293,8 +291,6 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { function prove_crossChainSendERC20(address _from, address _to, uint256 _amount, uint256 _chainId) public { setUpInlined(); - kevm.symbolicStorage(address(sourceToken)); - vm.assume(notBuiltinAddress(_from)); vm.assume(notBuiltinAddress(_to)); @@ -302,6 +298,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(_to != address(0)); vm.assume(_from != address(0)); + kevm.symbolicStorage(address(sourceToken)); + uint256 fromBalanceBefore = sourceToken.balanceOf(_from); uint256 toBalanceBefore = destToken.balanceOf(_to); uint256 sourceTotalSupplyBefore = sourceToken.totalSupply(); diff --git a/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol b/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol index dc4af91bca30..a199bfb792c1 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol @@ -61,7 +61,6 @@ contract MockL2ToL2Messenger { function crossDomainMessageSender() external view returns (address _sender) { if (crossDomainSenderSet) _sender = customCrossDomainSender; else if (msg.sender == SOURCE_TOKEN) _sender = SOURCE_TOKEN; - // Leaving the `if` here for clarity else if (msg.sender == DESTINATION_TOKEN) _sender = DESTINATION_TOKEN; } From d6d46daf28406af7955bf68c2628382cccef5134 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Fri, 6 Sep 2024 23:46:42 -0300 Subject: [PATCH 35/56] chore: remove symbolik storage feature since it failed --- .../properties/FoundryDebugSymbolic.t.sol | 42 +------------------ .../kontrol/OptimismSuperchainERC20.k.sol | 22 ++++------ 2 files changed, 11 insertions(+), 53 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol b/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol index f8895c57e3f7..fb01e0ec40b7 100644 --- a/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol +++ b/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol @@ -62,48 +62,10 @@ contract FoundryDebugTests is KontrolBase { assert(MESSENGER.crossDomainMessageSender() == address(destToken)); // Custom cross domain sender - assert(MESSENGER.crossDomainMessageSender() == address(0)); + MESSENGER.forTest_setCustomCrossDomainSender(address(420)); + assert(MESSENGER.crossDomainMessageSender() == address(420)); } - /// @custom:property-id 7 - /// @custom:property Calls to relayERC20 always succeed as long as the sender the cross-domain caller are valid - function test_proveRelayERC20OnlyFromL2ToL2Messenger() - // address _crossDomainSender, - // address _sender, - // address _from, - // address _to, - // uint256 _amount - public - { - address _crossDomainSender = address(263400868551549723330807389252719309078400616203); - address _sender = address(376793390874373408599387495934666716005045108771); - address _from = address(645326474426547203313410069153905908525362434350); - address _to = address(728815563385977040452943777879061427756277306519); - uint256 _amount = 0; - - /* Precondition */ - MESSENGER.forTest_setCustomCrossDomainSender(_crossDomainSender); - - // Expect the cross domain sender to be emitted so after confirming it matches, we can use it for checks - - vm.prank(_sender); - /* Action */ - try sourceToken.relayERC20(_from, _to, _amount) { - /* Postconditions */ - assert(_sender == address(MESSENGER) && MESSENGER.customCrossDomainSender() == address(sourceToken)); - } catch { - // Emit to bypass the check when the call fails - assert(_sender != address(MESSENGER) || MESSENGER.customCrossDomainSender() != address(sourceToken)); - } - } - // VV1__sender_114b9705 = 376793390874373408599387495934666716005045108771 - // VV3__to_114b9705 = 728815563385977040452943777879061427756277306519 - // VV0__crossDomainSender_114b9705 = 263400868551549723330807389252719309078400616203 - // ORIGIN_ID = 645326474426547203313410069153905908525362434350 - // CALLER_ID = 645326474426547203313410069153905908525362434350 - // VV4__amount_114b9705 = 0 - // VV2__from_114b9705 = 645326474426547203313410069153905908525362434350 - /// @custom:property-id 8 /// @custom:property `sendERC20` with a value of zero does not modify accounting function test_proveSendERC20ZeroCall() public { diff --git a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol index 8abad75d6fef..64cc8099e28c 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol @@ -49,6 +49,7 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /// @custom:property-id 6 /// @custom:property Calls to sendERC20 succeed as long as caller has enough balance function prove_sendERC20SucceedsOnlyIfEnoughBalance( + uint256 _initialBalance, address _from, uint256 _amount, address _to, @@ -58,8 +59,6 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { { setUpInlined(); - kevm.symbolicStorage(address(sourceToken)); - /* Preconditions */ vm.assume(_to != address(0)); vm.assume(_from != address(0)); @@ -68,10 +67,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(notBuiltinAddress(_to)); // Can't deal to unsupported cheatcode - // vm.prank(Predeploys.L2_STANDARD_BRIDGE); - // sourceToken.mint(_from, _initialBalance); - - uint256 _initialBalance = sourceToken.balanceOf(_from); + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + sourceToken.mint(_from, _initialBalance); vm.prank(_from); /* Action */ @@ -102,8 +99,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(notBuiltinAddress(_to)); vm.assume(notBuiltinAddress(_sender)); - kevm.symbolicStorage(address(MESSENGER)); - // MESSENGER.forTest_setCustomCrossDomainSender(_crossDomainSender); + // kevm.symbolicStorage(address(MESSENGER)); + MESSENGER.forTest_setCustomCrossDomainSender(_crossDomainSender); vm.prank(_sender); /* Action */ @@ -256,10 +253,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(_from != address(0)); vm.assume(notBuiltinAddress(_from)); - // vm.prank(Predeploys.L2_STANDARD_BRIDGE); - // sourceToken.mint(_from, _amount); - - kevm.symbolicStorage(address(sourceToken)); + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + sourceToken.mint(_from, _amount); uint256 _totalSupplyBefore = sourceToken.totalSupply(); uint256 _balanceBefore = sourceToken.balanceOf(_from); @@ -298,7 +293,8 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(_to != address(0)); vm.assume(_from != address(0)); - kevm.symbolicStorage(address(sourceToken)); + vm.prank(Predeploys.L2_STANDARD_BRIDGE); + sourceToken.mint(_from, _amount); uint256 fromBalanceBefore = sourceToken.balanceOf(_from); uint256 toBalanceBefore = destToken.balanceOf(_to); From 6b83938c04efeed7da682dca0f94ade4845de0a1 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Sat, 7 Sep 2024 15:20:07 -0300 Subject: [PATCH 36/56] chore: add quotes on kontrol toml --- packages/contracts-bedrock/kontrol.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/kontrol.toml b/packages/contracts-bedrock/kontrol.toml index dcd4d584e2af..4970211ee7a2 100644 --- a/packages/contracts-bedrock/kontrol.toml +++ b/packages/contracts-bedrock/kontrol.toml @@ -31,7 +31,7 @@ break-on-cheatcodes = false run-constructor = true symbolic-immutables = false schedule = CANCUN -init-node-from = supererc20-state-diff/StateDiff.json +init-node-from = 'supererc20-state-diff/StateDiff.json' [show.default] foundry-project-root = '.' From b4dd8dff5c03e61b72c3e2868745eb548c627860 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Sat, 7 Sep 2024 15:23:28 -0300 Subject: [PATCH 37/56] chore: update models to run on foundry debug, they dont fail on foundry --- .../properties/FoundryDebugSymbolic.t.sol | 68 ++++--------------- 1 file changed, 12 insertions(+), 56 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol b/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol index fb01e0ec40b7..8fbe8e5c668b 100644 --- a/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol +++ b/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol @@ -70,8 +70,8 @@ contract FoundryDebugTests is KontrolBase { /// @custom:property `sendERC20` with a value of zero does not modify accounting function test_proveSendERC20ZeroCall() public { /* Preconditions */ - address _from = address(376793390874373408599387495934666716005045108772); // 0x4200000000000000000000000000000000000024 - address _to = address(728815563385977040452943777879061427756277306519); // 0x7Fa9385Be102aC3eac297483DD6233d62B3e1497 + address _from = address(511347974759188522659820409854212399244223280810); + address _to = address(376793390874373408599387495934666716005045108769); // 0x7Fa9385Be102aC3eac297483DD6233d62B3e1497 uint256 _chainId = 0; uint256 _totalSupplyBefore = sourceToken.totalSupply(); @@ -87,20 +87,19 @@ contract FoundryDebugTests is KontrolBase { assert(sourceToken.balanceOf(_from) == _fromBalanceBefore); assert(sourceToken.balanceOf(_to) == _toBalanceBefore); } - - // VV2__chainId_114b9705 = 0 - // VV0__from_114b9705 = 376793390874373408599387495934666716005045108772 - // NUMBER_CELL = 16777217 - // VV1__to_114b9705 = 728815563385977040452943777879061427756277306519 + // ORIGIN_ID = 645326474426547203313410069153905908525362434350 // CALLER_ID = 645326474426547203313410069153905908525362434350 + // NUMBER_CELL = 16777217 + // VV2__chainId_114b9705 = 0 + // VV0__from_114b9705 = 511347974759188522659820409854212399244223280810 // TIMESTAMP_CELL = 1073741825 - // ORIGIN_ID = 645326474426547203313410069153905908525362434350 + // VV1__to_114b9705 = 376793390874373408599387495934666716005045108769 /// @custom:property-id 9 /// @custom:property `relayERC20` with a value of zero does not modify accounting function test_proveRelayERC20ZeroCall() public { /* Preconditions */ - address _from = address(728815563385977040452943777879061427756277306519); + address _from = address(645326474426547203313410069153905908525362434350); address _to = address(728815563385977040452943777879061427756277306519); uint256 _totalSupplyBefore = sourceToken.totalSupply(); @@ -116,53 +115,10 @@ contract FoundryDebugTests is KontrolBase { assert(sourceToken.balanceOf(_from) == _fromBalanceBefore); assert(sourceToken.balanceOf(_to) == _toBalanceBefore); } - // NUMBER_CELL = 16777217 - // VV1__to_114b9705 = 728815563385977040452943777879061427756277306519 - // CALLER_ID = 645326474426547203313410069153905908525362434350 - // TIMESTAMP_CELL = 1073741825 + // VV0__from_114b9705 = 645326474426547203313410069153905908525362434350 // ORIGIN_ID = 645326474426547203313410069153905908525362434350 - // VV0__from_114b9705 = 728815563385977040452943777879061427756277306519 - - function test_proveCrossChainSendERC20() public { - /* Preconditions */ - address _from = address(728815563385977040452943777879061427756277306519); - address _to = address(728815563385977040452943777879061427756277306519); - uint256 _amount = 0; - uint256 _chainId = 0; - // Mint the amount to send - vm.prank(Predeploys.L2_STANDARD_BRIDGE); - sourceToken.mint(_from, _amount); - - uint256 fromBalanceBefore = sourceToken.balanceOf(_from); - uint256 toBalanceBefore = destToken.balanceOf(_to); - uint256 sourceTotalSupplyBefore = sourceToken.totalSupply(); - uint256 destTotalSupplyBefore = destToken.totalSupply(); - - vm.prank(_from); - /* Action */ - try sourceToken.sendERC20(_to, _amount, _chainId) { - /* Postconditions */ - // Source - assert(sourceToken.balanceOf(_from) == fromBalanceBefore - _amount); - assert(sourceToken.totalSupply() == sourceTotalSupplyBefore - _amount); - - // Destination - if (_chainId == DESTINATION_CHAIN_ID) { - // If the destination chain matches the one of the dest token, check that the amount was minted - assert(destToken.balanceOf(_to) == toBalanceBefore + _amount); - assert(destToken.totalSupply() == destTotalSupplyBefore + _amount); - } else { - // Otherwise the balances should remain the same - assert(destToken.balanceOf(_to) == toBalanceBefore); - assert(destToken.totalSupply() == destTotalSupplyBefore); - } - } catch { - // Shouldn't fail - assert(false); - } - } + // CALLER_ID = 645326474426547203313410069153905908525362434350 + // NUMBER_CELL = 16777217 // VV1__to_114b9705 = 728815563385977040452943777879061427756277306519 - // VV0__from_114b9705 = 728815563385977040452943777879061427756277306519 - // VV2__amount_114b9705 = 0 - // VV3__chainId_114b9705 = 0 + // TIMESTAMP_CELL = 1073741825 } From 9633e793be688ba498f3ee2d7d690793ff97dc26 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Mon, 9 Sep 2024 15:34:23 -0300 Subject: [PATCH 38/56] fix: kontrol toml file --- packages/contracts-bedrock/kontrol.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/contracts-bedrock/kontrol.toml b/packages/contracts-bedrock/kontrol.toml index 4970211ee7a2..4a7b02a4f85b 100644 --- a/packages/contracts-bedrock/kontrol.toml +++ b/packages/contracts-bedrock/kontrol.toml @@ -30,8 +30,8 @@ break-on-basic-blocks = false break-on-cheatcodes = false run-constructor = true symbolic-immutables = false -schedule = CANCUN -init-node-from = 'supererc20-state-diff/StateDiff.json' +schedule = 'CANCUN' +init-node-from-diff = 'supererc20-state-diff/StateDiff.json' [show.default] foundry-project-root = '.' From f6a03efb2189270d6c542b69ca2fca121e9d050e Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:08:28 -0300 Subject: [PATCH 39/56] fix: kontrol toml --- packages/contracts-bedrock/kontrol.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/contracts-bedrock/kontrol.toml b/packages/contracts-bedrock/kontrol.toml index 4a7b02a4f85b..998cd05b41f3 100644 --- a/packages/contracts-bedrock/kontrol.toml +++ b/packages/contracts-bedrock/kontrol.toml @@ -10,7 +10,7 @@ auxiliary-lemmas = true # module-import = 'TestBase:KONTROL-LEMMAS' [prove.default] -foundry-project-root = '.' +foundry-project-root = './' verbose = false debug = false max-depth = 25000 @@ -31,7 +31,7 @@ break-on-cheatcodes = false run-constructor = true symbolic-immutables = false schedule = 'CANCUN' -init-node-from-diff = 'supererc20-state-diff/StateDiff.json' +init-node-from = 'supererc20-state-diff/StateDiff.json' [show.default] foundry-project-root = '.' From 6a9b8bd229bde15c4884525ae2ccc6ab94e8a2b0 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Mon, 9 Sep 2024 18:14:21 -0300 Subject: [PATCH 40/56] chore: remove unnecessary changes --- .../test/kontrol/scripts/run-kontrol.sh | 3 +- .../kontrol/optimism-superchain-lemmas.md | 33 ------------------- 2 files changed, 1 insertion(+), 35 deletions(-) delete mode 100644 packages/contracts-bedrock/test/properties/kontrol/optimism-superchain-lemmas.md diff --git a/packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh b/packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh index e87527086aeb..2d61b4243fe6 100755 --- a/packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh +++ b/packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh @@ -140,8 +140,7 @@ if [ "$SCRIPT_TESTS" == true ]; then "L1StandardBridgeKontrol.prove_finalizeBridgeERC20_paused" \ "L1StandardBridgeKontrol.prove_finalizeBridgeETH_paused" \ "L1ERC721BridgeKontrol.prove_finalizeBridgeERC721_paused" \ - "L1CrossDomainMessengerKontrol.prove_relayMessage_paused" \ - "OptimismSuperchainERC20Kontrol.prove_setup" + "L1CrossDomainMessengerKontrol.prove_relayMessage_paused" ) elif [ "$CUSTOM_TESTS" != 0 ]; then test_list=( "${@:${CUSTOM_TESTS}}" ) diff --git a/packages/contracts-bedrock/test/properties/kontrol/optimism-superchain-lemmas.md b/packages/contracts-bedrock/test/properties/kontrol/optimism-superchain-lemmas.md deleted file mode 100644 index 6cb29280402f..000000000000 --- a/packages/contracts-bedrock/test/properties/kontrol/optimism-superchain-lemmas.md +++ /dev/null @@ -1,33 +0,0 @@ -```k -requires "foundry.md" - -module OPTIMISM-SUPERCHAIN-LEMMAS - imports BOOL - imports FOUNDRY - imports INT-SYMBOLIC - - // Convert booleans to their word equivalents - rule bool2Word(true) => 1 - rule bool2Word(false) => 0 - - // Associativity and Commutativity Rules: - rule A +Int (B +Int C) => (A +Int B) +Int C - rule A *Int B => B *Int A - - // Comparison Normalization: - rule A +Int B A A false requires 0 <=Int B - rule A false requires 0 <=Int B - - rule A -Int A => 0 - rule 0 +Int A => A - rule A +Int 0 => A - rule A -Int 0 => A - - rule chop(I) => I requires #rangeUInt(256, I) - rule chop (chop (X:Int) +Int Y:Int) => chop (X +Int Y) - rule chop (X:Int +Int chop (Y:Int)) => chop (X +Int Y) -endmodule -``` From a9b30501ba9368959386fc0be3d2f9dc462a0a2e Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:16:22 -0300 Subject: [PATCH 41/56] chore: remove halmos --- .gitmodules | 3 - packages/contracts-bedrock/foundry.toml | 8 +- packages/contracts-bedrock/halmos.toml | 15 - packages/contracts-bedrock/justfile | 6 - .../contracts-bedrock/lib/halmos-cheatcodes | 1 - .../test/invariants/PROPERTIES.md | 64 ++-- .../test/properties/PROPERTIES.md | 100 +++--- .../properties/halmos/MockL2ToL2Messenger.sol | 65 ---- .../halmos/OptimismSuperchainERC20.t.sol | 302 ------------------ .../test/properties/helpers/HalmosBase.sol | 19 -- 10 files changed, 83 insertions(+), 500 deletions(-) delete mode 100644 packages/contracts-bedrock/halmos.toml delete mode 160000 packages/contracts-bedrock/lib/halmos-cheatcodes delete mode 100644 packages/contracts-bedrock/test/properties/halmos/MockL2ToL2Messenger.sol delete mode 100644 packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol delete mode 100644 packages/contracts-bedrock/test/properties/helpers/HalmosBase.sol diff --git a/.gitmodules b/.gitmodules index 222d45be7ccc..21ecaedbb77a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -29,6 +29,3 @@ [submodule "packages/contracts-bedrock/lib/openzeppelin-contracts-v5"] path = packages/contracts-bedrock/lib/openzeppelin-contracts-v5 url = https://github.com/OpenZeppelin/openzeppelin-contracts -[submodule "packages/contracts-bedrock/lib/halmos-cheatcodes"] - path = packages/contracts-bedrock/lib/halmos-cheatcodes - url = https://github.com/a16z/halmos-cheatcodes diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 1e268eadb67b..03cccb74539e 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -21,8 +21,7 @@ remappings = [ 'ds-test/=lib/forge-std/lib/ds-test/src', 'safe-contracts/=lib/safe-contracts/contracts', 'kontrol-cheatcodes/=lib/kontrol-cheatcodes/src', - 'gelato/=lib/automate/contracts', - 'halmos-cheatcodes/=lib/halmos-cheatcodes/' + 'gelato/=lib/automate/contracts' ] extra_output = ['devdoc', 'userdoc', 'metadata', 'storageLayout'] bytecode_hash = 'none' @@ -104,11 +103,6 @@ src = 'test/properties/medusa/' test = 'test/properties/medusa/' script = 'test/properties/medusa/' -[profile.halmos] -src = 'test/properties/halmos/' -test = 'test/properties/halmos/' -script = 'test/properties/halmos/' - [profile.kontrol-properties] src = "test/properties/kontrol" test = "test/properties/kontrol" diff --git a/packages/contracts-bedrock/halmos.toml b/packages/contracts-bedrock/halmos.toml deleted file mode 100644 index c431c6c3a532..000000000000 --- a/packages/contracts-bedrock/halmos.toml +++ /dev/null @@ -1,15 +0,0 @@ -# Halmos configuration file - -## The version needed is `halmos 0.1.15.dev2+gc3f45dd` -## Just running `halmos` will run the tests with the default configuration - -[global] -# Contract to test -match-contract = "SymTest_" - -# Path to the Forge artifacts directory -forge_build_out = "./forge-artifacts" - - -# Storage layout -storage_layout = "generic" \ No newline at end of file diff --git a/packages/contracts-bedrock/justfile b/packages/contracts-bedrock/justfile index 696809d86476..b770adbe3552 100644 --- a/packages/contracts-bedrock/justfile +++ b/packages/contracts-bedrock/justfile @@ -30,12 +30,6 @@ test-medusa timeout='100': FOUNDRY_PROFILE=medusa medusa fuzz --timeout {{timeout}} -test-halmos-all VERBOSE="-v": - FOUNDRY_PROFILE=halmos halmos {{VERBOSE}} - -test-halmos TEST VERBOSE="-v": - FOUNDRY_PROFILE=halmos halmos --function {{TEST}} {{VERBOSE}} - test-rerun: build-go-ffi forge test --rerun -vvv diff --git a/packages/contracts-bedrock/lib/halmos-cheatcodes b/packages/contracts-bedrock/lib/halmos-cheatcodes deleted file mode 160000 index c0d865508c0f..000000000000 --- a/packages/contracts-bedrock/lib/halmos-cheatcodes +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c0d865508c0fee0a11b97732c5e90f9cad6b65a5 diff --git a/packages/contracts-bedrock/test/invariants/PROPERTIES.md b/packages/contracts-bedrock/test/invariants/PROPERTIES.md index 5a5cc71d73b5..f06c9be65f16 100644 --- a/packages/contracts-bedrock/test/invariants/PROPERTIES.md +++ b/packages/contracts-bedrock/test/invariants/PROPERTIES.md @@ -10,56 +10,56 @@ legend: ## Unit test -| id | description | halmos | medusa | -| --- | ---------------------------------------------------------------------------------- | ------ | ------ | -| 0 | supertoken token address does not depend on the executing chain’s chainID | [ ] | [ ] | -| 1 | supertoken token address depends on name, remote token, address and decimals | [ ] | [ ] | -| 2 | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | [ ] | -| 3 | convert() only allows migrations between tokens representing the same remote asset | [ ] | [ ] | -| 4 | convert() only allows migrations from tokens with the same decimals | [ ] | [ ] | -| 5 | convert() burns the same amount of one token that it mints of the other | [ ] | [ ] | +| id | description | kontrol | medusa | +| --- | ---------------------------------------------------------------------------------- | ------- | ------ | +| 0 | supertoken token address does not depend on the executing chain’s chainID | [ ] | [ ] | +| 1 | supertoken token address depends on name, remote token, address and decimals | [ ] | [ ] | +| 2 | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | [ ] | +| 3 | convert() only allows migrations between tokens representing the same remote asset | [ ] | [ ] | +| 4 | convert() only allows migrations from tokens with the same decimals | [ ] | [ ] | +| 5 | convert() burns the same amount of one token that it mints of the other | [ ] | [ ] | ## Valid state -| id | description | halmos | medusa | +| id | description | kontrol | medusa | | --- | ------------------------------------------------------------------------------------------ | ------- | ------ | | 6 | calls to sendERC20 succeed as long as caller has enough balance | [x] | [ ] | | 7 | calls to relayERC20 always succeed as long as the sender and cross-domain caller are valid | **[~]** | [ ] | ## Variable transition -| id | description | halmos | medusa | -| --- | ------------------------------------------------------------------------------------------------- | ------ | ------ | -| 8 | sendERC20 with a value of zero does not modify accounting | [x] | [ ] | -| 9 | relayERC20 with a value of zero does not modify accounting | [x] | [ ] | -| 10 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | [ ] | -| 11 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [x] | [ ] | -| 12 | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [x] | [ ] | -| 13 | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [x] | [ ] | -| 14 | supertoken total supply starts at zero | [x] | [ ] | -| 15 | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | -| 16 | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | +| id | description | kontrol | medusa | +| --- | ------------------------------------------------------------------------------------------------- | ------- | ------ | +| 8 | sendERC20 with a value of zero does not modify accounting | [x] | [ ] | +| 9 | relayERC20 with a value of zero does not modify accounting | [x] | [ ] | +| 10 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | [ ] | +| 11 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [x] | [ ] | +| 12 | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [x] | [ ] | +| 13 | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [x] | [ ] | +| 14 | supertoken total supply starts at zero | [x] | [ ] | +| 15 | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | +| 16 | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | ## High level -| id | description | halmos | medusa | -| --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ------ | -| 17 | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | [ ] | -| 18 | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | [ ] | -| 19 | sum of total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | -| 20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | [ ] | -| 21 | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [ ] | [ ] | +| id | description | kontrol | medusa | +| --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | +| 17 | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | [ ] | +| 18 | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | [ ] | +| 19 | sum of total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | +| 20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | [ ] | +| 21 | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [ ] | [ ] | ## Atomic bridging pseudo-properties As another layer of defense, the following properties are defined which assume bridging operations to be atomic (that is, the sequencer and L2Inbox and CrossDomainMessenger contracts are fully abstracted away, `sendERC20` triggering the `relayERC20` call on the same transaction) It’s worth noting that these properties will not hold for a live system -| id | description | halmos | medusa | -| --- | ---------------------------------------------------------------------------------------------------------------------------------- | ------ | ------ | -| 22 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [x] | -| 23 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [x] | -| 24 | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [~] | +| id | description | kontrol | medusa | +| --- | ---------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | +| 22 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [x] | +| 23 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [x] | +| 24 | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [~] | # Expected external interactions diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md index 25dc9b036d3b..f6876df77469 100644 --- a/packages/contracts-bedrock/test/properties/PROPERTIES.md +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -5,7 +5,7 @@ This document defines a set of properties global to the supertoken ecosystem, for which we will: - run a [Medusa](https://github.com/crytic/medusa) fuzzing campaign, trying to break system invariants -- formally prove with [Halmos](https://github.com/a16z/halmos) whenever possible +- formally prove with [Kontrol](https://docs.runtimeverification.com/kontrol) whenever possible ## Milestones @@ -23,33 +23,33 @@ Given the [OP monorepo](https://github.com/ethereum-optimism/optimism) already h - including it in the mainline OP monorepo, in a subdirectory of the existing test contracts such as `test/invariants/medusa/superc20/` - keep the campaign in wonderland's fork of the repository, in its own feature branch, in which case the deliverable would consist primarily of: - - a summary of the results, extending this document - - PRs with extra unit tests replicating found issues to the main repo where applicable + - a summary of the results, extending this document + - PRs with extra unit tests replicating found issues to the main repo where applicable ## Contracts in scope -- [ ] [OptimismMintableERC20Factory](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol) (modifications to enable `convert` not yet merged) -- [ ] [OptimismSuperchainERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol1) -- [ ] [OptimismSuperchainERC20Factory](https://github.com/defi-wonderland/optimism/pull/8/files#diff-09838f5703c353d0f7c5ff395acc04c1768ef58becac67404bc17e1fb0018517) (not yet merged) -- [ ] [L2StandardBridgeInterop](https://github.com/defi-wonderland/optimism/pull/10/files#diff-56cf869412631eac0a04a03f7d026596f64a1e00fcffa713bc770d67c6856c2f) (not yet merged) +- [ ] [OptimismMintableERC20Factory](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20Factory.sol) (modifications to enable `convert` not yet merged) +- [ ] [OptimismSuperchainERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/L2/OptimismSuperchainERC20.sol1) +- [ ] [OptimismSuperchainERC20Factory](https://github.com/defi-wonderland/optimism/pull/8/files#diff-09838f5703c353d0f7c5ff395acc04c1768ef58becac67404bc17e1fb0018517) (not yet merged) +- [ ] [L2StandardBridgeInterop](https://github.com/defi-wonderland/optimism/pull/10/files#diff-56cf869412631eac0a04a03f7d026596f64a1e00fcffa713bc770d67c6856c2f) (not yet merged) ## Behavior assumed correct -- [ ] inclusion of relay transactions -- [ ] sequencer implementation -- [ ] [OptimismMintableERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol) -- [ ] [L2ToL2CrossDomainMessenger](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol) -- [ ] [CrossL2Inbox](https://github.com/defi-wonderland/src/L2/CrossL2Inbox.sol) +- [ ] inclusion of relay transactions +- [ ] sequencer implementation +- [ ] [OptimismMintableERC20](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/universal/OptimismMintableERC20.sol) +- [ ] [L2ToL2CrossDomainMessenger](https://github.com/defi-wonderland/optimism/blob/develop/packages/contracts-bedrock/src/L2/L2CrossDomainMessenger.sol) +- [ ] [CrossL2Inbox](https://github.com/defi-wonderland/src/L2/CrossL2Inbox.sol) ## Pain points -- existing fuzzing tools use the same EVM to run the tested contracts as they do for asserting invariants, tracking ghost variables and everything else necessary to provision a fuzzing campaign. While this is usually very convenient, it means that we can’t assert on the behaviour/state of *different* chains from within a fuzzing campaign. This means we will have to walk around the requirement of supertokens having the same address across all chains, and implement a way to mock tokens existing in different chains. We will strive to formally prove it in a unitary fashion to mitigate this in properties 0 and 1 +- existing fuzzing tools use the same EVM to run the tested contracts as they do for asserting invariants, tracking ghost variables and everything else necessary to provision a fuzzing campaign. While this is usually very convenient, it means that we can’t assert on the behaviour/state of _different_ chains from within a fuzzing campaign. This means we will have to walk around the requirement of supertokens having the same address across all chains, and implement a way to mock tokens existing in different chains. We will strive to formally prove it in a unitary fashion to mitigate this in properties 0 and 1 - a buffer to represent 'in transit' messages should be implemented to assert on invariants relating to the non-atomicity of bridging from one chain to another. It is yet to be determined if it’ll be a FIFO queue (assuming ideal message ordering by sequencers) or it’ll have random-access capability to simulate messages arriving out of order ## Definitions -- *legacy token:* an OptimismMintableERC20 or L2StandardERC20 token on the suprechain that has either been deployed by the factory after the liquidity migration upgrade to the latter, or has been deployed before it **but** added to factory’s `deployments` mapping as part of the upgrade. This testing campaign is not concerned with tokens on L1 or not listed in the factory’s `deployments` mapping. -- *supertoken:* a SuperchainERC20 contract deployed by the `OptimismSuperchainERC20Factory` +- _legacy token:_ an OptimismMintableERC20 or L2StandardERC20 token on the suprechain that has either been deployed by the factory after the liquidity migration upgrade to the latter, or has been deployed before it **but** added to factory’s `deployments` mapping as part of the upgrade. This testing campaign is not concerned with tokens on L1 or not listed in the factory’s `deployments` mapping. +- _supertoken:_ a SuperchainERC20 contract deployed by the `OptimismSuperchainERC20Factory` # Ecosystem properties @@ -63,56 +63,56 @@ legend: ## Unit test -| id | milestone | description | halmos | medusa | -| --- | --- | --- | --- | --- | -| 0 | Factories | supertoken token address does not depend on the executing chain’s chainID | [ ] | [ ] | -| 1 | Factories | supertoken token address depends on remote token, name, symbol and decimals | [ ] | [ ] | -| 2 | Liquidity Migration | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | [ ] | -| 3 | Liquidity Migration | convert() only allows migrations between tokens representing the same remote asset | [ ] | [ ] | -| 4 | Liquidity Migration | convert() only allows migrations from tokens with the same decimals | [ ] | [ ] | -| 5 | Liquidity Migration | convert() burns the same amount of legacy token that it mints of supertoken, and viceversa | [ ] | [ ] | +| id | milestone | description | kontrol | medusa | +| --- | ------------------- | ------------------------------------------------------------------------------------------ | ------- | ------ | +| 0 | Factories | supertoken token address does not depend on the executing chain’s chainID | [ ] | [ ] | +| 1 | Factories | supertoken token address depends on remote token, name, symbol and decimals | [ ] | [ ] | +| 2 | Liquidity Migration | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | [ ] | +| 3 | Liquidity Migration | convert() only allows migrations between tokens representing the same remote asset | [ ] | [ ] | +| 4 | Liquidity Migration | convert() only allows migrations from tokens with the same decimals | [ ] | [ ] | +| 5 | Liquidity Migration | convert() burns the same amount of legacy token that it mints of supertoken, and viceversa | [ ] | [ ] | ## Valid state -| id | milestone | description | halmos | medusa | -| --- | --- | --- | --- | --- | +| id | milestone | description | kontrol | medusa | +| --- | --------- | ------------------------------------------------------------------------------------------ | ------- | ------ | | 6 | SupERC20 | calls to sendERC20 succeed as long as caller has enough balance | [x] | [ ] | | 7 | SupERC20 | calls to relayERC20 always succeed as long as the sender and cross-domain caller are valid | **[~]** | [ ] | ## Variable transition -| id | milestone | description | halmos | medusa | -| --- | --- | --- | --- | --- | -| 8 | SupERC20 | sendERC20 with a value of zero does not modify accounting | [x] | [ ] | -| 9 | SupERC20 | relayERC20 with a value of zero does not modify accounting | [x] | [ ] | -| 10 | SupERC20 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | [ ] | -| 11 | SupERC20 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [x] | [ ] | -| 12 | Liquidity Migration | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [x] | [~] | -| 13 | Liquidity Migration | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [x] | [ ] | -| 14 | SupERC20 | supertoken total supply starts at zero | [x] | [x] | -| 15 | Factories | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | -| 16 | Factories | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | +| id | milestone | description | kontrol | medusa | +| --- | ------------------- | ------------------------------------------------------------------------------------------------- | ------- | ------ | +| 8 | SupERC20 | sendERC20 with a value of zero does not modify accounting | [x] | [ ] | +| 9 | SupERC20 | relayERC20 with a value of zero does not modify accounting | [x] | [ ] | +| 10 | SupERC20 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | [ ] | +| 11 | SupERC20 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [x] | [ ] | +| 12 | Liquidity Migration | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [x] | [~] | +| 13 | Liquidity Migration | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [x] | [ ] | +| 14 | SupERC20 | supertoken total supply starts at zero | [x] | [x] | +| 15 | Factories | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | +| 16 | Factories | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | ## High level -| id | milestone | description | halmos | medusa | -| --- | --- | --- | --- | --- | -| 17 | Liquidity Migration | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | [ ] | -| 18 | Liquidity Migration | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | [ ] | -| 19 | Liquidity Migration | sum of supertoken total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | -| 20 | SupERC20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | [ ] | -| 21 | Liquidity Migration | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [ ] | [ ] | +| id | milestone | description | kontrol | medusa | +| --- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | +| 17 | Liquidity Migration | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | [ ] | +| 18 | Liquidity Migration | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | [ ] | +| 19 | Liquidity Migration | sum of supertoken total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | +| 20 | SupERC20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | [ ] | +| 21 | Liquidity Migration | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [ ] | [ ] | ## Atomic bridging pseudo-properties As another layer of defense, the following properties are defined which assume bridging operations to be atomic (that is, the sequencer and L2Inbox and CrossDomainMessenger contracts are fully abstracted away, `sendERC20` triggering the `relayERC20` call on the same transaction) It’s worth noting that these properties will not hold for a live system -| id | milestone | description | halmos | medusa | -| --- | --- | --- | --- | --- | -| 22 | SupERC20 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [x] | -| 23 | SupERC20 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [x] | -| 24 | Liquidity Migration | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [~] | +| id | milestone | description | kontrol | medusa | +| --- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | +| 22 | SupERC20 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [x] | +| 23 | SupERC20 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [x] | +| 24 | Liquidity Migration | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [~] | # Expected external interactions @@ -122,5 +122,5 @@ It’s worth noting that these properties will not hold for a live system here we’ll list possible interactions that we intend the fuzzing campaign to support in order to help break invariants -- [ ] changing the decimals of tokens after deployment -- [ ] `convert()` ing between multiple (3+) representations of the same remote token, by having different names/symbols +- [ ] changing the decimals of tokens after deployment +- [ ] `convert()` ing between multiple (3+) representations of the same remote token, by having different names/symbols diff --git a/packages/contracts-bedrock/test/properties/halmos/MockL2ToL2Messenger.sol b/packages/contracts-bedrock/test/properties/halmos/MockL2ToL2Messenger.sol deleted file mode 100644 index 5f7aa3b301e7..000000000000 --- a/packages/contracts-bedrock/test/properties/halmos/MockL2ToL2Messenger.sol +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.25; - -import "src/L2/L2ToL2CrossDomainMessenger.sol"; -import { SafeCall } from "src/libraries/SafeCall.sol"; - -// TODO: Try to merge to a single mocked contract used by fuzzing and symbolic invariant tests - only if possible -// and is a low priorty -contract MockL2ToL2Messenger is IL2ToL2CrossDomainMessenger { - /// NOTE: Setting everything as immutable bc the storage layour is ignored when etching. - address internal immutable SOURCE_TOKEN; - address internal immutable DESTINATION_TOKEN; - uint256 public immutable DESTINATION_CHAIN_ID; - // Custom cross domain sender to be used when neither the source nor destination token are the callers - address internal immutable CUSTOM_CROSS_DOMAIN_SENDER; - - constructor( - address _sourceToken, - address _destinationToken, - uint256 _destinationChainId, - address _customCrossDomainSender - ) { - SOURCE_TOKEN = _sourceToken; - DESTINATION_TOKEN = _destinationToken; - DESTINATION_CHAIN_ID = _destinationChainId; - CUSTOM_CROSS_DOMAIN_SENDER = _customCrossDomainSender; - } - - function sendMessage(uint256 _destination, address, bytes calldata _message) external payable { - // Mocking the environment to allow atomicity by executing the message call - if (_destination == DESTINATION_CHAIN_ID) { - (bool _success) = SafeCall.call(DESTINATION_TOKEN, 0, _message); - if (!_success) revert("MockL2ToL2Messenger: sendMessage failed"); - } - } - - function relayMessage( - uint256, - uint256, - uint256, - address, - address _target, - bytes calldata _message - ) - external - payable - { - (bool succ, bytes memory ret) = _target.call{ value: msg.value }(_message); - if (!succ) revert(string(ret)); - - // TODO: Add more logic? Like replacing the (unsupported) `TSTORE` updates with `SSTORE` - or add the checks - } - - function crossDomainMessageSource() external view returns (uint256 _source) { - _source = block.chainid + 1; - } - - // Mock this function so it just always returns the expected if called by the supertoken, or otherwise defaults to - // the custom cross domain sender - function crossDomainMessageSender() external view returns (address _sender) { - if (msg.sender == SOURCE_TOKEN) _sender = SOURCE_TOKEN; - else if (msg.sender == DESTINATION_TOKEN) _sender = DESTINATION_TOKEN; - else _sender = CUSTOM_CROSS_DOMAIN_SENDER; - } -} diff --git a/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol b/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol deleted file mode 100644 index 37c591f24a63..000000000000 --- a/packages/contracts-bedrock/test/properties/halmos/OptimismSuperchainERC20.t.sol +++ /dev/null @@ -1,302 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.25; - -import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; -import { SymTest } from "halmos-cheatcodes/src/SymTest.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; -import { MockL2ToL2Messenger } from "./MockL2ToL2Messenger.sol"; -import { HalmosBase } from "../helpers/HalmosBase.sol"; - -contract SymTest_OptimismSuperchainERC20 is SymTest, HalmosBase { - MockL2ToL2Messenger internal constant MESSENGER = MockL2ToL2Messenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); - - OptimismSuperchainERC20 public superchainERC20Impl; - OptimismSuperchainERC20 internal sourceToken; - OptimismSuperchainERC20 internal destToken; - - function setUp() public { - // Deploy the OptimismSuperchainERC20 contract implementation and the proxy to be used - superchainERC20Impl = new OptimismSuperchainERC20(); - sourceToken = OptimismSuperchainERC20( - address( - // TODO: Update to beacon proxy - new ERC1967Proxy( - address(superchainERC20Impl), - abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) - ) - ) - ); - - destToken = OptimismSuperchainERC20( - address( - // TODO: Update to beacon proxy - new ERC1967Proxy( - address(superchainERC20Impl), - abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) - ) - ) - ); - - // Etch the mocked L2 to L2 Messenger since the messenger logic is out of scope for these test suite. Also, we - // avoid issues such as `TSTORE` opcode not being supported, or issues with `encodeVersionedNonce()` - address _mockL2ToL2CrossDomainMessenger = - address(new MockL2ToL2Messenger(address(sourceToken), address(destToken), DESTINATION_CHAIN_ID, address(0))); - vm.etch(address(MESSENGER), _mockL2ToL2CrossDomainMessenger.code); - // NOTE: We need to set the crossDomainMessageSender as an immutable or otherwise storage vars and not taken - // into account when etching on halmos. Setting a constant slot with setters and getters didn't work neither. - } - - /// @notice Check setup works as expected - function check_setup() public { - // Source token - assert(remoteToken != address(0)); - assert(sourceToken.remoteToken() == remoteToken); - assert(eqStrings(sourceToken.name(), name)); - assert(eqStrings(sourceToken.symbol(), symbol)); - assert(sourceToken.decimals() == decimals); - vm.prank(address(sourceToken)); - assert(MESSENGER.crossDomainMessageSender() == address(sourceToken)); - - // Destination token - assert(destToken.remoteToken() == remoteToken); - assert(eqStrings(destToken.name(), name)); - assert(eqStrings(destToken.symbol(), symbol)); - assert(destToken.decimals() == decimals); - assert(MESSENGER.DESTINATION_CHAIN_ID() == DESTINATION_CHAIN_ID); - vm.prank(address(destToken)); - assert(MESSENGER.crossDomainMessageSender() == address(destToken)); - - // Custom cross domain sender - assert(MESSENGER.crossDomainMessageSender() == address(0)); - } - - /// @custom:property-id 6 - /// @custom:property Calls to sendERC20 succeed as long as caller has enough balance - function check_sendERC20SucceedsOnlyIfEnoughBalance( - uint256 _initialBalance, - address _from, - uint256 _amount, - address _to, - uint256 _chainId - ) - public - { - /* Preconditions */ - vm.assume(_to != address(0)); - vm.assume(_from != address(0)); - - // Can't deal to unsupported cheatcode - vm.prank(Predeploys.L2_STANDARD_BRIDGE); - sourceToken.mint(_from, _initialBalance); - - vm.prank(_from); - /* Action */ - try sourceToken.sendERC20(_to, _amount, _chainId) { - /* Postcondition */ - assert(_initialBalance >= _amount); - } catch { - assert(_initialBalance < _amount); - } - } - - /// @custom:property-id 7 - /// @custom:property Calls to relayERC20 always succeed as long as the sender the cross-domain caller are valid - function check_relayERC20OnlyFromL2ToL2Messenger( - address _crossDomainSender, - address _sender, - address _from, - address _to, - uint256 _amount - ) - public - { - /* Precondition */ - vm.assume(_to != address(0)); - // Deploying a new messenger because of an issue of not being able to etch the storage layout of the mock - // contract. So needed to a new one setting the symbolic immutable variable for the crossDomainSender. - // Used 0 address on source token so when the `soureToken` calls it if returns the symbolic `_crossDomainSender` - vm.etch( - address(MESSENGER), address(new MockL2ToL2Messenger(address(0), address(0), 0, _crossDomainSender)).code - ); - - vm.prank(_sender); - /* Action */ - try sourceToken.relayERC20(_from, _to, _amount) { - /* Postconditions */ - assert(_sender == address(MESSENGER) && MESSENGER.crossDomainMessageSender() == address(sourceToken)); - } catch { - assert(_sender != address(MESSENGER) || MESSENGER.crossDomainMessageSender() != address(sourceToken)); - } - } - - /// @custom:property-id 8 - /// @custom:property `sendERC20` with a value of zero does not modify accounting - function check_sendERC20ZeroCall(address _from, address _to, uint256 _chainId) public { - /* Preconditions */ - vm.assume(_to != address(0)); - vm.assume(_to != address(Predeploys.CROSS_L2_INBOX) && _to != address(MESSENGER)); - - uint256 _totalSupplyBefore = sourceToken.totalSupply(); - uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); - uint256 _toBalanceBefore = sourceToken.balanceOf(_to); - - vm.startPrank(_from); - /* Action */ - sourceToken.sendERC20(_to, ZERO_AMOUNT, _chainId); - - /* Postcondition */ - assert(sourceToken.totalSupply() == _totalSupplyBefore); - assert(sourceToken.balanceOf(_from) == _fromBalanceBefore); - assert(sourceToken.balanceOf(_to) == _toBalanceBefore); - } - - /// @custom:property-id 9 - /// @custom:property `relayERC20` with a value of zero does not modify accounting - function check_relayERC20ZeroCall(address _from, address _to) public { - uint256 _totalSupplyBefore = sourceToken.totalSupply(); - /* Preconditions */ - uint256 _fromBalanceBefore = sourceToken.balanceOf(_from); - uint256 _toBalanceBefore = sourceToken.balanceOf(_to); - vm.prank(address(MESSENGER)); - - /* Action */ - sourceToken.relayERC20(_from, _to, ZERO_AMOUNT); - - /* Postconditions */ - assert(sourceToken.totalSupply() == _totalSupplyBefore); - assert(sourceToken.balanceOf(_from) == _fromBalanceBefore); - assert(sourceToken.balanceOf(_to) == _toBalanceBefore); - } - - /// @custom:property-id 10 - /// @custom:property `sendERC20` decreases the token's totalSupply in the source chain exactly by the input amount - function check_sendERC20DecreasesTotalSupply( - address _sender, - address _to, - uint256 _amount, - uint256 _chainId - ) - public - { - /* Preconditions */ - vm.assume(_to != address(0)); - - vm.prank(Predeploys.L2_STANDARD_BRIDGE); - sourceToken.mint(_sender, _amount); - - uint256 _totalSupplyBefore = sourceToken.totalSupply(); - uint256 _balanceBefore = sourceToken.balanceOf(_sender); - - vm.prank(_sender); - /* Action */ - sourceToken.sendERC20(Predeploys.CROSS_L2_INBOX, _amount, _chainId); - - /* Postconditions */ - assert(sourceToken.totalSupply() == _totalSupplyBefore - _amount); - assert(sourceToken.balanceOf(_sender) == _balanceBefore - _amount); - } - - /// @custom:property-id 11 - /// @custom:property `relayERC20` increases the token's totalSupply in the destination chain exactly by the input - /// amount - function check_relayERC20IncreasesTotalSupply(address _from, address _to, uint256 _amount) public { - /* Preconditions */ - uint256 _totalSupplyBefore = sourceToken.totalSupply(); - uint256 _toBalanceBefore = sourceToken.balanceOf(_to); - - vm.prank(address(MESSENGER)); - /* Action */ - sourceToken.relayERC20(_from, _to, _amount); - - /* Postconditions */ - assert(sourceToken.totalSupply() == _totalSupplyBefore + _amount); - assert(sourceToken.balanceOf(_to) == _toBalanceBefore + _amount); - } - - /// @custom:property-id 12 - /// @custom:property Increases the total supply on the amount minted by the bridge - function check_mint(address _from, uint256 _amount) public { - /* Preconditions */ - uint256 _totalSupplyBefore = sourceToken.totalSupply(); - uint256 _balanceBefore = sourceToken.balanceOf(_from); - - vm.startPrank(Predeploys.L2_STANDARD_BRIDGE); - /* Action */ - sourceToken.mint(_from, _amount); - - /* Postconditions */ - assert(sourceToken.totalSupply() == _totalSupplyBefore + _amount); - assert(sourceToken.balanceOf(_from) == _balanceBefore + _amount); - } - - /// @custom:property-id 13 - /// @custom:property Supertoken total supply only decreases on the amount burned by the bridge - function check_burn(address _from, uint256 _amount) public { - /* Preconditions */ - vm.prank(Predeploys.L2_STANDARD_BRIDGE); - sourceToken.mint(_from, _amount); - - uint256 _totalSupplyBefore = sourceToken.totalSupply(); - uint256 _balanceBefore = sourceToken.balanceOf(_from); - - vm.prank(Predeploys.L2_STANDARD_BRIDGE); - /* Action */ - sourceToken.burn(_from, _amount); - - /* Postconditions */ - assert(sourceToken.totalSupply() == _totalSupplyBefore - _amount); - assert(sourceToken.balanceOf(_from) == _balanceBefore - _amount); - } - - /// @custom:property-id 14 - /// @custom:property Supertoken total supply starts at zero - function check_totalSupplyStartsAtZero() public view { - /* Postconditions */ - assert(sourceToken.totalSupply() == 0); - } - - /// @custom:property-id 22 - /// @custom:property `sendERC20` decreases sender balance in source chain and increases receiver balance in - /// destination chain exactly by the input amount - /// @custom:property-id 23 - /// @custom:property `sendERC20` decreases total supply in source chain and increases it in destination chain - /// exactly by the input amount - function check_crossChainMintAndBurn(address _from, address _to, uint256 _amount, uint256 _chainId) public { - /* Preconditions */ - vm.assume(_to != address(0)); - vm.assume(_from != address(0)); - - // Mint the amount to send - vm.prank(Predeploys.L2_STANDARD_BRIDGE); - sourceToken.mint(_from, _amount); - - uint256 fromBalanceBefore = sourceToken.balanceOf(_from); - uint256 toBalanceBefore = destToken.balanceOf(_to); - uint256 sourceTotalSupplyBefore = sourceToken.totalSupply(); - uint256 destTotalSupplyBefore = destToken.totalSupply(); - - vm.prank(_from); - /* Action */ - try sourceToken.sendERC20(_to, _amount, _chainId) { - /* Postconditions */ - // Source - assert(sourceToken.balanceOf(_from) == fromBalanceBefore - _amount); - assert(sourceToken.totalSupply() == sourceTotalSupplyBefore - _amount); - - // Destination - if (_chainId == DESTINATION_CHAIN_ID) { - // If the destination chain matches the one of the dest token, check that the amount was minted - assert(destToken.balanceOf(_to) == toBalanceBefore + _amount); - assert(destToken.totalSupply() == destTotalSupplyBefore + _amount); - } else { - // Otherwise the balances should remain the same - assert(destToken.balanceOf(_to) == toBalanceBefore); - assert(destToken.totalSupply() == destTotalSupplyBefore); - } - } catch { - // Shouldn't fail - assert(false); - } - } -} diff --git a/packages/contracts-bedrock/test/properties/helpers/HalmosBase.sol b/packages/contracts-bedrock/test/properties/helpers/HalmosBase.sol deleted file mode 100644 index 5ffac1050d14..000000000000 --- a/packages/contracts-bedrock/test/properties/helpers/HalmosBase.sol +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -import { Test } from "forge-std/Test.sol"; - -contract HalmosBase is Test { - uint256 internal constant CURRENT_CHAIN_ID = 1; - uint256 internal constant DESTINATION_CHAIN_ID = 2; - uint256 internal constant ZERO_AMOUNT = 0; - - address internal remoteToken = address(bytes20(keccak256("remoteToken"))); - string internal name = "SuperchainERC20"; - string internal symbol = "SUPER"; - uint8 internal decimals = 18; - - function eqStrings(string memory a, string memory b) internal pure returns (bool) { - return keccak256(abi.encode(a)) == keccak256(abi.encode(b)); - } -} From 8e39079f89a2f59ffeeae14dfe19aea870717fc6 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:18:55 -0300 Subject: [PATCH 42/56] chore: update properties tackled --- .../contracts-bedrock/test/invariants/PROPERTIES.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/contracts-bedrock/test/invariants/PROPERTIES.md b/packages/contracts-bedrock/test/invariants/PROPERTIES.md index f06c9be65f16..122fef21da51 100644 --- a/packages/contracts-bedrock/test/invariants/PROPERTIES.md +++ b/packages/contracts-bedrock/test/invariants/PROPERTIES.md @@ -24,14 +24,14 @@ legend: | id | description | kontrol | medusa | | --- | ------------------------------------------------------------------------------------------ | ------- | ------ | | 6 | calls to sendERC20 succeed as long as caller has enough balance | [x] | [ ] | -| 7 | calls to relayERC20 always succeed as long as the sender and cross-domain caller are valid | **[~]** | [ ] | +| 7 | calls to relayERC20 always succeed as long as the sender and cross-domain caller are valid | **[x]** | [ ] | ## Variable transition | id | description | kontrol | medusa | | --- | ------------------------------------------------------------------------------------------------- | ------- | ------ | -| 8 | sendERC20 with a value of zero does not modify accounting | [x] | [ ] | -| 9 | relayERC20 with a value of zero does not modify accounting | [x] | [ ] | +| 8 | sendERC20 with a value of zero does not modify accounting | [] | [ ] | +| 9 | relayERC20 with a value of zero does not modify accounting | [] | [ ] | | 10 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | [ ] | | 11 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [x] | [ ] | | 12 | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [x] | [ ] | @@ -57,8 +57,8 @@ It’s worth noting that these properties will not hold for a live system | id | description | kontrol | medusa | | --- | ---------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | -| 22 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [ ] | [x] | -| 23 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [ ] | [x] | +| 22 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [x] | [x] | +| 23 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [x] | [x] | | 24 | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [~] | # Expected external interactions From 6342513bcc158431aad62c0131a44fb34f0531a6 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:25:29 -0300 Subject: [PATCH 43/56] chore: remove outdated properties file --- .../test/invariants/PROPERTIES.md | 73 ------------------- 1 file changed, 73 deletions(-) delete mode 100644 packages/contracts-bedrock/test/invariants/PROPERTIES.md diff --git a/packages/contracts-bedrock/test/invariants/PROPERTIES.md b/packages/contracts-bedrock/test/invariants/PROPERTIES.md deleted file mode 100644 index 122fef21da51..000000000000 --- a/packages/contracts-bedrock/test/invariants/PROPERTIES.md +++ /dev/null @@ -1,73 +0,0 @@ -# supertoken properties - -legend: - -- `[ ]`: property not yet tested -- `**[ ]**`: property not yet tested, dev/research team has asked for extra focus on it -- `[X]`: tested/proven property -- `[~]`: partially tested/proven property -- `:(`: property won't be tested due to some limitation - -## Unit test - -| id | description | kontrol | medusa | -| --- | ---------------------------------------------------------------------------------- | ------- | ------ | -| 0 | supertoken token address does not depend on the executing chain’s chainID | [ ] | [ ] | -| 1 | supertoken token address depends on name, remote token, address and decimals | [ ] | [ ] | -| 2 | convert() should only allow converting legacy tokens to supertoken and viceversa | [ ] | [ ] | -| 3 | convert() only allows migrations between tokens representing the same remote asset | [ ] | [ ] | -| 4 | convert() only allows migrations from tokens with the same decimals | [ ] | [ ] | -| 5 | convert() burns the same amount of one token that it mints of the other | [ ] | [ ] | - -## Valid state - -| id | description | kontrol | medusa | -| --- | ------------------------------------------------------------------------------------------ | ------- | ------ | -| 6 | calls to sendERC20 succeed as long as caller has enough balance | [x] | [ ] | -| 7 | calls to relayERC20 always succeed as long as the sender and cross-domain caller are valid | **[x]** | [ ] | - -## Variable transition - -| id | description | kontrol | medusa | -| --- | ------------------------------------------------------------------------------------------------- | ------- | ------ | -| 8 | sendERC20 with a value of zero does not modify accounting | [] | [ ] | -| 9 | relayERC20 with a value of zero does not modify accounting | [] | [ ] | -| 10 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | [ ] | -| 11 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [x] | [ ] | -| 12 | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [x] | [ ] | -| 13 | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [x] | [ ] | -| 14 | supertoken total supply starts at zero | [x] | [ ] | -| 15 | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | -| 16 | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | - -## High level - -| id | description | kontrol | medusa | -| --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | -| 17 | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | [ ] | -| 18 | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | [ ] | -| 19 | sum of total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | -| 20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | [ ] | -| 21 | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [ ] | [ ] | - -## Atomic bridging pseudo-properties - -As another layer of defense, the following properties are defined which assume bridging operations to be atomic (that is, the sequencer and L2Inbox and CrossDomainMessenger contracts are fully abstracted away, `sendERC20` triggering the `relayERC20` call on the same transaction) -It’s worth noting that these properties will not hold for a live system - -| id | description | kontrol | medusa | -| --- | ---------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | -| 22 | sendERC20 decreases sender balance in source chain and increases receiver balance in destination chain exactly by the input amount | [x] | [x] | -| 23 | sendERC20 decreases total supply in source chain and increases it in destination chain exactly by the input amount | [x] | [x] | -| 24 | sum of supertoken total supply across all chains is always equal to convert(legacy, super)- convert(super, legacy) | [ ] | [~] | - -# Expected external interactions - -- regular ERC20 operations between any accounts on the same chain, provided by [crytic ERC20 properties](https://github.com/crytic/properties?tab=readme-ov-file#erc20-tests) - -# Invariant-breaking candidates (brain dump) - -here we’ll list possible interactions that we intend the fuzzing campaign to support in order to help break invariants - -- [ ] changing the decimals of tokens after deployment -- [ ] `convert()` ing between multiple (3+) representations of the same remote token, by having different names/symbols From 763a5385cc3a807fe84515ea7c0ea682748d4590 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:32:04 -0300 Subject: [PATCH 44/56] chore: remove medusa stuff --- packages/contracts-bedrock/.gitignore | 1 - packages/contracts-bedrock/foundry.toml | 5 - packages/contracts-bedrock/justfile | 4 - packages/contracts-bedrock/kontrol.toml | 2 +- packages/contracts-bedrock/medusa.json | 82 ------------ .../medusa/Protocol.properties.t.sol | 93 ------------- .../medusa/handlers/Protocol.handler.t.sol | 122 ------------------ 7 files changed, 1 insertion(+), 308 deletions(-) delete mode 100644 packages/contracts-bedrock/medusa.json delete mode 100644 packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol delete mode 100644 packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol diff --git a/packages/contracts-bedrock/.gitignore b/packages/contracts-bedrock/.gitignore index e0676cfa0fd5..381d4fd80714 100644 --- a/packages/contracts-bedrock/.gitignore +++ b/packages/contracts-bedrock/.gitignore @@ -6,7 +6,6 @@ broadcast kout-deployment kout-proofs test/kontrol/logs -test/properties/medusa/corpus/ out/ # Metrics diff --git a/packages/contracts-bedrock/foundry.toml b/packages/contracts-bedrock/foundry.toml index 03cccb74539e..4d120365d1b1 100644 --- a/packages/contracts-bedrock/foundry.toml +++ b/packages/contracts-bedrock/foundry.toml @@ -98,11 +98,6 @@ out = 'kout-proofs' test = 'test/kontrol/proofs' script = 'test/kontrol/proofs' -[profile.medusa] -src = 'test/properties/medusa/' -test = 'test/properties/medusa/' -script = 'test/properties/medusa/' - [profile.kontrol-properties] src = "test/properties/kontrol" test = "test/properties/kontrol" diff --git a/packages/contracts-bedrock/justfile b/packages/contracts-bedrock/justfile index b770adbe3552..69a737d4430d 100644 --- a/packages/contracts-bedrock/justfile +++ b/packages/contracts-bedrock/justfile @@ -26,10 +26,6 @@ test-kontrol: build-go-ffi build kontrol-summary-full test-kontrol-no-build test-kontrol-no-build: ./test/kontrol/scripts/run-kontrol.sh script -test-medusa timeout='100': - FOUNDRY_PROFILE=medusa medusa fuzz --timeout {{timeout}} - - test-rerun: build-go-ffi forge test --rerun -vvv diff --git a/packages/contracts-bedrock/kontrol.toml b/packages/contracts-bedrock/kontrol.toml index 998cd05b41f3..12da12c128b1 100644 --- a/packages/contracts-bedrock/kontrol.toml +++ b/packages/contracts-bedrock/kontrol.toml @@ -31,7 +31,7 @@ break-on-cheatcodes = false run-constructor = true symbolic-immutables = false schedule = 'CANCUN' -init-node-from = 'supererc20-state-diff/StateDiff.json' +init-node-from-diff = 'supererc20-state-diff/StateDiff.json' [show.default] foundry-project-root = '.' diff --git a/packages/contracts-bedrock/medusa.json b/packages/contracts-bedrock/medusa.json deleted file mode 100644 index cb4737956fea..000000000000 --- a/packages/contracts-bedrock/medusa.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "fuzzing": { - "workers": 10, - "workerResetLimit": 50, - "timeout": 0, - "testLimit": 500000, - "callSequenceLength": 100, - "corpusDirectory": "test/properties/medusa/corpus/", - "coverageEnabled": true, - "targetContracts": ["ProtocolProperties"], - "targetContractsBalances": [], - "constructorArgs": {}, - "deployerAddress": "0x30000", - "senderAddresses": [ - "0x10000", - "0x20000", - "0x30000" - ], - "blockNumberDelayMax": 60480, - "blockTimestampDelayMax": 604800, - "blockGasLimit": 30000000, - "transactionGasLimit": 12500000, - "testing": { - "stopOnFailedTest": true, - "stopOnFailedContractMatching": false, - "stopOnNoTests": true, - "testAllContracts": false, - "traceAll": true, - "assertionTesting": { - "enabled": true, - "testViewMethods": true, - "panicCodeConfig": { - "failOnCompilerInsertedPanic": false, - "failOnAssertion": true, - "failOnArithmeticUnderflow": false, - "failOnDivideByZero": false, - "failOnEnumTypeConversionOutOfBounds": false, - "failOnIncorrectStorageAccess": false, - "failOnPopEmptyArray": false, - "failOnOutOfBoundsArrayAccess": false, - "failOnAllocateTooMuchMemory": false, - "failOnCallUninitializedVariable": false - } - }, - "propertyTesting": { - "enabled": false, - "testPrefixes": [ - "property_" - ] - }, - "optimizationTesting": { - "enabled": false, - "testPrefixes": [ - "optimize_" - ] - }, - "targetFunctionSignatures": [], - "excludeFunctionSignatures": [] - }, - "chainConfig": { - "codeSizeCheckDisabled": true, - "cheatCodes": { - "cheatCodesEnabled": true, - "enableFFI": false - } - } - }, - "compilation": { - "platform": "crytic-compile", - "platformConfig": { - "target": ".", - "solcVersion": "", - "exportDirectory": "", - "args": ["--foundry-out-directory", "artifacts","--foundry-compile-all"] - } - }, - "logging": { - "level": "info", - "logDirectory": "", - "noColor": false - } -} diff --git a/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol b/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol deleted file mode 100644 index dd169dc5748d..000000000000 --- a/packages/contracts-bedrock/test/properties/medusa/Protocol.properties.t.sol +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -import { ProtocolHandler } from "./handlers/Protocol.handler.t.sol"; -import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; -import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; - -contract ProtocolProperties is ProtocolHandler { - using EnumerableMap for EnumerableMap.Bytes32ToUintMap; - - // TODO: will need rework after - // - non-atomic bridge - // - `convert` - /// @custom:property-id 24 - /// @custom:property sum of supertoken total supply across all chains is always equal to convert(legacy, super)- - /// convert(super, legacy) - function property_totalSupplyAcrossChainsEqualsMints() external view { - // iterate over unique deploy salts aka supertokens that are supposed to be compatible with each other - for (uint256 deploySaltIndex = 0; deploySaltIndex < ghost_totalSupplyAcrossChains.length(); deploySaltIndex++) { - uint256 totalSupply = 0; - (bytes32 currentSalt, uint256 trackedSupply) = ghost_totalSupplyAcrossChains.at(deploySaltIndex); - // and then over all the (mocked) chain ids where that supertoken could be deployed - for (uint256 validChainId = 0; validChainId < MAX_CHAINS; validChainId++) { - address supertoken = MESSENGER.superTokenAddresses(validChainId, currentSalt); - if (supertoken != address(0)) { - totalSupply += OptimismSuperchainERC20(supertoken).totalSupply(); - } - } - assert(trackedSupply == totalSupply); - } - } - - /// @notice deploy a new supertoken with deploy salt determined by params, to the given (of course mocked) chainId - /// @custom:property-id 14 - /// @custom:property supertoken total supply starts at zero - function property_DeployNewSupertoken( - TokenDeployParams memory params, - uint256 chainId - ) - external - validateTokenDeployParams(params) - { - chainId = bound(chainId, 0, MAX_CHAINS - 1); - OptimismSuperchainERC20 supertoken = _deploySupertoken( - remoteTokens[params.remoteTokenIndex], - WORDS[params.nameIndex], - WORDS[params.symbolIndex], - DECIMALS[params.decimalsIndex], - chainId - ); - // 14 - assert(supertoken.totalSupply() == 0); - } - - /// @custom:property-id 22 - /// @custom:property sendERC20 decreases sender balance in source chain and increases receiver balance in - /// destination chain exactly by the input amount - /// @custom:property-id 23 - /// @custom:property sendERC20 decreases total supply in source chain and increases it in destination chain exactly - /// by the input amount - function property_SelfBridgeSupertoken(uint256 fromIndex, uint256 destinationChainId, uint256 amount) external { - destinationChainId = bound(destinationChainId, 0, MAX_CHAINS - 1); - fromIndex = bound(fromIndex, 0, allSuperTokens.length - 1); - OptimismSuperchainERC20 sourceToken = OptimismSuperchainERC20(allSuperTokens[fromIndex]); - OptimismSuperchainERC20 destinationToken = - MESSENGER.crossChainMessageReceiver(address(sourceToken), destinationChainId); - // TODO: when implementing non-atomic bridging, allow for the token to - // not yet be deployed and funds be recovered afterwards. - require(address(destinationToken) != address(0)); - uint256 sourceBalanceBefore = sourceToken.balanceOf(msg.sender); - uint256 sourceSupplyBefore = sourceToken.totalSupply(); - uint256 destinationBalanceBefore = destinationToken.balanceOf(msg.sender); - uint256 destinationSupplyBefore = destinationToken.totalSupply(); - - vm.prank(msg.sender); - try sourceToken.sendERC20(msg.sender, amount, destinationChainId) { - uint256 sourceBalanceAfter = sourceToken.balanceOf(msg.sender); - uint256 destinationBalanceAfter = destinationToken.balanceOf(msg.sender); - // no free mint - assert(sourceBalanceBefore + destinationBalanceBefore == sourceBalanceAfter + destinationBalanceAfter); - // 22 - assert(sourceBalanceBefore - amount == sourceBalanceAfter); - assert(destinationBalanceBefore + amount == destinationBalanceAfter); - uint256 sourceSupplyAfter = sourceToken.totalSupply(); - uint256 destinationSupplyAfter = destinationToken.totalSupply(); - // 23 - assert(sourceSupplyBefore - amount == sourceSupplyAfter); - assert(destinationSupplyBefore + amount == destinationSupplyAfter); - } catch { - assert(address(destinationToken) == address(sourceToken) || sourceBalanceBefore < amount); - } - } -} diff --git a/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol b/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol deleted file mode 100644 index 266650486e34..000000000000 --- a/packages/contracts-bedrock/test/properties/medusa/handlers/Protocol.handler.t.sol +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.25; - -import { TestBase } from "forge-std/Base.sol"; -import { StdUtils } from "forge-std/StdUtils.sol"; - -import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; -import { EnumerableMap } from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; -import { OptimismSuperchainERC20 } from "src/L2/OptimismSuperchainERC20.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { MockL2ToL2CrossDomainMessenger } from "../../helpers/MockL2ToL2CrossDomainMessenger.t.sol"; - -contract ProtocolHandler is TestBase, StdUtils { - using EnumerableMap for EnumerableMap.Bytes32ToUintMap; - - uint8 internal constant MAX_CHAINS = 4; - uint8 internal constant INITIAL_TOKENS = 1; - uint8 internal constant INITIAL_SUPERTOKENS = 1; - uint8 internal constant SUPERTOKEN_INITIAL_MINT = 100; - address internal constant BRIDGE = Predeploys.L2_STANDARD_BRIDGE; - MockL2ToL2CrossDomainMessenger internal constant MESSENGER = - MockL2ToL2CrossDomainMessenger(Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER); - OptimismSuperchainERC20 internal superchainERC20Impl; - // NOTE: having more options for this enables the fuzzer to configure - // different supertokens for the same remote token - string[] internal WORDS = ["TOKENS"]; - uint8[] internal DECIMALS = [6, 18]; - - struct TokenDeployParams { - uint8 remoteTokenIndex; - uint8 nameIndex; - uint8 symbolIndex; - uint8 decimalsIndex; - } - - address[] internal remoteTokens; - address[] internal allSuperTokens; - - //@notice 'real' deploy salt => total supply sum across chains - EnumerableMap.Bytes32ToUintMap internal ghost_totalSupplyAcrossChains; - - constructor() { - vm.etch(address(MESSENGER), address(new MockL2ToL2CrossDomainMessenger()).code); - superchainERC20Impl = new OptimismSuperchainERC20(); - for (uint256 remoteTokenIndex = 0; remoteTokenIndex < INITIAL_TOKENS; remoteTokenIndex++) { - _deployRemoteToken(); - for (uint256 supertokenChainId = 0; supertokenChainId < INITIAL_SUPERTOKENS; supertokenChainId++) { - _deploySupertoken(remoteTokens[remoteTokenIndex], WORDS[0], WORDS[0], DECIMALS[0], supertokenChainId); - } - } - } - - /// @notice the deploy params are _indexes_ to pick from a pre-defined array of options and limit - /// the amount of supertokens for a given remoteAsset that are incompatible between them, as - /// two supertokens have to share decimals, name, symbol and remoteAsset to be considered - /// the same asset, and therefore bridgable. - modifier validateTokenDeployParams(TokenDeployParams memory params) { - params.remoteTokenIndex = uint8(bound(params.remoteTokenIndex, 0, remoteTokens.length - 1)); - params.nameIndex = uint8(bound(params.nameIndex, 0, WORDS.length - 1)); - params.symbolIndex = uint8(bound(params.symbolIndex, 0, WORDS.length - 1)); - params.decimalsIndex = uint8(bound(params.decimalsIndex, 0, DECIMALS.length - 1)); - _; - } - - function handler_MockNewRemoteToken() external { - _deployRemoteToken(); - } - - /// @notice pick one already-deployed supertoken and mint an arbitrary amount of it - /// necessary so there is something to be bridged :D - /// TODO: will be replaced when testing the factories and `convert()` - function handler_MintSupertoken(uint256 index, uint96 amount) external { - index = bound(index, 0, allSuperTokens.length - 1); - address addr = allSuperTokens[index]; - vm.prank(BRIDGE); - // medusa calls with different senders by default - OptimismSuperchainERC20(addr).mint(msg.sender, amount); - // currentValue will be zero if key is not present - (, uint256 currentValue) = ghost_totalSupplyAcrossChains.tryGet(MESSENGER.superTokenInitDeploySalts(addr)); - ghost_totalSupplyAcrossChains.set(MESSENGER.superTokenInitDeploySalts(addr), currentValue + amount); - } - - /// @notice deploy a remote token, that supertokens will be a representation of. They are never called, so there - /// is no need to actually deploy a contract for them - function _deployRemoteToken() internal { - // make sure they don't conflict with predeploys/preinstalls/precompiles/other tokens - remoteTokens.push(address(uint160(1000 + remoteTokens.length))); - } - - /// @notice deploy a new supertoken representing remoteToken - /// remoteToken, name, symbol and decimals determine the 'real' deploy salt - /// and supertokens sharing it are interoperable between them - /// we however use the chainId as part of the deploy salt to mock the ability of - /// supertokens to exist on different chains on a single EVM. - function _deploySupertoken( - address remoteToken, - string memory name, - string memory symbol, - uint8 decimals, - uint256 chainId - ) - internal - returns (OptimismSuperchainERC20 supertoken) - { - // this salt would be used in production. Tokens sharing it will be bridgable with each other - bytes32 realSalt = keccak256(abi.encode(remoteToken, name, symbol, decimals)); - // what we use in the tests to walk around two contracts needing two different addresses - // tbf we could be using CREATE1, but this feels more verbose - bytes32 hackySalt = keccak256(abi.encode(remoteToken, name, symbol, decimals, chainId)); - supertoken = OptimismSuperchainERC20( - address( - // TODO: Use the SuperchainERC20 Beacon Proxy - new ERC1967Proxy{ salt: hackySalt }( - address(superchainERC20Impl), - abi.encodeCall(OptimismSuperchainERC20.initialize, (remoteToken, name, symbol, decimals)) - ) - ) - ); - MESSENGER.registerSupertoken(realSalt, chainId, address(supertoken)); - allSuperTokens.push(address(supertoken)); - } -} From 113bb45a331faaaebfb1e5edde3cf05029a30842 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Tue, 10 Sep 2024 15:14:35 -0300 Subject: [PATCH 45/56] chore: l2 standard bridge interop kontrol setup --- packages/contracts-bedrock/kontrol.toml | 19 ++++++++++++ .../test/properties/PROPERTIES.md | 22 +++++++------- .../kontrol/L2StandardBridgeInterop.k.sol | 30 +++++++++++++++++++ 3 files changed, 60 insertions(+), 11 deletions(-) create mode 100644 packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol diff --git a/packages/contracts-bedrock/kontrol.toml b/packages/contracts-bedrock/kontrol.toml index 12da12c128b1..5cd119de6a48 100644 --- a/packages/contracts-bedrock/kontrol.toml +++ b/packages/contracts-bedrock/kontrol.toml @@ -33,6 +33,25 @@ symbolic-immutables = false schedule = 'CANCUN' init-node-from-diff = 'supererc20-state-diff/StateDiff.json' +[prove.convert] +foundry-project-root = './' +verbose = false +debug = false +max-depth = 25000 +reinit = false +cse = false +failure-information = true +counterexample-information = true +minimize-proofs = false +fail-fast = true +smt-timeout = 1000 +break-every-step = false +break-on-jumpi = false +break-on-calls = false +break-on-storage = false +break-on-basic-blocks = false +break-on-cheatcodes = false + [show.default] foundry-project-root = '.' verbose = false diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md index f6876df77469..6116a21e6171 100644 --- a/packages/contracts-bedrock/test/properties/PROPERTIES.md +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -81,17 +81,17 @@ legend: ## Variable transition -| id | milestone | description | kontrol | medusa | -| --- | ------------------- | ------------------------------------------------------------------------------------------------- | ------- | ------ | -| 8 | SupERC20 | sendERC20 with a value of zero does not modify accounting | [x] | [ ] | -| 9 | SupERC20 | relayERC20 with a value of zero does not modify accounting | [x] | [ ] | -| 10 | SupERC20 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | [ ] | -| 11 | SupERC20 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [x] | [ ] | -| 12 | Liquidity Migration | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [x] | [~] | -| 13 | Liquidity Migration | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [x] | [ ] | -| 14 | SupERC20 | supertoken total supply starts at zero | [x] | [x] | -| 15 | Factories | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | -| 16 | Factories | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | +| id | milestone | description | kontrol | medusa | +| --- | --------- | ------------------------------------------------------------------------------------------------- | ------- | ------ | +| 8 | SupERC20 | sendERC20 with a value of zero does not modify accounting | [x] | [ ] | +| 9 | SupERC20 | relayERC20 with a value of zero does not modify accounting | [x] | [ ] | +| 10 | SupERC20 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | [ ] | +| 11 | SupERC20 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [x] | [ ] | +| 12 | SupERC20 | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [x] | [~] | +| 13 | SupERC20 | supertoken total supply only decreases on calls to burn() by the L2toL2StandardBridge | [x] | [ ] | +| 14 | SupERC20 | supertoken total supply starts at zero | [x] | [x] | +| 15 | Factories | deploying a supertoken registers its remote token in the factory | [ ] | [ ] | +| 16 | Factories | deploying an OptimismMintableERC20 registers its remote token in the factory | [ ] | [ ] | ## High level diff --git a/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol b/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol new file mode 100644 index 000000000000..455f37eb4f91 --- /dev/null +++ b/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { Predeploys } from "src/libraries/Predeploys.sol"; +import { L2StandardBridgeInterop } from "src/L2/L2StandardBridgeInterop.sol"; +import { L2StandardBridge } from "src/L2/L2StandardBridge.sol"; +import { Test } from "forge-std/Test.sol"; + +contract L2StandardBridgeInteropKontrol is Test { + L2StandardBridgeInterop public immutable l2StandardBridgeInterop = + L2StandardBridgeInterop(payable(Predeploys.L2_STANDARD_BRIDGE)); + address public otherBridge = address(uint160(uint256(keccak256("otherBridge")))); + + // TODO: Implement external computation + function setUp() public { + address _l2StandardBridgeInteropImpl = address(new L2StandardBridgeInterop()); + vm.etch(Predeploys.L2_STANDARD_BRIDGE, _l2StandardBridgeInteropImpl.code); + + l2StandardBridgeInterop.initialize(L2StandardBridge(payable(otherBridge))); + } + + function test_setup() public view { + assertEq(l2StandardBridgeInterop.version(), "1.11.1-beta.1+interop"); + } + + // TODO: Remove convert prefix + function prove_convertSetup() public view { + assertEq(l2StandardBridgeInterop.version(), "1.11.1-beta.1+interop"); + } +} From 16d19751309e3a7c7525c4ba483d65421d62b429 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Wed, 11 Sep 2024 18:50:45 -0300 Subject: [PATCH 46/56] feat: wip for the 3 and 4 properties tests --- packages/contracts-bedrock/kontrol.toml | 29 ++-- .../kontrol/L2StandardBridgeInterop.k.sol | 149 ++++++++++++++++-- 2 files changed, 145 insertions(+), 33 deletions(-) diff --git a/packages/contracts-bedrock/kontrol.toml b/packages/contracts-bedrock/kontrol.toml index 5cd119de6a48..de88cc6649d4 100644 --- a/packages/contracts-bedrock/kontrol.toml +++ b/packages/contracts-bedrock/kontrol.toml @@ -33,25 +33,6 @@ symbolic-immutables = false schedule = 'CANCUN' init-node-from-diff = 'supererc20-state-diff/StateDiff.json' -[prove.convert] -foundry-project-root = './' -verbose = false -debug = false -max-depth = 25000 -reinit = false -cse = false -failure-information = true -counterexample-information = true -minimize-proofs = false -fail-fast = true -smt-timeout = 1000 -break-every-step = false -break-on-jumpi = false -break-on-calls = false -break-on-storage = false -break-on-basic-blocks = false -break-on-cheatcodes = false - [show.default] foundry-project-root = '.' verbose = false @@ -61,3 +42,13 @@ use-hex-encoding = false [view-kcfg.default] foundry-project-root = '.' use-hex-encoding = false + +## Convert profile + +[build.convert] + +[prove.convert] + +[show.convert] + +[view-kcfg.convert] \ No newline at end of file diff --git a/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol b/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol index 455f37eb4f91..4f6ea9971957 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol @@ -5,26 +5,147 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; import { L2StandardBridgeInterop } from "src/L2/L2StandardBridgeInterop.sol"; import { L2StandardBridge } from "src/L2/L2StandardBridge.sol"; import { Test } from "forge-std/Test.sol"; +import { KontrolCheats } from "kontrol-cheatcodes/KontrolCheats.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import { L2StandardBridge } from "src/L2/L2StandardBridge.sol"; +import { StandardBridge } from "src/universal/StandardBridge.sol"; +import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import { ILegacyMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; +import { IOptimismERC20Factory } from "src/L2/interfaces/IOptimismERC20Factory.sol"; +import { IOptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; -contract L2StandardBridgeInteropKontrol is Test { - L2StandardBridgeInterop public immutable l2StandardBridgeInterop = - L2StandardBridgeInterop(payable(Predeploys.L2_STANDARD_BRIDGE)); - address public otherBridge = address(uint160(uint256(keccak256("otherBridge")))); - - // TODO: Implement external computation - function setUp() public { - address _l2StandardBridgeInteropImpl = address(new L2StandardBridgeInterop()); - vm.etch(Predeploys.L2_STANDARD_BRIDGE, _l2StandardBridgeInteropImpl.code); +contract L2StandardBridgeInteropKontrol is Test, KontrolCheats { + L2StandardBridgeInterop public l2StandardBridgeInterop; + address payable public constant otherBridge = payable(address(uint160(uint256(keccak256("otherBridge"))))); + address public constant from = address(uint160(uint256(keccak256("from")))); + address public constant to = address(uint160(uint256(keccak256("to")))); - l2StandardBridgeInterop.initialize(L2StandardBridge(payable(otherBridge))); + // Not declaring as `setUp` for performance reasons + function setUpInlined() public { + l2StandardBridgeInterop = L2StandardBridgeInterop( + payable( + address( + new ERC1967Proxy( + address(new L2StandardBridgeInterop()), + abi.encodeCall(L2StandardBridge.initialize, (StandardBridge(otherBridge))) + ) + ) + ) + ); } - function test_setup() public view { - assertEq(l2StandardBridgeInterop.version(), "1.11.1-beta.1+interop"); + function eqStrings(string memory a, string memory b) internal pure returns (bool) { + return keccak256(abi.encode(a)) == keccak256(abi.encode(b)); } // TODO: Remove convert prefix - function prove_convertSetup() public view { - assertEq(l2StandardBridgeInterop.version(), "1.11.1-beta.1+interop"); + function prove_convertSetup() public { + setUpInlined(); + assert(eqStrings(l2StandardBridgeInterop.version(), "1.11.1-beta.1+interop")); + assertEq(address(l2StandardBridgeInterop.OTHER_BRIDGE()), otherBridge); + } + + /// @custom:property-id 3 + /// @custom:property convert() only allows migrations between tokens representing the same remote asset + function prove_convertOnlyOnSameRemoteAsset( + address _fromRemoteAddress, + address _toRemoteAddress, + bool _supportsIERC165, + bool _supportsILegacyMintableERC20, + bool _supportsIOptimismMintableERC20 + ) + public + { + setUpInlined(); + + /* Preconditions */ + // Mock the decimals of the tokens to the same values so it doesn't revert + uint8 _decimals = 18; + vm.mockCall(from, abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(_decimals)); + vm.mockCall(to, abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(_decimals)); + // Mock the call over `supportsInterface` - not in the scope of the test, but required to avoid a revert + vm.mockCall( + from, + abi.encodeWithSelector(IERC165.supportsInterface.selector, type(IERC165).interfaceId), + abi.encode(_supportsIERC165) + ); + // Mock the call over `supportsInterface` - not in the scope of the test, but required to avoid a revert + vm.mockCall( + from, + abi.encodeWithSelector(IERC165.supportsInterface.selector, type(ILegacyMintableERC20).interfaceId), + abi.encode(_supportsILegacyMintableERC20) + ); + vm.mockCall( + from, + abi.encodeWithSelector(IERC165.supportsInterface.selector, type(IOptimismMintableERC20).interfaceId), + abi.encode(_supportsIOptimismMintableERC20) + ); + + // Mock the call over `deployments` for both tokens with the given symbolic remote addresses + vm.mockCall( + Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, + abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector), + abi.encode(address(_fromRemoteAddress)) + ); + vm.mockCall( + Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, + abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector), + abi.encode(address(_toRemoteAddress)) + ); + + uint256 _randomAmount = 100; + /* Action */ + try l2StandardBridgeInterop.convert(from, to, _randomAmount) { + /* Postconditions */ + assert(_fromRemoteAddress == _toRemoteAddress); + } catch { + assert(_fromRemoteAddress != _toRemoteAddress); + } + } + + /// @custom:property-id 4 + /// @custom:property convert() only allows migrations from tokens with the same decimals + function prove_convertOnlyTokenWithSameDecimals(uint8 _decimalsFrom, uint8 _decimalsTo) public { + setUpInlined(); + + /* Preconditions */ + // Mock the decimals of the tokens with the given symbolic decimals values + vm.mockCall(from, abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(_decimalsFrom)); + vm.mockCall(to, abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(_decimalsTo)); + + // Mock the call over `supportsInterface` - not in the scope of the test, but required to avoid a revert + vm.mockCall( + from, + abi.encodeWithSelector(IERC165.supportsInterface.selector, type(IERC165).interfaceId), + abi.encode(true) + ); + vm.mockCall( + from, + abi.encodeWithSelector(IERC165.supportsInterface.selector, type(ILegacyMintableERC20).interfaceId), + abi.encode(true) + ); + + // Mock the call over `deployments` - not in the scope of the test, but required to avoid a revert + address _randomAddress = address(420); + vm.mockCall( + Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, + abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector), + abi.encode(address(_randomAddress)) + ); + vm.mockCall( + Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY, + abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector), + abi.encode(address(_randomAddress)) + ); + + uint256 _randomAmount = 100; + /* Action */ + try l2StandardBridgeInterop.convert(from, to, _randomAmount) { + /* Postconditions */ + assert(_decimalsFrom == _decimalsTo); + } catch { + assert(_decimalsFrom != _decimalsTo); + } } } From ccfa037bfbfe0e662b795fcc712cfd9d9a3b44f5 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Wed, 11 Sep 2024 20:17:33 -0300 Subject: [PATCH 47/56] chore: update kontrol toml and add logs files for proofs three and four --- packages/contracts-bedrock/kontrol.toml | 27 +- packages/contracts-bedrock/proof-four.out | 1119 +++++++++++ packages/contracts-bedrock/proof-three.out | 2051 ++++++++++++++++++++ 3 files changed, 3191 insertions(+), 6 deletions(-) create mode 100644 packages/contracts-bedrock/proof-four.out create mode 100644 packages/contracts-bedrock/proof-three.out diff --git a/packages/contracts-bedrock/kontrol.toml b/packages/contracts-bedrock/kontrol.toml index de88cc6649d4..cd7325b08924 100644 --- a/packages/contracts-bedrock/kontrol.toml +++ b/packages/contracts-bedrock/kontrol.toml @@ -45,10 +45,25 @@ use-hex-encoding = false ## Convert profile -[build.convert] - [prove.convert] - -[show.convert] - -[view-kcfg.convert] \ No newline at end of file +foundry-project-root = './' +verbose = false +debug = false +max-depth = 25000 +reinit = false +cse = false +workers = 1 +failure-information = true +counterexample-information = true +minimize-proofs = false +fail-fast = true +smt-timeout = 1000 +break-every-step = false +break-on-jumpi = false +break-on-calls = false +break-on-storage = false +break-on-basic-blocks = false +break-on-cheatcodes = false +run-constructor = true +symbolic-immutables = false +schedule = 'CANCUN' \ No newline at end of file diff --git a/packages/contracts-bedrock/proof-four.out b/packages/contracts-bedrock/proof-four.out new file mode 100644 index 000000000000..8c631b8a4a61 --- /dev/null +++ b/packages/contracts-bedrock/proof-four.out @@ -0,0 +1,1119 @@ +Found 2 matching proofs for prove_convertOnlyTokenWithSameDecimals:None. Running the latest one. Use the `--version` flag to choose one. + +┌─ 1 (root, init) +│ k: #execute ~> CONTINUATION:K +│ pc: 0x0 +│ callDepth: 0x0 +│ statusCode: STATUSCODE:StatusCode +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:17:151 +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyTokenWithSameDecimals(uint8,uint8) +│ +│ (1000 steps) +├─ 3 +│ k: #execute ~> #codeDeposit 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ~> #pc [ CRE ... +│ pc: 0x180 +│ callDepth: 0x1 +│ statusCode: STATUSCODE:StatusCode +│ src: lib/forge-std/src/StdInvariant.sol:80:81 +│ +│ (358 steps) +├─ 4 +│ k: #halt ~> #codeDeposit 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ~> #pc [ CREATE ... +│ pc: 0x225 +│ callDepth: 0x1 +│ statusCode: EVMC_SUCCESS +│ src: lib/forge-std/src/StdInvariant.sol:104:105 +│ +│ (1000 steps) +├─ 5 +│ k: #gas [ ISZERO , ISZERO 0x0 ] ~> ISZERO 0x0 ~> #pc [ ISZERO ] ~> #execute ~> #cod ... +│ pc: 0x352 +│ callDepth: 0x1 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:113:114 +│ +│ (1000 steps) +├─ 6 +│ k: #endBasicBlock ~> #execute ~> #codeDeposit 0x2e234dae75c793f67a35089c9d99245e1c5 ... +│ pc: 0x74 +│ callDepth: 0x1 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:17:151 +│ +│ (1000 steps) +├─ 7 +│ k: #next [ DUP ( 0x2 ) ] ~> #execute ~> #return 0x1e0 0x0 ~> #pc [ DELEGATECALL ] ~ ... +│ pc: 0x30e7 +│ callDepth: 0x2 +│ statusCode: EVMC_SUCCESS +│ method: src%L2%L2StandardBridgeInterop.initialize(address) +│ +│ (681 steps) +├─ 8 +│ k: #halt ~> #return 0x1e0 0x0 ~> #pc [ DELEGATECALL ] ~> #execute ~> #codeDeposit 0 ... +│ pc: 0x1fb +│ callDepth: 0x2 +│ statusCode: EVMC_SUCCESS +│ src: lib/forge-std/src/StdInvariant.sol:104:105 +│ method: src%L2%L2StandardBridgeInterop.initialize(address) +│ +│ (428 steps) +├─ 9 +│ k: #halt ~> #codeDeposit 0x2e234dae75c793f67a35089c9d99245e1c58470b ~> #pc [ CREATE ... +│ pc: 0x43e +│ callDepth: 0x1 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:119:120 +│ +│ (1000 steps) +├─ 10 +│ k: #next [ AND ] ~> #execute ~> CONTINUATION:K +│ pc: 0x2166 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyTokenWithSameDecimals(uint8,uint8) +│ +│ (1000 steps) +├─ 11 +│ k: #gas [ JUMP , JUMP 0x20fb ] ~> JUMP 0x20fb ~> #pc [ JUMP ] ~> #execute ~> CONTIN ... +│ pc: 0x2114 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyTokenWithSameDecimals(uint8,uint8) +│ +│ (1000 steps) +├─ 12 +│ k: #exec [ MSTORE ] ~> #pc [ MSTORE ] ~> #execute ~> CONTINUATION:K +│ pc: 0x2125 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyTokenWithSameDecimals(uint8,uint8) +│ +│ (1000 steps) +├─ 13 +│ k: #pc [ JUMPDEST ] ~> #execute ~> CONTINUATION:K +│ pc: 0x20f8 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyTokenWithSameDecimals(uint8,uint8) +│ +│ (1000 steps) +├─ 14 +│ k: #execute ~> CONTINUATION:K +│ pc: 0xb3b +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:65:66 +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyTokenWithSameDecimals(uint8,uint8) +│ +│ (1000 steps) +├─ 15 +│ k: #execute ~> CONTINUATION:K +│ pc: 0xbe2 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:67:72 +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyTokenWithSameDecimals(uint8,uint8) +│ +│ (1000 steps) +├─ 16 +│ k: #next [ ISZERO ] ~> #execute ~> CONTINUATION:K +│ pc: 0xcd8 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:78:83 +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyTokenWithSameDecimals(uint8,uint8) +│ +│ (1000 steps) +├─ 17 +│ k: #gas [ JUMPDEST , JUMPDEST ] ~> JUMPDEST ~> #pc [ JUMPDEST ] ~> #execute ~> #ret ... +│ pc: 0x2c9e +│ callDepth: 0x2 +│ statusCode: EVMC_SUCCESS +│ method: src%L2%L2StandardBridgeInterop.convert(address,address,uint256) +│ +│ (1000 steps) +├─ 18 +│ k: #next [ JUMPI ] ~> #execute ~> #return 0x0 0x0 ~> #pc [ DELEGATECALL ] ~> #execu ... +│ pc: 0x20da +│ callDepth: 0x2 +│ statusCode: EVMC_SUCCESS +│ method: src%L2%L2StandardBridgeInterop.convert(address,address,uint256) +│ +│ (4 steps) +├─ 19 (split) +│ k: JUMPI 0x210c bool2Word ( VV0__decimalsFrom_114b9705:Int ==Int VV1__decimalsTo_11 ... +│ pc: 0x20da +│ callDepth: 0x2 +│ statusCode: EVMC_SUCCESS +│ method: src%L2%L2StandardBridgeInterop.convert(address,address,uint256) +┃ +┃ (branch) +┣━━┓ constraint: VV0__decimalsFrom_114b9705:Int ==Int VV1__decimalsTo_114b9705:Int +┃ │ +┃ └─ 20 (leaf, pending) +┃ k: JUMPI 0x210c bool2Word ( VV0__decimalsFrom_114b9705:Int ==Int VV1__decimalsTo_11 ... +┃ pc: 0x20da +┃ callDepth: 0x2 +┃ statusCode: EVMC_SUCCESS +┃ method: src%L2%L2StandardBridgeInterop.convert(address,address,uint256) +┃ +┗━━┓ constraint: ( notBool VV0__decimalsFrom_114b9705:Int ==Int VV1__decimalsTo_114b9705:Int ) + │ + └─ 21 (leaf, pending) + k: JUMPI 0x210c bool2Word ( VV0__decimalsFrom_114b9705:Int ==Int VV1__decimalsTo_11 ... + pc: 0x20da + callDepth: 0x2 + statusCode: EVMC_SUCCESS + method: src%L2%L2StandardBridgeInterop.convert(address,address,uint256) + + +┌─ 2 (root, leaf, target, terminal) +│ k: #halt ~> CONTINUATION:K +│ pc: PC_CELL_5d410f2a:Int +│ callDepth: CALLDEPTH_CELL_5d410f2a:Int +│ statusCode: STATUSCODE_FINAL:StatusCode + + +Node 21: + +( + + + + JUMPI 0x210c bool2Word ( VV0__decimalsFrom_114b9705:Int ==Int VV1__decimalsTo_114b9705:Int ) + ~> #pc [ JUMPI ] + ~> #execute + ~> #return 0x0 0x0 + ~> #pc [ DELEGATECALL ] + ~> #execute + ~> #return 0x35c 0x0 + ~> #pc [ CALL ] + ~> #execute + ~> CONTINUATION:K + + + NORMAL + + + CANCUN + + + false + + + + + #buf ( 0x20 , VV0__decimalsFrom_114b9705:Int ) + + + EVMC_SUCCESS + + + ListItem ( + + 0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + 0x00000000000000000000000000000000000100010000000100000000000000000000010000000001000100000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000100000000000000000001000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000100000000000000000000000000000100000000000100000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x248391ff000000000000000000000000e6a7a45f334393093061116b197e3240065ff2d80000000000000000000000007c05912fc4cbffd28f63f412fcdd194991f8db480000000000000000000000000000000000000000000000000000000000000064 + + + 0x0 + + + ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f : ( 0x27 : ( 0x11 : .WordStack ) ) ) + + + 0x248391ff000000000000000000000000e6a7a45f334393093061116b197e3240065ff2d80000000000000000000000007c05912fc4cbffd28f63f412fcdd194991f8db480000000000000000000000000000000000000000000000000000000000000064 + + + 0xc7 + + + 0x0 + + + 0x0 + + + 0x0 + + + false + + + 0x1 + + ) ListItem ( + + 0x60806040523480156200001157600080fd5b5060043610620001895760003560e01c8063916a17c611620000dd578063c89701a2116200008b578063d6a2ec76116200006e578063d6a2ec761462000341578063e20c9f711462000369578063fa7626d4146200037357600080fd5b8063c89701a214620002f1578063d5ce3389146200031957600080fd5b8063ba414fa611620000c0578063ba414fa61462000299578063bf4792f114620002b4578063c30fe4fe14620002da57600080fd5b8063916a17c61462000285578063b5508aa9146200028f57600080fd5b8063547d77c4116200013b57806385226c81116200011e57806385226c8114620002585780638ea3d06f14620002715780638fe30c69146200027b57600080fd5b8063547d77c4146200022657806366d9a9a0146200023f57600080fd5b80632ade388011620001705780632ade388014620001f95780633e5e3c2314620002125780633f7286f4146200021c57600080fd5b806313151981146200018e5780631ed7831c14620001e0575b600080fd5b620001b67f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001ea62000381565b604051620001d791906200209c565b62000203620003f2565b604051620001d7919062002173565b620001ea6200054d565b620001ea620005bc565b6200023d6200023736600462002299565b6200062b565b005b6200024962000df5565b604051620001d79190620022d1565b6200026262000f01565b604051620001d79190620023cb565b6200023d62000fdb565b6200023d620011ab565b62000249620012e6565b62000262620013f2565b620002a3620014cc565b6040519015158152602001620001d7565b601e54620001b690610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6200023d620002eb36600462002486565b620015a4565b620001b67f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa581565b620001b67f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d881565b620001b67f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d81565b620001ea62001f15565b601e54620002a39060ff1681565b60606016805480602002602001604051908101604052809291908181526020018280548015620003e857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575b5050505050905090565b6060601d805480602002602001604051908101604052809291908181526020016000905b8282101562000544576000848152602080822060408051808201825260028702909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939591948681019491929084015b828210156200052c5783829060005260206000200180546200049890620024fa565b80601f0160208091040260200160405190810160405280929190818152602001828054620004c690620024fa565b8015620005175780601f10620004eb5761010080835404028352916020019162000517565b820191906000526020600020905b815481529060010190602001808311620004f957829003601f168201915b50505050508152602001906001019062000476565b50505050815250508152602001906001019062000416565b50505050905090565b60606018805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60606017805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b62000635620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff86168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262000717927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8926044016200254f565b600060405180830381600087803b1580156200073257600080fd5b505af115801562000747573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e493506200082f927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b1580156200084a57600080fd5b505af11580156200085f573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909317909252835160018184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000956937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b1580156200097157600080fd5b505af115801562000986573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000179052835160018183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000a99937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562000ab457600080fd5b505af115801562000ac9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b37390000000000000000000000000000000000000000000000000000000017905282516101a481830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452929450737109709ecfa91a80626ff3989d68f67f5b1dd12d935063b96213e49262000ba8927342000000000000000000000000000000000000129290916044016200254f565b600060405180830381600087803b15801562000bc357600080fd5b505af115801562000bd8573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062000cc7927342000000000000000000000000000000000000269291906044016200254f565b600060405180830381600087803b15801562000ce257600080fd5b505af115801562000cf7573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562000da257600080fd5b505af192505050801562000db4575060015b62000dd7578260ff168460ff160362000dd15762000dd16200259e565b62000def565b8260ff168460ff161462000def5762000def6200259e565b50505050565b6060601b805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff16835260018101805483518187028101870190945280845293949193858301939283018282801562000ee857602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841162000e945790505b5050505050815250508152602001906001019062000e19565b6060601a805480602002602001604051908101604052809291908181526020016000905b828210156200054457838290600052602060002001805462000f4790620024fa565b80601f016020809104026020016040519081016040528092919081815260200182805462000f7590620024fa565b801562000fc65780601f1062000f9a5761010080835404028352916020019162000fc6565b820191906000526020600020905b81548152906001019060200180831162000fa857829003601f168201915b50505050508152602001906001019062000f25565b62000fe5620011ab565b620010db601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001057573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200109f9190810190620025fc565b6040518060400160405280601581526020017f312e31312e312d626574612e312b696e7465726f70000000000000000000000081525062001f84565b620010ea57620010ea6200259e565b620011a9601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f46ddb26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200115c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011829190620026d3565b7f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa562001fe1565b565b604051620011b99062002080565b604051809103906000f080158015620011d6573d6000803e3d6000fd5b5060405173754cd1bdd15c0ed896f2867165a2694d76f39fa56024820152604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de8000000000000000000000000000000000000000000000000000000001790525162001279906200208e565b62001286929190620026fa565b604051809103906000f080158015620012a3573d6000803e3d6000fd5b50601e60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6060601c805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939491938583019392830182828015620013d957602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411620013855790505b505050505081525050815260200190600101906200130a565b60606019805480602002602001604051908101604052809291908181526020016000905b82821015620005445783829060005260206000200180546200143890620024fa565b80601f01602080910402602001604051908101604052809291908181526020018280546200146690620024fa565b8015620014b75780601f106200148b57610100808354040283529160200191620014b7565b820191906000526020600020905b8154815290600101906020018083116200149957829003601f168201915b50505050508152602001906001019062001416565b60085460009060ff1615620014e5575060085460ff1690565b6040517f667f9d70000000000000000000000000000000000000000000000000000000008152737109709ecfa91a80626ff3989d68f67f5b1dd12d600482018190527f6661696c65640000000000000000000000000000000000000000000000000000602483015260009163667f9d7090604401602060405180830381865afa15801562001577573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200159d919062002733565b1415905090565b620015ae620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce567000000000000000000000000000000000000000000000000000000001790528251601281830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262001692927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d89291906044016200254f565b600060405180830381600087803b158015620016ad57600080fd5b505af1158015620016c2573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e49350620017aa927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b158015620017c557600080fd5b505af1158015620017da573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690931790925283518a15158184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e49450620018d2937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b158015620018ed57600080fd5b505af115801562001902573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518915158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001a16937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001a3157600080fd5b505af115801562001a46573d6000803e3d6000fd5b5050604080517fec4fc8e3000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518815158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001b5a937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001b7557600080fd5b505af115801562001b8a573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8c168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001c79927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001c9457600080fd5b505af115801562001ca9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8b168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001d98927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001db357600080fd5b505af115801562001dc8573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562001e7357600080fd5b505af192505050801562001e85575060015b62001ece578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362001ec85762001ec86200259e565b62001f0c565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001f0c5762001f0c6200259e565b50505050505050565b60606015805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60008160405160200162001f9991906200274d565b604051602081830303815290604052805190602001208360405160200162001fc291906200274d565b6040516020818303038152906040528051906020012014905092915050565b6040517f515361f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015282166024820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063515361f69060440160006040518083038186803b1580156200206357600080fd5b505afa15801562002078573d6000803e3d6000fd5b505050505050565b613623806200276383390190565b6107958062005d8683390190565b6020808252825182820181905260009190848201906040850190845b81811015620020ec57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101620020b8565b50909695505050505050565b60005b8381101562002115578181015183820152602001620020fb565b8381111562000def5750506000910152565b6000815180845262002141816020860160208601620020f8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602080825282518282018190526000919060409081850190600581811b8701840188860187805b8581101562002272577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08b85030187528251805173ffffffffffffffffffffffffffffffffffffffff1685528901518985018990528051898601819052908a0190606081881b870181019190870190855b818110156200225b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08985030183526200224884865162002127565b948e01949350918d01916001016200220b565b505050978a0197945050918801916001016200219a565b50919a9950505050505050505050565b803560ff811681146200229457600080fd5b919050565b60008060408385031215620022ad57600080fd5b620022b88362002282565b9150620022c86020840162002282565b90509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015620023bc578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00186528251805173ffffffffffffffffffffffffffffffffffffffff168552880151888501889052805188860181905290890190839060608701905b80831015620023a65783517fffffffff00000000000000000000000000000000000000000000000000000000168252928b019260019290920191908b019062002362565b50978a01979550505091870191600101620022f9565b50919998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562002442577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200242f85835162002127565b94509285019290850190600101620023f2565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146200247257600080fd5b50565b803580151581146200229457600080fd5b600080600080600060a086880312156200249f57600080fd5b8535620024ac816200244f565b94506020860135620024be816200244f565b9350620024ce6040870162002475565b9250620024de6060870162002475565b9150620024ee6080870162002475565b90509295509295909350565b600181811c908216806200250f57607f821691505b60208210810362002549577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600062002580606083018562002127565b828103604084015262002594818562002127565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156200260f57600080fd5b815167ffffffffffffffff808211156200262857600080fd5b818401915084601f8301126200263d57600080fd5b815181811115620026525762002652620025cd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156200269b576200269b620025cd565b81604052828152876020848701011115620026b557600080fd5b620026c8836020830160208801620020f8565b979650505050505050565b600060208284031215620026e657600080fd5b8151620026f3816200244f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006200272b604083018462002127565b949350505050565b6000602082840312156200274657600080fd5b5051919050565b602081526000620026f360208301846200212756fe60806040523480156200001157600080fd5b506200001e600062000024565b62000217565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016d60201b6200045a1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b62000122734200000000000000000000000000000000000007836200017c565b801562000169576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b6133fc80620002276000396000f3fe60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a608060405260405161079538038061079583398101604081905261002291610314565b61002e82826000610035565b5050610431565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161076e602791396101a9565b9392505050565b6100ea8161028760201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61029660201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610148565b600080856001600160a01b03168560405161022c91906103e2565b600060405180830381855af49150503d8060008114610267576040519150601f19603f3d011682016040523d82523d6000602084013e61026c565b606091505b50909250905061027d828286610299565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a85750816100d0565b8251156102b85782518084602001fd5b8160405162461bcd60e51b815260040161014891906103fe565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103035781810151838201526020016102eb565b838111156100645750506000910152565b6000806040838503121561032757600080fd5b82516001600160a01b038116811461033e57600080fd5b60208401519092506001600160401b038082111561035b57600080fd5b818501915085601f83011261036f57600080fd5b815181811115610381576103816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + 0x0000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000001000000000000000000000000000001000000000000000000010000000000000000000000000000010000000000000000000100000000000000000001000000000000000000000000000000000100000000000100010000000000000000000100000000000000000000000000000100000000000000000001000000000000000000000000000001000000000000000000010000000000000000000100000000000000000001000000000000000000010000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000100000000000100000000000000000000000000000000000000000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000100010000000000000000000000000001000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000010000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000001000000000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000001000000000000000000000000000000000000000000000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000010000000001000000000000000000000000000000000000000100000000000000000000010000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000001000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000100000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000001000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000100000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000100000000010000000000000000000000010000000000000000000000000000010000000001000000000000000000000000000100000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000010000000000000000010000000000000000000000000100000000000000000000000100000000000000000000000000000001000000000000000000000001000000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000100010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000100000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000010000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000001000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000000001000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000001000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000000000000000100000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000010000000000000000000000000000000000010000000000000000010000000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000001000000000000000000000100000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000001000000000000000001000000000000000000000000010000000000000000000000000000000000000000000000000100010000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000100000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000001000000000000000000000000000000000100000000000000000001000000000000000000000000000001000001000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000010000000000000000000000000000000000000000000000010000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000001000000000000000000000000000000000100000000000000000000000000000100000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100010000000100000000000000000000010000000001000100000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000100000000000000000001000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000100000000000000000000000000000100000000000100000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + CALLER_ID:Int + + + 0x547d77c4 +Bytes #buf ( 0x20 , VV0__decimalsFrom_114b9705:Int ) +Bytes #buf ( 0x20 , VV1__decimalsTo_114b9705:Int ) + + + 0x0 + + + ( 0x3c0 : ( 0x248391ff : ( 0x2e234dae75c793f67a35089c9d99245e1c58470b : ( 0x64 : ( 0x1a4 : ( VV1__decimalsTo_114b9705:Int : ( VV0__decimalsFrom_114b9705:Int : ( 0x23d : ( 0x547d77c4 : .WordStack ) ) ) ) ) ) ) ) ) + + + 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000754cd1bdd15c0ed896f2867165a2694d76f39fa50000000000000000000000000000000000000000000000000000000000000004313ce5670000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV0__decimalsFrom_114b9705:Int ) +Bytes 0x0000000000000000000000000000000000000000000000000000000000000004313ce5670000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV1__decimalsTo_114b9705:Int ) +Bytes 0x000000000000000000000000000000000000000000000000000000000000002401ffc9a701ffc9a70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002401ffc9a71d1d8b6300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000004316b3739000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a40000000000000000000000000000000000000000000000000000000000000004316b3739000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a4248391ff000000000000000000000000e6a7a45f334393093061116b197e3240065ff2d80000000000000000000000007c05912fc4cbffd28f63f412fcdd194991f8db4800000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000004316b373900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001a4816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c65640000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000754cd1bdd15c0ed896f2867165a2694d76f39fa50000000000000000000000000000000000000000000000000000000000000000604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + 0xda5 + + + 0x0 + + + 0x0 + + + 0x0 + + + false + + + 0x0 + + ) + + + ListItem ( { + ( + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x0 + + + 0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( ( 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc |-> 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) + ( 0x4 |-> 0x754cd1bdd15c0ed896f2867165a2694d76f39fa5 ) ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x4200000000000000000000000000000000000026 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x4200000000000000000000000000000000000012 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f + + + 0x0 + + + 0x60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( 0x4 |-> 0x0 ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x0 + + + 0x60806040523480156200001157600080fd5b5060043610620001895760003560e01c8063916a17c611620000dd578063c89701a2116200008b578063d6a2ec76116200006e578063d6a2ec761462000341578063e20c9f711462000369578063fa7626d4146200037357600080fd5b8063c89701a214620002f1578063d5ce3389146200031957600080fd5b8063ba414fa611620000c0578063ba414fa61462000299578063bf4792f114620002b4578063c30fe4fe14620002da57600080fd5b8063916a17c61462000285578063b5508aa9146200028f57600080fd5b8063547d77c4116200013b57806385226c81116200011e57806385226c8114620002585780638ea3d06f14620002715780638fe30c69146200027b57600080fd5b8063547d77c4146200022657806366d9a9a0146200023f57600080fd5b80632ade388011620001705780632ade388014620001f95780633e5e3c2314620002125780633f7286f4146200021c57600080fd5b806313151981146200018e5780631ed7831c14620001e0575b600080fd5b620001b67f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001ea62000381565b604051620001d791906200209c565b62000203620003f2565b604051620001d7919062002173565b620001ea6200054d565b620001ea620005bc565b6200023d6200023736600462002299565b6200062b565b005b6200024962000df5565b604051620001d79190620022d1565b6200026262000f01565b604051620001d79190620023cb565b6200023d62000fdb565b6200023d620011ab565b62000249620012e6565b62000262620013f2565b620002a3620014cc565b6040519015158152602001620001d7565b601e54620001b690610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6200023d620002eb36600462002486565b620015a4565b620001b67f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa581565b620001b67f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d881565b620001b67f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d81565b620001ea62001f15565b601e54620002a39060ff1681565b60606016805480602002602001604051908101604052809291908181526020018280548015620003e857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575b5050505050905090565b6060601d805480602002602001604051908101604052809291908181526020016000905b8282101562000544576000848152602080822060408051808201825260028702909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939591948681019491929084015b828210156200052c5783829060005260206000200180546200049890620024fa565b80601f0160208091040260200160405190810160405280929190818152602001828054620004c690620024fa565b8015620005175780601f10620004eb5761010080835404028352916020019162000517565b820191906000526020600020905b815481529060010190602001808311620004f957829003601f168201915b50505050508152602001906001019062000476565b50505050815250508152602001906001019062000416565b50505050905090565b60606018805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60606017805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b62000635620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff86168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262000717927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8926044016200254f565b600060405180830381600087803b1580156200073257600080fd5b505af115801562000747573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e493506200082f927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b1580156200084a57600080fd5b505af11580156200085f573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909317909252835160018184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000956937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b1580156200097157600080fd5b505af115801562000986573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000179052835160018183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000a99937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562000ab457600080fd5b505af115801562000ac9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b37390000000000000000000000000000000000000000000000000000000017905282516101a481830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452929450737109709ecfa91a80626ff3989d68f67f5b1dd12d935063b96213e49262000ba8927342000000000000000000000000000000000000129290916044016200254f565b600060405180830381600087803b15801562000bc357600080fd5b505af115801562000bd8573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062000cc7927342000000000000000000000000000000000000269291906044016200254f565b600060405180830381600087803b15801562000ce257600080fd5b505af115801562000cf7573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562000da257600080fd5b505af192505050801562000db4575060015b62000dd7578260ff168460ff160362000dd15762000dd16200259e565b62000def565b8260ff168460ff161462000def5762000def6200259e565b50505050565b6060601b805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff16835260018101805483518187028101870190945280845293949193858301939283018282801562000ee857602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841162000e945790505b5050505050815250508152602001906001019062000e19565b6060601a805480602002602001604051908101604052809291908181526020016000905b828210156200054457838290600052602060002001805462000f4790620024fa565b80601f016020809104026020016040519081016040528092919081815260200182805462000f7590620024fa565b801562000fc65780601f1062000f9a5761010080835404028352916020019162000fc6565b820191906000526020600020905b81548152906001019060200180831162000fa857829003601f168201915b50505050508152602001906001019062000f25565b62000fe5620011ab565b620010db601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001057573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200109f9190810190620025fc565b6040518060400160405280601581526020017f312e31312e312d626574612e312b696e7465726f70000000000000000000000081525062001f84565b620010ea57620010ea6200259e565b620011a9601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f46ddb26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200115c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011829190620026d3565b7f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa562001fe1565b565b604051620011b99062002080565b604051809103906000f080158015620011d6573d6000803e3d6000fd5b5060405173754cd1bdd15c0ed896f2867165a2694d76f39fa56024820152604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de8000000000000000000000000000000000000000000000000000000001790525162001279906200208e565b62001286929190620026fa565b604051809103906000f080158015620012a3573d6000803e3d6000fd5b50601e60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6060601c805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939491938583019392830182828015620013d957602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411620013855790505b505050505081525050815260200190600101906200130a565b60606019805480602002602001604051908101604052809291908181526020016000905b82821015620005445783829060005260206000200180546200143890620024fa565b80601f01602080910402602001604051908101604052809291908181526020018280546200146690620024fa565b8015620014b75780601f106200148b57610100808354040283529160200191620014b7565b820191906000526020600020905b8154815290600101906020018083116200149957829003601f168201915b50505050508152602001906001019062001416565b60085460009060ff1615620014e5575060085460ff1690565b6040517f667f9d70000000000000000000000000000000000000000000000000000000008152737109709ecfa91a80626ff3989d68f67f5b1dd12d600482018190527f6661696c65640000000000000000000000000000000000000000000000000000602483015260009163667f9d7090604401602060405180830381865afa15801562001577573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200159d919062002733565b1415905090565b620015ae620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce567000000000000000000000000000000000000000000000000000000001790528251601281830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262001692927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d89291906044016200254f565b600060405180830381600087803b158015620016ad57600080fd5b505af1158015620016c2573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e49350620017aa927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b158015620017c557600080fd5b505af1158015620017da573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690931790925283518a15158184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e49450620018d2937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b158015620018ed57600080fd5b505af115801562001902573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518915158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001a16937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001a3157600080fd5b505af115801562001a46573d6000803e3d6000fd5b5050604080517fec4fc8e3000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518815158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001b5a937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001b7557600080fd5b505af115801562001b8a573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8c168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001c79927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001c9457600080fd5b505af115801562001ca9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8b168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001d98927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001db357600080fd5b505af115801562001dc8573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562001e7357600080fd5b505af192505050801562001e85575060015b62001ece578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362001ec85762001ec86200259e565b62001f0c565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001f0c5762001f0c6200259e565b50505050505050565b60606015805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60008160405160200162001f9991906200274d565b604051602081830303815290604052805190602001208360405160200162001fc291906200274d565b6040516020818303038152906040528051906020012014905092915050565b6040517f515361f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015282166024820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063515361f69060440160006040518083038186803b1580156200206357600080fd5b505afa15801562002078573d6000803e3d6000fd5b505050505050565b613623806200276383390190565b6107958062005d8683390190565b6020808252825182820181905260009190848201906040850190845b81811015620020ec57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101620020b8565b50909695505050505050565b60005b8381101562002115578181015183820152602001620020fb565b8381111562000def5750506000910152565b6000815180845262002141816020860160208601620020f8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602080825282518282018190526000919060409081850190600581811b8701840188860187805b8581101562002272577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08b85030187528251805173ffffffffffffffffffffffffffffffffffffffff1685528901518985018990528051898601819052908a0190606081881b870181019190870190855b818110156200225b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08985030183526200224884865162002127565b948e01949350918d01916001016200220b565b505050978a0197945050918801916001016200219a565b50919a9950505050505050505050565b803560ff811681146200229457600080fd5b919050565b60008060408385031215620022ad57600080fd5b620022b88362002282565b9150620022c86020840162002282565b90509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015620023bc578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00186528251805173ffffffffffffffffffffffffffffffffffffffff168552880151888501889052805188860181905290890190839060608701905b80831015620023a65783517fffffffff00000000000000000000000000000000000000000000000000000000168252928b019260019290920191908b019062002362565b50978a01979550505091870191600101620022f9565b50919998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562002442577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200242f85835162002127565b94509285019290850190600101620023f2565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146200247257600080fd5b50565b803580151581146200229457600080fd5b600080600080600060a086880312156200249f57600080fd5b8535620024ac816200244f565b94506020860135620024be816200244f565b9350620024ce6040870162002475565b9250620024de6060870162002475565b9150620024ee6080870162002475565b90509295509295909350565b600181811c908216806200250f57607f821691505b60208210810362002549577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600062002580606083018562002127565b828103604084015262002594818562002127565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156200260f57600080fd5b815167ffffffffffffffff808211156200262857600080fd5b818401915084601f8301126200263d57600080fd5b815181811115620026525762002652620025cd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156200269b576200269b620025cd565b81604052828152876020848701011115620026b557600080fd5b620026c8836020830160208801620020f8565b979650505050505050565b600060208284031215620026e657600080fd5b8151620026f3816200244f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006200272b604083018462002127565b949350505050565b6000602082840312156200274657600080fd5b5051919050565b602081526000620026f360208301846200212756fe60806040523480156200001157600080fd5b506200001e600062000024565b62000217565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016d60201b6200045a1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b62000122734200000000000000000000000000000000000007836200017c565b801562000169576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b6133fc80620002276000396000f3fe60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a608060405260405161079538038061079583398101604081905261002291610314565b61002e82826000610035565b5050610431565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161076e602791396101a9565b9392505050565b6100ea8161028760201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61029660201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610148565b600080856001600160a01b03168560405161022c91906103e2565b600060405180830381855af49150503d8060008114610267576040519150601f19603f3d011682016040523d82523d6000602084013e61026c565b606091505b50909250905061027d828286610299565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a85750816100d0565b8251156102b85782518084602001fd5b8160405162461bcd60e51b815260040161014891906103fe565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103035781810151838201526020016102eb565b838111156100645750506000910152565b6000806040838503121561032757600080fd5b82516001600160a01b038116811461033e57600080fd5b60208401519092506001600160401b038082111561035b57600080fd5b818501915085601f83011261036f57600080fd5b815181811115610381576103816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( 0x1e |-> 0x2e234dae75c793f67a35089c9d99245e1c58470b00 ) + + + .Map + + + .Map + + + 0x3 + + + ( + + 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + + + 0xe6a7a45f334393093061116b197e3240065ff2d8 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + ) ) ) ) ) ) ) + | + + SELFDESTRUCT_CELL:Set + + + ListItem ( { 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b ) ListItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) | 0x } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) + + + 0x0 + + + ( SetItem ( 0x7fa9385be102ac3eac297483dd6233d62b3e1496 ) ( SetItem ( 0xe6a7a45f334393093061116b197e3240065ff2d8 ) ( SetItem ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 ) ( SetItem ( 0x4200000000000000000000000000000000000012 ) ( SetItem ( 0x4200000000000000000000000000000000000026 ) ( SetItem ( 0x2e234dae75c793f67a35089c9d99245e1c58470b ) ( SetItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) SetItem ( 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d ) ) ) ) ) ) ) ) + + + .Map + + } ) ListItem ( { + ( + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x0 + + + 0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( ( 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc |-> 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) + ( 0x4 |-> 0x754cd1bdd15c0ed896f2867165a2694d76f39fa5 ) ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x4200000000000000000000000000000000000026 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x4200000000000000000000000000000000000012 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f + + + 0x0 + + + 0x60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( 0x4 |-> 0x0 ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x0 + + + 0x60806040523480156200001157600080fd5b5060043610620001895760003560e01c8063916a17c611620000dd578063c89701a2116200008b578063d6a2ec76116200006e578063d6a2ec761462000341578063e20c9f711462000369578063fa7626d4146200037357600080fd5b8063c89701a214620002f1578063d5ce3389146200031957600080fd5b8063ba414fa611620000c0578063ba414fa61462000299578063bf4792f114620002b4578063c30fe4fe14620002da57600080fd5b8063916a17c61462000285578063b5508aa9146200028f57600080fd5b8063547d77c4116200013b57806385226c81116200011e57806385226c8114620002585780638ea3d06f14620002715780638fe30c69146200027b57600080fd5b8063547d77c4146200022657806366d9a9a0146200023f57600080fd5b80632ade388011620001705780632ade388014620001f95780633e5e3c2314620002125780633f7286f4146200021c57600080fd5b806313151981146200018e5780631ed7831c14620001e0575b600080fd5b620001b67f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001ea62000381565b604051620001d791906200209c565b62000203620003f2565b604051620001d7919062002173565b620001ea6200054d565b620001ea620005bc565b6200023d6200023736600462002299565b6200062b565b005b6200024962000df5565b604051620001d79190620022d1565b6200026262000f01565b604051620001d79190620023cb565b6200023d62000fdb565b6200023d620011ab565b62000249620012e6565b62000262620013f2565b620002a3620014cc565b6040519015158152602001620001d7565b601e54620001b690610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6200023d620002eb36600462002486565b620015a4565b620001b67f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa581565b620001b67f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d881565b620001b67f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d81565b620001ea62001f15565b601e54620002a39060ff1681565b60606016805480602002602001604051908101604052809291908181526020018280548015620003e857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575b5050505050905090565b6060601d805480602002602001604051908101604052809291908181526020016000905b8282101562000544576000848152602080822060408051808201825260028702909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939591948681019491929084015b828210156200052c5783829060005260206000200180546200049890620024fa565b80601f0160208091040260200160405190810160405280929190818152602001828054620004c690620024fa565b8015620005175780601f10620004eb5761010080835404028352916020019162000517565b820191906000526020600020905b815481529060010190602001808311620004f957829003601f168201915b50505050508152602001906001019062000476565b50505050815250508152602001906001019062000416565b50505050905090565b60606018805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60606017805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b62000635620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff86168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262000717927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8926044016200254f565b600060405180830381600087803b1580156200073257600080fd5b505af115801562000747573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e493506200082f927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b1580156200084a57600080fd5b505af11580156200085f573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909317909252835160018184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000956937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b1580156200097157600080fd5b505af115801562000986573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000179052835160018183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000a99937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562000ab457600080fd5b505af115801562000ac9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b37390000000000000000000000000000000000000000000000000000000017905282516101a481830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452929450737109709ecfa91a80626ff3989d68f67f5b1dd12d935063b96213e49262000ba8927342000000000000000000000000000000000000129290916044016200254f565b600060405180830381600087803b15801562000bc357600080fd5b505af115801562000bd8573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062000cc7927342000000000000000000000000000000000000269291906044016200254f565b600060405180830381600087803b15801562000ce257600080fd5b505af115801562000cf7573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562000da257600080fd5b505af192505050801562000db4575060015b62000dd7578260ff168460ff160362000dd15762000dd16200259e565b62000def565b8260ff168460ff161462000def5762000def6200259e565b50505050565b6060601b805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff16835260018101805483518187028101870190945280845293949193858301939283018282801562000ee857602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841162000e945790505b5050505050815250508152602001906001019062000e19565b6060601a805480602002602001604051908101604052809291908181526020016000905b828210156200054457838290600052602060002001805462000f4790620024fa565b80601f016020809104026020016040519081016040528092919081815260200182805462000f7590620024fa565b801562000fc65780601f1062000f9a5761010080835404028352916020019162000fc6565b820191906000526020600020905b81548152906001019060200180831162000fa857829003601f168201915b50505050508152602001906001019062000f25565b62000fe5620011ab565b620010db601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001057573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200109f9190810190620025fc565b6040518060400160405280601581526020017f312e31312e312d626574612e312b696e7465726f70000000000000000000000081525062001f84565b620010ea57620010ea6200259e565b620011a9601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f46ddb26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200115c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011829190620026d3565b7f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa562001fe1565b565b604051620011b99062002080565b604051809103906000f080158015620011d6573d6000803e3d6000fd5b5060405173754cd1bdd15c0ed896f2867165a2694d76f39fa56024820152604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de8000000000000000000000000000000000000000000000000000000001790525162001279906200208e565b62001286929190620026fa565b604051809103906000f080158015620012a3573d6000803e3d6000fd5b50601e60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6060601c805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939491938583019392830182828015620013d957602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411620013855790505b505050505081525050815260200190600101906200130a565b60606019805480602002602001604051908101604052809291908181526020016000905b82821015620005445783829060005260206000200180546200143890620024fa565b80601f01602080910402602001604051908101604052809291908181526020018280546200146690620024fa565b8015620014b75780601f106200148b57610100808354040283529160200191620014b7565b820191906000526020600020905b8154815290600101906020018083116200149957829003601f168201915b50505050508152602001906001019062001416565b60085460009060ff1615620014e5575060085460ff1690565b6040517f667f9d70000000000000000000000000000000000000000000000000000000008152737109709ecfa91a80626ff3989d68f67f5b1dd12d600482018190527f6661696c65640000000000000000000000000000000000000000000000000000602483015260009163667f9d7090604401602060405180830381865afa15801562001577573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200159d919062002733565b1415905090565b620015ae620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce567000000000000000000000000000000000000000000000000000000001790528251601281830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262001692927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d89291906044016200254f565b600060405180830381600087803b158015620016ad57600080fd5b505af1158015620016c2573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e49350620017aa927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b158015620017c557600080fd5b505af1158015620017da573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690931790925283518a15158184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e49450620018d2937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b158015620018ed57600080fd5b505af115801562001902573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518915158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001a16937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001a3157600080fd5b505af115801562001a46573d6000803e3d6000fd5b5050604080517fec4fc8e3000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518815158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001b5a937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001b7557600080fd5b505af115801562001b8a573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8c168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001c79927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001c9457600080fd5b505af115801562001ca9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8b168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001d98927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001db357600080fd5b505af115801562001dc8573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562001e7357600080fd5b505af192505050801562001e85575060015b62001ece578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362001ec85762001ec86200259e565b62001f0c565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001f0c5762001f0c6200259e565b50505050505050565b60606015805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60008160405160200162001f9991906200274d565b604051602081830303815290604052805190602001208360405160200162001fc291906200274d565b6040516020818303038152906040528051906020012014905092915050565b6040517f515361f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015282166024820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063515361f69060440160006040518083038186803b1580156200206357600080fd5b505afa15801562002078573d6000803e3d6000fd5b505050505050565b613623806200276383390190565b6107958062005d8683390190565b6020808252825182820181905260009190848201906040850190845b81811015620020ec57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101620020b8565b50909695505050505050565b60005b8381101562002115578181015183820152602001620020fb565b8381111562000def5750506000910152565b6000815180845262002141816020860160208601620020f8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602080825282518282018190526000919060409081850190600581811b8701840188860187805b8581101562002272577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08b85030187528251805173ffffffffffffffffffffffffffffffffffffffff1685528901518985018990528051898601819052908a0190606081881b870181019190870190855b818110156200225b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08985030183526200224884865162002127565b948e01949350918d01916001016200220b565b505050978a0197945050918801916001016200219a565b50919a9950505050505050505050565b803560ff811681146200229457600080fd5b919050565b60008060408385031215620022ad57600080fd5b620022b88362002282565b9150620022c86020840162002282565b90509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015620023bc578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00186528251805173ffffffffffffffffffffffffffffffffffffffff168552880151888501889052805188860181905290890190839060608701905b80831015620023a65783517fffffffff00000000000000000000000000000000000000000000000000000000168252928b019260019290920191908b019062002362565b50978a01979550505091870191600101620022f9565b50919998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562002442577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200242f85835162002127565b94509285019290850190600101620023f2565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146200247257600080fd5b50565b803580151581146200229457600080fd5b600080600080600060a086880312156200249f57600080fd5b8535620024ac816200244f565b94506020860135620024be816200244f565b9350620024ce6040870162002475565b9250620024de6060870162002475565b9150620024ee6080870162002475565b90509295509295909350565b600181811c908216806200250f57607f821691505b60208210810362002549577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600062002580606083018562002127565b828103604084015262002594818562002127565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156200260f57600080fd5b815167ffffffffffffffff808211156200262857600080fd5b818401915084601f8301126200263d57600080fd5b815181811115620026525762002652620025cd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156200269b576200269b620025cd565b81604052828152876020848701011115620026b557600080fd5b620026c8836020830160208801620020f8565b979650505050505050565b600060208284031215620026e657600080fd5b8151620026f3816200244f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006200272b604083018462002127565b949350505050565b6000602082840312156200274657600080fd5b5051919050565b602081526000620026f360208301846200212756fe60806040523480156200001157600080fd5b506200001e600062000024565b62000217565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016d60201b6200045a1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b62000122734200000000000000000000000000000000000007836200017c565b801562000169576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b6133fc80620002276000396000f3fe60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a608060405260405161079538038061079583398101604081905261002291610314565b61002e82826000610035565b5050610431565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161076e602791396101a9565b9392505050565b6100ea8161028760201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61029660201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610148565b600080856001600160a01b03168560405161022c91906103e2565b600060405180830381855af49150503d8060008114610267576040519150601f19603f3d011682016040523d82523d6000602084013e61026c565b606091505b50909250905061027d828286610299565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a85750816100d0565b8251156102b85782518084602001fd5b8160405162461bcd60e51b815260040161014891906103fe565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103035781810151838201526020016102eb565b838111156100645750506000910152565b6000806040838503121561032757600080fd5b82516001600160a01b038116811461033e57600080fd5b60208401519092506001600160401b038082111561035b57600080fd5b818501915085601f83011261036f57600080fd5b815181811115610381576103816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( 0x1e |-> 0x2e234dae75c793f67a35089c9d99245e1c58470b00 ) + + + .Map + + + .Map + + + 0x3 + + + ( + + 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + + + 0xe6a7a45f334393093061116b197e3240065ff2d8 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + ) ) ) ) ) ) ) + | + + SELFDESTRUCT_CELL:Set + + + ListItem ( { 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b ) ListItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) | 0x } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) + + + 0x0 + + + ( SetItem ( 0x7fa9385be102ac3eac297483dd6233d62b3e1496 ) ( SetItem ( 0xe6a7a45f334393093061116b197e3240065ff2d8 ) ( SetItem ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 ) ( SetItem ( 0x4200000000000000000000000000000000000012 ) ( SetItem ( 0x4200000000000000000000000000000000000026 ) ( SetItem ( 0x2e234dae75c793f67a35089c9d99245e1c58470b ) ( SetItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) SetItem ( 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d ) ) ) ) ) ) ) ) + + + .Map + + } ) + + + ( SetItem ( 0x7fa9385be102ac3eac297483dd6233d62b3e1496 ) ( SetItem ( 0x2e234dae75c793f67a35089c9d99245e1c58470b ) SetItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) ) ) + + + + 0x60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000100000000010000000000000000000000010000000000000000000000000000010000000001000000000000000000000000000100000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000010000000000000000010000000000000000000000000100000000000000000000000100000000000000000000000000000001000000000000000000000001000000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000100010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000100000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000010000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000001000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000000001000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000001000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000000000000000100000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000010000000000000000000000000000000000010000000000000000010000000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000001000000000000000000000100000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000 + + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x248391ff000000000000000000000000e6a7a45f334393093061116b197e3240065ff2d80000000000000000000000007c05912fc4cbffd28f63f412fcdd194991f8db480000000000000000000000000000000000000000000000000000000000000064 + + + 0x0 + + + ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 : ( 0xe6a7a45f334393093061116b197e3240065ff2d8 : ( 0xebb : ( 0x64 : ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 : ( 0xe6a7a45f334393093061116b197e3240065ff2d8 : ( 0x1fa : ( 0x248391ff : .WordStack ) ) ) ) ) ) ) ) + + + 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000 +Bytes #buf ( 0x20 , VV1__decimalsTo_114b9705:Int ) +Bytes #buf ( 0x20 , VV0__decimalsFrom_114b9705:Int ) + + + 0x20da + + + 0x0 + + + 0x0 + + + 0x0 + + + false + + + 0x2 + + + + + SELFDESTRUCT_CELL:Set + + + ListItem ( { 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b ) ListItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) | 0x } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) + + + 0x0 + + + ( SetItem ( 0x7fa9385be102ac3eac297483dd6233d62b3e1496 ) ( SetItem ( 0xe6a7a45f334393093061116b197e3240065ff2d8 ) ( SetItem ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 ) ( SetItem ( 0x4200000000000000000000000000000000000012 ) ( SetItem ( 0x4200000000000000000000000000000000000026 ) ( SetItem ( 0x2e234dae75c793f67a35089c9d99245e1c58470b ) ( SetItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) SetItem ( 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d ) ) ) ) ) ) ) ) + + + .Map + + + + ORIGIN_ID:Int + + + + NUMBER_CELL:Int + + + TIMESTAMP_CELL:Int + + ... + + ... + + + + 0x1 + + + ( + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x0 + + + 0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( ( 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc |-> 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) + ( 0x4 |-> 0x754cd1bdd15c0ed896f2867165a2694d76f39fa5 ) ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x4200000000000000000000000000000000000026 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x4200000000000000000000000000000000000012 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f + + + 0x0 + + + 0x60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( 0x4 |-> 0x0 ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x0 + + + 0x60806040523480156200001157600080fd5b5060043610620001895760003560e01c8063916a17c611620000dd578063c89701a2116200008b578063d6a2ec76116200006e578063d6a2ec761462000341578063e20c9f711462000369578063fa7626d4146200037357600080fd5b8063c89701a214620002f1578063d5ce3389146200031957600080fd5b8063ba414fa611620000c0578063ba414fa61462000299578063bf4792f114620002b4578063c30fe4fe14620002da57600080fd5b8063916a17c61462000285578063b5508aa9146200028f57600080fd5b8063547d77c4116200013b57806385226c81116200011e57806385226c8114620002585780638ea3d06f14620002715780638fe30c69146200027b57600080fd5b8063547d77c4146200022657806366d9a9a0146200023f57600080fd5b80632ade388011620001705780632ade388014620001f95780633e5e3c2314620002125780633f7286f4146200021c57600080fd5b806313151981146200018e5780631ed7831c14620001e0575b600080fd5b620001b67f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001ea62000381565b604051620001d791906200209c565b62000203620003f2565b604051620001d7919062002173565b620001ea6200054d565b620001ea620005bc565b6200023d6200023736600462002299565b6200062b565b005b6200024962000df5565b604051620001d79190620022d1565b6200026262000f01565b604051620001d79190620023cb565b6200023d62000fdb565b6200023d620011ab565b62000249620012e6565b62000262620013f2565b620002a3620014cc565b6040519015158152602001620001d7565b601e54620001b690610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6200023d620002eb36600462002486565b620015a4565b620001b67f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa581565b620001b67f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d881565b620001b67f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d81565b620001ea62001f15565b601e54620002a39060ff1681565b60606016805480602002602001604051908101604052809291908181526020018280548015620003e857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575b5050505050905090565b6060601d805480602002602001604051908101604052809291908181526020016000905b8282101562000544576000848152602080822060408051808201825260028702909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939591948681019491929084015b828210156200052c5783829060005260206000200180546200049890620024fa565b80601f0160208091040260200160405190810160405280929190818152602001828054620004c690620024fa565b8015620005175780601f10620004eb5761010080835404028352916020019162000517565b820191906000526020600020905b815481529060010190602001808311620004f957829003601f168201915b50505050508152602001906001019062000476565b50505050815250508152602001906001019062000416565b50505050905090565b60606018805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60606017805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b62000635620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff86168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262000717927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8926044016200254f565b600060405180830381600087803b1580156200073257600080fd5b505af115801562000747573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e493506200082f927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b1580156200084a57600080fd5b505af11580156200085f573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909317909252835160018184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000956937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b1580156200097157600080fd5b505af115801562000986573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000179052835160018183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000a99937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562000ab457600080fd5b505af115801562000ac9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b37390000000000000000000000000000000000000000000000000000000017905282516101a481830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452929450737109709ecfa91a80626ff3989d68f67f5b1dd12d935063b96213e49262000ba8927342000000000000000000000000000000000000129290916044016200254f565b600060405180830381600087803b15801562000bc357600080fd5b505af115801562000bd8573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062000cc7927342000000000000000000000000000000000000269291906044016200254f565b600060405180830381600087803b15801562000ce257600080fd5b505af115801562000cf7573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562000da257600080fd5b505af192505050801562000db4575060015b62000dd7578260ff168460ff160362000dd15762000dd16200259e565b62000def565b8260ff168460ff161462000def5762000def6200259e565b50505050565b6060601b805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff16835260018101805483518187028101870190945280845293949193858301939283018282801562000ee857602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841162000e945790505b5050505050815250508152602001906001019062000e19565b6060601a805480602002602001604051908101604052809291908181526020016000905b828210156200054457838290600052602060002001805462000f4790620024fa565b80601f016020809104026020016040519081016040528092919081815260200182805462000f7590620024fa565b801562000fc65780601f1062000f9a5761010080835404028352916020019162000fc6565b820191906000526020600020905b81548152906001019060200180831162000fa857829003601f168201915b50505050508152602001906001019062000f25565b62000fe5620011ab565b620010db601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001057573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200109f9190810190620025fc565b6040518060400160405280601581526020017f312e31312e312d626574612e312b696e7465726f70000000000000000000000081525062001f84565b620010ea57620010ea6200259e565b620011a9601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f46ddb26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200115c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011829190620026d3565b7f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa562001fe1565b565b604051620011b99062002080565b604051809103906000f080158015620011d6573d6000803e3d6000fd5b5060405173754cd1bdd15c0ed896f2867165a2694d76f39fa56024820152604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de8000000000000000000000000000000000000000000000000000000001790525162001279906200208e565b62001286929190620026fa565b604051809103906000f080158015620012a3573d6000803e3d6000fd5b50601e60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6060601c805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939491938583019392830182828015620013d957602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411620013855790505b505050505081525050815260200190600101906200130a565b60606019805480602002602001604051908101604052809291908181526020016000905b82821015620005445783829060005260206000200180546200143890620024fa565b80601f01602080910402602001604051908101604052809291908181526020018280546200146690620024fa565b8015620014b75780601f106200148b57610100808354040283529160200191620014b7565b820191906000526020600020905b8154815290600101906020018083116200149957829003601f168201915b50505050508152602001906001019062001416565b60085460009060ff1615620014e5575060085460ff1690565b6040517f667f9d70000000000000000000000000000000000000000000000000000000008152737109709ecfa91a80626ff3989d68f67f5b1dd12d600482018190527f6661696c65640000000000000000000000000000000000000000000000000000602483015260009163667f9d7090604401602060405180830381865afa15801562001577573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200159d919062002733565b1415905090565b620015ae620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce567000000000000000000000000000000000000000000000000000000001790528251601281830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262001692927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d89291906044016200254f565b600060405180830381600087803b158015620016ad57600080fd5b505af1158015620016c2573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e49350620017aa927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b158015620017c557600080fd5b505af1158015620017da573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690931790925283518a15158184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e49450620018d2937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b158015620018ed57600080fd5b505af115801562001902573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518915158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001a16937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001a3157600080fd5b505af115801562001a46573d6000803e3d6000fd5b5050604080517fec4fc8e3000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518815158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001b5a937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001b7557600080fd5b505af115801562001b8a573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8c168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001c79927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001c9457600080fd5b505af115801562001ca9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8b168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001d98927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001db357600080fd5b505af115801562001dc8573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562001e7357600080fd5b505af192505050801562001e85575060015b62001ece578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362001ec85762001ec86200259e565b62001f0c565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001f0c5762001f0c6200259e565b50505050505050565b60606015805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60008160405160200162001f9991906200274d565b604051602081830303815290604052805190602001208360405160200162001fc291906200274d565b6040516020818303038152906040528051906020012014905092915050565b6040517f515361f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015282166024820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063515361f69060440160006040518083038186803b1580156200206357600080fd5b505afa15801562002078573d6000803e3d6000fd5b505050505050565b613623806200276383390190565b6107958062005d8683390190565b6020808252825182820181905260009190848201906040850190845b81811015620020ec57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101620020b8565b50909695505050505050565b60005b8381101562002115578181015183820152602001620020fb565b8381111562000def5750506000910152565b6000815180845262002141816020860160208601620020f8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602080825282518282018190526000919060409081850190600581811b8701840188860187805b8581101562002272577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08b85030187528251805173ffffffffffffffffffffffffffffffffffffffff1685528901518985018990528051898601819052908a0190606081881b870181019190870190855b818110156200225b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08985030183526200224884865162002127565b948e01949350918d01916001016200220b565b505050978a0197945050918801916001016200219a565b50919a9950505050505050505050565b803560ff811681146200229457600080fd5b919050565b60008060408385031215620022ad57600080fd5b620022b88362002282565b9150620022c86020840162002282565b90509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015620023bc578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00186528251805173ffffffffffffffffffffffffffffffffffffffff168552880151888501889052805188860181905290890190839060608701905b80831015620023a65783517fffffffff00000000000000000000000000000000000000000000000000000000168252928b019260019290920191908b019062002362565b50978a01979550505091870191600101620022f9565b50919998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562002442577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200242f85835162002127565b94509285019290850190600101620023f2565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146200247257600080fd5b50565b803580151581146200229457600080fd5b600080600080600060a086880312156200249f57600080fd5b8535620024ac816200244f565b94506020860135620024be816200244f565b9350620024ce6040870162002475565b9250620024de6060870162002475565b9150620024ee6080870162002475565b90509295509295909350565b600181811c908216806200250f57607f821691505b60208210810362002549577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600062002580606083018562002127565b828103604084015262002594818562002127565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156200260f57600080fd5b815167ffffffffffffffff808211156200262857600080fd5b818401915084601f8301126200263d57600080fd5b815181811115620026525762002652620025cd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156200269b576200269b620025cd565b81604052828152876020848701011115620026b557600080fd5b620026c8836020830160208801620020f8565b979650505050505050565b600060208284031215620026e657600080fd5b8151620026f3816200244f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006200272b604083018462002127565b949350505050565b6000602082840312156200274657600080fd5b5051919050565b602081526000620026f360208301846200212756fe60806040523480156200001157600080fd5b506200001e600062000024565b62000217565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016d60201b6200045a1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b62000122734200000000000000000000000000000000000007836200017c565b801562000169576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b6133fc80620002276000396000f3fe60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a608060405260405161079538038061079583398101604081905261002291610314565b61002e82826000610035565b5050610431565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161076e602791396101a9565b9392505050565b6100ea8161028760201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61029660201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610148565b600080856001600160a01b03168560405161022c91906103e2565b600060405180830381855af49150503d8060008114610267576040519150601f19603f3d011682016040523d82523d6000602084013e61026c565b606091505b50909250905061027d828286610299565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a85750816100d0565b8251156102b85782518084602001fd5b8160405162461bcd60e51b815260040161014891906103fe565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103035781810151838201526020016102eb565b838111156100645750506000910152565b6000806040838503121561032757600080fd5b82516001600160a01b038116811461033e57600080fd5b60208401519092506001600160401b038082111561035b57600080fd5b818501915085601f83011261036f57600080fd5b815181811115610381576103816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( 0x1e |-> 0x2e234dae75c793f67a35089c9d99245e1c58470b00 ) + + + .Map + + + .Map + + + 0x3 + + + ( + + 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + + + 0xe6a7a45f334393093061116b197e3240065ff2d8 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + ) ) ) ) ) ) ) + + ... + + + ... + + + + + false + + + false + + ... + + + + false + + ... + + + + false + + ... + + + + false + + + false + + ... + + + + false + + + false + + + .List + + + .List + + + + + + 0x4200000000000000000000000000000000000012 + + + ( 0x316b3739 |-> 0x00000000000000000000000000000000000000000000000000000000000001a4 ) + + + + 0x4200000000000000000000000000000000000026 + + + ( 0x316b3739 |-> 0x00000000000000000000000000000000000000000000000000000000000001a4 ) + + + + 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 + + + ( 0x313ce567 |-> #buf ( 0x20 , VV1__decimalsTo_114b9705:Int ) ) + + + + 0xe6a7a45f334393093061116b197e3240065ff2d8 + + + ( ( 0x01ffc9a701ffc9a700000000000000000000000000000000000000000000000000000000 |-> 0x0000000000000000000000000000000000000000000000000000000000000001 ) + ( ( 0x01ffc9a71d1d8b6300000000000000000000000000000000000000000000000000000000 |-> 0x0000000000000000000000000000000000000000000000000000000000000001 ) + ( 0x313ce567 |-> #buf ( 0x20 , VV0__decimalsFrom_114b9705:Int ) ) ) ) + + + + + .MockFunctionCellMap + + + + + false + + + false + + + false + + + false + + + false + + + .List + + + + ... + +#And ( { true #Equals 0x0 <=Int CALLER_ID:Int } +#And ( { true #Equals 0x0 <=Int ORIGIN_ID:Int } +#And ( { true #Equals 0x1000000 CONTINUATION:K +│ pc: 0x0 +│ callDepth: 0x0 +│ statusCode: STATUSCODE:StatusCode +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:17:151 +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 3 +│ k: #execute ~> CONTINUATION:K +│ pc: 0x11bd +│ callDepth: 0x0 +│ statusCode: STATUSCODE:StatusCode +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (743 steps) +├─ 4 +│ k: #halt ~> #codeDeposit 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ~> #pc [ CREATE ... +│ pc: 0x225 +│ callDepth: 0x1 +│ statusCode: EVMC_SUCCESS +│ src: lib/forge-std/src/StdInvariant.sol:104:105 +│ +│ (1000 steps) +├─ 5 +│ k: #gas [ ISZERO , ISZERO 0x0 ] ~> ISZERO 0x0 ~> #pc [ ISZERO ] ~> #execute ~> #cod ... +│ pc: 0x352 +│ callDepth: 0x1 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:113:114 +│ +│ (1000 steps) +├─ 6 +│ k: #endBasicBlock ~> #execute ~> #codeDeposit 0x2e234dae75c793f67a35089c9d99245e1c5 ... +│ pc: 0x74 +│ callDepth: 0x1 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:17:151 +│ +│ (1000 steps) +├─ 7 +│ k: #next [ DUP ( 0x2 ) ] ~> #execute ~> #return 0x1e0 0x0 ~> #pc [ DELEGATECALL ] ~ ... +│ pc: 0x30e7 +│ callDepth: 0x2 +│ statusCode: EVMC_SUCCESS +│ method: src%L2%L2StandardBridgeInterop.initialize(address) +│ +│ (681 steps) +├─ 8 +│ k: #halt ~> #return 0x1e0 0x0 ~> #pc [ DELEGATECALL ] ~> #execute ~> #codeDeposit 0 ... +│ pc: 0x1fb +│ callDepth: 0x2 +│ statusCode: EVMC_SUCCESS +│ src: lib/forge-std/src/StdInvariant.sol:104:105 +│ method: src%L2%L2StandardBridgeInterop.initialize(address) +│ +│ (428 steps) +├─ 9 +│ k: #halt ~> #codeDeposit 0x2e234dae75c793f67a35089c9d99245e1c58470b ~> #pc [ CREATE ... +│ pc: 0x43e +│ callDepth: 0x1 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:119:120 +│ +│ (1000 steps) +├─ 10 +│ k: #next [ ADD ] ~> #execute ~> CONTINUATION:K +│ pc: 0x2144 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 11 +│ k: #execute ~> CONTINUATION:K +│ pc: 0x2114 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 12 +│ k: #exec [ POP ] ~> #pc [ POP ] ~> #execute ~> CONTINUATION:K +│ pc: 0x211f +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 13 +│ k: #exec [ MSTORE ] ~> #pc [ MSTORE ] ~> #execute ~> CONTINUATION:K +│ pc: 0x212e +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 14 +│ k: #addr [ EVMOR ] ~> #exec [ EVMOR ] ~> #pc [ EVMOR ] ~> #execute ~> CONTINUATION: ... +│ pc: 0x1ace +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 15 +│ k: #next [ SUB ] ~> #execute ~> CONTINUATION:K +│ pc: 0x1b62 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 16 +│ k: #next [ AND ] ~> #execute ~> CONTINUATION:K +│ pc: 0x2166 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 17 +│ k: #gas [ JUMP , JUMP 0x20fb ] ~> JUMP 0x20fb ~> #pc [ JUMP ] ~> #execute ~> CONTIN ... +│ pc: 0x2114 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 18 +│ k: #next [ PUSH ( 0x4 ) ] ~> #execute ~> #return 0x0 0x0 ~> #pc [ DELEGATECALL ] ~> ... +│ pc: 0x11f +│ callDepth: 0x2 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:24:36 +│ method: src%L2%L2StandardBridgeInterop.convert(address,address,uint256) +│ +│ (1000 steps) +└─ 19 (leaf, pending) + k: #execute ~> #return 0x0 0x0 ~> #pc [ DELEGATECALL ] ~> #execute ~> #return 0x3e0 ... + pc: 0x20b3 + callDepth: 0x2 + statusCode: EVMC_SUCCESS + method: src%L2%L2StandardBridgeInterop.convert(address,address,uint256) + + +┌─ 2 (root, leaf, target, terminal) +│ k: #halt ~> CONTINUATION:K +│ pc: PC_CELL_5d410f2a:Int +│ callDepth: CALLDEPTH_CELL_5d410f2a:Int +│ statusCode: STATUSCODE_FINAL:StatusCode + + +Node 19: + +( + + + + #execute + ~> #return 0x0 0x0 + ~> #pc [ DELEGATECALL ] + ~> #execute + ~> #return 0x3e0 0x0 + ~> #pc [ CALL ] + ~> #execute + ~> CONTINUATION:K + + + NORMAL + + + SHANGHAI + + + false + + + + + 0x0000000000000000000000000000000000000000000000000000000000000012 + + + EVMC_SUCCESS + + + ListItem ( + + 0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + 0x00000000000000000000000000000000000100010000000100000000000000000000010000000001000100000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000100000000000000000001000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000100000000000000000000000000000100000000000100000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x248391ff000000000000000000000000e6a7a45f334393093061116b197e3240065ff2d80000000000000000000000007c05912fc4cbffd28f63f412fcdd194991f8db480000000000000000000000000000000000000000000000000000000000000064 + + + 0x0 + + + ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f : ( 0x27 : ( 0x11 : .WordStack ) ) ) + + + 0x248391ff000000000000000000000000e6a7a45f334393093061116b197e3240065ff2d80000000000000000000000007c05912fc4cbffd28f63f412fcdd194991f8db480000000000000000000000000000000000000000000000000000000000000064 + + + 0xc7 + + + 0x0 + + + 0x0 + + + 0x0 + + + false + + + 0x1 + + ) ListItem ( + + 0x60806040523480156200001157600080fd5b5060043610620001895760003560e01c8063916a17c611620000dd578063c89701a2116200008b578063d6a2ec76116200006e578063d6a2ec761462000341578063e20c9f711462000369578063fa7626d4146200037357600080fd5b8063c89701a214620002f1578063d5ce3389146200031957600080fd5b8063ba414fa611620000c0578063ba414fa61462000299578063bf4792f114620002b4578063c30fe4fe14620002da57600080fd5b8063916a17c61462000285578063b5508aa9146200028f57600080fd5b8063547d77c4116200013b57806385226c81116200011e57806385226c8114620002585780638ea3d06f14620002715780638fe30c69146200027b57600080fd5b8063547d77c4146200022657806366d9a9a0146200023f57600080fd5b80632ade388011620001705780632ade388014620001f95780633e5e3c2314620002125780633f7286f4146200021c57600080fd5b806313151981146200018e5780631ed7831c14620001e0575b600080fd5b620001b67f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001ea62000381565b604051620001d791906200209c565b62000203620003f2565b604051620001d7919062002173565b620001ea6200054d565b620001ea620005bc565b6200023d6200023736600462002299565b6200062b565b005b6200024962000df5565b604051620001d79190620022d1565b6200026262000f01565b604051620001d79190620023cb565b6200023d62000fdb565b6200023d620011ab565b62000249620012e6565b62000262620013f2565b620002a3620014cc565b6040519015158152602001620001d7565b601e54620001b690610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6200023d620002eb36600462002486565b620015a4565b620001b67f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa581565b620001b67f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d881565b620001b67f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d81565b620001ea62001f15565b601e54620002a39060ff1681565b60606016805480602002602001604051908101604052809291908181526020018280548015620003e857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575b5050505050905090565b6060601d805480602002602001604051908101604052809291908181526020016000905b8282101562000544576000848152602080822060408051808201825260028702909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939591948681019491929084015b828210156200052c5783829060005260206000200180546200049890620024fa565b80601f0160208091040260200160405190810160405280929190818152602001828054620004c690620024fa565b8015620005175780601f10620004eb5761010080835404028352916020019162000517565b820191906000526020600020905b815481529060010190602001808311620004f957829003601f168201915b50505050508152602001906001019062000476565b50505050815250508152602001906001019062000416565b50505050905090565b60606018805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60606017805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b62000635620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff86168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262000717927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8926044016200254f565b600060405180830381600087803b1580156200073257600080fd5b505af115801562000747573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e493506200082f927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b1580156200084a57600080fd5b505af11580156200085f573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909317909252835160018184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000956937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b1580156200097157600080fd5b505af115801562000986573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000179052835160018183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000a99937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562000ab457600080fd5b505af115801562000ac9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b37390000000000000000000000000000000000000000000000000000000017905282516101a481830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452929450737109709ecfa91a80626ff3989d68f67f5b1dd12d935063b96213e49262000ba8927342000000000000000000000000000000000000129290916044016200254f565b600060405180830381600087803b15801562000bc357600080fd5b505af115801562000bd8573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062000cc7927342000000000000000000000000000000000000269291906044016200254f565b600060405180830381600087803b15801562000ce257600080fd5b505af115801562000cf7573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562000da257600080fd5b505af192505050801562000db4575060015b62000dd7578260ff168460ff160362000dd15762000dd16200259e565b62000def565b8260ff168460ff161462000def5762000def6200259e565b50505050565b6060601b805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff16835260018101805483518187028101870190945280845293949193858301939283018282801562000ee857602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841162000e945790505b5050505050815250508152602001906001019062000e19565b6060601a805480602002602001604051908101604052809291908181526020016000905b828210156200054457838290600052602060002001805462000f4790620024fa565b80601f016020809104026020016040519081016040528092919081815260200182805462000f7590620024fa565b801562000fc65780601f1062000f9a5761010080835404028352916020019162000fc6565b820191906000526020600020905b81548152906001019060200180831162000fa857829003601f168201915b50505050508152602001906001019062000f25565b62000fe5620011ab565b620010db601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001057573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200109f9190810190620025fc565b6040518060400160405280601581526020017f312e31312e312d626574612e312b696e7465726f70000000000000000000000081525062001f84565b620010ea57620010ea6200259e565b620011a9601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f46ddb26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200115c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011829190620026d3565b7f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa562001fe1565b565b604051620011b99062002080565b604051809103906000f080158015620011d6573d6000803e3d6000fd5b5060405173754cd1bdd15c0ed896f2867165a2694d76f39fa56024820152604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de8000000000000000000000000000000000000000000000000000000001790525162001279906200208e565b62001286929190620026fa565b604051809103906000f080158015620012a3573d6000803e3d6000fd5b50601e60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6060601c805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939491938583019392830182828015620013d957602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411620013855790505b505050505081525050815260200190600101906200130a565b60606019805480602002602001604051908101604052809291908181526020016000905b82821015620005445783829060005260206000200180546200143890620024fa565b80601f01602080910402602001604051908101604052809291908181526020018280546200146690620024fa565b8015620014b75780601f106200148b57610100808354040283529160200191620014b7565b820191906000526020600020905b8154815290600101906020018083116200149957829003601f168201915b50505050508152602001906001019062001416565b60085460009060ff1615620014e5575060085460ff1690565b6040517f667f9d70000000000000000000000000000000000000000000000000000000008152737109709ecfa91a80626ff3989d68f67f5b1dd12d600482018190527f6661696c65640000000000000000000000000000000000000000000000000000602483015260009163667f9d7090604401602060405180830381865afa15801562001577573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200159d919062002733565b1415905090565b620015ae620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce567000000000000000000000000000000000000000000000000000000001790528251601281830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262001692927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d89291906044016200254f565b600060405180830381600087803b158015620016ad57600080fd5b505af1158015620016c2573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e49350620017aa927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b158015620017c557600080fd5b505af1158015620017da573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690931790925283518a15158184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e49450620018d2937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b158015620018ed57600080fd5b505af115801562001902573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518915158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001a16937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001a3157600080fd5b505af115801562001a46573d6000803e3d6000fd5b5050604080517fec4fc8e3000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518815158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001b5a937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001b7557600080fd5b505af115801562001b8a573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8c168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001c79927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001c9457600080fd5b505af115801562001ca9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8b168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001d98927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001db357600080fd5b505af115801562001dc8573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562001e7357600080fd5b505af192505050801562001e85575060015b62001ece578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362001ec85762001ec86200259e565b62001f0c565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001f0c5762001f0c6200259e565b50505050505050565b60606015805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60008160405160200162001f9991906200274d565b604051602081830303815290604052805190602001208360405160200162001fc291906200274d565b6040516020818303038152906040528051906020012014905092915050565b6040517f515361f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015282166024820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063515361f69060440160006040518083038186803b1580156200206357600080fd5b505afa15801562002078573d6000803e3d6000fd5b505050505050565b613623806200276383390190565b6107958062005d8683390190565b6020808252825182820181905260009190848201906040850190845b81811015620020ec57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101620020b8565b50909695505050505050565b60005b8381101562002115578181015183820152602001620020fb565b8381111562000def5750506000910152565b6000815180845262002141816020860160208601620020f8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602080825282518282018190526000919060409081850190600581811b8701840188860187805b8581101562002272577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08b85030187528251805173ffffffffffffffffffffffffffffffffffffffff1685528901518985018990528051898601819052908a0190606081881b870181019190870190855b818110156200225b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08985030183526200224884865162002127565b948e01949350918d01916001016200220b565b505050978a0197945050918801916001016200219a565b50919a9950505050505050505050565b803560ff811681146200229457600080fd5b919050565b60008060408385031215620022ad57600080fd5b620022b88362002282565b9150620022c86020840162002282565b90509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015620023bc578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00186528251805173ffffffffffffffffffffffffffffffffffffffff168552880151888501889052805188860181905290890190839060608701905b80831015620023a65783517fffffffff00000000000000000000000000000000000000000000000000000000168252928b019260019290920191908b019062002362565b50978a01979550505091870191600101620022f9565b50919998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562002442577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200242f85835162002127565b94509285019290850190600101620023f2565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146200247257600080fd5b50565b803580151581146200229457600080fd5b600080600080600060a086880312156200249f57600080fd5b8535620024ac816200244f565b94506020860135620024be816200244f565b9350620024ce6040870162002475565b9250620024de6060870162002475565b9150620024ee6080870162002475565b90509295509295909350565b600181811c908216806200250f57607f821691505b60208210810362002549577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600062002580606083018562002127565b828103604084015262002594818562002127565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156200260f57600080fd5b815167ffffffffffffffff808211156200262857600080fd5b818401915084601f8301126200263d57600080fd5b815181811115620026525762002652620025cd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156200269b576200269b620025cd565b81604052828152876020848701011115620026b557600080fd5b620026c8836020830160208801620020f8565b979650505050505050565b600060208284031215620026e657600080fd5b8151620026f3816200244f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006200272b604083018462002127565b949350505050565b6000602082840312156200274657600080fd5b5051919050565b602081526000620026f360208301846200212756fe60806040523480156200001157600080fd5b506200001e600062000024565b62000217565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016d60201b6200045a1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b62000122734200000000000000000000000000000000000007836200017c565b801562000169576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b6133fc80620002276000396000f3fe60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a608060405260405161079538038061079583398101604081905261002291610314565b61002e82826000610035565b5050610431565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161076e602791396101a9565b9392505050565b6100ea8161028760201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61029660201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610148565b600080856001600160a01b03168560405161022c91906103e2565b600060405180830381855af49150503d8060008114610267576040519150601f19603f3d011682016040523d82523d6000602084013e61026c565b606091505b50909250905061027d828286610299565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a85750816100d0565b8251156102b85782518084602001fd5b8160405162461bcd60e51b815260040161014891906103fe565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103035781810151838201526020016102eb565b838111156100645750506000910152565b6000806040838503121561032757600080fd5b82516001600160a01b038116811461033e57600080fd5b60208401519092506001600160401b038082111561035b57600080fd5b818501915085601f83011261036f57600080fd5b815181811115610381576103816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + 0x0000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000001000000000000000000000000000001000000000000000000010000000000000000000000000000010000000000000000000100000000000000000001000000000000000000000000000000000100000000000100010000000000000000000100000000000000000000000000000100000000000000000001000000000000000000000000000001000000000000000000010000000000000000000100000000000000000001000000000000000000010000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000100000000000100000000000000000000000000000000000000000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000100010000000000000000000000000001000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000010000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000001000000000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000001000000000000000000000000000000000000000000000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000010000000001000000000000000000000000000000000000000100000000000000000000010000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000001000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000100000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000001000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000100000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000100000000010000000000000000000000010000000000000000000000000000010000000001000000000000000000000000000100000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000010000000000000000010000000000000000000000000100000000000000000000000100000000000000000000000000000001000000000000000000000001000000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000100010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000100000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000010000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000001000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000000001000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000001000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000000000000000100000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000010000000000000000000000000000000000010000000000000000010000000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000001000000000000000000000100000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000001000000000000000001000000000000000000000000010000000000000000000000000000000000000000000000000100010000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000100000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000001000000000000000000000000000000000100000000000000000001000000000000000000000000000001000001000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000010000000000000000000000000000000000000000000000010000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000001000000000000000000000000000000000100000000000000000000000000000100000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100010000000100000000000000000000010000000001000100000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000100000000000000000001000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000100000000000000000000000000000100000000000100000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + CALLER_ID:Int + + + 0xc30fe4fe +Bytes #buf ( 0x20 , VV0__fromRemoteAddress_114b9705:Int ) +Bytes #buf ( 0x20 , VV1__toRemoteAddress_114b9705:Int ) +Bytes #buf ( 0x20 , VV2__supportsIERC165_114b9705:Int ) +Bytes #buf ( 0x20 , VV3__supportsILegacyMintableERC20_114b9705:Int ) +Bytes #buf ( 0x20 , VV4__supportsIOptimismMintableERC20_114b9705:Int ) + + + 0x0 + + + ( 0x444 : ( 0x248391ff : ( 0x2e234dae75c793f67a35089c9d99245e1c58470b : ( 0x64 : ( 0x12 : ( VV4__supportsIOptimismMintableERC20_114b9705:Int : ( VV3__supportsILegacyMintableERC20_114b9705:Int : ( VV2__supportsIERC165_114b9705:Int : ( VV1__toRemoteAddress_114b9705:Int : ( VV0__fromRemoteAddress_114b9705:Int : ( 0x23d : ( 0xc30fe4fe : .WordStack ) ) ) ) ) ) ) ) ) ) ) ) + + + 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000754cd1bdd15c0ed896f2867165a2694d76f39fa50000000000000000000000000000000000000000000000000000000000000004313ce567000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000004313ce56700000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000002401ffc9a701ffc9a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV2__supportsIERC165_114b9705:Int ) +Bytes 0x000000000000000000000000000000000000000000000000000000000000002401ffc9a71d1d8b63000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV3__supportsILegacyMintableERC20_114b9705:Int ) +Bytes 0x000000000000000000000000000000000000000000000000000000000000002401ffc9a7ec4fc8e3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV4__supportsIOptimismMintableERC20_114b9705:Int ) +Bytes 0x0000000000000000000000000000000000000000000000000000000000000004316b37390000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV0__fromRemoteAddress_114b9705:Int ) +Bytes 0x0000000000000000000000000000000000000000000000000000000000000004316b37390000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV1__toRemoteAddress_114b9705:Int ) +Bytes 0x248391ff000000000000000000000000e6a7a45f334393093061116b197e3240065ff2d80000000000000000000000007c05912fc4cbffd28f63f412fcdd194991f8db4800000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000004316b3739000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV1__toRemoteAddress_114b9705:Int ) +Bytes 0x2081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c65640000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000754cd1bdd15c0ed896f2867165a2694d76f39fa50000000000000000000000000000000000000000000000000000000000000000604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + 0x1e76 + + + 0x0 + + + 0x0 + + + 0x0 + + + false + + + 0x0 + + ) + + + ListItem ( { + ( + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x0 + + + 0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( ( 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc |-> 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) + ( 0x4 |-> 0x754cd1bdd15c0ed896f2867165a2694d76f39fa5 ) ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x4200000000000000000000000000000000000012 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f + + + 0x0 + + + 0x60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( 0x4 |-> 0x0 ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x0 + + + 0x60806040523480156200001157600080fd5b5060043610620001895760003560e01c8063916a17c611620000dd578063c89701a2116200008b578063d6a2ec76116200006e578063d6a2ec761462000341578063e20c9f711462000369578063fa7626d4146200037357600080fd5b8063c89701a214620002f1578063d5ce3389146200031957600080fd5b8063ba414fa611620000c0578063ba414fa61462000299578063bf4792f114620002b4578063c30fe4fe14620002da57600080fd5b8063916a17c61462000285578063b5508aa9146200028f57600080fd5b8063547d77c4116200013b57806385226c81116200011e57806385226c8114620002585780638ea3d06f14620002715780638fe30c69146200027b57600080fd5b8063547d77c4146200022657806366d9a9a0146200023f57600080fd5b80632ade388011620001705780632ade388014620001f95780633e5e3c2314620002125780633f7286f4146200021c57600080fd5b806313151981146200018e5780631ed7831c14620001e0575b600080fd5b620001b67f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001ea62000381565b604051620001d791906200209c565b62000203620003f2565b604051620001d7919062002173565b620001ea6200054d565b620001ea620005bc565b6200023d6200023736600462002299565b6200062b565b005b6200024962000df5565b604051620001d79190620022d1565b6200026262000f01565b604051620001d79190620023cb565b6200023d62000fdb565b6200023d620011ab565b62000249620012e6565b62000262620013f2565b620002a3620014cc565b6040519015158152602001620001d7565b601e54620001b690610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6200023d620002eb36600462002486565b620015a4565b620001b67f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa581565b620001b67f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d881565b620001b67f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d81565b620001ea62001f15565b601e54620002a39060ff1681565b60606016805480602002602001604051908101604052809291908181526020018280548015620003e857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575b5050505050905090565b6060601d805480602002602001604051908101604052809291908181526020016000905b8282101562000544576000848152602080822060408051808201825260028702909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939591948681019491929084015b828210156200052c5783829060005260206000200180546200049890620024fa565b80601f0160208091040260200160405190810160405280929190818152602001828054620004c690620024fa565b8015620005175780601f10620004eb5761010080835404028352916020019162000517565b820191906000526020600020905b815481529060010190602001808311620004f957829003601f168201915b50505050508152602001906001019062000476565b50505050815250508152602001906001019062000416565b50505050905090565b60606018805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60606017805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b62000635620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff86168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262000717927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8926044016200254f565b600060405180830381600087803b1580156200073257600080fd5b505af115801562000747573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e493506200082f927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b1580156200084a57600080fd5b505af11580156200085f573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909317909252835160018184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000956937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b1580156200097157600080fd5b505af115801562000986573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000179052835160018183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000a99937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562000ab457600080fd5b505af115801562000ac9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b37390000000000000000000000000000000000000000000000000000000017905282516101a481830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452929450737109709ecfa91a80626ff3989d68f67f5b1dd12d935063b96213e49262000ba8927342000000000000000000000000000000000000129290916044016200254f565b600060405180830381600087803b15801562000bc357600080fd5b505af115801562000bd8573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062000cc7927342000000000000000000000000000000000000269291906044016200254f565b600060405180830381600087803b15801562000ce257600080fd5b505af115801562000cf7573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562000da257600080fd5b505af192505050801562000db4575060015b62000dd7578260ff168460ff160362000dd15762000dd16200259e565b62000def565b8260ff168460ff161462000def5762000def6200259e565b50505050565b6060601b805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff16835260018101805483518187028101870190945280845293949193858301939283018282801562000ee857602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841162000e945790505b5050505050815250508152602001906001019062000e19565b6060601a805480602002602001604051908101604052809291908181526020016000905b828210156200054457838290600052602060002001805462000f4790620024fa565b80601f016020809104026020016040519081016040528092919081815260200182805462000f7590620024fa565b801562000fc65780601f1062000f9a5761010080835404028352916020019162000fc6565b820191906000526020600020905b81548152906001019060200180831162000fa857829003601f168201915b50505050508152602001906001019062000f25565b62000fe5620011ab565b620010db601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001057573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200109f9190810190620025fc565b6040518060400160405280601581526020017f312e31312e312d626574612e312b696e7465726f70000000000000000000000081525062001f84565b620010ea57620010ea6200259e565b620011a9601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f46ddb26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200115c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011829190620026d3565b7f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa562001fe1565b565b604051620011b99062002080565b604051809103906000f080158015620011d6573d6000803e3d6000fd5b5060405173754cd1bdd15c0ed896f2867165a2694d76f39fa56024820152604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de8000000000000000000000000000000000000000000000000000000001790525162001279906200208e565b62001286929190620026fa565b604051809103906000f080158015620012a3573d6000803e3d6000fd5b50601e60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6060601c805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939491938583019392830182828015620013d957602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411620013855790505b505050505081525050815260200190600101906200130a565b60606019805480602002602001604051908101604052809291908181526020016000905b82821015620005445783829060005260206000200180546200143890620024fa565b80601f01602080910402602001604051908101604052809291908181526020018280546200146690620024fa565b8015620014b75780601f106200148b57610100808354040283529160200191620014b7565b820191906000526020600020905b8154815290600101906020018083116200149957829003601f168201915b50505050508152602001906001019062001416565b60085460009060ff1615620014e5575060085460ff1690565b6040517f667f9d70000000000000000000000000000000000000000000000000000000008152737109709ecfa91a80626ff3989d68f67f5b1dd12d600482018190527f6661696c65640000000000000000000000000000000000000000000000000000602483015260009163667f9d7090604401602060405180830381865afa15801562001577573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200159d919062002733565b1415905090565b620015ae620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce567000000000000000000000000000000000000000000000000000000001790528251601281830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262001692927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d89291906044016200254f565b600060405180830381600087803b158015620016ad57600080fd5b505af1158015620016c2573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e49350620017aa927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b158015620017c557600080fd5b505af1158015620017da573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690931790925283518a15158184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e49450620018d2937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b158015620018ed57600080fd5b505af115801562001902573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518915158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001a16937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001a3157600080fd5b505af115801562001a46573d6000803e3d6000fd5b5050604080517fec4fc8e3000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518815158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001b5a937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001b7557600080fd5b505af115801562001b8a573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8c168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001c79927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001c9457600080fd5b505af115801562001ca9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8b168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001d98927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001db357600080fd5b505af115801562001dc8573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562001e7357600080fd5b505af192505050801562001e85575060015b62001ece578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362001ec85762001ec86200259e565b62001f0c565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001f0c5762001f0c6200259e565b50505050505050565b60606015805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60008160405160200162001f9991906200274d565b604051602081830303815290604052805190602001208360405160200162001fc291906200274d565b6040516020818303038152906040528051906020012014905092915050565b6040517f515361f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015282166024820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063515361f69060440160006040518083038186803b1580156200206357600080fd5b505afa15801562002078573d6000803e3d6000fd5b505050505050565b613623806200276383390190565b6107958062005d8683390190565b6020808252825182820181905260009190848201906040850190845b81811015620020ec57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101620020b8565b50909695505050505050565b60005b8381101562002115578181015183820152602001620020fb565b8381111562000def5750506000910152565b6000815180845262002141816020860160208601620020f8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602080825282518282018190526000919060409081850190600581811b8701840188860187805b8581101562002272577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08b85030187528251805173ffffffffffffffffffffffffffffffffffffffff1685528901518985018990528051898601819052908a0190606081881b870181019190870190855b818110156200225b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08985030183526200224884865162002127565b948e01949350918d01916001016200220b565b505050978a0197945050918801916001016200219a565b50919a9950505050505050505050565b803560ff811681146200229457600080fd5b919050565b60008060408385031215620022ad57600080fd5b620022b88362002282565b9150620022c86020840162002282565b90509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015620023bc578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00186528251805173ffffffffffffffffffffffffffffffffffffffff168552880151888501889052805188860181905290890190839060608701905b80831015620023a65783517fffffffff00000000000000000000000000000000000000000000000000000000168252928b019260019290920191908b019062002362565b50978a01979550505091870191600101620022f9565b50919998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562002442577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200242f85835162002127565b94509285019290850190600101620023f2565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146200247257600080fd5b50565b803580151581146200229457600080fd5b600080600080600060a086880312156200249f57600080fd5b8535620024ac816200244f565b94506020860135620024be816200244f565b9350620024ce6040870162002475565b9250620024de6060870162002475565b9150620024ee6080870162002475565b90509295509295909350565b600181811c908216806200250f57607f821691505b60208210810362002549577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600062002580606083018562002127565b828103604084015262002594818562002127565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156200260f57600080fd5b815167ffffffffffffffff808211156200262857600080fd5b818401915084601f8301126200263d57600080fd5b815181811115620026525762002652620025cd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156200269b576200269b620025cd565b81604052828152876020848701011115620026b557600080fd5b620026c8836020830160208801620020f8565b979650505050505050565b600060208284031215620026e657600080fd5b8151620026f3816200244f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006200272b604083018462002127565b949350505050565b6000602082840312156200274657600080fd5b5051919050565b602081526000620026f360208301846200212756fe60806040523480156200001157600080fd5b506200001e600062000024565b62000217565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016d60201b6200045a1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b62000122734200000000000000000000000000000000000007836200017c565b801562000169576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b6133fc80620002276000396000f3fe60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a608060405260405161079538038061079583398101604081905261002291610314565b61002e82826000610035565b5050610431565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161076e602791396101a9565b9392505050565b6100ea8161028760201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61029660201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610148565b600080856001600160a01b03168560405161022c91906103e2565b600060405180830381855af49150503d8060008114610267576040519150601f19603f3d011682016040523d82523d6000602084013e61026c565b606091505b50909250905061027d828286610299565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a85750816100d0565b8251156102b85782518084602001fd5b8160405162461bcd60e51b815260040161014891906103fe565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103035781810151838201526020016102eb565b838111156100645750506000910152565b6000806040838503121561032757600080fd5b82516001600160a01b038116811461033e57600080fd5b60208401519092506001600160401b038082111561035b57600080fd5b818501915085601f83011261036f57600080fd5b815181811115610381576103816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( 0x1e |-> 0x2e234dae75c793f67a35089c9d99245e1c58470b00 ) + + + .Map + + + .Map + + + 0x3 + + + ( + + 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + + + 0xe6a7a45f334393093061116b197e3240065ff2d8 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + ) ) ) ) ) ) + | + + SELFDESTRUCT_CELL:Set + + + ListItem ( { 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b ) ListItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) | 0x } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) + + + 0x0 + + + ( SetItem ( 0x7fa9385be102ac3eac297483dd6233d62b3e1496 ) ( SetItem ( 0xe6a7a45f334393093061116b197e3240065ff2d8 ) ( SetItem ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 ) ( SetItem ( 0x4200000000000000000000000000000000000012 ) ( SetItem ( 0x2e234dae75c793f67a35089c9d99245e1c58470b ) ( SetItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) SetItem ( 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d ) ) ) ) ) ) ) + + + .Map + + } ) ListItem ( { + ( + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x0 + + + 0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( ( 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc |-> 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) + ( 0x4 |-> 0x754cd1bdd15c0ed896f2867165a2694d76f39fa5 ) ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x4200000000000000000000000000000000000012 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f + + + 0x0 + + + 0x60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( 0x4 |-> 0x0 ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x0 + + + 0x60806040523480156200001157600080fd5b5060043610620001895760003560e01c8063916a17c611620000dd578063c89701a2116200008b578063d6a2ec76116200006e578063d6a2ec761462000341578063e20c9f711462000369578063fa7626d4146200037357600080fd5b8063c89701a214620002f1578063d5ce3389146200031957600080fd5b8063ba414fa611620000c0578063ba414fa61462000299578063bf4792f114620002b4578063c30fe4fe14620002da57600080fd5b8063916a17c61462000285578063b5508aa9146200028f57600080fd5b8063547d77c4116200013b57806385226c81116200011e57806385226c8114620002585780638ea3d06f14620002715780638fe30c69146200027b57600080fd5b8063547d77c4146200022657806366d9a9a0146200023f57600080fd5b80632ade388011620001705780632ade388014620001f95780633e5e3c2314620002125780633f7286f4146200021c57600080fd5b806313151981146200018e5780631ed7831c14620001e0575b600080fd5b620001b67f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001ea62000381565b604051620001d791906200209c565b62000203620003f2565b604051620001d7919062002173565b620001ea6200054d565b620001ea620005bc565b6200023d6200023736600462002299565b6200062b565b005b6200024962000df5565b604051620001d79190620022d1565b6200026262000f01565b604051620001d79190620023cb565b6200023d62000fdb565b6200023d620011ab565b62000249620012e6565b62000262620013f2565b620002a3620014cc565b6040519015158152602001620001d7565b601e54620001b690610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6200023d620002eb36600462002486565b620015a4565b620001b67f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa581565b620001b67f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d881565b620001b67f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d81565b620001ea62001f15565b601e54620002a39060ff1681565b60606016805480602002602001604051908101604052809291908181526020018280548015620003e857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575b5050505050905090565b6060601d805480602002602001604051908101604052809291908181526020016000905b8282101562000544576000848152602080822060408051808201825260028702909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939591948681019491929084015b828210156200052c5783829060005260206000200180546200049890620024fa565b80601f0160208091040260200160405190810160405280929190818152602001828054620004c690620024fa565b8015620005175780601f10620004eb5761010080835404028352916020019162000517565b820191906000526020600020905b815481529060010190602001808311620004f957829003601f168201915b50505050508152602001906001019062000476565b50505050815250508152602001906001019062000416565b50505050905090565b60606018805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60606017805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b62000635620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff86168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262000717927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8926044016200254f565b600060405180830381600087803b1580156200073257600080fd5b505af115801562000747573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e493506200082f927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b1580156200084a57600080fd5b505af11580156200085f573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909317909252835160018184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000956937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b1580156200097157600080fd5b505af115801562000986573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000179052835160018183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000a99937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562000ab457600080fd5b505af115801562000ac9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b37390000000000000000000000000000000000000000000000000000000017905282516101a481830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452929450737109709ecfa91a80626ff3989d68f67f5b1dd12d935063b96213e49262000ba8927342000000000000000000000000000000000000129290916044016200254f565b600060405180830381600087803b15801562000bc357600080fd5b505af115801562000bd8573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062000cc7927342000000000000000000000000000000000000269291906044016200254f565b600060405180830381600087803b15801562000ce257600080fd5b505af115801562000cf7573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562000da257600080fd5b505af192505050801562000db4575060015b62000dd7578260ff168460ff160362000dd15762000dd16200259e565b62000def565b8260ff168460ff161462000def5762000def6200259e565b50505050565b6060601b805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff16835260018101805483518187028101870190945280845293949193858301939283018282801562000ee857602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841162000e945790505b5050505050815250508152602001906001019062000e19565b6060601a805480602002602001604051908101604052809291908181526020016000905b828210156200054457838290600052602060002001805462000f4790620024fa565b80601f016020809104026020016040519081016040528092919081815260200182805462000f7590620024fa565b801562000fc65780601f1062000f9a5761010080835404028352916020019162000fc6565b820191906000526020600020905b81548152906001019060200180831162000fa857829003601f168201915b50505050508152602001906001019062000f25565b62000fe5620011ab565b620010db601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001057573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200109f9190810190620025fc565b6040518060400160405280601581526020017f312e31312e312d626574612e312b696e7465726f70000000000000000000000081525062001f84565b620010ea57620010ea6200259e565b620011a9601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f46ddb26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200115c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011829190620026d3565b7f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa562001fe1565b565b604051620011b99062002080565b604051809103906000f080158015620011d6573d6000803e3d6000fd5b5060405173754cd1bdd15c0ed896f2867165a2694d76f39fa56024820152604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de8000000000000000000000000000000000000000000000000000000001790525162001279906200208e565b62001286929190620026fa565b604051809103906000f080158015620012a3573d6000803e3d6000fd5b50601e60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6060601c805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939491938583019392830182828015620013d957602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411620013855790505b505050505081525050815260200190600101906200130a565b60606019805480602002602001604051908101604052809291908181526020016000905b82821015620005445783829060005260206000200180546200143890620024fa565b80601f01602080910402602001604051908101604052809291908181526020018280546200146690620024fa565b8015620014b75780601f106200148b57610100808354040283529160200191620014b7565b820191906000526020600020905b8154815290600101906020018083116200149957829003601f168201915b50505050508152602001906001019062001416565b60085460009060ff1615620014e5575060085460ff1690565b6040517f667f9d70000000000000000000000000000000000000000000000000000000008152737109709ecfa91a80626ff3989d68f67f5b1dd12d600482018190527f6661696c65640000000000000000000000000000000000000000000000000000602483015260009163667f9d7090604401602060405180830381865afa15801562001577573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200159d919062002733565b1415905090565b620015ae620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce567000000000000000000000000000000000000000000000000000000001790528251601281830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262001692927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d89291906044016200254f565b600060405180830381600087803b158015620016ad57600080fd5b505af1158015620016c2573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e49350620017aa927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b158015620017c557600080fd5b505af1158015620017da573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690931790925283518a15158184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e49450620018d2937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b158015620018ed57600080fd5b505af115801562001902573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518915158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001a16937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001a3157600080fd5b505af115801562001a46573d6000803e3d6000fd5b5050604080517fec4fc8e3000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518815158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001b5a937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001b7557600080fd5b505af115801562001b8a573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8c168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001c79927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001c9457600080fd5b505af115801562001ca9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8b168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001d98927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001db357600080fd5b505af115801562001dc8573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562001e7357600080fd5b505af192505050801562001e85575060015b62001ece578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362001ec85762001ec86200259e565b62001f0c565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001f0c5762001f0c6200259e565b50505050505050565b60606015805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60008160405160200162001f9991906200274d565b604051602081830303815290604052805190602001208360405160200162001fc291906200274d565b6040516020818303038152906040528051906020012014905092915050565b6040517f515361f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015282166024820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063515361f69060440160006040518083038186803b1580156200206357600080fd5b505afa15801562002078573d6000803e3d6000fd5b505050505050565b613623806200276383390190565b6107958062005d8683390190565b6020808252825182820181905260009190848201906040850190845b81811015620020ec57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101620020b8565b50909695505050505050565b60005b8381101562002115578181015183820152602001620020fb565b8381111562000def5750506000910152565b6000815180845262002141816020860160208601620020f8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602080825282518282018190526000919060409081850190600581811b8701840188860187805b8581101562002272577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08b85030187528251805173ffffffffffffffffffffffffffffffffffffffff1685528901518985018990528051898601819052908a0190606081881b870181019190870190855b818110156200225b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08985030183526200224884865162002127565b948e01949350918d01916001016200220b565b505050978a0197945050918801916001016200219a565b50919a9950505050505050505050565b803560ff811681146200229457600080fd5b919050565b60008060408385031215620022ad57600080fd5b620022b88362002282565b9150620022c86020840162002282565b90509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015620023bc578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00186528251805173ffffffffffffffffffffffffffffffffffffffff168552880151888501889052805188860181905290890190839060608701905b80831015620023a65783517fffffffff00000000000000000000000000000000000000000000000000000000168252928b019260019290920191908b019062002362565b50978a01979550505091870191600101620022f9565b50919998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562002442577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200242f85835162002127565b94509285019290850190600101620023f2565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146200247257600080fd5b50565b803580151581146200229457600080fd5b600080600080600060a086880312156200249f57600080fd5b8535620024ac816200244f565b94506020860135620024be816200244f565b9350620024ce6040870162002475565b9250620024de6060870162002475565b9150620024ee6080870162002475565b90509295509295909350565b600181811c908216806200250f57607f821691505b60208210810362002549577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600062002580606083018562002127565b828103604084015262002594818562002127565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156200260f57600080fd5b815167ffffffffffffffff808211156200262857600080fd5b818401915084601f8301126200263d57600080fd5b815181811115620026525762002652620025cd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156200269b576200269b620025cd565b81604052828152876020848701011115620026b557600080fd5b620026c8836020830160208801620020f8565b979650505050505050565b600060208284031215620026e657600080fd5b8151620026f3816200244f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006200272b604083018462002127565b949350505050565b6000602082840312156200274657600080fd5b5051919050565b602081526000620026f360208301846200212756fe60806040523480156200001157600080fd5b506200001e600062000024565b62000217565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016d60201b6200045a1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b62000122734200000000000000000000000000000000000007836200017c565b801562000169576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b6133fc80620002276000396000f3fe60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a608060405260405161079538038061079583398101604081905261002291610314565b61002e82826000610035565b5050610431565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161076e602791396101a9565b9392505050565b6100ea8161028760201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61029660201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610148565b600080856001600160a01b03168560405161022c91906103e2565b600060405180830381855af49150503d8060008114610267576040519150601f19603f3d011682016040523d82523d6000602084013e61026c565b606091505b50909250905061027d828286610299565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a85750816100d0565b8251156102b85782518084602001fd5b8160405162461bcd60e51b815260040161014891906103fe565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103035781810151838201526020016102eb565b838111156100645750506000910152565b6000806040838503121561032757600080fd5b82516001600160a01b038116811461033e57600080fd5b60208401519092506001600160401b038082111561035b57600080fd5b818501915085601f83011261036f57600080fd5b815181811115610381576103816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( 0x1e |-> 0x2e234dae75c793f67a35089c9d99245e1c58470b00 ) + + + .Map + + + .Map + + + 0x3 + + + ( + + 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + + + 0xe6a7a45f334393093061116b197e3240065ff2d8 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + ) ) ) ) ) ) + | + + SELFDESTRUCT_CELL:Set + + + ListItem ( { 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b ) ListItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) | 0x } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) + + + 0x0 + + + ( SetItem ( 0x7fa9385be102ac3eac297483dd6233d62b3e1496 ) ( SetItem ( 0xe6a7a45f334393093061116b197e3240065ff2d8 ) ( SetItem ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 ) ( SetItem ( 0x4200000000000000000000000000000000000012 ) ( SetItem ( 0x2e234dae75c793f67a35089c9d99245e1c58470b ) ( SetItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) SetItem ( 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d ) ) ) ) ) ) ) + + + .Map + + } ) + + + ( SetItem ( 0x7fa9385be102ac3eac297483dd6233d62b3e1496 ) ( SetItem ( 0x2e234dae75c793f67a35089c9d99245e1c58470b ) SetItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) ) ) + + + + 0x60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000100000000010000000000000000000000010000000000000000000000000000010000000001000000000000000000000000000100000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000010000000000000000010000000000000000000000000100000000000000000000000100000000000000000000000000000001000000000000000000000001000000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000100010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000100000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000010000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000001000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000000001000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000001000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000000000000000100000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000010000000000000000000000000000000000010000000000000000010000000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000001000000000000000000000100000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000 + + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x248391ff000000000000000000000000e6a7a45f334393093061116b197e3240065ff2d80000000000000000000000007c05912fc4cbffd28f63f412fcdd194991f8db480000000000000000000000000000000000000000000000000000000000000064 + + + 0x0 + + + ( 0x12 : ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 : ( 0xe6a7a45f334393093061116b197e3240065ff2d8 : ( 0xebb : ( 0x64 : ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 : ( 0xe6a7a45f334393093061116b197e3240065ff2d8 : ( 0x1fa : ( 0x248391ff : .WordStack ) ) ) ) ) ) ) ) ) + + + 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000012 + + + 0x20b3 + + + 0x0 + + + 0x0 + + + 0x0 + + + false + + + 0x2 + + + + + SELFDESTRUCT_CELL:Set + + + ListItem ( { 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b ) ListItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) | 0x } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) + + + 0x0 + + + ( SetItem ( 0x7fa9385be102ac3eac297483dd6233d62b3e1496 ) ( SetItem ( 0xe6a7a45f334393093061116b197e3240065ff2d8 ) ( SetItem ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 ) ( SetItem ( 0x4200000000000000000000000000000000000012 ) ( SetItem ( 0x2e234dae75c793f67a35089c9d99245e1c58470b ) ( SetItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) SetItem ( 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d ) ) ) ) ) ) ) + + + .Map + + + + ORIGIN_ID:Int + + + + NUMBER_CELL:Int + + + TIMESTAMP_CELL:Int + + ... + + ... + + + + 0x1 + + + ( + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x0 + + + 0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( ( 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc |-> 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) + ( 0x4 |-> 0x754cd1bdd15c0ed896f2867165a2694d76f39fa5 ) ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x4200000000000000000000000000000000000012 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f + + + 0x0 + + + 0x60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( 0x4 |-> 0x0 ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x0 + + + 0x60806040523480156200001157600080fd5b5060043610620001895760003560e01c8063916a17c611620000dd578063c89701a2116200008b578063d6a2ec76116200006e578063d6a2ec761462000341578063e20c9f711462000369578063fa7626d4146200037357600080fd5b8063c89701a214620002f1578063d5ce3389146200031957600080fd5b8063ba414fa611620000c0578063ba414fa61462000299578063bf4792f114620002b4578063c30fe4fe14620002da57600080fd5b8063916a17c61462000285578063b5508aa9146200028f57600080fd5b8063547d77c4116200013b57806385226c81116200011e57806385226c8114620002585780638ea3d06f14620002715780638fe30c69146200027b57600080fd5b8063547d77c4146200022657806366d9a9a0146200023f57600080fd5b80632ade388011620001705780632ade388014620001f95780633e5e3c2314620002125780633f7286f4146200021c57600080fd5b806313151981146200018e5780631ed7831c14620001e0575b600080fd5b620001b67f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001ea62000381565b604051620001d791906200209c565b62000203620003f2565b604051620001d7919062002173565b620001ea6200054d565b620001ea620005bc565b6200023d6200023736600462002299565b6200062b565b005b6200024962000df5565b604051620001d79190620022d1565b6200026262000f01565b604051620001d79190620023cb565b6200023d62000fdb565b6200023d620011ab565b62000249620012e6565b62000262620013f2565b620002a3620014cc565b6040519015158152602001620001d7565b601e54620001b690610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6200023d620002eb36600462002486565b620015a4565b620001b67f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa581565b620001b67f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d881565b620001b67f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d81565b620001ea62001f15565b601e54620002a39060ff1681565b60606016805480602002602001604051908101604052809291908181526020018280548015620003e857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575b5050505050905090565b6060601d805480602002602001604051908101604052809291908181526020016000905b8282101562000544576000848152602080822060408051808201825260028702909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939591948681019491929084015b828210156200052c5783829060005260206000200180546200049890620024fa565b80601f0160208091040260200160405190810160405280929190818152602001828054620004c690620024fa565b8015620005175780601f10620004eb5761010080835404028352916020019162000517565b820191906000526020600020905b815481529060010190602001808311620004f957829003601f168201915b50505050508152602001906001019062000476565b50505050815250508152602001906001019062000416565b50505050905090565b60606018805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60606017805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b62000635620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff86168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262000717927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8926044016200254f565b600060405180830381600087803b1580156200073257600080fd5b505af115801562000747573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e493506200082f927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b1580156200084a57600080fd5b505af11580156200085f573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909317909252835160018184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000956937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b1580156200097157600080fd5b505af115801562000986573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000179052835160018183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000a99937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562000ab457600080fd5b505af115801562000ac9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b37390000000000000000000000000000000000000000000000000000000017905282516101a481830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452929450737109709ecfa91a80626ff3989d68f67f5b1dd12d935063b96213e49262000ba8927342000000000000000000000000000000000000129290916044016200254f565b600060405180830381600087803b15801562000bc357600080fd5b505af115801562000bd8573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062000cc7927342000000000000000000000000000000000000269291906044016200254f565b600060405180830381600087803b15801562000ce257600080fd5b505af115801562000cf7573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562000da257600080fd5b505af192505050801562000db4575060015b62000dd7578260ff168460ff160362000dd15762000dd16200259e565b62000def565b8260ff168460ff161462000def5762000def6200259e565b50505050565b6060601b805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff16835260018101805483518187028101870190945280845293949193858301939283018282801562000ee857602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841162000e945790505b5050505050815250508152602001906001019062000e19565b6060601a805480602002602001604051908101604052809291908181526020016000905b828210156200054457838290600052602060002001805462000f4790620024fa565b80601f016020809104026020016040519081016040528092919081815260200182805462000f7590620024fa565b801562000fc65780601f1062000f9a5761010080835404028352916020019162000fc6565b820191906000526020600020905b81548152906001019060200180831162000fa857829003601f168201915b50505050508152602001906001019062000f25565b62000fe5620011ab565b620010db601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001057573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200109f9190810190620025fc565b6040518060400160405280601581526020017f312e31312e312d626574612e312b696e7465726f70000000000000000000000081525062001f84565b620010ea57620010ea6200259e565b620011a9601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f46ddb26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200115c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011829190620026d3565b7f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa562001fe1565b565b604051620011b99062002080565b604051809103906000f080158015620011d6573d6000803e3d6000fd5b5060405173754cd1bdd15c0ed896f2867165a2694d76f39fa56024820152604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de8000000000000000000000000000000000000000000000000000000001790525162001279906200208e565b62001286929190620026fa565b604051809103906000f080158015620012a3573d6000803e3d6000fd5b50601e60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6060601c805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939491938583019392830182828015620013d957602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411620013855790505b505050505081525050815260200190600101906200130a565b60606019805480602002602001604051908101604052809291908181526020016000905b82821015620005445783829060005260206000200180546200143890620024fa565b80601f01602080910402602001604051908101604052809291908181526020018280546200146690620024fa565b8015620014b75780601f106200148b57610100808354040283529160200191620014b7565b820191906000526020600020905b8154815290600101906020018083116200149957829003601f168201915b50505050508152602001906001019062001416565b60085460009060ff1615620014e5575060085460ff1690565b6040517f667f9d70000000000000000000000000000000000000000000000000000000008152737109709ecfa91a80626ff3989d68f67f5b1dd12d600482018190527f6661696c65640000000000000000000000000000000000000000000000000000602483015260009163667f9d7090604401602060405180830381865afa15801562001577573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200159d919062002733565b1415905090565b620015ae620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce567000000000000000000000000000000000000000000000000000000001790528251601281830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262001692927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d89291906044016200254f565b600060405180830381600087803b158015620016ad57600080fd5b505af1158015620016c2573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e49350620017aa927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b158015620017c557600080fd5b505af1158015620017da573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690931790925283518a15158184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e49450620018d2937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b158015620018ed57600080fd5b505af115801562001902573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518915158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001a16937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001a3157600080fd5b505af115801562001a46573d6000803e3d6000fd5b5050604080517fec4fc8e3000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518815158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001b5a937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001b7557600080fd5b505af115801562001b8a573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8c168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001c79927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001c9457600080fd5b505af115801562001ca9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8b168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001d98927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001db357600080fd5b505af115801562001dc8573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562001e7357600080fd5b505af192505050801562001e85575060015b62001ece578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362001ec85762001ec86200259e565b62001f0c565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001f0c5762001f0c6200259e565b50505050505050565b60606015805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60008160405160200162001f9991906200274d565b604051602081830303815290604052805190602001208360405160200162001fc291906200274d565b6040516020818303038152906040528051906020012014905092915050565b6040517f515361f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015282166024820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063515361f69060440160006040518083038186803b1580156200206357600080fd5b505afa15801562002078573d6000803e3d6000fd5b505050505050565b613623806200276383390190565b6107958062005d8683390190565b6020808252825182820181905260009190848201906040850190845b81811015620020ec57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101620020b8565b50909695505050505050565b60005b8381101562002115578181015183820152602001620020fb565b8381111562000def5750506000910152565b6000815180845262002141816020860160208601620020f8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602080825282518282018190526000919060409081850190600581811b8701840188860187805b8581101562002272577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08b85030187528251805173ffffffffffffffffffffffffffffffffffffffff1685528901518985018990528051898601819052908a0190606081881b870181019190870190855b818110156200225b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08985030183526200224884865162002127565b948e01949350918d01916001016200220b565b505050978a0197945050918801916001016200219a565b50919a9950505050505050505050565b803560ff811681146200229457600080fd5b919050565b60008060408385031215620022ad57600080fd5b620022b88362002282565b9150620022c86020840162002282565b90509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015620023bc578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00186528251805173ffffffffffffffffffffffffffffffffffffffff168552880151888501889052805188860181905290890190839060608701905b80831015620023a65783517fffffffff00000000000000000000000000000000000000000000000000000000168252928b019260019290920191908b019062002362565b50978a01979550505091870191600101620022f9565b50919998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562002442577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200242f85835162002127565b94509285019290850190600101620023f2565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146200247257600080fd5b50565b803580151581146200229457600080fd5b600080600080600060a086880312156200249f57600080fd5b8535620024ac816200244f565b94506020860135620024be816200244f565b9350620024ce6040870162002475565b9250620024de6060870162002475565b9150620024ee6080870162002475565b90509295509295909350565b600181811c908216806200250f57607f821691505b60208210810362002549577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600062002580606083018562002127565b828103604084015262002594818562002127565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156200260f57600080fd5b815167ffffffffffffffff808211156200262857600080fd5b818401915084601f8301126200263d57600080fd5b815181811115620026525762002652620025cd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156200269b576200269b620025cd565b81604052828152876020848701011115620026b557600080fd5b620026c8836020830160208801620020f8565b979650505050505050565b600060208284031215620026e657600080fd5b8151620026f3816200244f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006200272b604083018462002127565b949350505050565b6000602082840312156200274657600080fd5b5051919050565b602081526000620026f360208301846200212756fe60806040523480156200001157600080fd5b506200001e600062000024565b62000217565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016d60201b6200045a1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b62000122734200000000000000000000000000000000000007836200017c565b801562000169576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b6133fc80620002276000396000f3fe60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a608060405260405161079538038061079583398101604081905261002291610314565b61002e82826000610035565b5050610431565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161076e602791396101a9565b9392505050565b6100ea8161028760201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61029660201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610148565b600080856001600160a01b03168560405161022c91906103e2565b600060405180830381855af49150503d8060008114610267576040519150601f19603f3d011682016040523d82523d6000602084013e61026c565b606091505b50909250905061027d828286610299565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a85750816100d0565b8251156102b85782518084602001fd5b8160405162461bcd60e51b815260040161014891906103fe565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103035781810151838201526020016102eb565b838111156100645750506000910152565b6000806040838503121561032757600080fd5b82516001600160a01b038116811461033e57600080fd5b60208401519092506001600160401b038082111561035b57600080fd5b818501915085601f83011261036f57600080fd5b815181811115610381576103816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( 0x1e |-> 0x2e234dae75c793f67a35089c9d99245e1c58470b00 ) + + + .Map + + + .Map + + + 0x3 + + + ( + + 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + + + 0xe6a7a45f334393093061116b197e3240065ff2d8 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + ) ) ) ) ) ) + + ... + + + ... + + + + + false + + + false + + ... + + + + false + + ... + + + + false + + ... + + + + false + + + false + + ... + + + + false + + + false + + + .List + + + .List + + + + + + 0x4200000000000000000000000000000000000012 + + + ( 0x316b3739 |-> #buf ( 0x20 , VV1__toRemoteAddress_114b9705:Int ) ) + + + + 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 + + + ( 0x313ce567 |-> 0x0000000000000000000000000000000000000000000000000000000000000012 ) + + + + 0xe6a7a45f334393093061116b197e3240065ff2d8 + + + ( ( 0x313ce567 |-> 0x0000000000000000000000000000000000000000000000000000000000000012 ) + ( ( 0x01ffc9a701ffc9a700000000000000000000000000000000000000000000000000000000 |-> #buf ( 0x20 , VV2__supportsIERC165_114b9705:Int ) ) + ( ( 0x01ffc9a71d1d8b6300000000000000000000000000000000000000000000000000000000 |-> #buf ( 0x20 , VV3__supportsILegacyMintableERC20_114b9705:Int ) ) + ( 0x01ffc9a7ec4fc8e300000000000000000000000000000000000000000000000000000000 |-> #buf ( 0x20 , VV4__supportsIOptimismMintableERC20_114b9705:Int ) ) ) ) ) + + + + + .MockFunctionCellMap + + + + + false + + + false + + + false + + + false + + + false + + + .List + + + + ... + +#And ( { true #Equals 0x0 <=Int CALLER_ID:Int } +#And ( { true #Equals 0x0 <=Int ORIGIN_ID:Int } +#And ( { true #Equals 0x1000000 CONTINUATION:K +│ pc: 0x0 +│ callDepth: 0x0 +│ statusCode: STATUSCODE:StatusCode +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:17:151 +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 3 +│ k: #execute ~> CONTINUATION:K +│ pc: 0x11bd +│ callDepth: 0x0 +│ statusCode: STATUSCODE:StatusCode +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (743 steps) +├─ 4 +│ k: #halt ~> #codeDeposit 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ~> #pc [ CREATE ... +│ pc: 0x225 +│ callDepth: 0x1 +│ statusCode: EVMC_SUCCESS +│ src: lib/forge-std/src/StdInvariant.sol:104:105 +│ +│ (1000 steps) +├─ 5 +│ k: #gas [ ISZERO , ISZERO 0x0 ] ~> ISZERO 0x0 ~> #pc [ ISZERO ] ~> #execute ~> #cod ... +│ pc: 0x352 +│ callDepth: 0x1 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:113:114 +│ +│ (1000 steps) +├─ 6 +│ k: #endBasicBlock ~> #execute ~> #codeDeposit 0x2e234dae75c793f67a35089c9d99245e1c5 ... +│ pc: 0x74 +│ callDepth: 0x1 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:17:151 +│ +│ (1000 steps) +├─ 7 +│ k: #next [ DUP ( 0x2 ) ] ~> #execute ~> #return 0x1e0 0x0 ~> #pc [ DELEGATECALL ] ~ ... +│ pc: 0x30e7 +│ callDepth: 0x2 +│ statusCode: EVMC_SUCCESS +│ method: src%L2%L2StandardBridgeInterop.initialize(address) +│ +│ (681 steps) +├─ 8 +│ k: #halt ~> #return 0x1e0 0x0 ~> #pc [ DELEGATECALL ] ~> #execute ~> #codeDeposit 0 ... +│ pc: 0x1fb +│ callDepth: 0x2 +│ statusCode: EVMC_SUCCESS +│ src: lib/forge-std/src/StdInvariant.sol:104:105 +│ method: src%L2%L2StandardBridgeInterop.initialize(address) +│ +│ (428 steps) +├─ 9 +│ k: #halt ~> #codeDeposit 0x2e234dae75c793f67a35089c9d99245e1c58470b ~> #pc [ CREATE ... +│ pc: 0x43e +│ callDepth: 0x1 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:119:120 +│ +│ (1000 steps) +├─ 10 +│ k: #next [ ADD ] ~> #execute ~> CONTINUATION:K +│ pc: 0x2144 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 11 +│ k: #execute ~> CONTINUATION:K +│ pc: 0x2114 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 12 +│ k: #exec [ POP ] ~> #pc [ POP ] ~> #execute ~> CONTINUATION:K +│ pc: 0x211f +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 13 +│ k: #exec [ MSTORE ] ~> #pc [ MSTORE ] ~> #execute ~> CONTINUATION:K +│ pc: 0x212e +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 14 +│ k: #addr [ EVMOR ] ~> #exec [ EVMOR ] ~> #pc [ EVMOR ] ~> #execute ~> CONTINUATION: ... +│ pc: 0x1ace +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 15 +│ k: #next [ SUB ] ~> #execute ~> CONTINUATION:K +│ pc: 0x1b62 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 16 +│ k: #next [ AND ] ~> #execute ~> CONTINUATION:K +│ pc: 0x2166 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 17 +│ k: #gas [ JUMP , JUMP 0x20fb ] ~> JUMP 0x20fb ~> #pc [ JUMP ] ~> #execute ~> CONTIN ... +│ pc: 0x2114 +│ callDepth: 0x0 +│ statusCode: EVMC_SUCCESS +│ method: test%properties%kontrol%L2StandardBridgeInteropKontrol.prove_convertOnlyOnSameRemoteAsset(address,address,bool,bool,bool) +│ +│ (1000 steps) +├─ 18 +│ k: #next [ PUSH ( 0x4 ) ] ~> #execute ~> #return 0x0 0x0 ~> #pc [ DELEGATECALL ] ~> ... +│ pc: 0x11f +│ callDepth: 0x2 +│ statusCode: EVMC_SUCCESS +│ src: test/properties/kontrol/L2StandardBridgeInterop.k.sol:24:36 +│ method: src%L2%L2StandardBridgeInterop.convert(address,address,uint256) +│ +│ (1000 steps) +└─ 19 (leaf, pending) + k: #execute ~> #return 0x0 0x0 ~> #pc [ DELEGATECALL ] ~> #execute ~> #return 0x3e0 ... + pc: 0x20b3 + callDepth: 0x2 + statusCode: EVMC_SUCCESS + method: src%L2%L2StandardBridgeInterop.convert(address,address,uint256) + + +┌─ 2 (root, leaf, target, terminal) +│ k: #halt ~> CONTINUATION:K +│ pc: PC_CELL_5d410f2a:Int +│ callDepth: CALLDEPTH_CELL_5d410f2a:Int +│ statusCode: STATUSCODE_FINAL:StatusCode + + +Node 19: + +( + + + + #execute + ~> #return 0x0 0x0 + ~> #pc [ DELEGATECALL ] + ~> #execute + ~> #return 0x3e0 0x0 + ~> #pc [ CALL ] + ~> #execute + ~> CONTINUATION:K + + + NORMAL + + + CANCUN + + + false + + + + + 0x0000000000000000000000000000000000000000000000000000000000000012 + + + EVMC_SUCCESS + + + ListItem ( + + 0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + 0x00000000000000000000000000000000000100010000000100000000000000000000010000000001000100000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000100000000000000000001000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000100000000000000000000000000000100000000000100000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x248391ff000000000000000000000000e6a7a45f334393093061116b197e3240065ff2d80000000000000000000000007c05912fc4cbffd28f63f412fcdd194991f8db480000000000000000000000000000000000000000000000000000000000000064 + + + 0x0 + + + ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f : ( 0x27 : ( 0x11 : .WordStack ) ) ) + + + 0x248391ff000000000000000000000000e6a7a45f334393093061116b197e3240065ff2d80000000000000000000000007c05912fc4cbffd28f63f412fcdd194991f8db480000000000000000000000000000000000000000000000000000000000000064 + + + 0xc7 + + + 0x0 + + + 0x0 + + + 0x0 + + + false + + + 0x1 + + ) ListItem ( + + 0x60806040523480156200001157600080fd5b5060043610620001895760003560e01c8063916a17c611620000dd578063c89701a2116200008b578063d6a2ec76116200006e578063d6a2ec761462000341578063e20c9f711462000369578063fa7626d4146200037357600080fd5b8063c89701a214620002f1578063d5ce3389146200031957600080fd5b8063ba414fa611620000c0578063ba414fa61462000299578063bf4792f114620002b4578063c30fe4fe14620002da57600080fd5b8063916a17c61462000285578063b5508aa9146200028f57600080fd5b8063547d77c4116200013b57806385226c81116200011e57806385226c8114620002585780638ea3d06f14620002715780638fe30c69146200027b57600080fd5b8063547d77c4146200022657806366d9a9a0146200023f57600080fd5b80632ade388011620001705780632ade388014620001f95780633e5e3c2314620002125780633f7286f4146200021c57600080fd5b806313151981146200018e5780631ed7831c14620001e0575b600080fd5b620001b67f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001ea62000381565b604051620001d791906200209c565b62000203620003f2565b604051620001d7919062002173565b620001ea6200054d565b620001ea620005bc565b6200023d6200023736600462002299565b6200062b565b005b6200024962000df5565b604051620001d79190620022d1565b6200026262000f01565b604051620001d79190620023cb565b6200023d62000fdb565b6200023d620011ab565b62000249620012e6565b62000262620013f2565b620002a3620014cc565b6040519015158152602001620001d7565b601e54620001b690610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6200023d620002eb36600462002486565b620015a4565b620001b67f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa581565b620001b67f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d881565b620001b67f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d81565b620001ea62001f15565b601e54620002a39060ff1681565b60606016805480602002602001604051908101604052809291908181526020018280548015620003e857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575b5050505050905090565b6060601d805480602002602001604051908101604052809291908181526020016000905b8282101562000544576000848152602080822060408051808201825260028702909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939591948681019491929084015b828210156200052c5783829060005260206000200180546200049890620024fa565b80601f0160208091040260200160405190810160405280929190818152602001828054620004c690620024fa565b8015620005175780601f10620004eb5761010080835404028352916020019162000517565b820191906000526020600020905b815481529060010190602001808311620004f957829003601f168201915b50505050508152602001906001019062000476565b50505050815250508152602001906001019062000416565b50505050905090565b60606018805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60606017805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b62000635620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff86168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262000717927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8926044016200254f565b600060405180830381600087803b1580156200073257600080fd5b505af115801562000747573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e493506200082f927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b1580156200084a57600080fd5b505af11580156200085f573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909317909252835160018184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000956937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b1580156200097157600080fd5b505af115801562000986573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000179052835160018183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000a99937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562000ab457600080fd5b505af115801562000ac9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b37390000000000000000000000000000000000000000000000000000000017905282516101a481830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452929450737109709ecfa91a80626ff3989d68f67f5b1dd12d935063b96213e49262000ba8927342000000000000000000000000000000000000129290916044016200254f565b600060405180830381600087803b15801562000bc357600080fd5b505af115801562000bd8573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062000cc7927342000000000000000000000000000000000000269291906044016200254f565b600060405180830381600087803b15801562000ce257600080fd5b505af115801562000cf7573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562000da257600080fd5b505af192505050801562000db4575060015b62000dd7578260ff168460ff160362000dd15762000dd16200259e565b62000def565b8260ff168460ff161462000def5762000def6200259e565b50505050565b6060601b805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff16835260018101805483518187028101870190945280845293949193858301939283018282801562000ee857602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841162000e945790505b5050505050815250508152602001906001019062000e19565b6060601a805480602002602001604051908101604052809291908181526020016000905b828210156200054457838290600052602060002001805462000f4790620024fa565b80601f016020809104026020016040519081016040528092919081815260200182805462000f7590620024fa565b801562000fc65780601f1062000f9a5761010080835404028352916020019162000fc6565b820191906000526020600020905b81548152906001019060200180831162000fa857829003601f168201915b50505050508152602001906001019062000f25565b62000fe5620011ab565b620010db601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001057573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200109f9190810190620025fc565b6040518060400160405280601581526020017f312e31312e312d626574612e312b696e7465726f70000000000000000000000081525062001f84565b620010ea57620010ea6200259e565b620011a9601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f46ddb26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200115c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011829190620026d3565b7f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa562001fe1565b565b604051620011b99062002080565b604051809103906000f080158015620011d6573d6000803e3d6000fd5b5060405173754cd1bdd15c0ed896f2867165a2694d76f39fa56024820152604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de8000000000000000000000000000000000000000000000000000000001790525162001279906200208e565b62001286929190620026fa565b604051809103906000f080158015620012a3573d6000803e3d6000fd5b50601e60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6060601c805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939491938583019392830182828015620013d957602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411620013855790505b505050505081525050815260200190600101906200130a565b60606019805480602002602001604051908101604052809291908181526020016000905b82821015620005445783829060005260206000200180546200143890620024fa565b80601f01602080910402602001604051908101604052809291908181526020018280546200146690620024fa565b8015620014b75780601f106200148b57610100808354040283529160200191620014b7565b820191906000526020600020905b8154815290600101906020018083116200149957829003601f168201915b50505050508152602001906001019062001416565b60085460009060ff1615620014e5575060085460ff1690565b6040517f667f9d70000000000000000000000000000000000000000000000000000000008152737109709ecfa91a80626ff3989d68f67f5b1dd12d600482018190527f6661696c65640000000000000000000000000000000000000000000000000000602483015260009163667f9d7090604401602060405180830381865afa15801562001577573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200159d919062002733565b1415905090565b620015ae620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce567000000000000000000000000000000000000000000000000000000001790528251601281830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262001692927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d89291906044016200254f565b600060405180830381600087803b158015620016ad57600080fd5b505af1158015620016c2573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e49350620017aa927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b158015620017c557600080fd5b505af1158015620017da573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690931790925283518a15158184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e49450620018d2937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b158015620018ed57600080fd5b505af115801562001902573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518915158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001a16937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001a3157600080fd5b505af115801562001a46573d6000803e3d6000fd5b5050604080517fec4fc8e3000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518815158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001b5a937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001b7557600080fd5b505af115801562001b8a573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8c168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001c79927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001c9457600080fd5b505af115801562001ca9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8b168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001d98927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001db357600080fd5b505af115801562001dc8573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562001e7357600080fd5b505af192505050801562001e85575060015b62001ece578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362001ec85762001ec86200259e565b62001f0c565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001f0c5762001f0c6200259e565b50505050505050565b60606015805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60008160405160200162001f9991906200274d565b604051602081830303815290604052805190602001208360405160200162001fc291906200274d565b6040516020818303038152906040528051906020012014905092915050565b6040517f515361f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015282166024820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063515361f69060440160006040518083038186803b1580156200206357600080fd5b505afa15801562002078573d6000803e3d6000fd5b505050505050565b613623806200276383390190565b6107958062005d8683390190565b6020808252825182820181905260009190848201906040850190845b81811015620020ec57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101620020b8565b50909695505050505050565b60005b8381101562002115578181015183820152602001620020fb565b8381111562000def5750506000910152565b6000815180845262002141816020860160208601620020f8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602080825282518282018190526000919060409081850190600581811b8701840188860187805b8581101562002272577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08b85030187528251805173ffffffffffffffffffffffffffffffffffffffff1685528901518985018990528051898601819052908a0190606081881b870181019190870190855b818110156200225b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08985030183526200224884865162002127565b948e01949350918d01916001016200220b565b505050978a0197945050918801916001016200219a565b50919a9950505050505050505050565b803560ff811681146200229457600080fd5b919050565b60008060408385031215620022ad57600080fd5b620022b88362002282565b9150620022c86020840162002282565b90509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015620023bc578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00186528251805173ffffffffffffffffffffffffffffffffffffffff168552880151888501889052805188860181905290890190839060608701905b80831015620023a65783517fffffffff00000000000000000000000000000000000000000000000000000000168252928b019260019290920191908b019062002362565b50978a01979550505091870191600101620022f9565b50919998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562002442577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200242f85835162002127565b94509285019290850190600101620023f2565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146200247257600080fd5b50565b803580151581146200229457600080fd5b600080600080600060a086880312156200249f57600080fd5b8535620024ac816200244f565b94506020860135620024be816200244f565b9350620024ce6040870162002475565b9250620024de6060870162002475565b9150620024ee6080870162002475565b90509295509295909350565b600181811c908216806200250f57607f821691505b60208210810362002549577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600062002580606083018562002127565b828103604084015262002594818562002127565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156200260f57600080fd5b815167ffffffffffffffff808211156200262857600080fd5b818401915084601f8301126200263d57600080fd5b815181811115620026525762002652620025cd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156200269b576200269b620025cd565b81604052828152876020848701011115620026b557600080fd5b620026c8836020830160208801620020f8565b979650505050505050565b600060208284031215620026e657600080fd5b8151620026f3816200244f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006200272b604083018462002127565b949350505050565b6000602082840312156200274657600080fd5b5051919050565b602081526000620026f360208301846200212756fe60806040523480156200001157600080fd5b506200001e600062000024565b62000217565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016d60201b6200045a1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b62000122734200000000000000000000000000000000000007836200017c565b801562000169576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b6133fc80620002276000396000f3fe60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a608060405260405161079538038061079583398101604081905261002291610314565b61002e82826000610035565b5050610431565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161076e602791396101a9565b9392505050565b6100ea8161028760201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61029660201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610148565b600080856001600160a01b03168560405161022c91906103e2565b600060405180830381855af49150503d8060008114610267576040519150601f19603f3d011682016040523d82523d6000602084013e61026c565b606091505b50909250905061027d828286610299565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a85750816100d0565b8251156102b85782518084602001fd5b8160405162461bcd60e51b815260040161014891906103fe565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103035781810151838201526020016102eb565b838111156100645750506000910152565b6000806040838503121561032757600080fd5b82516001600160a01b038116811461033e57600080fd5b60208401519092506001600160401b038082111561035b57600080fd5b818501915085601f83011261036f57600080fd5b815181811115610381576103816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + 0x0000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000001000000000000000000000000000001000000000000000000010000000000000000000000000000010000000000000000000100000000000000000001000000000000000000000000000000000100000000000100010000000000000000000100000000000000000000000000000100000000000000000001000000000000000000000000000001000000000000000000010000000000000000000100000000000000000001000000000000000000010000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000100000000000100000000000000000000000000000000000000000000000100000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000100010000000000000000000000000001000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000010000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000010000000000000001000000000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000001000000000000000000000000000000000000000000000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000010000000001000000000000000000000000000000000000000100000000000000000000010000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000001000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000100000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000100000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000001000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000100000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000100000000010000000000000000000000010000000000000000000000000000010000000001000000000000000000000000000100000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000010000000000000000010000000000000000000000000100000000000000000000000100000000000000000000000000000001000000000000000000000001000000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000100010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000100000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000010000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000001000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000000001000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000001000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000000000000000100000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000010000000000000000000000000000000000010000000000000000010000000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000001000000000000000000000100000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000001000000000000000001000000000000000000000000010000000000000000000000000000000000000000000000000100010000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000100000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000001000000000000000000000000000000000100000000000000000001000000000000000000000000000001000001000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000010000000000000000000000000000000000000000000000010000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000001000000000000000000000000000000000100000000000000000000000000000100000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100010000000100000000000000000000010000000001000100000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000100000000000000000001000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000100000000000000000000000000000100000000000100000000000000000000000000000000000100000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + CALLER_ID:Int + + + 0xc30fe4fe +Bytes #buf ( 0x20 , VV0__fromRemoteAddress_114b9705:Int ) +Bytes #buf ( 0x20 , VV1__toRemoteAddress_114b9705:Int ) +Bytes #buf ( 0x20 , VV2__supportsIERC165_114b9705:Int ) +Bytes #buf ( 0x20 , VV3__supportsILegacyMintableERC20_114b9705:Int ) +Bytes #buf ( 0x20 , VV4__supportsIOptimismMintableERC20_114b9705:Int ) + + + 0x0 + + + ( 0x444 : ( 0x248391ff : ( 0x2e234dae75c793f67a35089c9d99245e1c58470b : ( 0x64 : ( 0x12 : ( VV4__supportsIOptimismMintableERC20_114b9705:Int : ( VV3__supportsILegacyMintableERC20_114b9705:Int : ( VV2__supportsIERC165_114b9705:Int : ( VV1__toRemoteAddress_114b9705:Int : ( VV0__fromRemoteAddress_114b9705:Int : ( 0x23d : ( 0xc30fe4fe : .WordStack ) ) ) ) ) ) ) ) ) ) ) ) + + + 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000754cd1bdd15c0ed896f2867165a2694d76f39fa50000000000000000000000000000000000000000000000000000000000000004313ce567000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000004313ce56700000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000002401ffc9a701ffc9a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV2__supportsIERC165_114b9705:Int ) +Bytes 0x000000000000000000000000000000000000000000000000000000000000002401ffc9a71d1d8b63000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV3__supportsILegacyMintableERC20_114b9705:Int ) +Bytes 0x000000000000000000000000000000000000000000000000000000000000002401ffc9a7ec4fc8e3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV4__supportsIOptimismMintableERC20_114b9705:Int ) +Bytes 0x0000000000000000000000000000000000000000000000000000000000000004316b37390000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV0__fromRemoteAddress_114b9705:Int ) +Bytes 0x0000000000000000000000000000000000000000000000000000000000000004316b37390000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV1__toRemoteAddress_114b9705:Int ) +Bytes 0x248391ff000000000000000000000000e6a7a45f334393093061116b197e3240065ff2d80000000000000000000000007c05912fc4cbffd28f63f412fcdd194991f8db4800000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000004316b3739000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020 +Bytes #buf ( 0x20 , VV1__toRemoteAddress_114b9705:Int ) +Bytes 0x2081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c65640000000000000000000000005615deb798bb3e4dfa0139dfa1b3d433cc23b72f00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000754cd1bdd15c0ed896f2867165a2694d76f39fa50000000000000000000000000000000000000000000000000000000000000000604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + 0x1e76 + + + 0x0 + + + 0x0 + + + 0x0 + + + false + + + 0x0 + + ) + + + ListItem ( { + ( + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x0 + + + 0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( ( 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc |-> 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) + ( 0x4 |-> 0x754cd1bdd15c0ed896f2867165a2694d76f39fa5 ) ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x4200000000000000000000000000000000000012 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f + + + 0x0 + + + 0x60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( 0x4 |-> 0x0 ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x0 + + + 0x60806040523480156200001157600080fd5b5060043610620001895760003560e01c8063916a17c611620000dd578063c89701a2116200008b578063d6a2ec76116200006e578063d6a2ec761462000341578063e20c9f711462000369578063fa7626d4146200037357600080fd5b8063c89701a214620002f1578063d5ce3389146200031957600080fd5b8063ba414fa611620000c0578063ba414fa61462000299578063bf4792f114620002b4578063c30fe4fe14620002da57600080fd5b8063916a17c61462000285578063b5508aa9146200028f57600080fd5b8063547d77c4116200013b57806385226c81116200011e57806385226c8114620002585780638ea3d06f14620002715780638fe30c69146200027b57600080fd5b8063547d77c4146200022657806366d9a9a0146200023f57600080fd5b80632ade388011620001705780632ade388014620001f95780633e5e3c2314620002125780633f7286f4146200021c57600080fd5b806313151981146200018e5780631ed7831c14620001e0575b600080fd5b620001b67f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001ea62000381565b604051620001d791906200209c565b62000203620003f2565b604051620001d7919062002173565b620001ea6200054d565b620001ea620005bc565b6200023d6200023736600462002299565b6200062b565b005b6200024962000df5565b604051620001d79190620022d1565b6200026262000f01565b604051620001d79190620023cb565b6200023d62000fdb565b6200023d620011ab565b62000249620012e6565b62000262620013f2565b620002a3620014cc565b6040519015158152602001620001d7565b601e54620001b690610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6200023d620002eb36600462002486565b620015a4565b620001b67f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa581565b620001b67f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d881565b620001b67f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d81565b620001ea62001f15565b601e54620002a39060ff1681565b60606016805480602002602001604051908101604052809291908181526020018280548015620003e857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575b5050505050905090565b6060601d805480602002602001604051908101604052809291908181526020016000905b8282101562000544576000848152602080822060408051808201825260028702909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939591948681019491929084015b828210156200052c5783829060005260206000200180546200049890620024fa565b80601f0160208091040260200160405190810160405280929190818152602001828054620004c690620024fa565b8015620005175780601f10620004eb5761010080835404028352916020019162000517565b820191906000526020600020905b815481529060010190602001808311620004f957829003601f168201915b50505050508152602001906001019062000476565b50505050815250508152602001906001019062000416565b50505050905090565b60606018805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60606017805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b62000635620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff86168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262000717927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8926044016200254f565b600060405180830381600087803b1580156200073257600080fd5b505af115801562000747573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e493506200082f927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b1580156200084a57600080fd5b505af11580156200085f573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909317909252835160018184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000956937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b1580156200097157600080fd5b505af115801562000986573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000179052835160018183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000a99937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562000ab457600080fd5b505af115801562000ac9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b37390000000000000000000000000000000000000000000000000000000017905282516101a481830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452929450737109709ecfa91a80626ff3989d68f67f5b1dd12d935063b96213e49262000ba8927342000000000000000000000000000000000000129290916044016200254f565b600060405180830381600087803b15801562000bc357600080fd5b505af115801562000bd8573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062000cc7927342000000000000000000000000000000000000269291906044016200254f565b600060405180830381600087803b15801562000ce257600080fd5b505af115801562000cf7573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562000da257600080fd5b505af192505050801562000db4575060015b62000dd7578260ff168460ff160362000dd15762000dd16200259e565b62000def565b8260ff168460ff161462000def5762000def6200259e565b50505050565b6060601b805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff16835260018101805483518187028101870190945280845293949193858301939283018282801562000ee857602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841162000e945790505b5050505050815250508152602001906001019062000e19565b6060601a805480602002602001604051908101604052809291908181526020016000905b828210156200054457838290600052602060002001805462000f4790620024fa565b80601f016020809104026020016040519081016040528092919081815260200182805462000f7590620024fa565b801562000fc65780601f1062000f9a5761010080835404028352916020019162000fc6565b820191906000526020600020905b81548152906001019060200180831162000fa857829003601f168201915b50505050508152602001906001019062000f25565b62000fe5620011ab565b620010db601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001057573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200109f9190810190620025fc565b6040518060400160405280601581526020017f312e31312e312d626574612e312b696e7465726f70000000000000000000000081525062001f84565b620010ea57620010ea6200259e565b620011a9601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f46ddb26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200115c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011829190620026d3565b7f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa562001fe1565b565b604051620011b99062002080565b604051809103906000f080158015620011d6573d6000803e3d6000fd5b5060405173754cd1bdd15c0ed896f2867165a2694d76f39fa56024820152604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de8000000000000000000000000000000000000000000000000000000001790525162001279906200208e565b62001286929190620026fa565b604051809103906000f080158015620012a3573d6000803e3d6000fd5b50601e60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6060601c805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939491938583019392830182828015620013d957602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411620013855790505b505050505081525050815260200190600101906200130a565b60606019805480602002602001604051908101604052809291908181526020016000905b82821015620005445783829060005260206000200180546200143890620024fa565b80601f01602080910402602001604051908101604052809291908181526020018280546200146690620024fa565b8015620014b75780601f106200148b57610100808354040283529160200191620014b7565b820191906000526020600020905b8154815290600101906020018083116200149957829003601f168201915b50505050508152602001906001019062001416565b60085460009060ff1615620014e5575060085460ff1690565b6040517f667f9d70000000000000000000000000000000000000000000000000000000008152737109709ecfa91a80626ff3989d68f67f5b1dd12d600482018190527f6661696c65640000000000000000000000000000000000000000000000000000602483015260009163667f9d7090604401602060405180830381865afa15801562001577573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200159d919062002733565b1415905090565b620015ae620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce567000000000000000000000000000000000000000000000000000000001790528251601281830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262001692927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d89291906044016200254f565b600060405180830381600087803b158015620016ad57600080fd5b505af1158015620016c2573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e49350620017aa927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b158015620017c557600080fd5b505af1158015620017da573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690931790925283518a15158184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e49450620018d2937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b158015620018ed57600080fd5b505af115801562001902573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518915158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001a16937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001a3157600080fd5b505af115801562001a46573d6000803e3d6000fd5b5050604080517fec4fc8e3000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518815158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001b5a937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001b7557600080fd5b505af115801562001b8a573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8c168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001c79927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001c9457600080fd5b505af115801562001ca9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8b168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001d98927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001db357600080fd5b505af115801562001dc8573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562001e7357600080fd5b505af192505050801562001e85575060015b62001ece578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362001ec85762001ec86200259e565b62001f0c565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001f0c5762001f0c6200259e565b50505050505050565b60606015805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60008160405160200162001f9991906200274d565b604051602081830303815290604052805190602001208360405160200162001fc291906200274d565b6040516020818303038152906040528051906020012014905092915050565b6040517f515361f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015282166024820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063515361f69060440160006040518083038186803b1580156200206357600080fd5b505afa15801562002078573d6000803e3d6000fd5b505050505050565b613623806200276383390190565b6107958062005d8683390190565b6020808252825182820181905260009190848201906040850190845b81811015620020ec57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101620020b8565b50909695505050505050565b60005b8381101562002115578181015183820152602001620020fb565b8381111562000def5750506000910152565b6000815180845262002141816020860160208601620020f8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602080825282518282018190526000919060409081850190600581811b8701840188860187805b8581101562002272577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08b85030187528251805173ffffffffffffffffffffffffffffffffffffffff1685528901518985018990528051898601819052908a0190606081881b870181019190870190855b818110156200225b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08985030183526200224884865162002127565b948e01949350918d01916001016200220b565b505050978a0197945050918801916001016200219a565b50919a9950505050505050505050565b803560ff811681146200229457600080fd5b919050565b60008060408385031215620022ad57600080fd5b620022b88362002282565b9150620022c86020840162002282565b90509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015620023bc578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00186528251805173ffffffffffffffffffffffffffffffffffffffff168552880151888501889052805188860181905290890190839060608701905b80831015620023a65783517fffffffff00000000000000000000000000000000000000000000000000000000168252928b019260019290920191908b019062002362565b50978a01979550505091870191600101620022f9565b50919998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562002442577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200242f85835162002127565b94509285019290850190600101620023f2565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146200247257600080fd5b50565b803580151581146200229457600080fd5b600080600080600060a086880312156200249f57600080fd5b8535620024ac816200244f565b94506020860135620024be816200244f565b9350620024ce6040870162002475565b9250620024de6060870162002475565b9150620024ee6080870162002475565b90509295509295909350565b600181811c908216806200250f57607f821691505b60208210810362002549577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600062002580606083018562002127565b828103604084015262002594818562002127565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156200260f57600080fd5b815167ffffffffffffffff808211156200262857600080fd5b818401915084601f8301126200263d57600080fd5b815181811115620026525762002652620025cd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156200269b576200269b620025cd565b81604052828152876020848701011115620026b557600080fd5b620026c8836020830160208801620020f8565b979650505050505050565b600060208284031215620026e657600080fd5b8151620026f3816200244f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006200272b604083018462002127565b949350505050565b6000602082840312156200274657600080fd5b5051919050565b602081526000620026f360208301846200212756fe60806040523480156200001157600080fd5b506200001e600062000024565b62000217565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016d60201b6200045a1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b62000122734200000000000000000000000000000000000007836200017c565b801562000169576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b6133fc80620002276000396000f3fe60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a608060405260405161079538038061079583398101604081905261002291610314565b61002e82826000610035565b5050610431565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161076e602791396101a9565b9392505050565b6100ea8161028760201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61029660201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610148565b600080856001600160a01b03168560405161022c91906103e2565b600060405180830381855af49150503d8060008114610267576040519150601f19603f3d011682016040523d82523d6000602084013e61026c565b606091505b50909250905061027d828286610299565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a85750816100d0565b8251156102b85782518084602001fd5b8160405162461bcd60e51b815260040161014891906103fe565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103035781810151838201526020016102eb565b838111156100645750506000910152565b6000806040838503121561032757600080fd5b82516001600160a01b038116811461033e57600080fd5b60208401519092506001600160401b038082111561035b57600080fd5b818501915085601f83011261036f57600080fd5b815181811115610381576103816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( 0x1e |-> 0x2e234dae75c793f67a35089c9d99245e1c58470b00 ) + + + .Map + + + .Map + + + 0x3 + + + ( + + 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + + + 0xe6a7a45f334393093061116b197e3240065ff2d8 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + ) ) ) ) ) ) + | + + SELFDESTRUCT_CELL:Set + + + ListItem ( { 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b ) ListItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) | 0x } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) + + + 0x0 + + + ( SetItem ( 0x7fa9385be102ac3eac297483dd6233d62b3e1496 ) ( SetItem ( 0xe6a7a45f334393093061116b197e3240065ff2d8 ) ( SetItem ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 ) ( SetItem ( 0x4200000000000000000000000000000000000012 ) ( SetItem ( 0x2e234dae75c793f67a35089c9d99245e1c58470b ) ( SetItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) SetItem ( 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d ) ) ) ) ) ) ) + + + .Map + + } ) ListItem ( { + ( + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x0 + + + 0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( ( 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc |-> 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) + ( 0x4 |-> 0x754cd1bdd15c0ed896f2867165a2694d76f39fa5 ) ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x4200000000000000000000000000000000000012 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f + + + 0x0 + + + 0x60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( 0x4 |-> 0x0 ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x0 + + + 0x60806040523480156200001157600080fd5b5060043610620001895760003560e01c8063916a17c611620000dd578063c89701a2116200008b578063d6a2ec76116200006e578063d6a2ec761462000341578063e20c9f711462000369578063fa7626d4146200037357600080fd5b8063c89701a214620002f1578063d5ce3389146200031957600080fd5b8063ba414fa611620000c0578063ba414fa61462000299578063bf4792f114620002b4578063c30fe4fe14620002da57600080fd5b8063916a17c61462000285578063b5508aa9146200028f57600080fd5b8063547d77c4116200013b57806385226c81116200011e57806385226c8114620002585780638ea3d06f14620002715780638fe30c69146200027b57600080fd5b8063547d77c4146200022657806366d9a9a0146200023f57600080fd5b80632ade388011620001705780632ade388014620001f95780633e5e3c2314620002125780633f7286f4146200021c57600080fd5b806313151981146200018e5780631ed7831c14620001e0575b600080fd5b620001b67f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001ea62000381565b604051620001d791906200209c565b62000203620003f2565b604051620001d7919062002173565b620001ea6200054d565b620001ea620005bc565b6200023d6200023736600462002299565b6200062b565b005b6200024962000df5565b604051620001d79190620022d1565b6200026262000f01565b604051620001d79190620023cb565b6200023d62000fdb565b6200023d620011ab565b62000249620012e6565b62000262620013f2565b620002a3620014cc565b6040519015158152602001620001d7565b601e54620001b690610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6200023d620002eb36600462002486565b620015a4565b620001b67f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa581565b620001b67f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d881565b620001b67f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d81565b620001ea62001f15565b601e54620002a39060ff1681565b60606016805480602002602001604051908101604052809291908181526020018280548015620003e857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575b5050505050905090565b6060601d805480602002602001604051908101604052809291908181526020016000905b8282101562000544576000848152602080822060408051808201825260028702909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939591948681019491929084015b828210156200052c5783829060005260206000200180546200049890620024fa565b80601f0160208091040260200160405190810160405280929190818152602001828054620004c690620024fa565b8015620005175780601f10620004eb5761010080835404028352916020019162000517565b820191906000526020600020905b815481529060010190602001808311620004f957829003601f168201915b50505050508152602001906001019062000476565b50505050815250508152602001906001019062000416565b50505050905090565b60606018805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60606017805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b62000635620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff86168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262000717927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8926044016200254f565b600060405180830381600087803b1580156200073257600080fd5b505af115801562000747573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e493506200082f927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b1580156200084a57600080fd5b505af11580156200085f573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909317909252835160018184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000956937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b1580156200097157600080fd5b505af115801562000986573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000179052835160018183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000a99937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562000ab457600080fd5b505af115801562000ac9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b37390000000000000000000000000000000000000000000000000000000017905282516101a481830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452929450737109709ecfa91a80626ff3989d68f67f5b1dd12d935063b96213e49262000ba8927342000000000000000000000000000000000000129290916044016200254f565b600060405180830381600087803b15801562000bc357600080fd5b505af115801562000bd8573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062000cc7927342000000000000000000000000000000000000269291906044016200254f565b600060405180830381600087803b15801562000ce257600080fd5b505af115801562000cf7573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562000da257600080fd5b505af192505050801562000db4575060015b62000dd7578260ff168460ff160362000dd15762000dd16200259e565b62000def565b8260ff168460ff161462000def5762000def6200259e565b50505050565b6060601b805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff16835260018101805483518187028101870190945280845293949193858301939283018282801562000ee857602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841162000e945790505b5050505050815250508152602001906001019062000e19565b6060601a805480602002602001604051908101604052809291908181526020016000905b828210156200054457838290600052602060002001805462000f4790620024fa565b80601f016020809104026020016040519081016040528092919081815260200182805462000f7590620024fa565b801562000fc65780601f1062000f9a5761010080835404028352916020019162000fc6565b820191906000526020600020905b81548152906001019060200180831162000fa857829003601f168201915b50505050508152602001906001019062000f25565b62000fe5620011ab565b620010db601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001057573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200109f9190810190620025fc565b6040518060400160405280601581526020017f312e31312e312d626574612e312b696e7465726f70000000000000000000000081525062001f84565b620010ea57620010ea6200259e565b620011a9601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f46ddb26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200115c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011829190620026d3565b7f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa562001fe1565b565b604051620011b99062002080565b604051809103906000f080158015620011d6573d6000803e3d6000fd5b5060405173754cd1bdd15c0ed896f2867165a2694d76f39fa56024820152604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de8000000000000000000000000000000000000000000000000000000001790525162001279906200208e565b62001286929190620026fa565b604051809103906000f080158015620012a3573d6000803e3d6000fd5b50601e60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6060601c805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939491938583019392830182828015620013d957602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411620013855790505b505050505081525050815260200190600101906200130a565b60606019805480602002602001604051908101604052809291908181526020016000905b82821015620005445783829060005260206000200180546200143890620024fa565b80601f01602080910402602001604051908101604052809291908181526020018280546200146690620024fa565b8015620014b75780601f106200148b57610100808354040283529160200191620014b7565b820191906000526020600020905b8154815290600101906020018083116200149957829003601f168201915b50505050508152602001906001019062001416565b60085460009060ff1615620014e5575060085460ff1690565b6040517f667f9d70000000000000000000000000000000000000000000000000000000008152737109709ecfa91a80626ff3989d68f67f5b1dd12d600482018190527f6661696c65640000000000000000000000000000000000000000000000000000602483015260009163667f9d7090604401602060405180830381865afa15801562001577573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200159d919062002733565b1415905090565b620015ae620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce567000000000000000000000000000000000000000000000000000000001790528251601281830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262001692927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d89291906044016200254f565b600060405180830381600087803b158015620016ad57600080fd5b505af1158015620016c2573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e49350620017aa927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b158015620017c557600080fd5b505af1158015620017da573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690931790925283518a15158184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e49450620018d2937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b158015620018ed57600080fd5b505af115801562001902573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518915158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001a16937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001a3157600080fd5b505af115801562001a46573d6000803e3d6000fd5b5050604080517fec4fc8e3000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518815158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001b5a937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001b7557600080fd5b505af115801562001b8a573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8c168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001c79927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001c9457600080fd5b505af115801562001ca9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8b168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001d98927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001db357600080fd5b505af115801562001dc8573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562001e7357600080fd5b505af192505050801562001e85575060015b62001ece578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362001ec85762001ec86200259e565b62001f0c565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001f0c5762001f0c6200259e565b50505050505050565b60606015805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60008160405160200162001f9991906200274d565b604051602081830303815290604052805190602001208360405160200162001fc291906200274d565b6040516020818303038152906040528051906020012014905092915050565b6040517f515361f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015282166024820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063515361f69060440160006040518083038186803b1580156200206357600080fd5b505afa15801562002078573d6000803e3d6000fd5b505050505050565b613623806200276383390190565b6107958062005d8683390190565b6020808252825182820181905260009190848201906040850190845b81811015620020ec57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101620020b8565b50909695505050505050565b60005b8381101562002115578181015183820152602001620020fb565b8381111562000def5750506000910152565b6000815180845262002141816020860160208601620020f8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602080825282518282018190526000919060409081850190600581811b8701840188860187805b8581101562002272577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08b85030187528251805173ffffffffffffffffffffffffffffffffffffffff1685528901518985018990528051898601819052908a0190606081881b870181019190870190855b818110156200225b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08985030183526200224884865162002127565b948e01949350918d01916001016200220b565b505050978a0197945050918801916001016200219a565b50919a9950505050505050505050565b803560ff811681146200229457600080fd5b919050565b60008060408385031215620022ad57600080fd5b620022b88362002282565b9150620022c86020840162002282565b90509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015620023bc578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00186528251805173ffffffffffffffffffffffffffffffffffffffff168552880151888501889052805188860181905290890190839060608701905b80831015620023a65783517fffffffff00000000000000000000000000000000000000000000000000000000168252928b019260019290920191908b019062002362565b50978a01979550505091870191600101620022f9565b50919998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562002442577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200242f85835162002127565b94509285019290850190600101620023f2565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146200247257600080fd5b50565b803580151581146200229457600080fd5b600080600080600060a086880312156200249f57600080fd5b8535620024ac816200244f565b94506020860135620024be816200244f565b9350620024ce6040870162002475565b9250620024de6060870162002475565b9150620024ee6080870162002475565b90509295509295909350565b600181811c908216806200250f57607f821691505b60208210810362002549577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600062002580606083018562002127565b828103604084015262002594818562002127565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156200260f57600080fd5b815167ffffffffffffffff808211156200262857600080fd5b818401915084601f8301126200263d57600080fd5b815181811115620026525762002652620025cd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156200269b576200269b620025cd565b81604052828152876020848701011115620026b557600080fd5b620026c8836020830160208801620020f8565b979650505050505050565b600060208284031215620026e657600080fd5b8151620026f3816200244f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006200272b604083018462002127565b949350505050565b6000602082840312156200274657600080fd5b5051919050565b602081526000620026f360208301846200212756fe60806040523480156200001157600080fd5b506200001e600062000024565b62000217565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016d60201b6200045a1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b62000122734200000000000000000000000000000000000007836200017c565b801562000169576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b6133fc80620002276000396000f3fe60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a608060405260405161079538038061079583398101604081905261002291610314565b61002e82826000610035565b5050610431565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161076e602791396101a9565b9392505050565b6100ea8161028760201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61029660201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610148565b600080856001600160a01b03168560405161022c91906103e2565b600060405180830381855af49150503d8060008114610267576040519150601f19603f3d011682016040523d82523d6000602084013e61026c565b606091505b50909250905061027d828286610299565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a85750816100d0565b8251156102b85782518084602001fd5b8160405162461bcd60e51b815260040161014891906103fe565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103035781810151838201526020016102eb565b838111156100645750506000910152565b6000806040838503121561032757600080fd5b82516001600160a01b038116811461033e57600080fd5b60208401519092506001600160401b038082111561035b57600080fd5b818501915085601f83011261036f57600080fd5b815181811115610381576103816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( 0x1e |-> 0x2e234dae75c793f67a35089c9d99245e1c58470b00 ) + + + .Map + + + .Map + + + 0x3 + + + ( + + 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + + + 0xe6a7a45f334393093061116b197e3240065ff2d8 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + ) ) ) ) ) ) + | + + SELFDESTRUCT_CELL:Set + + + ListItem ( { 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b ) ListItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) | 0x } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) + + + 0x0 + + + ( SetItem ( 0x7fa9385be102ac3eac297483dd6233d62b3e1496 ) ( SetItem ( 0xe6a7a45f334393093061116b197e3240065ff2d8 ) ( SetItem ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 ) ( SetItem ( 0x4200000000000000000000000000000000000012 ) ( SetItem ( 0x2e234dae75c793f67a35089c9d99245e1c58470b ) ( SetItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) SetItem ( 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d ) ) ) ) ) ) ) + + + .Map + + } ) + + + ( SetItem ( 0x7fa9385be102ac3eac297483dd6233d62b3e1496 ) ( SetItem ( 0x2e234dae75c793f67a35089c9d99245e1c58470b ) SetItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) ) ) + + + + 0x60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + 0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000100000000010000000000000000000000010000000000000000000000000000010000000001000000000000000000000000000100000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000100000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000010000000000000000010000000000000000000000000100000000000000000000000100000000000000000000000000000001000000000000000000000001000000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000100000000000000000000000100000000000000000000000000000100000000010000000000000000000000010000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000100010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000100000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000010000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000010000000000000000000000000000010000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000001000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000010000000000000000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000000001000000000000000000000000000000000000000100000000010000000000000000000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000000000000000001000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000000001000000000000000000000000000000010000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000100000100000000000000000000000000000000000000000000000100000000000000000000000000000000010000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000000000000000000000000000000000100000000000000000000010000000000000000000000000000000100000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000001000000000000000000000000000000000000010000000000000000000001000000000000000000000000000000010000000000000000000001000000000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000001000000000000000000000100000000000000000000000000010000000000000000000000000000000000000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000000000000000100000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000001000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000100000000000000000000000000000000000001000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000010000000000000000000000000000000000010000000000000000010000000000000000000000000000000000010000000000000000000000000000000100000000000000000000000000000000000001000000000000000000000100000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000100000000000000000000000000000000000100000000000000000000000000000000000000000000 + + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x248391ff000000000000000000000000e6a7a45f334393093061116b197e3240065ff2d80000000000000000000000007c05912fc4cbffd28f63f412fcdd194991f8db480000000000000000000000000000000000000000000000000000000000000064 + + + 0x0 + + + ( 0x12 : ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 : ( 0xe6a7a45f334393093061116b197e3240065ff2d8 : ( 0xebb : ( 0x64 : ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 : ( 0xe6a7a45f334393093061116b197e3240065ff2d8 : ( 0x1fa : ( 0x248391ff : .WordStack ) ) ) ) ) ) ) ) ) + + + 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000012 + + + 0x20b3 + + + 0x0 + + + 0x0 + + + 0x0 + + + false + + + 0x2 + + + + + SELFDESTRUCT_CELL:Set + + + ListItem ( { 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b ) ListItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) | 0x } ) ListItem ( { 0x2e234dae75c793f67a35089c9d99245e1c58470b | ListItem ( 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498 ) | 0x0000000000000000000000000000000000000000000000000000000000000001 } ) + + + 0x0 + + + ( SetItem ( 0x7fa9385be102ac3eac297483dd6233d62b3e1496 ) ( SetItem ( 0xe6a7a45f334393093061116b197e3240065ff2d8 ) ( SetItem ( 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 ) ( SetItem ( 0x4200000000000000000000000000000000000012 ) ( SetItem ( 0x2e234dae75c793f67a35089c9d99245e1c58470b ) ( SetItem ( 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) SetItem ( 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d ) ) ) ) ) ) ) + + + .Map + + + + ORIGIN_ID:Int + + + + NUMBER_CELL:Int + + + TIMESTAMP_CELL:Int + + ... + + ... + + + + 0x1 + + + ( + + 0x2e234dae75c793f67a35089c9d99245e1c58470b + + + 0x0 + + + 0x60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( ( 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc |-> 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f ) + ( 0x4 |-> 0x754cd1bdd15c0ed896f2867165a2694d76f39fa5 ) ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7109709ecfa91a80626ff3989d68f67f5b1dd12d + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x4200000000000000000000000000000000000012 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + ( + + 0x5615deb798bb3e4dfa0139dfa1b3d433cc23b72f + + + 0x0 + + + 0x60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a + + + ( ( 0x3 |-> 0x4200000000000000000000000000000000000007 ) + ( ( 0x0 |-> 0x1 ) + ( 0x4 |-> 0x0 ) ) ) + + + .Map + + + .Map + + + 0x1 + + + ( + + 0x7fa9385be102ac3eac297483dd6233d62b3e1496 + + + 0x0 + + + 0x60806040523480156200001157600080fd5b5060043610620001895760003560e01c8063916a17c611620000dd578063c89701a2116200008b578063d6a2ec76116200006e578063d6a2ec761462000341578063e20c9f711462000369578063fa7626d4146200037357600080fd5b8063c89701a214620002f1578063d5ce3389146200031957600080fd5b8063ba414fa611620000c0578063ba414fa61462000299578063bf4792f114620002b4578063c30fe4fe14620002da57600080fd5b8063916a17c61462000285578063b5508aa9146200028f57600080fd5b8063547d77c4116200013b57806385226c81116200011e57806385226c8114620002585780638ea3d06f14620002715780638fe30c69146200027b57600080fd5b8063547d77c4146200022657806366d9a9a0146200023f57600080fd5b80632ade388011620001705780632ade388014620001f95780633e5e3c2314620002125780633f7286f4146200021c57600080fd5b806313151981146200018e5780631ed7831c14620001e0575b600080fd5b620001b67f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001ea62000381565b604051620001d791906200209c565b62000203620003f2565b604051620001d7919062002173565b620001ea6200054d565b620001ea620005bc565b6200023d6200023736600462002299565b6200062b565b005b6200024962000df5565b604051620001d79190620022d1565b6200026262000f01565b604051620001d79190620023cb565b6200023d62000fdb565b6200023d620011ab565b62000249620012e6565b62000262620013f2565b620002a3620014cc565b6040519015158152602001620001d7565b601e54620001b690610100900473ffffffffffffffffffffffffffffffffffffffff1681565b6200023d620002eb36600462002486565b620015a4565b620001b67f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa581565b620001b67f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d881565b620001b67f885cb69240a935d632d79c317109709ecfa91a80626ff3989d68f67f5b1dd12d81565b620001ea62001f15565b601e54620002a39060ff1681565b60606016805480602002602001604051908101604052809291908181526020018280548015620003e857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575b5050505050905090565b6060601d805480602002602001604051908101604052809291908181526020016000905b8282101562000544576000848152602080822060408051808201825260028702909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939591948681019491929084015b828210156200052c5783829060005260206000200180546200049890620024fa565b80601f0160208091040260200160405190810160405280929190818152602001828054620004c690620024fa565b8015620005175780601f10620004eb5761010080835404028352916020019162000517565b820191906000526020600020905b815481529060010190602001808311620004f957829003601f168201915b50505050508152602001906001019062000476565b50505050815250508152602001906001019062000416565b50505050905090565b60606018805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60606017805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b62000635620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff86168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262000717927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8926044016200254f565b600060405180830381600087803b1580156200073257600080fd5b505af115801562000747573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e493506200082f927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b1580156200084a57600080fd5b505af11580156200085f573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16909317909252835160018184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000956937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b1580156200097157600080fd5b505af115801562000986573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000179052835160018183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062000a99937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562000ab457600080fd5b505af115801562000ac9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b37390000000000000000000000000000000000000000000000000000000017905282516101a481830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452929450737109709ecfa91a80626ff3989d68f67f5b1dd12d935063b96213e49262000ba8927342000000000000000000000000000000000000129290916044016200254f565b600060405180830381600087803b15801562000bc357600080fd5b505af115801562000bd8573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062000cc7927342000000000000000000000000000000000000269291906044016200254f565b600060405180830381600087803b15801562000ce257600080fd5b505af115801562000cf7573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562000da257600080fd5b505af192505050801562000db4575060015b62000dd7578260ff168460ff160362000dd15762000dd16200259e565b62000def565b8260ff168460ff161462000def5762000def6200259e565b50505050565b6060601b805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff16835260018101805483518187028101870190945280845293949193858301939283018282801562000ee857602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906004019060208260030104928301926001038202915080841162000e945790505b5050505050815250508152602001906001019062000e19565b6060601a805480602002602001604051908101604052809291908181526020016000905b828210156200054457838290600052602060002001805462000f4790620024fa565b80601f016020809104026020016040519081016040528092919081815260200182805462000f7590620024fa565b801562000fc65780601f1062000f9a5761010080835404028352916020019162000fc6565b820191906000526020600020905b81548152906001019060200180831162000fa857829003601f168201915b50505050508152602001906001019062000f25565b62000fe5620011ab565b620010db601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166354fd4d506040518163ffffffff1660e01b8152600401600060405180830381865afa15801562001057573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200109f9190810190620025fc565b6040518060400160405280601581526020017f312e31312e312d626574612e312b696e7465726f70000000000000000000000081525062001f84565b620010ea57620010ea6200259e565b620011a9601e60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16637f46ddb26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200115c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620011829190620026d3565b7f8b09dbc54fd3f3ff75c77578754cd1bdd15c0ed896f2867165a2694d76f39fa562001fe1565b565b604051620011b99062002080565b604051809103906000f080158015620011d6573d6000803e3d6000fd5b5060405173754cd1bdd15c0ed896f2867165a2694d76f39fa56024820152604401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de8000000000000000000000000000000000000000000000000000000001790525162001279906200208e565b62001286929190620026fa565b604051809103906000f080158015620012a3573d6000803e3d6000fd5b50601e60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6060601c805480602002602001604051908101604052809291908181526020016000905b828210156200054457600084815260209081902060408051808201825260028602909201805473ffffffffffffffffffffffffffffffffffffffff168352600181018054835181870281018701909452808452939491938583019392830182828015620013d957602002820191906000526020600020906000905b82829054906101000a900460e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681526020019060040190602082600301049283019260010382029150808411620013855790505b505050505081525050815260200190600101906200130a565b60606019805480602002602001604051908101604052809291908181526020016000905b82821015620005445783829060005260206000200180546200143890620024fa565b80601f01602080910402602001604051908101604052809291908181526020018280546200146690620024fa565b8015620014b75780601f106200148b57610100808354040283529160200191620014b7565b820191906000526020600020905b8154815290600101906020018083116200149957829003601f168201915b50505050508152602001906001019062001416565b60085460009060ff1615620014e5575060085460ff1690565b6040517f667f9d70000000000000000000000000000000000000000000000000000000008152737109709ecfa91a80626ff3989d68f67f5b1dd12d600482018190527f6661696c65640000000000000000000000000000000000000000000000000000602483015260009163667f9d7090604401602060405180830381865afa15801562001577573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200159d919062002733565b1415905090565b620015ae620011ab565b6040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce567000000000000000000000000000000000000000000000000000000001790528251601281830181905284518083039093018352818501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d9263b96213e49262001692927f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d89291906044016200254f565b600060405180830381600087803b158015620016ad57600080fd5b505af1158015620016c2573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f313ce56700000000000000000000000000000000000000000000000000000000179052825160ff87168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e49350620017aa927f1b56e27094b67facb247d55c7c05912fc4cbffd28f63f412fcdd194991f8db489291906044016200254f565b600060405180830381600087803b158015620017c557600080fd5b505af1158015620017da573d6000803e3d6000fd5b5050604080517f01ffc9a70000000000000000000000000000000000000000000000000000000060248083018290528351808403909101815260449283018452602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690931790925283518a15158184015284518082039093018352808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e49450620018d2937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893919291016200254f565b600060405180830381600087803b158015620018ed57600080fd5b505af115801562001902573d6000803e3d6000fd5b5050604080517f1d1d8b63000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518915158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001a16937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001a3157600080fd5b505af115801562001a46573d6000803e3d6000fd5b5050604080517fec4fc8e3000000000000000000000000000000000000000000000000000000006024808301919091528251808303909101815260449182018352602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a70000000000000000000000000000000000000000000000000000000017905283518815158183015284518082039092018252808501948590527fb96213e400000000000000000000000000000000000000000000000000000000909452737109709ecfa91a80626ff3989d68f67f5b1dd12d955063b96213e4945062001b5a937f45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d893016200254f565b600060405180830381600087803b15801562001b7557600080fd5b505af115801562001b8a573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8c168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001c79927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001c9457600080fd5b505af115801562001ca9573d6000803e3d6000fd5b50506040805160048152602481018252602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f316b373900000000000000000000000000000000000000000000000000000000179052825173ffffffffffffffffffffffffffffffffffffffff8b168183015283518082039092018252808401938490527fb96213e400000000000000000000000000000000000000000000000000000000909352737109709ecfa91a80626ff3989d68f67f5b1dd12d945063b96213e4935062001d98927342000000000000000000000000000000000000129291906044016200254f565b600060405180830381600087803b15801562001db357600080fd5b505af115801562001dc8573d6000803e3d6000fd5b5050601e546040517f248391ff00000000000000000000000000000000000000000000000000000000815273e6a7a45f334393093061116b197e3240065ff2d86004820152737c05912fc4cbffd28f63f412fcdd194991f8db486024820152606460448201819052935061010090910473ffffffffffffffffffffffffffffffffffffffff16915063248391ff908301600060405180830381600087803b15801562001e7357600080fd5b505af192505050801562001e85575060015b62001ece578573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160362001ec85762001ec86200259e565b62001f0c565b8573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161462001f0c5762001f0c6200259e565b50505050505050565b60606015805480602002602001604051908101604052809291908181526020018280548015620003e85760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311620003bc575050505050905090565b60008160405160200162001f9991906200274d565b604051602081830303815290604052805190602001208360405160200162001fc291906200274d565b6040516020818303038152906040528051906020012014905092915050565b6040517f515361f600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff808416600483015282166024820152737109709ecfa91a80626ff3989d68f67f5b1dd12d9063515361f69060440160006040518083038186803b1580156200206357600080fd5b505afa15801562002078573d6000803e3d6000fd5b505050505050565b613623806200276383390190565b6107958062005d8683390190565b6020808252825182820181905260009190848201906040850190845b81811015620020ec57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101620020b8565b50909695505050505050565b60005b8381101562002115578181015183820152602001620020fb565b8381111562000def5750506000910152565b6000815180845262002141816020860160208601620020f8565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602080825282518282018190526000919060409081850190600581811b8701840188860187805b8581101562002272577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08b85030187528251805173ffffffffffffffffffffffffffffffffffffffff1685528901518985018990528051898601819052908a0190606081881b870181019190870190855b818110156200225b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08985030183526200224884865162002127565b948e01949350918d01916001016200220b565b505050978a0197945050918801916001016200219a565b50919a9950505050505050505050565b803560ff811681146200229457600080fd5b919050565b60008060408385031215620022ad57600080fd5b620022b88362002282565b9150620022c86020840162002282565b90509250929050565b60006020808301818452808551808352604092508286019150828160051b8701018488016000805b84811015620023bc578984037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00186528251805173ffffffffffffffffffffffffffffffffffffffff168552880151888501889052805188860181905290890190839060608701905b80831015620023a65783517fffffffff00000000000000000000000000000000000000000000000000000000168252928b019260019290920191908b019062002362565b50978a01979550505091870191600101620022f9565b50919998505050505050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101562002442577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526200242f85835162002127565b94509285019290850190600101620023f2565b5092979650505050505050565b73ffffffffffffffffffffffffffffffffffffffff811681146200247257600080fd5b50565b803580151581146200229457600080fd5b600080600080600060a086880312156200249f57600080fd5b8535620024ac816200244f565b94506020860135620024be816200244f565b9350620024ce6040870162002475565b9250620024de6060870162002475565b9150620024ee6080870162002475565b90509295509295909350565b600181811c908216806200250f57607f821691505b60208210810362002549577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b73ffffffffffffffffffffffffffffffffffffffff8416815260606020820152600062002580606083018562002127565b828103604084015262002594818562002127565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052600160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156200260f57600080fd5b815167ffffffffffffffff808211156200262857600080fd5b818401915084601f8301126200263d57600080fd5b815181811115620026525762002652620025cd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156200269b576200269b620025cd565b81604052828152876020848701011115620026b557600080fd5b620026c8836020830160208801620020f8565b979650505050505050565b600060208284031215620026e657600080fd5b8151620026f3816200244f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff831681526040602082015260006200272b604083018462002127565b949350505050565b6000602082840312156200274657600080fd5b5051919050565b602081526000620026f360208301846200212756fe60806040523480156200001157600080fd5b506200001e600062000024565b62000217565b600054610100900460ff1615808015620000455750600054600160ff909116105b8062000075575062000062306200016d60201b6200045a1760201c565b15801562000075575060005460ff166001145b620000de5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b6000805460ff19166001179055801562000102576000805461ff0019166101001790555b62000122734200000000000000000000000000000000000007836200017c565b801562000169576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6001600160a01b03163b151590565b600054610100900460ff16620001e95760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620000d5565b600380546001600160a01b039384166001600160a01b03199182161790915560048054929093169116179055565b6133fc80620002276000396000f3fe60806040526004361061012d5760003560e01c80635c975abb116100a5578063927ede2d11610074578063c4d66de811610059578063c4d66de8146103fa578063c89701a21461041a578063e11013dd1461044757600080fd5b8063927ede2d146103bc578063a3a79548146103e757600080fd5b80635c975abb1461033a5780637f46ddb21461027a57806387087623146103565780638f601f661461037657600080fd5b806332b7006d116100fc5780633cb747bf116100e15780633cb747bf146102cb578063540abf73146102f857806354fd4d501461031857600080fd5b806332b7006d1461026757806336c717c11461027a57600080fd5b80630166a07a1461020157806309fc8843146102215780631635f5fd14610234578063248391ff1461024757600080fd5b366101fc57333b156101c6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084015b60405180910390fd5b6101fa73deaddeaddeaddeaddeaddeaddeaddeaddead000033333462030d4060405180602001604052806000815250610476565b005b600080fd5b34801561020d57600080fd5b506101fa61021c366004612d0c565b610551565b6101fa61022f366004612dbd565b6108f3565b6101fa610242366004612e10565b6109ca565b34801561025357600080fd5b506101fa610262366004612e83565b610eb1565b6101fa610275366004612ec4565b61104a565b34801561028657600080fd5b5060045473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156102d757600080fd5b506003546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b34801561030457600080fd5b506101fa610313366004612f18565b6111b9565b34801561032457600080fd5b5061032d6111fe565b6040516102c29190613005565b34801561034657600080fd5b50604051600081526020016102c2565b34801561036257600080fd5b506101fa610371366004613018565b61125e565b34801561038257600080fd5b506103ae61039136600461309b565b600260209081526000928352604080842090915290825290205481565b6040519081526020016102c2565b3480156103c857600080fd5b5060035473ffffffffffffffffffffffffffffffffffffffff166102a1565b6101fa6103f5366004613018565b611332565b34801561040657600080fd5b506101fa6104153660046130d4565b61140b565b34801561042657600080fd5b506004546102a19073ffffffffffffffffffffffffffffffffffffffff1681565b6101fa6104553660046130f1565b6115b4565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b7fffffffffffffffffffffffff215221522152215221522152215221522153000073ffffffffffffffffffffffffffffffffffffffff8716016104c5576104c085858585856115fd565b610549565b60008673ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015610512573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105369190613154565b90506105478782888888888861185c565b505b505050505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610624575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa1580156105e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061060c9190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b6106d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b6106df87611c15565b1561082d576106ee8787611c77565b6107a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f40c10f1900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152602482018590528816906340c10f1990604401600060405180830381600087803b15801561081057600080fd5b505af1158015610824573d6000803e3d6000fd5b505050506108af565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a168352929052205461086b9084906131a0565b73ffffffffffffffffffffffffffffffffffffffff8089166000818152600260209081526040808320948c16835293905291909120919091556108af908585611d97565b610547878787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611e6b92505050565b333b15610982576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6109c53333348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b505050565b60035473ffffffffffffffffffffffffffffffffffffffff1633148015610a9d575060048054600354604080517f6e296e45000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff938416949390921692636e296e459282820192602092908290030181865afa158015610a61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a859190613154565b73ffffffffffffffffffffffffffffffffffffffff16145b610b4f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604160248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20746865206f7468657220627269646760648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a4016101bd565b610b57611ef9565b15610be4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414610c73576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f5374616e646172644272696467653a20616d6f756e742073656e7420646f657360448201527f206e6f74206d6174636820616d6f756e7420726571756972656400000000000060648201526084016101bd565b3073ffffffffffffffffffffffffffffffffffffffff851603610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f207360448201527f656c66000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b60035473ffffffffffffffffffffffffffffffffffffffff90811690851603610dc3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f5374616e646172644272696467653a2063616e6e6f742073656e6420746f206d60448201527f657373656e67657200000000000000000000000000000000000000000000000060648201526084016101bd565b610e0585858585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611f3892505050565b6000610e22855a8660405180602001604052806000815250611fd9565b905080610549576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f5374616e646172644272696467653a20455448207472616e736665722066616960448201527f6c6564000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b610ebb8383611ff1565b6040517f9dc29fac0000000000000000000000000000000000000000000000000000000081523360048201526024810182905273ffffffffffffffffffffffffffffffffffffffff841690639dc29fac90604401600060405180830381600087803b158015610f2957600080fd5b505af1158015610f3d573d6000803e3d6000fd5b50506040517f40c10f190000000000000000000000000000000000000000000000000000000081523360048201526024810184905273ffffffffffffffffffffffffffffffffffffffff851692506340c10f199150604401600060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050503373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167ff98522c4d7ccb9de6d7bb8395a567bd90003fe876d577e4d0fd4b53e1ddfedf88460405161103d91815260200190565b60405180910390a4505050565b333b156110d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b6110e1611ef9565b1561116e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b6111b2853333878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b5050505050565b61054787873388888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b606061123a60408051808201909152600d81527f312e31312e312d626574612e3100000000000000000000000000000000000000602082015290565b60405160200161124a91906131b7565b604051602081830303815290604052905090565b333b156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2066756e6374696f6e2063616e206f6e6c60448201527f792062652063616c6c65642066726f6d20616e20454f4100000000000000000060648201526084016101bd565b61054986863333888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061185c92505050565b61133a611ef9565b156113c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c325374616e646172644272696467653a206e6f7420737570706f727465642060448201527f7769746820637573746f6d2067617320746f6b656e000000000000000000000060648201526084016101bd565b610549863387878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061047692505050565b600054610100900460ff161580801561142b5750600054600160ff909116105b806114455750303b158015611445575060005460ff166001145b6114d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016101bd565b600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561152f57600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b61154d7342000000000000000000000000000000000000078361212e565b80156115b057600080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b5050565b6115f73385348686868080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506115fd92505050565b50505050565b611605611ef9565b15611692576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f5374616e646172644272696467653a2063616e6e6f742062726964676520455460448201527f48207769746820637573746f6d2067617320746f6b656e00000000000000000060648201526084016101bd565b823414611721576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f5374616e646172644272696467653a206272696467696e6720455448206d757360448201527f7420696e636c7564652073756666696369656e74204554482076616c7565000060648201526084016101bd565b61172d85858584612218565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9287929116907f1635f5fd0000000000000000000000000000000000000000000000000000000090611790908b908b9086908a906024016131f8565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e086901b909216825261182392918890600401613241565b6000604051808303818588803b15801561183c57600080fd5b505af1158015611850573d6000803e3d6000fd5b50505050505050505050565b34156118ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5374616e646172644272696467653a2063616e6e6f742073656e642076616c7560448201527f650000000000000000000000000000000000000000000000000000000000000060648201526084016101bd565b6118f387611c15565b15611a41576119028787611c77565b6119b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604a60248201527f5374616e646172644272696467653a2077726f6e672072656d6f746520746f6b60448201527f656e20666f72204f7074696d69736d204d696e7461626c65204552433230206c60648201527f6f63616c20746f6b656e00000000000000000000000000000000000000000000608482015260a4016101bd565b6040517f9dc29fac00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff868116600483015260248201859052881690639dc29fac90604401600060405180830381600087803b158015611a2457600080fd5b505af1158015611a38573d6000803e3d6000fd5b50505050611ad5565b611a6373ffffffffffffffffffffffffffffffffffffffff88168630866122b9565b73ffffffffffffffffffffffffffffffffffffffff8088166000908152600260209081526040808320938a1683529290522054611aa1908490613286565b73ffffffffffffffffffffffffffffffffffffffff8089166000908152600260209081526040808320938b16835292905220555b611ae3878787878786612317565b60035460045460405173ffffffffffffffffffffffffffffffffffffffff92831692633dbb202b9216907f0166a07a0000000000000000000000000000000000000000000000000000000090611b47908b908d908c908c908c908b9060240161329e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009485161790525160e085901b9092168252611bda92918790600401613241565b600060405180830381600087803b158015611bf457600080fd5b505af1158015611c08573d6000803e3d6000fd5b5050505050505050505050565b6000611c41827f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b80611c715750611c71827fec4fc8e3000000000000000000000000000000000000000000000000000000006123a5565b92915050565b6000611ca3837f1d1d8b63000000000000000000000000000000000000000000000000000000006123a5565b15611d4c578273ffffffffffffffffffffffffffffffffffffffff1663c01e1bd66040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d179190613154565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149050611c71565b8273ffffffffffffffffffffffffffffffffffffffff1663d6c0b2c46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf3573d6000803e3d6000fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526109c59084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526123c8565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611ee3939291906132f9565b60405180910390a46105498686868686866124d4565b600080611f0461255c565b5073ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141592915050565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fb0444523268717a02698be47d0803aa7468c00acbed2f8bd93a0459cde61dd89868686604051611fc5939291906132f9565b60405180910390a46115f7848484846125ea565b6000806000835160208501868989f195945050505050565b8073ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561203c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120609190613348565b60ff168273ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d29190613348565b60ff161461210c576040517fd25598a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61211582611c15565b15612124576115b08282612657565b6115b08183612657565b600054610100900460ff166121c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201527f6e697469616c697a696e6700000000000000000000000000000000000000000060648201526084016101bd565b6003805473ffffffffffffffffffffffffffffffffffffffff9384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560048054929093169116179055565b8373ffffffffffffffffffffffffffffffffffffffff1673deaddeaddeaddeaddeaddeaddeaddeaddead000073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e8686866040516122a5939291906132f9565b60405180910390a46115f7848484846128a4565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526115f79085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611de9565b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f73d170910aba9e6d50b102db522b1dbcd796216f5128b445aa2135272886497e86868660405161238f939291906132f9565b60405180910390a4610549868686868686612903565b60006123b08361297b565b80156123c157506123c183836129df565b9392505050565b600061242a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612aae9092919063ffffffff16565b8051909150156109c557808060200190518101906124489190613363565b6109c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101bd565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167fd59c65b35445225835c83f50b6ede06a7be047d22e357073e250d9af537518cd86868660405161254c939291906132f9565b60405180910390a4505050505050565b60008073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16634397dfef6040518163ffffffff1660e01b81526004016040805180830381865afa1580156125bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125e19190613385565b90939092509050565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f31b2166ff604fc5672ea5df08a78081d2bc6d746cadce880747f3643d819e83d84846040516126499291906133ba565b60405180910390a350505050565b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000129063316b373990602401602060405180830381865afa1580156126d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126fc9190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661274b576040517fb3d370d400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f316b373900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526000907342000000000000000000000000000000000000269063316b373990602401602060405180830381865afa1580156127cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127f09190613154565b905073ffffffffffffffffffffffffffffffffffffffff811661283f576040517f7acfd45300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146115f7576040517f8686656d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f2849b43074093a05396b6f2a937dee8565b15a48a7b3d4bffb732a5017380af584846040516126499291906133ba565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f7ff126db8024424bbfd9826e8ab82ff59136289ea440b04b39a0df1b03b9cabf86868660405161254c939291906132f9565b60006129a7827f01ffc9a7000000000000000000000000000000000000000000000000000000006129df565b8015611c7157506129d8827fffffffff000000000000000000000000000000000000000000000000000000006129df565b1592915050565b604080517fffffffff000000000000000000000000000000000000000000000000000000008316602480830191909152825180830390910181526044909101909152602080820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825160009392849283928392918391908a617530fa92503d91506000519050828015612a97575060208210155b8015612aa35750600081115b979650505050505050565b6060612abd8484600085612ac5565b949350505050565b606082471015612b57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101bd565b73ffffffffffffffffffffffffffffffffffffffff85163b612bd5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101bd565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051612bfe91906133d3565b60006040518083038185875af1925050503d8060008114612c3b576040519150601f19603f3d011682016040523d82523d6000602084013e612c40565b606091505b5091509150612aa382828660608315612c5a5750816123c1565b825115612c6a5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101bd9190613005565b73ffffffffffffffffffffffffffffffffffffffff81168114612cc057600080fd5b50565b60008083601f840112612cd557600080fd5b50813567ffffffffffffffff811115612ced57600080fd5b602083019150836020828501011115612d0557600080fd5b9250929050565b600080600080600080600060c0888a031215612d2757600080fd5b8735612d3281612c9e565b96506020880135612d4281612c9e565b95506040880135612d5281612c9e565b94506060880135612d6281612c9e565b93506080880135925060a088013567ffffffffffffffff811115612d8557600080fd5b612d918a828b01612cc3565b989b979a50959850939692959293505050565b803563ffffffff81168114612db857600080fd5b919050565b600080600060408486031215612dd257600080fd5b612ddb84612da4565b9250602084013567ffffffffffffffff811115612df757600080fd5b612e0386828701612cc3565b9497909650939450505050565b600080600080600060808688031215612e2857600080fd5b8535612e3381612c9e565b94506020860135612e4381612c9e565b935060408601359250606086013567ffffffffffffffff811115612e6657600080fd5b612e7288828901612cc3565b969995985093965092949392505050565b600080600060608486031215612e9857600080fd5b8335612ea381612c9e565b92506020840135612eb381612c9e565b929592945050506040919091013590565b600080600080600060808688031215612edc57600080fd5b8535612ee781612c9e565b945060208601359350612efc60408701612da4565b9250606086013567ffffffffffffffff811115612e6657600080fd5b600080600080600080600060c0888a031215612f3357600080fd5b8735612f3e81612c9e565b96506020880135612f4e81612c9e565b95506040880135612f5e81612c9e565b945060608801359350612f7360808901612da4565b925060a088013567ffffffffffffffff811115612d8557600080fd5b60005b83811015612faa578181015183820152602001612f92565b838111156115f75750506000910152565b60008151808452612fd3816020860160208601612f8f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006123c16020830184612fbb565b60008060008060008060a0878903121561303157600080fd5b863561303c81612c9e565b9550602087013561304c81612c9e565b94506040870135935061306160608801612da4565b9250608087013567ffffffffffffffff81111561307d57600080fd5b61308989828a01612cc3565b979a9699509497509295939492505050565b600080604083850312156130ae57600080fd5b82356130b981612c9e565b915060208301356130c981612c9e565b809150509250929050565b6000602082840312156130e657600080fd5b81356123c181612c9e565b6000806000806060858703121561310757600080fd5b843561311281612c9e565b935061312060208601612da4565b9250604085013567ffffffffffffffff81111561313c57600080fd5b61314887828801612cc3565b95989497509550505050565b60006020828403121561316657600080fd5b81516123c181612c9e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156131b2576131b2613171565b500390565b600082516131c9818460208701612f8f565b7f2b696e7465726f70000000000000000000000000000000000000000000000000920191825250600801919050565b600073ffffffffffffffffffffffffffffffffffffffff8087168352808616602084015250836040830152608060608301526132376080830184612fbb565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff841681526060602082015260006132706060830185612fbb565b905063ffffffff83166040830152949350505050565b6000821982111561329957613299613171565b500190565b600073ffffffffffffffffffffffffffffffffffffffff80891683528088166020840152808716604084015280861660608401525083608083015260c060a08301526132ed60c0830184612fbb565b98975050505050505050565b73ffffffffffffffffffffffffffffffffffffffff8416815282602082015260606040820152600061332e6060830184612fbb565b95945050505050565b805160ff81168114612db857600080fd5b60006020828403121561335a57600080fd5b6123c182613337565b60006020828403121561337557600080fd5b815180151581146123c157600080fd5b6000806040838503121561339857600080fd5b82516133a381612c9e565b91506133b160208401613337565b90509250929050565b828152604060208201526000612abd6040830184612fbb565b600082516133e5818460208701612f8f565b919091019291505056fea164736f6c634300080f000a608060405260405161079538038061079583398101604081905261002291610314565b61002e82826000610035565b5050610431565b61003e8361006b565b60008251118061004b5750805b156100665761006483836100ab60201b6100291760201c565b505b505050565b610074816100d7565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100d0838360405180606001604052806027815260200161076e602791396101a9565b9392505050565b6100ea8161028760201b6100551760201c565b6101515760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b806101887f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b61029660201b6100711760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b60606001600160a01b0384163b6102115760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b6064820152608401610148565b600080856001600160a01b03168560405161022c91906103e2565b600060405180830381855af49150503d8060008114610267576040519150601f19603f3d011682016040523d82523d6000602084013e61026c565b606091505b50909250905061027d828286610299565b9695505050505050565b6001600160a01b03163b151590565b90565b606083156102a85750816100d0565b8251156102b85782518084602001fd5b8160405162461bcd60e51b815260040161014891906103fe565b634e487b7160e01b600052604160045260246000fd5b60005b838110156103035781810151838201526020016102eb565b838111156100645750506000910152565b6000806040838503121561032757600080fd5b82516001600160a01b038116811461033e57600080fd5b60208401519092506001600160401b038082111561035b57600080fd5b818501915085601f83011261036f57600080fd5b815181811115610381576103816102d2565b604051601f8201601f19908116603f011681019083821181831017156103a9576103a96102d2565b816040528281528860208487010111156103c257600080fd5b6103d38360208301602088016102e8565b80955050505050509250929050565b600082516103f48184602087016102e8565b9190910192915050565b602081526000825180602084015261041d8160408501602087016102e8565b601f01601f19169190910160400192915050565b61032e806104406000396000f3fe60806040523661001357610011610017565b005b6100115b610027610022610074565b6100b9565b565b606061004e83836040518060600160405280602781526020016102fb602791396100dd565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b90565b60006100b47f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e8080156100d8573d6000f35b3d6000fd5b606073ffffffffffffffffffffffffffffffffffffffff84163b610188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e7472616374000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516101b0919061028d565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b509150915061020082828661020a565b9695505050505050565b6060831561021957508161004e565b8251156102295782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161017f91906102a9565b60005b83811015610278578181015183820152602001610260565b83811115610287576000848401525b50505050565b6000825161029f81846020870161025d565b9190910192915050565b60208152600082518060208401526102c881604085016020870161025d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c634300080f000a + + + ( 0x1e |-> 0x2e234dae75c793f67a35089c9d99245e1c58470b00 ) + + + .Map + + + .Map + + + 0x3 + + + ( + + 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + + + + 0xe6a7a45f334393093061116b197e3240065ff2d8 + + + 0x0 + + + 0x00 + + + .Map + + + .Map + + + .Map + + + 0x0 + + ) ) ) ) ) ) + + ... + + + ... + + + + + false + + + false + + ... + + + + false + + ... + + + + false + + ... + + + + false + + + false + + ... + + + + false + + + false + + + .List + + + .List + + + + + + 0x4200000000000000000000000000000000000012 + + + ( 0x316b3739 |-> #buf ( 0x20 , VV1__toRemoteAddress_114b9705:Int ) ) + + + + 0x7c05912fc4cbffd28f63f412fcdd194991f8db48 + + + ( 0x313ce567 |-> 0x0000000000000000000000000000000000000000000000000000000000000012 ) + + + + 0xe6a7a45f334393093061116b197e3240065ff2d8 + + + ( ( 0x313ce567 |-> 0x0000000000000000000000000000000000000000000000000000000000000012 ) + ( ( 0x01ffc9a701ffc9a700000000000000000000000000000000000000000000000000000000 |-> #buf ( 0x20 , VV2__supportsIERC165_114b9705:Int ) ) + ( ( 0x01ffc9a71d1d8b6300000000000000000000000000000000000000000000000000000000 |-> #buf ( 0x20 , VV3__supportsILegacyMintableERC20_114b9705:Int ) ) + ( 0x01ffc9a7ec4fc8e300000000000000000000000000000000000000000000000000000000 |-> #buf ( 0x20 , VV4__supportsIOptimismMintableERC20_114b9705:Int ) ) ) ) ) + + + + + .MockFunctionCellMap + + + + + false + + + false + + + false + + + false + + + false + + + .List + + + + ... + +#And ( { true #Equals 0x0 <=Int CALLER_ID:Int } +#And ( { true #Equals 0x0 <=Int ORIGIN_ID:Int } +#And ( { true #Equals 0x1000000 Date: Thu, 12 Sep 2024 18:23:17 -0300 Subject: [PATCH 48/56] fix: zero address check on id three test --- .../test/properties/kontrol/L2StandardBridgeInterop.k.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol b/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol index 4f6ea9971957..5b51fb513727 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol @@ -98,9 +98,12 @@ contract L2StandardBridgeInteropKontrol is Test, KontrolCheats { /* Action */ try l2StandardBridgeInterop.convert(from, to, _randomAmount) { /* Postconditions */ + // Assume the addresses are not zero and they match + assert(_fromRemoteAddress != address(0)); assert(_fromRemoteAddress == _toRemoteAddress); } catch { - assert(_fromRemoteAddress != _toRemoteAddress); + // Assert the addresses differ or that they are both zero + assert(_fromRemoteAddress != _toRemoteAddress || _fromRemoteAddress == address(0)); } } From 413ae97ea6a00cb23d9d7b7c019577b774d51737 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Fri, 13 Sep 2024 12:02:30 -0300 Subject: [PATCH 49/56] chore: update tackled properties and polish natspec --- packages/contracts-bedrock/test/properties/PROPERTIES.md | 6 +++--- .../test/properties/kontrol/OptimismSuperchainERC20.k.sol | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md index f6876df77469..748d9c306266 100644 --- a/packages/contracts-bedrock/test/properties/PROPERTIES.md +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -77,14 +77,14 @@ legend: | id | milestone | description | kontrol | medusa | | --- | --------- | ------------------------------------------------------------------------------------------ | ------- | ------ | | 6 | SupERC20 | calls to sendERC20 succeed as long as caller has enough balance | [x] | [ ] | -| 7 | SupERC20 | calls to relayERC20 always succeed as long as the sender and cross-domain caller are valid | **[~]** | [ ] | +| 7 | SupERC20 | calls to relayERC20 always succeed as long as the sender and cross-domain caller are valid | **[x]** | [ ] | ## Variable transition | id | milestone | description | kontrol | medusa | | --- | ------------------- | ------------------------------------------------------------------------------------------------- | ------- | ------ | -| 8 | SupERC20 | sendERC20 with a value of zero does not modify accounting | [x] | [ ] | -| 9 | SupERC20 | relayERC20 with a value of zero does not modify accounting | [x] | [ ] | +| 8 | SupERC20 | sendERC20 with a value of zero does not modify accounting | [:(] | [ ] | +| 9 | SupERC20 | relayERC20 with a value of zero does not modify accounting | [:(] | [ ] | | 10 | SupERC20 | sendERC20 decreases the token's totalSupply in the source chain exactly by the input amount | [x] | [ ] | | 11 | SupERC20 | relayERC20 increases the token's totalSupply in the destination chain exactly by the input amount | [x] | [ ] | | 12 | Liquidity Migration | supertoken total supply only increases on calls to mint() by the L2toL2StandardBridge | [x] | [~] | diff --git a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol index 64cc8099e28c..12847065b92b 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol @@ -10,6 +10,7 @@ import { InitialState } from "./deployments/InitialState.sol"; contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { event CrossDomainMessageSender(address _sender); + /// @notice Use this function instead of `setUp()` for performance reasons when running the proofs with Kontrol function setUpInlined() public { superchainERC20Impl = OptimismSuperchainERC20(superchainERC20ImplAddress); sourceToken = OptimismSuperchainERC20(sourceTokenAddress); @@ -81,7 +82,7 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { } /// @custom:property-id 7 - /// @custom:property Calls to relayERC20 always succeed as long as the sender the cross-domain caller are valid + /// @custom:property Calls to relayERC20 always succeed as long as the sender and the cross-domain caller are valid function prove_relayERC20OnlyFromL2ToL2Messenger( address _crossDomainSender, address _sender, @@ -99,7 +100,6 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(notBuiltinAddress(_to)); vm.assume(notBuiltinAddress(_sender)); - // kevm.symbolicStorage(address(MESSENGER)); MESSENGER.forTest_setCustomCrossDomainSender(_crossDomainSender); vm.prank(_sender); @@ -117,6 +117,7 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /// @custom:property-id 8 /// @custom:property `sendERC20` with a value of zero does not modify accounting + /// @custom:property-not-tested The proof fails - probably needs some fixes through lemmas and node pruning function prove_sendERC20ZeroCall(address _from, address _to, uint256 _chainId) public { setUpInlined(); @@ -144,6 +145,7 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { /// @custom:property-id 9 /// @custom:property `relayERC20` with a value of zero does not modify accounting + /// @custom:property-not-tested The proof fails - probably needs some fixes through lemmas and node pruning function prove_relayERC20ZeroCall(address _from, address _to) public { setUpInlined(); From 984947cadf415cc4de1bba2b98e97178b53fdc9f Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Fri, 13 Sep 2024 20:05:47 -0300 Subject: [PATCH 50/56] feat: write test for property 5 * refactor: update setup * chore: create optimism superchain erc20 mock contract with compatible compiler version * refactor: update 3 and 4 properties tests --- .../kontrol/L2StandardBridgeInterop.k.sol | 258 +++++++++++++----- .../helpers/OptimismSuperchainERC20Mock.sol | 192 +++++++++++++ 2 files changed, 375 insertions(+), 75 deletions(-) create mode 100644 packages/contracts-bedrock/test/properties/kontrol/helpers/OptimismSuperchainERC20Mock.sol diff --git a/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol b/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol index 5b51fb513727..3f2d13a12bf2 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.15; import { Predeploys } from "src/libraries/Predeploys.sol"; import { L2StandardBridgeInterop } from "src/L2/L2StandardBridgeInterop.sol"; -import { L2StandardBridge } from "src/L2/L2StandardBridge.sol"; import { Test } from "forge-std/Test.sol"; import { KontrolCheats } from "kontrol-cheatcodes/KontrolCheats.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; @@ -14,21 +13,48 @@ import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol import { ILegacyMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; import { IOptimismERC20Factory } from "src/L2/interfaces/IOptimismERC20Factory.sol"; import { IOptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; +import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; +import { OptimismSuperchainERC20Mock } from "./helpers/OptimismSuperchainERC20Mock.sol"; + +import "forge-std/Test.sol"; contract L2StandardBridgeInteropKontrol is Test, KontrolCheats { - L2StandardBridgeInterop public l2StandardBridgeInterop; - address payable public constant otherBridge = payable(address(uint160(uint256(keccak256("otherBridge"))))); - address public constant from = address(uint160(uint256(keccak256("from")))); - address public constant to = address(uint160(uint256(keccak256("to")))); + address payable public constant OTHER_BRIDGE = payable(address(uint160(uint256(keccak256("otherBridge"))))); + address payable public constant REMOTE_TOKEN = payable(address(uint160(uint256(keccak256("remoteToken"))))); + uint256 public constant RANDOM_AMOUNT = 100; + uint256 public constant ZERO_AMOUNT = 0; + uint8 public constant DECIMALS = 18; + L2StandardBridgeInterop public immutable L2_BRIDGE = L2StandardBridgeInterop(payable(Predeploys.L2_STANDARD_BRIDGE)); + string public legacyName = "Legacy"; + string public legacySymbol = "LEGACY"; + string public superName = "Super"; + string public superSymbol = "SUPER"; + + OptimismMintableERC20 public legacyToken; + OptimismSuperchainERC20Mock public superToken; // Not declaring as `setUp` for performance reasons function setUpInlined() public { - l2StandardBridgeInterop = L2StandardBridgeInterop( - payable( - address( - new ERC1967Proxy( - address(new L2StandardBridgeInterop()), - abi.encodeCall(L2StandardBridge.initialize, (StandardBridge(otherBridge))) + // Deploy L2 Standard Bridge Interop and etch it into the L2 Standard Bridge predeploy + address l2StandardBridgeInteropImpl = address(new L2StandardBridgeInterop()); + vm.etch(address(L2_BRIDGE), address(l2StandardBridgeInteropImpl).code); + + // Update the implementation slot and initialize the bridge + bytes32 _implementationSlot = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + vm.store(address(L2_BRIDGE), _implementationSlot, bytes32(uint256(uint160(l2StandardBridgeInteropImpl)))); + L2_BRIDGE.initialize(StandardBridge(OTHER_BRIDGE)); + + // Deploy legacy + legacyToken = new OptimismMintableERC20(address(L2_BRIDGE), REMOTE_TOKEN, legacyName, legacySymbol, DECIMALS); + + // Deploy supertoken + superToken = OptimismSuperchainERC20Mock( + address( + // TODO: Update to beacon proxy + new ERC1967Proxy( + address(new OptimismSuperchainERC20Mock()), + abi.encodeCall( + OptimismSuperchainERC20Mock.initialize, (REMOTE_TOKEN, superName, superSymbol, DECIMALS) ) ) ) @@ -39,116 +65,198 @@ contract L2StandardBridgeInteropKontrol is Test, KontrolCheats { return keccak256(abi.encode(a)) == keccak256(abi.encode(b)); } - // TODO: Remove convert prefix - function prove_convertSetup() public { + /// @notice Check the setup works as expected + function test_convertSetup() public { setUpInlined(); - assert(eqStrings(l2StandardBridgeInterop.version(), "1.11.1-beta.1+interop")); - assertEq(address(l2StandardBridgeInterop.OTHER_BRIDGE()), otherBridge); + + // L2 Standard Bridge Interop checks + assert(address(L2_BRIDGE.OTHER_BRIDGE()) == OTHER_BRIDGE); + assert(eqStrings(L2_BRIDGE.version(), "1.11.1-beta.1+interop")); + + // Legacy token checks + assert(legacyToken.REMOTE_TOKEN() == REMOTE_TOKEN); + assert(legacyToken.BRIDGE() == address(L2_BRIDGE)); + assert(legacyToken.decimals() == DECIMALS); + assert(eqStrings(legacyToken.version(), "1.3.1-beta.1")); + assert(eqStrings(legacyToken.name(), legacyName)); + assert(eqStrings(legacyToken.symbol(), legacySymbol)); + + // Super token checks + assert(eqStrings(superToken.version(), "1.0.0-beta.2")); + assert(superToken.remoteToken() == REMOTE_TOKEN); + assert(eqStrings(superToken.name(), superName)); + assert(eqStrings(superToken.symbol(), superSymbol)); + assert(superToken.decimals() == DECIMALS); } /// @custom:property-id 3 /// @custom:property convert() only allows migrations between tokens representing the same remote asset - function prove_convertOnlyOnSameRemoteAsset( - address _fromRemoteAddress, - address _toRemoteAddress, - bool _supportsIERC165, - bool _supportsILegacyMintableERC20, - bool _supportsIOptimismMintableERC20 + function test_convertOnlyOnSameRemoteAsset( + bool _legacyIsFrom, + address _legacyRemoteAddress, + address _superRemoteAddress, + address _sender ) public { setUpInlined(); /* Preconditions */ - // Mock the decimals of the tokens to the same values so it doesn't revert - uint8 _decimals = 18; - vm.mockCall(from, abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(_decimals)); - vm.mockCall(to, abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(_decimals)); - // Mock the call over `supportsInterface` - not in the scope of the test, but required to avoid a revert - vm.mockCall( - from, - abi.encodeWithSelector(IERC165.supportsInterface.selector, type(IERC165).interfaceId), - abi.encode(_supportsIERC165) - ); - // Mock the call over `supportsInterface` - not in the scope of the test, but required to avoid a revert - vm.mockCall( - from, - abi.encodeWithSelector(IERC165.supportsInterface.selector, type(ILegacyMintableERC20).interfaceId), - abi.encode(_supportsILegacyMintableERC20) - ); - vm.mockCall( - from, - abi.encodeWithSelector(IERC165.supportsInterface.selector, type(IOptimismMintableERC20).interfaceId), - abi.encode(_supportsIOptimismMintableERC20) - ); + vm.assume(_sender != address(0)); // Mock the call over `deployments` for both tokens with the given symbolic remote addresses vm.mockCall( Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, - abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector), - abi.encode(address(_fromRemoteAddress)) + abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector, address(legacyToken)), + abi.encode(address(_legacyRemoteAddress)) ); vm.mockCall( Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, - abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector), - abi.encode(address(_toRemoteAddress)) + abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector, address(superToken)), + abi.encode(address(_superRemoteAddress)) ); - uint256 _randomAmount = 100; - /* Action */ - try l2StandardBridgeInterop.convert(from, to, _randomAmount) { - /* Postconditions */ - // Assume the addresses are not zero and they match - assert(_fromRemoteAddress != address(0)); - assert(_fromRemoteAddress == _toRemoteAddress); - } catch { - // Assert the addresses differ or that they are both zero - assert(_fromRemoteAddress != _toRemoteAddress || _fromRemoteAddress == address(0)); + vm.startPrank(_sender); + + bool success; + if (_legacyIsFrom) { + /* Action */ + // Execute `convert` with `legacyToken` as the `from` token + (success,) = address(L2_BRIDGE).call( + abi.encodeWithSelector( + L2_BRIDGE.convert.selector, + address(legacyToken), + address(superToken), + ZERO_AMOUNT // Amount is not relevant for this test + ) + ); + } else { + // Execute `convert` with `superToken` as the `from` token + (success,) = address(L2_BRIDGE).call( + abi.encodeWithSelector( + L2_BRIDGE.convert.selector, + address(superToken), + address(legacyToken), + ZERO_AMOUNT // Amount is not relevant for this test + ) + ); + } + + /* Preconditions */ + // The property should hold regardless of the order of the tokens + if (success) { + assert(_legacyRemoteAddress != address(0)); + assert(_legacyRemoteAddress == _superRemoteAddress); + } else { + assert(_legacyRemoteAddress != _superRemoteAddress || _legacyRemoteAddress == address(0)); } } /// @custom:property-id 4 /// @custom:property convert() only allows migrations from tokens with the same decimals - function prove_convertOnlyTokenWithSameDecimals(uint8 _decimalsFrom, uint8 _decimalsTo) public { + function test_convertOnlyTokenWithSameDecimals( + bool _fromIsLegacy, + uint8 _decimalsLegacy, + uint8 _decimalsSuper, + address _sender + ) + public + { setUpInlined(); /* Preconditions */ - // Mock the decimals of the tokens with the given symbolic decimals values - vm.mockCall(from, abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(_decimalsFrom)); - vm.mockCall(to, abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(_decimalsTo)); + vm.assume(_sender != address(0)); - // Mock the call over `supportsInterface` - not in the scope of the test, but required to avoid a revert + // Mock calls over `decimals` vm.mockCall( - from, - abi.encodeWithSelector(IERC165.supportsInterface.selector, type(IERC165).interfaceId), - abi.encode(true) + address(legacyToken), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(_decimalsLegacy) ); vm.mockCall( - from, - abi.encodeWithSelector(IERC165.supportsInterface.selector, type(ILegacyMintableERC20).interfaceId), - abi.encode(true) + address(superToken), abi.encodeWithSelector(IERC20Metadata.decimals.selector), abi.encode(_decimalsSuper) ); // Mock the call over `deployments` - not in the scope of the test, but required to avoid a revert - address _randomAddress = address(420); vm.mockCall( Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector), - abi.encode(address(_randomAddress)) + abi.encode(REMOTE_TOKEN) ); vm.mockCall( Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY, abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector), - abi.encode(address(_randomAddress)) + abi.encode(REMOTE_TOKEN) ); - uint256 _randomAmount = 100; + vm.prank(_sender); + + // Using zero amount since it is not relevant for this test + bool _success; + if (_fromIsLegacy) { + /* Action */ + // Execute `convert` with `legacyToken` as the `from` token + (_success,) = address(L2_BRIDGE).call( + abi.encodeWithSelector( + L2_BRIDGE.convert.selector, + address(legacyToken), + address(superToken), + ZERO_AMOUNT // Amount is not relevant for this test + ) + ); + } else { + // Execute `convert` with `superToken` as the `from` token + (_success,) = address(L2_BRIDGE).call( + abi.encodeWithSelector( + L2_BRIDGE.convert.selector, + address(superToken), + address(legacyToken), + ZERO_AMOUNT // Amount is not relevant for this test + ) + ); + } + + /* Preconditions */ + // The property should hold regardless of the order of the tokens + if (_success) assert(_decimalsLegacy == _decimalsSuper); + else assert(_decimalsLegacy != _decimalsSuper); + } + + /// @custom:property-id 5 + /// @custom:property convert() burns the same amount of legacy token that it mints of supertoken, and viceversa + function test_mintAndBurnSameAmount(address _sender, bool _legacyIsFrom, uint256 _amount) public { + setUpInlined(); + + /* Preconditions */ + vm.assume(_sender != address(0)); + // Mock the call over `deployments` - not in the scope of the test, but required to avoid a revert + vm.mockCall( + Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, + abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector), + abi.encode(REMOTE_TOKEN) + ); + vm.mockCall( + Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY, + abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector), + abi.encode(REMOTE_TOKEN) + ); + + // Mint tokens to the sender and get the balances before the conversion + vm.prank(address(L2_BRIDGE)); + if (_legacyIsFrom) legacyToken.mint(_sender, _amount); + else superToken.mint(_sender, _amount); + uint256 legacyBalanceBefore = legacyToken.balanceOf(_sender); + uint256 superBalanceBefore = superToken.balanceOf(_sender); + + vm.prank(_sender); /* Action */ - try l2StandardBridgeInterop.convert(from, to, _randomAmount) { + if (_legacyIsFrom) { + L2_BRIDGE.convert(address(legacyToken), address(superToken), _amount); /* Postconditions */ - assert(_decimalsFrom == _decimalsTo); - } catch { - assert(_decimalsFrom != _decimalsTo); + assert(legacyToken.balanceOf(_sender) == legacyBalanceBefore - _amount); + assert(superToken.balanceOf(_sender) == superBalanceBefore + _amount); + } else { + L2_BRIDGE.convert(address(superToken), address(legacyToken), _amount); + assert(legacyToken.balanceOf(_sender) == legacyBalanceBefore + _amount); + assert(superToken.balanceOf(_sender) == superBalanceBefore - _amount); } } } diff --git a/packages/contracts-bedrock/test/properties/kontrol/helpers/OptimismSuperchainERC20Mock.sol b/packages/contracts-bedrock/test/properties/kontrol/helpers/OptimismSuperchainERC20Mock.sol new file mode 100644 index 000000000000..98db6dcf3eaf --- /dev/null +++ b/packages/contracts-bedrock/test/properties/kontrol/helpers/OptimismSuperchainERC20Mock.sol @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.15; + +import { IOptimismSuperchainERC20Extension } from "src/L2/interfaces/IOptimismSuperchainERC20.sol"; +import { ERC20 } from "@solady/tokens/ERC20.sol"; +import { IL2ToL2CrossDomainMessenger } from "src/L2/interfaces/IL2ToL2CrossDomainMessenger.sol"; +import { ISemver } from "src/universal/interfaces/ISemver.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; +// Changed this imports to a lower compiler version in order to be compatible wiht 0.8.15 +import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; +import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; + +/// @notice Thrown when attempting to relay a message and the function caller (msg.sender) is not +/// L2ToL2CrossDomainMessenger. +error CallerNotL2ToL2CrossDomainMessenger(); + +/// @notice Thrown when attempting to relay a message and the cross domain message sender is not this +/// OptimismSuperchainERC20. +error InvalidCrossDomainSender(); + +/// @notice Thrown when attempting to mint or burn tokens and the function caller is not the StandardBridge. +error OnlyBridge(); + +/// @notice Thrown when attempting to mint or burn tokens and the account is the zero address. +error ZeroAddress(); + +/// @custom:proxied true +/// @title OptimismSuperchainERC20 +/// @notice OptimismSuperchainERC20 is a standard extension of the base ERC20 token contract that unifies ERC20 token +/// bridging to make it fungible across the Superchain. This construction allows the L2StandardBridge to burn +/// and mint tokens. This makes it possible to convert a valid OptimismMintableERC20 token to a SuperchainERC20 +/// token, turning it fungible and interoperable across the superchain. Likewise, it also enables the inverse +/// conversion path. +/// Moreover, it builds on top of the L2ToL2CrossDomainMessenger for both replay protection and domain binding. +contract OptimismSuperchainERC20Mock is IOptimismSuperchainERC20Extension, ERC20, ISemver, Initializable, ERC165 { + /// @notice Address of the L2ToL2CrossDomainMessenger Predeploy. + address internal immutable MESSENGER = Predeploys.L2_TO_L2_CROSS_DOMAIN_MESSENGER; + + /// @notice Address of the StandardBridge Predeploy. + address internal immutable BRIDGE = Predeploys.L2_STANDARD_BRIDGE; + + /// @notice Storage slot that the OptimismSuperchainERC20Metadata struct is stored at. + /// keccak256(abi.encode(uint256(keccak256("optimismSuperchainERC20.metadata")) - 1)) & ~bytes32(uint256(0xff)); + bytes32 internal constant OPTIMISM_SUPERCHAIN_ERC20_METADATA_SLOT = + 0x07f04e84143df95a6373fcf376312ae41da81a193a3089073a54f47a74d8fb00; + + /// @notice Storage struct for the OptimismSuperchainERC20 metadata. + /// @custom:storage-location erc7201:optimismSuperchainERC20.metadata + struct OptimismSuperchainERC20Metadata { + /// @notice Address of the corresponding version of this token on the remote chain. + address remoteToken; + /// @notice Name of the token + string name; + /// @notice Symbol of the token + string symbol; + /// @notice Decimals of the token + uint8 decimals; + } + + /// @notice Returns the storage for the OptimismSuperchainERC20Metadata. + function _getMetadataStorage() private pure returns (OptimismSuperchainERC20Metadata storage _storage) { + assembly { + _storage.slot := OPTIMISM_SUPERCHAIN_ERC20_METADATA_SLOT + } + } + + /// @notice A modifier that only allows the bridge to call + modifier onlyBridge() { + if (msg.sender != BRIDGE) revert OnlyBridge(); + _; + } + + /// @notice Semantic version. + /// @custom:semver 1.0.0-beta.2 + string public constant version = "1.0.0-beta.2"; + + /// @notice Constructs the OptimismSuperchainERC20 contract. + constructor() { + _disableInitializers(); + } + + /// @notice Initializes the contract. + /// @param _remoteToken Address of the corresponding remote token. + /// @param _name ERC20 name. + /// @param _symbol ERC20 symbol. + /// @param _decimals ERC20 decimals. + function initialize( + address _remoteToken, + string memory _name, + string memory _symbol, + uint8 _decimals + ) + external + initializer + { + OptimismSuperchainERC20Metadata storage _storage = _getMetadataStorage(); + _storage.remoteToken = _remoteToken; + _storage.name = _name; + _storage.symbol = _symbol; + _storage.decimals = _decimals; + } + + /// @notice Allows the L2StandardBridge to mint tokens. + /// @param _to Address to mint tokens to. + /// @param _amount Amount of tokens to mint. + function mint(address _to, uint256 _amount) external virtual onlyBridge { + if (_to == address(0)) revert ZeroAddress(); + + _mint(_to, _amount); + + emit Mint(_to, _amount); + } + + /// @notice Allows the L2StandardBridge to burn tokens. + /// @param _from Address to burn tokens from. + /// @param _amount Amount of tokens to burn. + function burn(address _from, uint256 _amount) external virtual onlyBridge { + if (_from == address(0)) revert ZeroAddress(); + + _burn(_from, _amount); + + emit Burn(_from, _amount); + } + + /// @notice Sends tokens to some target address on another chain. + /// @param _to Address to send tokens to. + /// @param _amount Amount of tokens to send. + /// @param _chainId Chain ID of the destination chain. + function sendERC20(address _to, uint256 _amount, uint256 _chainId) external { + if (_to == address(0)) revert ZeroAddress(); + + _burn(msg.sender, _amount); + + bytes memory _message = abi.encodeCall(this.relayERC20, (msg.sender, _to, _amount)); + IL2ToL2CrossDomainMessenger(MESSENGER).sendMessage(_chainId, address(this), _message); + + emit SendERC20(msg.sender, _to, _amount, _chainId); + } + + /// @notice Relays tokens received from another chain. + /// @param _from Address of the msg.sender of sendERC20 on the source chain. + /// @param _to Address to relay tokens to. + /// @param _amount Amount of tokens to relay. + function relayERC20(address _from, address _to, uint256 _amount) external { + if (_to == address(0)) revert ZeroAddress(); + + if (msg.sender != MESSENGER) revert CallerNotL2ToL2CrossDomainMessenger(); + + if (IL2ToL2CrossDomainMessenger(MESSENGER).crossDomainMessageSender() != address(this)) { + revert InvalidCrossDomainSender(); + } + + uint256 source = IL2ToL2CrossDomainMessenger(MESSENGER).crossDomainMessageSource(); + + _mint(_to, _amount); + + emit RelayERC20(_from, _to, _amount, source); + } + + /// @notice Returns the address of the corresponding version of this token on the remote chain. + function remoteToken() public view override returns (address) { + return _getMetadataStorage().remoteToken; + } + + /// @notice Returns the name of the token. + function name() public view virtual override returns (string memory) { + return _getMetadataStorage().name; + } + + /// @notice Returns the symbol of the token. + function symbol() public view virtual override returns (string memory) { + return _getMetadataStorage().symbol; + } + + /// @notice Returns the number of decimals used to get its user representation. + /// For example, if `decimals` equals `2`, a balance of `505` tokens should + /// be displayed to a user as `5.05` (`505 / 10 ** 2`). + /// NOTE: This information is only used for _display_ purposes: it in + /// no way affects any of the arithmetic of the contract, including + /// {IERC20-balanceOf} and {IERC20-transfer}. + function decimals() public view override returns (uint8) { + return _getMetadataStorage().decimals; + } + + /// @notice ERC165 interface check function. + /// @param _interfaceId Interface ID to check. + /// @return Whether or not the interface is supported by this contract. + function supportsInterface(bytes4 _interfaceId) public view virtual override returns (bool) { + return + _interfaceId == type(IOptimismSuperchainERC20Extension).interfaceId || super.supportsInterface(_interfaceId); + } +} From 9c914ef932d1eeab5487a57a1329308953095074 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Mon, 16 Sep 2024 12:31:36 -0300 Subject: [PATCH 51/56] chore: update natspec on debug file --- .../test/properties/FoundryDebugSymbolic.t.sol | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol b/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol index 8fbe8e5c668b..3ec067e25926 100644 --- a/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol +++ b/packages/contracts-bedrock/test/properties/FoundryDebugSymbolic.t.sol @@ -6,7 +6,6 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; import { MockL2ToL2Messenger } from "test/properties/kontrol/helpers/MockL2ToL2Messenger.sol"; import { KontrolBase } from "test/properties/kontrol/KontrolBase.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts-v5/proxy/ERC1967/ERC1967Proxy.sol"; - import "forge-std/Test.sol"; // TODO: File to debug faster with foundry replicating scenarios where the proof failed, needs removal afterwards. @@ -41,7 +40,7 @@ contract FoundryDebugTests is KontrolBase { vm.etch(address(MESSENGER), address(mockL2ToL2Messenger).code); } - /// @notice Check setup works as expected + /// Check setup works as expected function test_proveSetup() public { // Source token assert(remoteToken != address(0)); @@ -66,8 +65,8 @@ contract FoundryDebugTests is KontrolBase { assert(MESSENGER.crossDomainMessageSender() == address(420)); } - /// @custom:property-id 8 - /// @custom:property `sendERC20` with a value of zero does not modify accounting + // debug property-id 8 + // `sendERC20` with a value of zero does not modify accounting function test_proveSendERC20ZeroCall() public { /* Preconditions */ address _from = address(511347974759188522659820409854212399244223280810); @@ -95,8 +94,8 @@ contract FoundryDebugTests is KontrolBase { // TIMESTAMP_CELL = 1073741825 // VV1__to_114b9705 = 376793390874373408599387495934666716005045108769 - /// @custom:property-id 9 - /// @custom:property `relayERC20` with a value of zero does not modify accounting + // debug 9 + // `relayERC20` with a value of zero does not modify accounting function test_proveRelayERC20ZeroCall() public { /* Preconditions */ address _from = address(645326474426547203313410069153905908525362434350); From a4d6cd12f5dfc3399ffdedf28319fb1e45a2643e Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:12:44 -0300 Subject: [PATCH 52/56] feat: test properties 17 and 18 --- .../test/properties/PROPERTIES.md | 4 +- .../kontrol/L2StandardBridgeInterop.k.sol | 52 ++++++++++++++++++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md index 748d9c306266..fc731a8ac65e 100644 --- a/packages/contracts-bedrock/test/properties/PROPERTIES.md +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -97,8 +97,8 @@ legend: | id | milestone | description | kontrol | medusa | | --- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | -| 17 | Liquidity Migration | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | [ ] | -| 18 | Liquidity Migration | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | [ ] | +| 17 | Liquidity Migration | only calls to convert(legacy, super) can increase a supertoken’s total supply and decrease legacy's one across chains | [ ] | [ ] | +| 18 | Liquidity Migration | only calls to convert(super, legacy) can decrease a supertoken’s total supply and increase the legacy's one across chains | [ ] | [ ] | | 19 | Liquidity Migration | sum of supertoken total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | | 20 | SupERC20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | [ ] | | 21 | Liquidity Migration | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [ ] | [ ] | diff --git a/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol b/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol index 3f2d13a12bf2..4f2b1ccb819e 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.15; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { L2StandardBridgeInterop } from "src/L2/L2StandardBridgeInterop.sol"; +import "src/L2/L2StandardBridgeInterop.sol"; import { Test } from "forge-std/Test.sol"; import { KontrolCheats } from "kontrol-cheatcodes/KontrolCheats.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; @@ -227,6 +227,7 @@ contract L2StandardBridgeInteropKontrol is Test, KontrolCheats { /* Preconditions */ vm.assume(_sender != address(0)); + // Mock the call over `deployments` - not in the scope of the test, but required to avoid a revert vm.mockCall( Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, @@ -259,4 +260,53 @@ contract L2StandardBridgeInteropKontrol is Test, KontrolCheats { assert(superToken.balanceOf(_sender) == superBalanceBefore - _amount); } } + + /// @custom:property-id 17 + /// @custom:property Only calls to convert(legacy, super) can increase a supertoken’s total supply + /// and decrease legacy's one across chains + /// @custom:property-id 18 + /// @custom:property Only calls to convert(super, legacy) can decrease a supertoken’s total supply and increase + /// legacy's one across chains + function test_convertUpdatesTotalSupply(bool _legacyIsFrom, address _sender, uint256 _amount) public { + setUpInlined(); + + /* Preconditions */ + vm.assume(_sender != address(0)); + + // Mock the call over `deployments` - not in the scope of the test, but required to avoid a revert + vm.mockCall( + Predeploys.OPTIMISM_MINTABLE_ERC20_FACTORY, + abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector), + abi.encode(REMOTE_TOKEN) + ); + vm.mockCall( + Predeploys.OPTIMISM_SUPERCHAIN_ERC20_FACTORY, + abi.encodeWithSelector(IOptimismERC20Factory.deployments.selector), + abi.encode(REMOTE_TOKEN) + ); + + // Mint tokens to the sender and get the balances before the conversion + vm.prank(address(L2_BRIDGE)); + if (_legacyIsFrom) legacyToken.mint(_sender, _amount); + else superToken.mint(_sender, _amount); + uint256 legacyBalanceBefore = legacyToken.balanceOf(_sender); + uint256 superBalanceBefore = superToken.balanceOf(_sender); + + vm.startPrank(_sender); + /* Action */ + if (_legacyIsFrom) { + L2_BRIDGE.convert(address(legacyToken), address(superToken), _amount); + + /* Postconditions */ + assert(superToken.totalSupply() == superBalanceBefore + _amount); + assert(legacyToken.totalSupply() == legacyBalanceBefore - _amount); + } else { + /* Action */ + L2_BRIDGE.convert(address(superToken), address(legacyToken), _amount); + + /* Postconditions */ + assert(superToken.totalSupply() == superBalanceBefore - _amount); + assert(legacyToken.totalSupply() == legacyBalanceBefore + _amount); + } + } } From 602589f9fef2016c99659b0d2ca55ad82138acf3 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Mon, 16 Sep 2024 22:35:33 -0300 Subject: [PATCH 53/56] chore: update comments and attribution --- .../test/properties/kontrol/OptimismSuperchainERC20.k.sol | 2 +- .../test/properties/kontrol/helpers/RecordStateDiff.sol | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol index 12847065b92b..854ea6353af1 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/OptimismSuperchainERC20.k.sol @@ -67,7 +67,7 @@ contract OptimismSuperchainERC20Kontrol is KontrolBase, InitialState { vm.assume(notBuiltinAddress(_from)); vm.assume(notBuiltinAddress(_to)); - // Can't deal to unsupported cheatcode + // Mint the amount to the caller vm.prank(Predeploys.L2_STANDARD_BRIDGE); sourceToken.mint(_from, _initialBalance); diff --git a/packages/contracts-bedrock/test/properties/kontrol/helpers/RecordStateDiff.sol b/packages/contracts-bedrock/test/properties/kontrol/helpers/RecordStateDiff.sol index a49cb41b6545..5251d4b4d70b 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/helpers/RecordStateDiff.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/helpers/RecordStateDiff.sol @@ -1,4 +1,8 @@ +// This code was originally copied from: +// https://github.com/runtimeverification/kontrol/blob/86451cbdaef8bed0370bf804fa4b545ec8b7a28a/docs/external-computation/test/kontrol/state-diff/record-state-diff/RecordStateDiff.sol +// It has been slightly modified, including changes to the compiler version. // SPDX-License-Identifier: MIT + pragma solidity 0.8.25; import { console2 as console } from "forge-std/console2.sol"; From b714f0e94cb195db1a5ca0a059f2f3b1f8bce6a7 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Tue, 17 Sep 2024 11:47:02 -0300 Subject: [PATCH 54/56] chore: update mock messenger description comment --- .../test/properties/kontrol/helpers/MockL2ToL2Messenger.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol b/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol index a199bfb792c1..82a6ce20c768 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/helpers/MockL2ToL2Messenger.sol @@ -3,10 +3,8 @@ pragma solidity 0.8.25; import "src/L2/L2ToL2CrossDomainMessenger.sol"; import { SafeCall } from "src/libraries/SafeCall.sol"; -import "forge-std/Test.sol"; -// TODO: Try to merge to a single mocked contract used by fuzzing and symbolic invariant tests - only if possible -// and is a low priorty +// Mock contract for the L2ToL2Messenger contract where cross chain atomicity is simulated contract MockL2ToL2Messenger { event CrossDomainMessageSender(address _sender); From 1278f03e953cafb08fa211c4810b1e7c554e347d Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Thu, 19 Sep 2024 16:53:51 -0300 Subject: [PATCH 55/56] fix: conflicts --- packages/contracts-bedrock/kontrol.toml | 3 --- packages/contracts-bedrock/test/properties/PROPERTIES.md | 5 ----- 2 files changed, 8 deletions(-) diff --git a/packages/contracts-bedrock/kontrol.toml b/packages/contracts-bedrock/kontrol.toml index 3cd4fbafa86c..12a3b2e02a4f 100644 --- a/packages/contracts-bedrock/kontrol.toml +++ b/packages/contracts-bedrock/kontrol.toml @@ -42,7 +42,6 @@ use-hex-encoding = false [view-kcfg.default] foundry-project-root = '.' use-hex-encoding = false -<<<<<<< HEAD ## Convert profile @@ -68,5 +67,3 @@ break-on-cheatcodes = false run-constructor = true symbolic-immutables = false schedule = 'CANCUN' -======= ->>>>>>> feat/symbolic-testing diff --git a/packages/contracts-bedrock/test/properties/PROPERTIES.md b/packages/contracts-bedrock/test/properties/PROPERTIES.md index ee1405a38d25..fc731a8ac65e 100644 --- a/packages/contracts-bedrock/test/properties/PROPERTIES.md +++ b/packages/contracts-bedrock/test/properties/PROPERTIES.md @@ -97,13 +97,8 @@ legend: | id | milestone | description | kontrol | medusa | | --- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------ | -<<<<<<< HEAD | 17 | Liquidity Migration | only calls to convert(legacy, super) can increase a supertoken’s total supply and decrease legacy's one across chains | [ ] | [ ] | | 18 | Liquidity Migration | only calls to convert(super, legacy) can decrease a supertoken’s total supply and increase the legacy's one across chains | [ ] | [ ] | -======= -| 17 | Liquidity Migration | only calls to convert(legacy, super) can increase a supertoken’s total supply across chains | [ ] | [ ] | -| 18 | Liquidity Migration | only calls to convert(super, legacy) can decrease a supertoken’s total supply across chains | [ ] | [ ] | ->>>>>>> feat/symbolic-testing | 19 | Liquidity Migration | sum of supertoken total supply across all chains is always <= to convert(legacy, super)- convert(super, legacy) | [ ] | [ ] | | 20 | SupERC20 | tokens sendERC20-ed on a source chain to a destination chain can be relayERC20-ed on it as long as the source chain is in the dependency set of the destination chain | [ ] | [ ] | | 21 | Liquidity Migration | sum of supertoken total supply across all chains is = to convert(legacy, super)- convert(super, legacy) when all cross-chain messages are processed | [ ] | [ ] | From e2a25c716f7ef8174ac8cdeebfa8eb98386e0c83 Mon Sep 17 00:00:00 2001 From: 0xDiscotech <131301107+0xDiscotech@users.noreply.github.com> Date: Thu, 19 Sep 2024 17:07:03 -0300 Subject: [PATCH 56/56] chore: update tests names --- .../properties/kontrol/L2StandardBridgeInterop.k.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol b/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol index 4f2b1ccb819e..5818877af686 100644 --- a/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol +++ b/packages/contracts-bedrock/test/properties/kontrol/L2StandardBridgeInterop.k.sol @@ -66,7 +66,7 @@ contract L2StandardBridgeInteropKontrol is Test, KontrolCheats { } /// @notice Check the setup works as expected - function test_convertSetup() public { + function prove_convertSetup() public { setUpInlined(); // L2 Standard Bridge Interop checks @@ -91,7 +91,7 @@ contract L2StandardBridgeInteropKontrol is Test, KontrolCheats { /// @custom:property-id 3 /// @custom:property convert() only allows migrations between tokens representing the same remote asset - function test_convertOnlyOnSameRemoteAsset( + function prove_convertOnlyOnSameRemoteAsset( bool _legacyIsFrom, address _legacyRemoteAddress, address _superRemoteAddress, @@ -154,7 +154,7 @@ contract L2StandardBridgeInteropKontrol is Test, KontrolCheats { /// @custom:property-id 4 /// @custom:property convert() only allows migrations from tokens with the same decimals - function test_convertOnlyTokenWithSameDecimals( + function prove_convertOnlyTokenWithSameDecimals( bool _fromIsLegacy, uint8 _decimalsLegacy, uint8 _decimalsSuper, @@ -222,7 +222,7 @@ contract L2StandardBridgeInteropKontrol is Test, KontrolCheats { /// @custom:property-id 5 /// @custom:property convert() burns the same amount of legacy token that it mints of supertoken, and viceversa - function test_mintAndBurnSameAmount(address _sender, bool _legacyIsFrom, uint256 _amount) public { + function prove_mintAndBurnSameAmount(address _sender, bool _legacyIsFrom, uint256 _amount) public { setUpInlined(); /* Preconditions */ @@ -267,7 +267,7 @@ contract L2StandardBridgeInteropKontrol is Test, KontrolCheats { /// @custom:property-id 18 /// @custom:property Only calls to convert(super, legacy) can decrease a supertoken’s total supply and increase /// legacy's one across chains - function test_convertUpdatesTotalSupply(bool _legacyIsFrom, address _sender, uint256 _amount) public { + function prove_convertUpdatesTotalSupply(bool _legacyIsFrom, address _sender, uint256 _amount) public { setUpInlined(); /* Preconditions */