diff --git a/.github/workflows/secret_scanner.yaml b/.github/workflows/secret_scanner.yaml index 7d745ae80..2e05cdf57 100644 --- a/.github/workflows/secret_scanner.yaml +++ b/.github/workflows/secret_scanner.yaml @@ -14,4 +14,4 @@ jobs: path: ./ base: ${{ github.event.repository.default_branch }} head: HEAD - extra_args: --debug --only-verified --exclude-globs=zk-tests/src/Cheatcodes.t.sol # TODO: Remove this file once merged \ No newline at end of file + extra_args: --debug --only-verified \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d09ca0342..35e78affd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -89,32 +89,6 @@ jobs: cache-on-failure: true - name: cargo hack run: cargo hack check - - # TODO: This test currently hangs in the CI - # zk-test: - # name: zk-test - # runs-on: ubuntu-22.04-github-hosted-16core - # steps: - # - uses: actions/checkout@v4 - # with: - # submodules: recursive - # ref: ${{ github.event.pull_request.head.sha }} - - # - name: Install Rust - # uses: actions-rust-lang/setup-rust-toolchain@v1 - # with: - # toolchain: nightly-2024-04-28 - - - # - name: Get solc - # run: | - # mkdir /tmp/solc-bin - # wget https://github.com/ethereum/solidity/releases/download/v0.8.24/solc-static-linux -qO /tmp/solc-bin/solc - # chmod +x /tmp/solc-bin/solc - # echo "/tmp/solc-bin" >> $GITHUB_PATH - - # - name: Test ZK VM - # run: RUST_LOG=1 cargo test --package forge --test it --jobs=1 -- zk zk-cargo-test: name: zk-cargo-test @@ -147,27 +121,6 @@ jobs: RUST_BACKTRACE: full TEST_MAINNET_URL: http://localhost:8011 run: cargo test zk - - zk-smoke-test: - name: zk-smoke-test - runs-on: ubuntu-22.04-github-hosted-16core - - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - submodules: recursive - ref: ${{ github.event.pull_request.head.sha }} - - - name: Install Rust - uses: actions-rust-lang/setup-rust-toolchain@v1 - with: - toolchain: nightly-2024-04-28 - - - name: Run smoke-test - env: - RUST_BACKTRACE: full - run: cd zk-tests && ./test.sh check-ci-install: name: CI install diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 54950567d..000000000 --- a/.gitmodules +++ /dev/null @@ -1,12 +0,0 @@ -[submodule "zk-tests/lib/forge-std"] - path = zk-tests/lib/forge-std - url = https://github.com/foundry-rs/forge-std -[submodule "zk-tests/lib/ds-test"] - path = zk-tests/lib/ds-test - url = https://github.com/dapphub/ds-test -[submodule "zk-tests/lib/solmate"] - path = zk-tests/lib/solmate - url = https://github.com/transmissions11/solmate -[submodule "zk-tests/lib/openzeppelin-contracts"] - path = zk-tests/lib/openzeppelin-contracts - url = https://github.com/Openzeppelin/openzeppelin-contracts diff --git a/zk-tests/.gitignore b/zk-tests/.gitignore deleted file mode 100644 index 6b989b4de..000000000 --- a/zk-tests/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -/target -/Cargo.lock - -zkout/ -solc-v* -*.log -era_test_node -cache/ -broadcast/ -.zksolc-libraries-cache/ diff --git a/zk-tests/foundry.toml b/zk-tests/foundry.toml deleted file mode 100644 index f832875b5..000000000 --- a/zk-tests/foundry.toml +++ /dev/null @@ -1,22 +0,0 @@ -[profile.default] -src = 'src' -out = 'out' -libs = ['lib'] -fs_permissions = [{ access = "read", path = "./zkout/ConstantNumber.sol/ConstantNumber.json"}] - -[fuzz] -no_zksync_reserved_addresses = true - -[rpc_endpoints] -local = "${ERA_TEST_NODE_RPC_URL}" -mainnet = "https://mainnet.era.zksync.io:443" -testnet = "https://testnet.era.zksync.dev:443" - -# See more config options https://github.com/foundry-rs/foundry/tree/master/config - -[profile.default.invariant] -runs = 10 -depth = 1 - -[etherscan] -testnet = { key = "PLACEHOLDER", chain = "300", url = "https://api-sepolia-era.zksync.network/api" } diff --git a/zk-tests/lib/ds-test b/zk-tests/lib/ds-test deleted file mode 160000 index e282159d5..000000000 --- a/zk-tests/lib/ds-test +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e282159d5170298eb2455a6c05280ab5a73a4ef0 diff --git a/zk-tests/lib/forge-std b/zk-tests/lib/forge-std deleted file mode 160000 index 2f6762e4f..000000000 --- a/zk-tests/lib/forge-std +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2f6762e4f73f3d835457c220b5f62dfeeb6f6341 diff --git a/zk-tests/lib/openzeppelin-contracts b/zk-tests/lib/openzeppelin-contracts deleted file mode 160000 index dbb6104ce..000000000 --- a/zk-tests/lib/openzeppelin-contracts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit dbb6104ce834628e473d2173bbc9d47f81a9eec3 diff --git a/zk-tests/lib/solmate b/zk-tests/lib/solmate deleted file mode 160000 index c89230993..000000000 --- a/zk-tests/lib/solmate +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c892309933b25c03d32b1b0d674df7ae292ba925 diff --git a/zk-tests/script/Deploy.s.sol b/zk-tests/script/Deploy.s.sol deleted file mode 100644 index 10dc95c8a..000000000 --- a/zk-tests/script/Deploy.s.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import {Script} from "forge-std/Script.sol"; -import {Greeter} from "../src/Greeter.sol"; - -contract DeployScript is Script { - // Vm constant vm = Vm(HEVM_ADDRESS); - - Greeter greeter; - string greeting; - - function run() external { - // test is using old Vm.sol interface, so we call manually - (bool success, ) = address(vm).call( - abi.encodeWithSignature("zkVm(bool)", true) - ); - require(success, "zkVm() call failed"); - vm.startBroadcast(); - - greeter = new Greeter(); - - greeter.setAge(123); - uint256 age = greeter.getAge(); - - greeter.greeting("john"); - - vm.stopBroadcast(); - - assert(age == 123); - } -} diff --git a/zk-tests/script/Factory.s.sol b/zk-tests/script/Factory.s.sol deleted file mode 100644 index b0ef29adb..000000000 --- a/zk-tests/script/Factory.s.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.0; - -import {Script} from 'forge-std/Script.sol'; - -import '../src/Factory.sol'; - -contract ZkClassicFactoryScript is Script { - function run() external { - vm.startBroadcast(); - MyClassicFactory factory = new MyClassicFactory(); - factory.create(42); - - vm.stopBroadcast(); - assert(factory.getNumber() == 42); - } -} - -contract ZkConstructorFactoryScript is Script { - function run() external { - vm.startBroadcast(); - MyConstructorFactory factory = new MyConstructorFactory(42); - - vm.stopBroadcast(); - assert(factory.getNumber() == 42); - } -} - -contract ZkNestedFactoryScript is Script{ - function run() external { - vm.startBroadcast(); - MyNestedFactory factory = new MyNestedFactory(); - factory.create(42); - - vm.stopBroadcast(); - assert(factory.getNumber() == 42); - } -} - -contract ZkNestedConstructorFactoryScript is Script{ - function run() external { - vm.startBroadcast(); - MyNestedConstructorFactory factory = new MyNestedConstructorFactory(42); - - vm.stopBroadcast(); - assert(factory.getNumber() == 42); - } -} - -//FIXME: fails with 'trying to decode unexisting hash' -contract ZkUserFactoryScript is Script { - function run() external { - vm.startBroadcast(); - MyClassicFactory factory = new MyClassicFactory(); - MyUserFactory user = new MyUserFactory(); - user.create(address(factory), 42); - - vm.stopBroadcast(); - assert(user.getNumber(address(factory)) == 42); - } -} - -contract ZkUserConstructorFactoryScript is Script{ - function run() external { - vm.startBroadcast(); - MyConstructorFactory factory = new MyConstructorFactory(42); - MyUserFactory user = new MyUserFactory(); - - vm.stopBroadcast(); - assert(user.getNumber(address(factory)) == 42); - } -} diff --git a/zk-tests/script/NFT.s.sol b/zk-tests/script/NFT.s.sol deleted file mode 100644 index 9475f5aa4..000000000 --- a/zk-tests/script/NFT.s.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.10; - -import "forge-std/Script.sol"; -import "solmate/tokens/ERC721.sol"; -import "openzeppelin-contracts/contracts/utils/Strings.sol"; -import "openzeppelin-contracts/contracts/access/Ownable.sol"; - -error MintPriceNotPaid(); -error MaxSupply(); -error NonExistentTokenURI(); -error WithdrawTransfer(); - -contract NFT is ERC721, Ownable { - using Strings for uint256; - string public baseURI; - uint256 public currentTokenId; - uint256 public constant TOTAL_SUPPLY = 10_000; - uint256 public constant MINT_PRICE = 0.08 ether; - - constructor( - string memory _name, - string memory _symbol, - string memory _baseURI - ) ERC721(_name, _symbol) Ownable(msg.sender) { - baseURI = _baseURI; - } - - function mintTo(address recipient) public payable returns (uint256) { - if (msg.value != MINT_PRICE) { - revert MintPriceNotPaid(); - } - uint256 newTokenId = ++currentTokenId; - if (newTokenId > TOTAL_SUPPLY) { - revert MaxSupply(); - } - _safeMint(recipient, newTokenId); - return newTokenId; - } - - function tokenURI( - uint256 tokenId - ) public view virtual override returns (string memory) { - if (ownerOf(tokenId) == address(0)) { - revert NonExistentTokenURI(); - } - return - bytes(baseURI).length > 0 - ? string(abi.encodePacked(baseURI, tokenId.toString())) - : ""; - } - - function withdrawPayments(address payable payee) external onlyOwner { - uint256 balance = address(this).balance; - (bool transferTx, ) = payee.call{value: balance}(""); - if (!transferTx) { - revert WithdrawTransfer(); - } - } -} - -contract MyScript is Script { - function run() external { - vm.startBroadcast( - 0x7becc4a46e0c3b512d380ca73a4c868f790d1055a7698f38fb3ca2b2ac97efbb - ); - - new NFT("NFT_tutorial", "TUT", "baseUri"); - - vm.stopBroadcast(); - } -} diff --git a/zk-tests/script/Proxy.s.sol b/zk-tests/script/Proxy.s.sol deleted file mode 100644 index cebc77bf1..000000000 --- a/zk-tests/script/Proxy.s.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity >=0.8.7 <0.9.0; - -import 'forge-std/Script.sol'; -import '@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol'; - -contract ProxyScript { - function run() public { - //deploy Foo - ERC1967Proxy proxy = new ERC1967Proxy(address(new Foo()), ""); - - Foo foo = Foo(payable(proxy)); - foo.initialize(msg.sender); - - console.log("Foo deployed at: ", address(foo)); - console.log("Bar: ", foo.getAddress()); - } -} - -contract Foo { - address bar; - - function initialize(address _bar) public { - bar = _bar; - } - - function getAddress() public returns (address) { - return bar; - } -} diff --git a/zk-tests/src/Basic.t.sol b/zk-tests/src/Basic.t.sol deleted file mode 100644 index 93db18a92..000000000 --- a/zk-tests/src/Basic.t.sol +++ /dev/null @@ -1,176 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "forge-std/Test.sol"; - -contract BlockEnv { - uint256 public number; - uint256 public timestamp; - uint256 public basefee; - uint256 public chainid; - - constructor() { - number = block.number; - timestamp = block.timestamp; - basefee = block.basefee; - chainid = block.chainid; - } - - function zkBlockhash(uint256 _blockNumber) public view returns (bytes32) { - return blockhash(_blockNumber); - } -} - -contract ZkBasicTest is Test { - uint256 constant ERA_FORK_BLOCK = 19579636; - uint256 constant ERA_FORK_BLOCK_TS = 1700601590; - - uint256 constant ETH_FORK_BLOCK = 19225195; - uint256 constant ETH_FORK_BLOCK_TS = 1707901427; - - address constant TEST_ADDRESS = 0x6Eb28604685b1F182dAB800A1Bfa4BaFdBA8a79a; - - uint256 forkEra; - uint256 forkEth; - uint256 latestForkEth; - - function setUp() public { - forkEra = vm.createFork("mainnet", ERA_FORK_BLOCK); - forkEth = vm.createFork( - "https://eth-mainnet.alchemyapi.io/v2/Lc7oIGYeL_QvInzI0Wiu_pOZZDEKBrdf", //trufflehog:ignore - ETH_FORK_BLOCK - ); - latestForkEth = vm.createFork( - "https://eth-mainnet.alchemyapi.io/v2/Lc7oIGYeL_QvInzI0Wiu_pOZZDEKBrdf" //trufflehog:ignore - ); - } - - function testZkBasicBlockNumber() public { - vm.selectFork(forkEra); - require(block.number == ERA_FORK_BLOCK, "era block number mismatch"); - - vm.selectFork(forkEth); - require(block.number == ETH_FORK_BLOCK, "eth block number mismatch"); - } - - function testZkBasicBlockTimestamp() public { - vm.selectFork(forkEra); - require( - block.timestamp == ERA_FORK_BLOCK_TS, - "era block timestamp mismatch" - ); - - vm.selectFork(forkEth); - require( - block.timestamp == ETH_FORK_BLOCK_TS, - "eth block timestamp mismatch" - ); - } - - function testZkBasicAddressBalance() public { - vm.makePersistent(TEST_ADDRESS); - vm.deal(TEST_ADDRESS, 100); - - vm.selectFork(forkEra); - require(TEST_ADDRESS.balance == 100, "era balance mismatch"); - - vm.selectFork(forkEth); - require(TEST_ADDRESS.balance == 100, "eth balance mismatch"); - } - - function testZkPropagatedBlockEnv() public { - BlockEnv be = new BlockEnv(); - require( - be.number() == block.number, - "propagated block number is the same as current" - ); - require( - be.timestamp() == block.timestamp, - "propagated block timestamp is the same as current" - ); - require( - be.basefee() == block.basefee, - "propagated block basefee is the same as current" - ); - require( - be.chainid() == block.chainid, - "propagated block chainid is the same as current" - ); - - require( - be.zkBlockhash(block.number) == blockhash(block.number), - "blockhash of the current block should be zero" - ); - - // this corresponds to the the genesis block since the test runs in block #1 - require( - be.zkBlockhash(block.number - 1) == blockhash(block.number - 1), - "blockhash of the previous block should be equal" - ); - - require( - be.zkBlockhash(0) == blockhash(0), - "blockhash of the genesis block should be equal" - ); - - be = new BlockEnv(); - require( - be.number() == block.number, - "propagated block number stays constant" - ); - require( - be.timestamp() == block.timestamp, - "propagated block timestamp stays constant" - ); - require( - be.basefee() == block.basefee, - "propagated block basefee stays constant" - ); - require( - be.chainid() == block.chainid, - "propagated block chainid stays constant" - ); - - vm.roll(42); - vm.warp(42); - - be = new BlockEnv(); - require(be.number() == block.number, "propagated block number rolls"); - require( - be.timestamp() == block.timestamp, - "propagated block timestamp warps" - ); - require( - be.basefee() == block.basefee, - "propagated block basefee warps" - ); - } - - function testZkBasicBlockBaseFee() public { - BlockEnv beBefore = new BlockEnv(); - require( - beBefore.basefee() == block.basefee, - "propagated block basefee is the same as current" - ); - - vm.selectFork(forkEra); - BlockEnv beAfter = new BlockEnv(); - require( - beAfter.basefee() == block.basefee, - "propagated block basefee is the same as before" - ); - require( - beAfter.basefee() == block.basefee, - "propagated block basefee is the same as before" - ); - } - - function testzkBlockhashWithNewerBlocks() public { - vm.selectFork(latestForkEth); - BlockEnv be = new BlockEnv(); - require( - be.zkBlockhash(block.number) == blockhash(block.number), - "blockhash mismatch" - ); - } -} diff --git a/zk-tests/src/Cheatcodes.t.sol b/zk-tests/src/Cheatcodes.t.sol deleted file mode 100644 index 696d04898..000000000 --- a/zk-tests/src/Cheatcodes.t.sol +++ /dev/null @@ -1,266 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import "forge-std/Test.sol"; - -contract FixedSlot { - uint8 num; // slot index: 0 - - function setSlot0(uint8 _num) public { - num = _num; - } -} - -contract InnerMock { - function getBytes() public payable returns (bytes memory) { - bytes memory r = bytes(hex"abcd"); - return r; - } -} - -contract Mock { - InnerMock private inner; - - constructor(InnerMock _inner) payable { - inner = _inner; - } - - function getBytes() public returns (bytes memory) { - return inner.getBytes{value: 10}(); - } -} - -interface IMyProxyCaller { - function transact(uint8 _data) external; -} - -contract MyProxyCaller { - address inner; - - constructor(address _inner) { - inner = _inner; - } - - function transact() public { - IMyProxyCaller(inner).transact(10); - } -} - -contract Emitter { - event EventConstructor(string message); - event EventFunction(string message); - - constructor() { - emit EventConstructor("constructor"); - } - - function functionEmit() public { - emit EventFunction("function"); - } -} - -contract ZkCheatcodesTest is Test { - event EventConstructor(string message); - event EventFunction(string message); - uint256 testSlot = 0; //0x000000000000000000000000000000000000000000000000000000000000001e slot - uint256 constant ERA_FORK_BLOCK = 19579636; - uint256 constant ERA_FORK_BLOCK_TS = 1700601590; - - uint256 constant ETH_FORK_BLOCK = 19225195; - uint256 constant ETH_FORK_BLOCK_TS = 1707901427; - - address constant TEST_ADDRESS = 0x6Eb28604685b1F182dAB800A1Bfa4BaFdBA8a79a; - - uint256 forkEra; - uint256 forkEth; - - function setUp() public { - forkEra = vm.createFork("mainnet", ERA_FORK_BLOCK); - forkEth = vm.createFork( - "https://eth-mainnet.alchemyapi.io/v2/Lc7oIGYeL_QvInzI0Wiu_pOZZDEKBrdf", - ETH_FORK_BLOCK - ); - } - - function testZkCheatcodesRoll() public { - vm.selectFork(forkEra); - require(block.number == ERA_FORK_BLOCK, "era block number mismatch"); - - vm.roll(ERA_FORK_BLOCK + 1); - require( - block.number == ERA_FORK_BLOCK + 1, - "era block number mismatch" - ); - } - - function testZkCheatcodesWarp() public { - vm.selectFork(forkEra); - require( - block.timestamp == ERA_FORK_BLOCK_TS, - "era block timestamp mismatch" - ); - - vm.warp(ERA_FORK_BLOCK_TS + 1); - require( - block.timestamp == ERA_FORK_BLOCK_TS + 1, - "era block timestamp mismatch" - ); - } - - function testZkCheatcodesDeal() public { - vm.selectFork(forkEra); - require(TEST_ADDRESS.balance == 0, "era balance mismatch"); - - vm.deal(TEST_ADDRESS, 100); - require(TEST_ADDRESS.balance == 100, "era balance mismatch"); - } - - function testZkCheatcodesSetNonce() public { - vm.selectFork(forkEra); - require(vm.getNonce(TEST_ADDRESS) == 0, "era nonce mismatch"); - - vm.setNonce(TEST_ADDRESS, 10); - require(vm.getNonce(TEST_ADDRESS) == 10, "era nonce mismatch"); - - vm.resetNonce(TEST_ADDRESS); - require(vm.getNonce(TEST_ADDRESS) == 0, "era nonce mismatch"); - } - - function testZkCheatcodesEtch() public { - vm.selectFork(forkEra); - - string memory artifact = vm.readFile( - "zkout/ConstantNumber.sol/ConstantNumber.json" - ); - bytes memory constantNumberCode = vm.parseJsonBytes( - artifact, - ".bytecode.object" - ); - vm.etch(TEST_ADDRESS, constantNumberCode); - - (bool success, bytes memory output) = TEST_ADDRESS.call( - abi.encodeWithSignature("ten()") - ); - require(success, "ten() call failed"); - - uint8 number = abi.decode(output, (uint8)); - require(number == 10, "era etched code incorrect"); - } - - function testRecord() public { - FixedSlot fs = new FixedSlot(); - vm.record(); - fs.setSlot0(10); - (bytes32[] memory reads, bytes32[] memory writes) = vm.accesses( - address(fs) - ); - bytes32 keySlot0 = bytes32(uint256(0)); - assertEq(reads[0], keySlot0); - assertEq(writes[0], keySlot0); - } - - function testExpectEmit() public { - vm.expectEmit(true, true, true, true); - emit EventFunction("function"); - Emitter emitter = new Emitter(); - emitter.functionEmit(); - } - - function testExpectEmitOnCreate() public { - vm.expectEmit(true, true, true, true); - emit EventConstructor("constructor"); - new Emitter(); - } - - function testZkCheatcodesValueFunctionMockReturn() public { - InnerMock inner = new InnerMock(); - // Send some funds to so it can pay for the inner call - Mock target = new Mock{value: 50}(inner); - - bytes memory dataBefore = target.getBytes(); - assertEq(dataBefore, bytes(hex"abcd")); - - vm.mockCall( - address(inner), - abi.encodeWithSelector(inner.getBytes.selector), - abi.encode(bytes(hex"a1b1")) - ); - - bytes memory dataAfter = target.getBytes(); - assertEq(dataAfter, bytes(hex"a1b1")); - } - - function testZkCheatcodesCanMockCallTestContract() public { - address thisAddress = address(this); - MyProxyCaller transactor = new MyProxyCaller(thisAddress); - - vm.mockCall( - thisAddress, - abi.encodeWithSelector(IMyProxyCaller.transact.selector), - abi.encode() - ); - - transactor.transact(); - } - - function testZkCheatcodesCanMockCall(address mockMe) public { - vm.assume(mockMe != address(vm)); - - //zkVM currently doesn't support mocking the transaction sender - vm.assume(mockMe != msg.sender); - - MyProxyCaller transactor = new MyProxyCaller(mockMe); - - vm.mockCall( - mockMe, - abi.encodeWithSelector(IMyProxyCaller.transact.selector), - abi.encode() - ); - - transactor.transact(); - } - - function testZkCheatcodesCanBeUsedAfterFork() public { - assertEq( - 0, - address(0x4e59b44847b379578588920cA78FbF26c0B4956C).balance - ); - - vm.createSelectFork( - "https://eth-mainnet.alchemyapi.io/v2/Lc7oIGYeL_QvInzI0Wiu_pOZZDEKBrdf", // trufflehog:ignore - ETH_FORK_BLOCK - ); - assertEq( - 0, - address(0x4e59b44847b379578588920cA78FbF26c0B4956C).balance - ); - - vm.deal(0x4e59b44847b379578588920cA78FbF26c0B4956C, 1 ether); - assertEq( - 1 ether, - address(0x4e59b44847b379578588920cA78FbF26c0B4956C).balance - ); - } - - function testRecordLogsInZkVm() public { - // ensure we are in zkvm - (bool _success, bytes memory _ret) = address(vm).call(abi.encodeWithSignature("zkVm(bool)", true)); - vm.recordLogs(); - Emitter emitter = new Emitter(); // +7 logs from system contracts - emitter.functionEmit(); // +3 from system contracts - - Vm.Log[] memory entries = vm.getRecordedLogs(); - assertEq(entries.length, 12); - // 0,1: EthToken, 2,3: L1 Messanger, 4: Known Code Storage - assertEq(entries[5].topics.length, 1); - assertEq(entries[5].topics[0], keccak256("EventConstructor(string)")); - assertEq(entries[5].data, abi.encode("constructor")); - // 6: L2 Deployer, 7: EthToken - - // 8,9: EthToken - assertEq(entries[10].topics.length, 1); - assertEq(entries[10].topics[0], keccak256("EventFunction(string)")); - assertEq(entries[10].data, abi.encode("function")); - // 11: EthToken - } -} diff --git a/zk-tests/src/Console.t.sol b/zk-tests/src/Console.t.sol deleted file mode 100644 index f4f825117..000000000 --- a/zk-tests/src/Console.t.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test, console2 as console} from "forge-std/Test.sol"; - -contract Printer { - function print() public pure { - console.log("print"); - } -} - -contract ZkConsoleTest is Test { - uint256 constant ERA_FORK_BLOCK = 19579636; - uint256 constant ERA_FORK_BLOCK_TS = 1700601590; - - uint256 forkEra; - - function setUp() public { - forkEra = vm.createFork("mainnet", ERA_FORK_BLOCK); - } - - // The test must be run with parameter `-vv` to print logs - function testZkConsoleOutput() public { - (bool success, ) = address(vm).call( - abi.encodeWithSignature("zkVm(bool)", true) - ); - require(success, "zkVm() call failed"); - - Printer printer = new Printer(); - printer.print(); - console.log("outer print"); - console.logAddress(address(this)); - printer.print(); - console.logBytes1(0xff); - printer.print(); - } -} diff --git a/zk-tests/src/ConstantNumber.sol b/zk-tests/src/ConstantNumber.sol deleted file mode 100644 index e93362f9a..000000000 --- a/zk-tests/src/ConstantNumber.sol +++ /dev/null @@ -1,8 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.20; - -contract ConstantNumber { - function ten() public pure returns (uint8) { - return 10; - } -} diff --git a/zk-tests/src/Contracts.t.sol b/zk-tests/src/Contracts.t.sol deleted file mode 100644 index 1bde15fd3..000000000 --- a/zk-tests/src/Contracts.t.sol +++ /dev/null @@ -1,340 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test, console2 as console} from "forge-std/Test.sol"; -import {ConstantNumber} from "./ConstantNumber.sol"; -import {Greeter} from "./Greeter.sol"; - -interface ISystemContractDeployer { - function getNewAddressCreate2( - address _sender, - bytes32 _bytecodeHash, - bytes32 _salt, - bytes calldata _input - ) external view returns (address newAddress); -} - -contract Number { - function ten() public pure returns (uint8) { - return 10; - } -} - -contract FixedNumber { - function five() public pure returns (uint8) { - return 5; - } -} - -contract FixedGreeter { - function greet(string memory _name) public pure returns (string memory) { - string memory greeting = string(abi.encodePacked("Hello ", _name)); - return greeting; - } -} - -contract MultiNumber { - function one() public pure returns (uint8) { - return 1; - } - - function two() public pure returns (uint8) { - return 2; - } -} - -contract PayableFixedNumber { - address sender; - uint256 value; - receive() external payable {} - - constructor() payable { - sender = msg.sender; - value = msg.value; - console.log(msg.value); - } - - function transfer(address payable dest, uint256 amt) public { - (bool success, ) = dest.call{value: amt}(""); - require(success); - } - - function five() public pure returns (uint8) { - return 5; - } -} - -contract CustomNumber { - uint8 value; - - constructor(uint8 _value) { - value = _value; - } - - function number() public view returns (uint8) { - return value; - } -} - -contract CustomStorage { - uint8 num; - string str; - - constructor(string memory _str, uint8 _num) { - str = _str; - num = _num; - } - - function getStr() public view returns (string memory) { - return str; - } - - function getNum() public view returns (uint8) { - return num; - } -} - -contract ZkContractsTest is Test { - Number number; - CustomNumber customNumber; - MultiNumber multiNumber; - - uint256 constant ERA_FORK_BLOCK = 19579636; - uint256 constant ERA_FORK_BLOCK_TS = 1700601590; - - uint256 constant ETH_FORK_BLOCK = 19225195; - uint256 constant ETH_FORK_BLOCK_TS = 1707901427; - - uint256 forkEra; - uint256 forkEth; - - function setUp() public { - number = new Number(); - customNumber = new CustomNumber(20); - multiNumber = new MultiNumber(); - vm.makePersistent(address(number)); - vm.makePersistent(address(customNumber)); - - forkEra = vm.createFork("mainnet", ERA_FORK_BLOCK); - forkEth = vm.createFork( - "https://eth-mainnet.alchemyapi.io/v2/Lc7oIGYeL_QvInzI0Wiu_pOZZDEKBrdf", - ETH_FORK_BLOCK - ); - } - - function testZkContractCanCallMethod() public { - FixedGreeter g = new FixedGreeter(); - vm.makePersistent(address(g)); - vm.selectFork(forkEra); - assertEq("Hello hi", g.greet("hi")); - } - - function testZkContractsPersistedDeployedContractNoArgs() public { - require(number.ten() == 10, "base setUp contract value mismatch"); - - vm.selectFork(forkEra); - require(number.ten() == 10, "era setUp contract value mismatch"); - - vm.selectFork(forkEth); - require(number.ten() == 10, "eth setUp contract value mismatch"); - } - - function testZkContractsPersistedDeployedContractArgs() public { - require( - customNumber.number() == 20, - "base setUp contract value mismatch" - ); - - vm.selectFork(forkEra); - require( - customNumber.number() == 20, - "era setUp contract value mismatch" - ); - - vm.selectFork(forkEth); - require( - customNumber.number() == 20, - "eth setUp contract value mismatch" - ); - } - - function testZkContractsInlineDeployedContractNoArgs() public { - vm.selectFork(forkEra); - FixedNumber fixedNumber = new FixedNumber(); - require( - fixedNumber.five() == 5, - "era deployed contract value mismatch" - ); - } - - function testZkContractsInlineDeployedContractBalance() public { - vm.selectFork(forkEra); - PayableFixedNumber payableFixedNumber = new PayableFixedNumber{ - value: 10 - }(); - require(address(payableFixedNumber).balance == 10, "incorrect balance"); - } - - function testZkContractsExpectedBalances() public { - vm.selectFork(forkEra); - uint balanceBefore = address(this).balance; - - PayableFixedNumber one = new PayableFixedNumber{value: 10}(); - - PayableFixedNumber two = new PayableFixedNumber(); - one.transfer(payable(address(two)), 5); - - require( - address(one).balance == 5, - "first contract's balance not decreased" - ); - require( - address(two).balance == 5, - "second contract's balance not increased" - ); - require( - address(this).balance == balanceBefore - 10, - "test address balance not decreased" - ); - } - - function testZkContractsInlineDeployedContractComplexArgs() public { - CustomStorage customStorage = new CustomStorage("hello", 10); - vm.makePersistent(address(customStorage)); - require( - keccak256(abi.encodePacked(customStorage.getStr())) == - keccak256(abi.encodePacked("hello")), - "base inline contract value mismatch (complex args)" - ); - require( - customStorage.getNum() == 10, - "base inline contract value mismatch (complex args)" - ); - - vm.selectFork(forkEra); - require( - keccak256(abi.encodePacked(customStorage.getStr())) == - keccak256(abi.encodePacked("hello")), - "era inline contract value mismatch (complex args)" - ); - require( - customStorage.getNum() == 10, - "era inline contract value mismatch (complex args)" - ); - - vm.selectFork(forkEth); - require( - keccak256(abi.encodePacked(customStorage.getStr())) == - keccak256(abi.encodePacked("hello")), - "eth inline contract value mismatch (complex args)" - ); - require( - customStorage.getNum() == 10, - "era inline contract value mismatch (complex args)" - ); - } - - function testZkContractsCreate2() public { - vm.selectFork(forkEra); - - // ConstantNumber zksolc hash obtained from zkout/ConstantNumber.sol/artifacts.json - string memory artifact = vm.readFile( - "zkout/ConstantNumber.sol/ConstantNumber.json" - ); - bytes32 bytecodeHash = vm.parseJsonBytes32(artifact, ".hash"); - address sender = address(0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496); - bytes32 salt = "12345"; - bytes32 constructorInputHash = keccak256(abi.encode()); - address expectedDeployedAddress = _computeCreate2Address( - sender, - salt, - bytes32(bytecodeHash), - constructorInputHash - ); - - // deploy via create2 - address actualDeployedAddress = address( - new ConstantNumber{salt: salt}() - ); - assertEq(expectedDeployedAddress, actualDeployedAddress); - } - - function _computeCreate2Address( - address sender, - bytes32 salt, - bytes32 creationCodeHash, - bytes32 constructorInputHash - ) private pure returns (address) { - bytes32 zksync_create2_prefix = keccak256("zksyncCreate2"); - bytes32 address_hash = keccak256( - bytes.concat( - zksync_create2_prefix, - bytes32(uint256(uint160(sender))), - salt, - creationCodeHash, - constructorInputHash - ) - ); - - return address(uint160(uint256(address_hash))); - } - - function testZkContractsCallSystemContract() public { - (bool success, ) = address(vm).call( - abi.encodeWithSignature("zkVm(bool)", true) - ); - require(success, "zkVm() call failed"); - - ISystemContractDeployer deployer = ISystemContractDeployer( - address(0x0000000000000000000000000000000000008006) - ); - - address addr = deployer.getNewAddressCreate2( - address(this), - 0x0100000781e55a60f3f14fd7dd67e3c8caab896b7b0fca4a662583959299eede, - 0x0100000781e55a60f3f14fd7dd67e3c8caab896b7b0fca4a662583959299eede, - "" - ); - - assertEq(address(0x46efB6258A2A539f7C8b44e2EF659D778fb5BAAd), addr); - } - - function testZkContractsDeployedInSetupAreMockable() public { - vm.mockCall( - address(multiNumber), - abi.encodeWithSelector(MultiNumber.one.selector), - abi.encode(42) - ); - - assertEq(42, multiNumber.one()); - assertEq(2, multiNumber.two()); - } - - function testZkStaticCalls() public { - (bool success, ) = address(vm).call( - abi.encodeWithSignature("zkVm(bool)", true) - ); - require(success, "zkVm() call failed"); - address sender = address(this); - uint64 startingNonce = vm.getNonce(sender); - - //this ensures calls & deployments increase the nonce - vm.startBroadcast(sender); - - Greeter greeter = new Greeter(); - assert(vm.getNonce(sender) == startingNonce + 1); - - greeter.setAge(42); - assert(vm.getNonce(sender) == startingNonce + 2); - - // static-call, nonce shouldn't change - uint256 age = greeter.getAge(); - assert(age == 42); - assert(vm.getNonce(sender) == startingNonce + 2); - - uint256 num = greeter.greeting2("zksync", 2); - assert(num == 4); - assert(vm.getNonce(sender) == startingNonce + 3); - vm.stopBroadcast(); - } -} diff --git a/zk-tests/src/Deposit.sol b/zk-tests/src/Deposit.sol deleted file mode 100644 index f6ccd4bc7..000000000 --- a/zk-tests/src/Deposit.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.0; - -contract Deposit { - address public seller = msg.sender; - mapping(address => uint256) public balance; - - function deposit() external payable { - balance[msg.sender] += msg.value; - } - - function withdraw() external { - uint256 amount = balance[msg.sender]; - balance[msg.sender] = 0; - (bool s, ) = msg.sender.call{value: amount}(""); - require(s, "failed to send"); - } -} diff --git a/zk-tests/src/ERC20.sol b/zk-tests/src/ERC20.sol deleted file mode 100644 index 6b1dca2ec..000000000 --- a/zk-tests/src/ERC20.sol +++ /dev/null @@ -1,30 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0; - -contract MyToken { - string public owner; - string public constant name = "MyToken"; - string public constant symbol = "MTK"; - uint8 public constant decimals = 18; - uint256 public totalSupply = 1000000 * (10 ** uint256(decimals)); - mapping(address => uint256) public balanceOf; - - event Transfer(address indexed from, address indexed to, uint256 value); - - - constructor() { - balanceOf[msg.sender] = totalSupply; - } - - function setTotalSupply(uint256 amount) public { - totalSupply = amount; - } - - function transfer(address to, uint256 amount) public returns (bool) { - require(balanceOf[msg.sender] >= amount, "Not enough tokens"); - balanceOf[msg.sender] -= amount; - balanceOf[to] += amount; - emit Transfer(msg.sender, to, amount); - return true; - } -} diff --git a/zk-tests/src/Factory.sol b/zk-tests/src/Factory.sol deleted file mode 100644 index 68e93dc74..000000000 --- a/zk-tests/src/Factory.sol +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.0; - -/// Set of tests for factory contracts -/// -/// *Constructor factories build their dependencies in their constructors -/// *User factories don't deploy but assume the given address to be a deployed factory - -contract MyContract { - uint256 public number; - constructor(uint256 _number) { - number = _number; - } -} - -contract MyClassicFactory { - MyContract item; - - function create(uint256 _number) public { - item = new MyContract(_number); - } - - function getNumber() public view returns (uint256) { - return item.number(); - } -} - -contract MyConstructorFactory { - MyContract item; - - constructor(uint256 _number) { - item = new MyContract(_number); - } - - function getNumber() public view returns (uint256) { - return item.number(); - } -} - -contract MyNestedFactory { - MyClassicFactory nested; - - function create(uint256 _number) public { - nested = new MyClassicFactory(); - - nested.create(_number); - } - - function getNumber() public view returns (uint256) { - return nested.getNumber(); - } -} - -contract MyNestedConstructorFactory { - MyClassicFactory nested; - - constructor(uint256 _number) { - nested = new MyClassicFactory(); - - nested.create(_number); - } - - function getNumber() public view returns (uint256) { - return nested.getNumber(); - } -} - -contract MyUserFactory { - function create(address classicFactory, uint256 _number) public { - MyClassicFactory(classicFactory).create(_number); - } - - function getNumber(address classicFactory) public view returns (uint256) { - return MyClassicFactory(classicFactory).getNumber(); - } -} diff --git a/zk-tests/src/Factory.t.sol b/zk-tests/src/Factory.t.sol deleted file mode 100644 index 64f7a4d5e..000000000 --- a/zk-tests/src/Factory.t.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: Unlicense -pragma solidity ^0.8.0; - -import {Test} from 'forge-std/Test.sol'; - -import './Factory.sol'; - -contract ZkFactoryTest is Test { - function testClassicFactory() public { - MyClassicFactory factory = new MyClassicFactory(); - factory.create(42); - - assert(factory.getNumber() == 42); - } - - function testConstructorFactory() public { - MyConstructorFactory factory = new MyConstructorFactory(42); - - assert(factory.getNumber() == 42); - } - - function testNestedFactory() public { - MyNestedFactory factory = new MyNestedFactory(); - factory.create(42); - - assert(factory.getNumber() == 42); - } - - function testNestedConstructorFactory() public { - MyNestedConstructorFactory factory = new MyNestedConstructorFactory(42); - - assert(factory.getNumber() == 42); - } - - function testUserFactory() public { - MyClassicFactory factory = new MyClassicFactory(); - MyUserFactory user = new MyUserFactory(); - user.create(address(factory), 42); - - assert(user.getNumber(address(factory)) == 42); - } - - function testUserConstructorFactory() public { - MyConstructorFactory factory = new MyConstructorFactory(42); - MyUserFactory user = new MyUserFactory(); - - assert(user.getNumber(address(factory)) == 42); - } -} diff --git a/zk-tests/src/Fuzz.t.sol b/zk-tests/src/Fuzz.t.sol deleted file mode 100644 index 1d51c3411..000000000 --- a/zk-tests/src/Fuzz.t.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test} from "forge-std/Test.sol"; - -contract ZkFuzzTest is Test { - function testZkFuzzAvoidSystemAddresses(address addr) public pure { - assert(addr > address(65535)); - } -} diff --git a/zk-tests/src/Greeter.sol b/zk-tests/src/Greeter.sol deleted file mode 100644 index 0989f53e6..000000000 --- a/zk-tests/src/Greeter.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -contract Greeter { - string name; - uint256 age; - - event Greet(string greet); - - function greeting(string memory _name) public returns (string memory) { - name = _name; - - string memory greet = string(abi.encodePacked("Hello ", _name)); - emit Greet(greet); - - return greet; - } - - function greeting2( - string memory _name, - uint256 n - ) public returns (uint256) { - name = _name; - - string memory greet = string(abi.encodePacked("Hello ", _name)); - emit Greet(greet); - - return n * 2; - } - - function setAge(uint256 _age) public { - age = _age; - } - - function getAge() public view returns (uint256) { - return age; - } -} diff --git a/zk-tests/src/InvariantDeposit.t.sol b/zk-tests/src/InvariantDeposit.t.sol deleted file mode 100644 index 4e53f890b..000000000 --- a/zk-tests/src/InvariantDeposit.t.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; -import "forge-std/Test.sol"; -import "../src/Deposit.sol"; - -contract InvariantDeposit is Test { - // forge-config: default.invariant.runs = 2 - Deposit deposit; - - function setUp() external { - deposit = new Deposit(); - vm.deal(address(deposit), 100 ether); - } - - // forge-config: default.invariant.runs = 2 - function invariant_alwaysWithdrawable() external payable { - deposit.deposit{value: 1 ether}(); - uint256 balanceBefore = deposit.balance(address(this)); - assertEq(balanceBefore, 1 ether); - deposit.withdraw(); - uint256 balanceAfter = deposit.balance(address(this)); - assertGt(balanceBefore, balanceAfter); - } - - receive() external payable {} -} diff --git a/zk-tests/src/Issues.t.sol b/zk-tests/src/Issues.t.sol deleted file mode 100644 index 97b9f659f..000000000 --- a/zk-tests/src/Issues.t.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "forge-std/Test.sol"; - -// https://github.com/matter-labs/foundry-zksync/issues/497 -contract Issue497 is Test { - uint256 constant ERA_FORK_BLOCK = 19579636; - - uint256 forkEra; - - function setUp() public { - forkEra = vm.createFork("mainnet", ERA_FORK_BLOCK); - } - - function testZkEnsureContractMigratedWhenForkZkSyncThenZkVmOff() external { - vm.selectFork(forkEra); - (bool success, ) = address(vm).call( - abi.encodeWithSignature("zkVm(bool)", false) - ); - assert(address(vm).codehash != 0); - } -} diff --git a/zk-tests/src/LargeContracts.sol b/zk-tests/src/LargeContracts.sol deleted file mode 100644 index bb1fcc2de..000000000 --- a/zk-tests/src/LargeContracts.sol +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.20; - -/** -String generated via the following JS code: - -function getHexString() { - const result = []; - const hexRef = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; - - for (let n = 0; n < 20000; n++) { - result.push(hexRef[Math.floor(Math.random() * 16)]); - } - console.log(result.join('')); -} - -*/ - -/// Bytecodes: 1760, 106208, 106976 -contract LargeContract { - LargeContractA largeA; - LargeContractB largeB; - SmallContractA smallA; - SmallContractB smallB; - - constructor() { - largeA = new LargeContractA(); - largeB = new LargeContractB(); - smallA = new SmallContractA(); - smallB = new SmallContractB(); - } -} - -contract SmallContractA { - function ten() public pure returns (uint32) { - return 10; - } -} - -contract SmallContractB { - function ten() public pure returns (uint32) { - return 10; - } -} - -/// Bytecode: 106208 bytes -contract LargeContractA { - function data100000_1() public pure returns (string memory) { - return "690a855a0b6a4c870a8c105f0b133c7113111aa4e08a28d68860dc9edbbf187591eb355a2c735e1c5277358a0bf8feed5f5859d0d9511db8fe53d9cdaf68d190e5df0aa7865f283743680b614c7c13036ea324a1a5e8c5623e1d5b71f274d058954acdd483368ed7a878af83391bf07d143ae4ea7cd3af215cbf9912cc918e508cd67938306917c3cd3b8e4b0f65e0b94482632b8a0050c8a47072c405f7719a27ce859d4dc4ab4ec06d2c69ac573978b9ff7a78bd8500fa532c42df9fd7a4f97b924f921b1af063466180fb891f1eaea0af7ed8400c16c9970c9b1d5fd2b90010fa166b3e36114c9473cb71bbb89017b0d544a10ad26722d577b8bf570f70bfeb0264a1e4382cafb14e3b4e50453b00d972cf1f70d5a9f8c1cdb454d8e1c0e8385e3d2a11394740c40b3149a226963ad3fb68820b11d511382c25ee390a9713c2d2d8df3596b9c7f30c3e93f998a064cf2e473a23f1380de6499b4cd1fd14fb347a4fefeda70ca8e8c54db61bbfd42751fa6b44e383a93c178dbc94e97267bf2d402501c12c6812c4579dd1fdac551d078ca9024b6c78e861071a132b7f627a9f37f9d8fac166b1c3159c4881d761d1cbdc94083b7e1396855c496ac74b1d7fdfa029fb0ff8fd12813df06b0913281ad2e2486133ae69b902f2fe7a31e8cd17a0c029594059726713279970378a7712f2494e760609d102d30ea9528022792f183a2cc92c7d4a6dabf06a1217c400369f78363794550c39710d81d1a164120de34b5deaca54185820fdc56f9a20af2afa9711dbd330a15280305530c766a0d2fe3f4dbc5dbda948be4517d9afba37672e4963d21c0e063e87d3ac44b4f7d9ca37e6d975127cece4567b01d9df5f31c880587a759a032a620a811a50504099a4add519c63e0e886b5ae345cc7d066a16189053f8da7a75aa0f2eb2880135fe48bdae76f254fe8255efbd20c83f819114204b97a9bd9359897c382ce10c1a6e28560067542472d484ebc281c5b626387a0a2739a9b7dd12e33e5805ec6b54cc2bcb826f28004c29a3c5ca66c4c88ad65eeec52381409828ee31e8124f0fdab9b90a787d5dc80137c4d73289be6f495a5afe96c4e3d3a29f6bf985afb32dec28a59d0c6f42b0343fb52c876a0620fa8227a604baa85b0c48041875eb1a5333850aa1152c4c51f9dfe0088d4a1b28111e6612e66aaaafa44640786ed7a687c8af2e2539ecacd0258491b5eed01cfefb92f69252013cb7d28daad4d6e804e4865d1b6116a3035e0e3df6dcf199d80b83f58fcaed7ac182272afc40878df3f4fbd66b8e83dda1a7e316baec8529b6f736a2c2a5193bd47dfa932e624aac21b926eb665c4b406ee4993e579c53ae59ea7f3f28d9045f0c1d1c84fea48c839c26ddd4de38ee1989792c54c7f11f4b99eb06c487196e1a5d7aa211ec2e6176e1e4fa2d47324cf880766dc422ed4d1e4cd47ea2398bc068e0d23d458c39f4b57ebec179f2679a8a22c2930f202c0fba14e2851a240bcc2a921423805e1fe682a2e6a7f25a63692d34c4765b7e594f93073b553f15ca4e948ff741f1d1514d30f24eff89f1ab81371486e8708d1d7e2c20430d7701aeefc4b434fca012741582971a141b1b18c62fb7a76dab36de5c46438c7c4b35bd1d945cb9c60758777f41dfd2a6d5afb70505dbd6829982e9f77f3a04f1cc2fc715483813147b2e5506c3a9a565f63dc24bfe6f429ca76d64355b4890b20e3430bdaa8185b7c66bf0a512f13dcec2e884b17ca88c83ba6408ec0f512d32f734a7e32f3e8896de7f1ecbf0bf7703035562e8d00d2a37ae8f803ce9db56619af953db4056c562cef409321f65ed583f06ca47e93faa4f87ba217e2af5accde3771ab096bb5d8dfa112fee796d0f40548b669a1ba3f47f04b042240aedee5ded8fe6adb9b22ed6e5aff704999fa91f3a4b3d6a8907f3103655c474bfebac84b0b1c7fae7350b84726816c000e6112e99fe381f8080d65d81bbc7a0ad5643d291a4b674eb9b41ee4eddda0b585612e53b10418b4df12f1fb8ab88369e955a0bdf8d91d6398c4476027482b93e603bdbfaab2f425a41e8c594f5c76e6eb10767481423a9e49f1db5ec571cf8808803f742d114c815f54627e72e916c70cb3412aed8c0863724fed256f9fd0eb4ebc03f41c89676c625abcedf20486a82be2a5859929f939b3e3fc89e9ee0240a4a6bbf1c8754dc9f1ebaf9768310bef2d3d7dc9addba87f6f8034d1c5a8cd733d8fa81ad4d8f19ca03097f3e59fa91127ef81f6002c6b27e5fcee7e2a23152d856cb46a482c5581311bb29f7ab48b6763bee26606bdebf37864330dd203c813b7ef956084084001e289f18f4284f457df690b5b260d63daa3a3aad5bb5041a20cd15b3153e17ea2d1c788ba85374a32d124a4a289ebfd7d2dd2bb2078b6183fbec078587972fa35aea032d2a102b2a1b4395b29feb6e61e61be968931b84b9961a53a5785524b5b7b1acf2b39c008649c89915a5a8708327e01b49d888b92788255f781eb6ff83bfbb19678c039b5723b77f1e0a3b6124df3507a2c15032c62a1231d02384590823d76b1ab0d5c3f5fce7262a4a375ef691ef35a34d0e461c45ea00c113b433e89b48ad895fc3507918425e9166f6c4c055b2e29f9a6ef411db745f871d755c048785412c6a1d766c16afe9f166a8409eec1a85e1e8542b6fbdb871bed1ca65f317e03f3d8fee94b1926ab71dc3eb90daeb4beafc124d6f0a35990bc37f5cb20be651881c793ae549f75303630a660c1569366daed18d9b61a42fb79fd7dd43a1fae1442f72119c78877e8fd43f3d24c924c9a428c667d25a6e994ea232f5a1953f128854b252a3d027964bfea990e0808aa70ac91bd675d75c0b35138eeb75cc3d65cff5ef1c229cdc5e0de986b97ef9a2c5642e140cd23635d369cf551ad08635ffd20592aec0a5a99b0b869b34a6e3c48097ed2485ee0213f21d5973bf56f6e2305bc6def1d2ec5d5463ffbc2a5330717cefdddc60120f6e2d07beb2ca63090f4301561beb94df8f7cc5767764cc7c47d17bac422f7556b6c09589c0ef2076615fd57462a8ebb5cb1af31fbcb48868196f20f2ab7e8794196d2c471e9a94b166f42c81224f3e4bf0f8ae9548c04375e0d66894b5ccf033392ea5d3384989ece25c062beadb69b420c7e922123b182820ad8582e73f1646d55e3b6d38724af410bcfb4529aa33eea2fc9e9c974c2dc2736886ff07a2cb6c65b206186459d3f62cbc9273f69dee409700434d0f37e33336c2375760a2d2c0d9b5cf1cc774821aa2814774e02614ea929452f0a1293bb2932806f4cc4f0b3fc11bcea15a85b1ae684c4c6444ffcbb70291947db0434747cf2550c7df4e0c728f509623d215ad8e8bff7ad36bc9d7ecc68a5465439927e02fdd8dcef73fd89f9f12142a9151cec384d53f8737ae668ec61334a7724ac946c8b0b467ab8a82e2b56a6a7570408f6a2f7b765fc1fdc1d5992ef98980082496885e1b802b1dca01e07dbc2c8291cc611b9568ef92811fc92e7fcb4c342ab779c56f7abeabeaa7b80741b1e9d008934672cbd80a9d5f3cb1ab9afd77f35b0516c0deadf8d7728f8a5d987cdcbdc24cc5b346d37115cbd36f5918ba272a7ed794dcfbb68a1bdb0f96d2f17534af725f0fcb89bd2b2fd159060c7f0101e84044f56bd13d4478a50dee59fafedd48a400cb2a170d58c366e6d42f24224153fc4a7ac578be77b1d00e3eda35d1d87ced615eb615bf11e8c0a9b6f4747f73be4fcb53c5c247760c93d4210a7dca29a04d125ca7b0372201749e8668173cf7008fc18ae448ba09cfc0831e2d832f9f8c572e48197a705752689298f842e188ed7b939055d66e7db8ac459c05861cd8c23ded79679e19f7f5d8b72180d984a389eacedca318b5fad8fcc359780f4e91ef3cdcc655502015e6ba50999eadf8e15aaca7cee06e15c96fffdb24f3735c20c1d8da47404bb72c99f075ecd6d044675918be9735eece118379259f961013da16dd8a50a8aea77141cb55c39872798624ce73226f1616f8fad5922c6f640a06e0158e6bb2a79ab99dc52a5b6dfe57fe6309c69eef199f8e480f4d15ccbc8652d17e24a45fc5c8240ac433745e7d16a5a25c30ffb1fd9a626e02ee48900645c151fff7a6c42bc6639c0e7b087a992645e9adba132f69aec6658e48a0cb61343e2ca8bebc16e8472efe6a6d76f5d06fb1cb3133e116085b16410016eea7e1629d88ffa28791604035ab581e02cb1d54f4af2e4fb26bc1c8ef4ecb48a691fe88681d2e2c10366e9aafb1b0f9efd32e70d6b881247d4bfe0ad75584d3f0f3885464cde41824969b02e22ca6888837f7ca4e17f5706274ced4158494a014ea327997411c6c0a4421f1cff8c08675b1595c3e28728ca513570f813b7d9180cb9c4309c457535d846ee59fb1e5d5f523a9f92a6c963f3b17f046ec3cd8b79214591a38d0ccda15861fe9aa968cb3e9962bf87715c426bb265da5bb34d5bda3b9ecb92a840336865938b55ae0a909130544e3691bc764e0f9c280bf8eadf9410c2cad16aae69dfb753825586cf3ea865bdd3e0ff97c7e37ac971e4597bb85db3ae12b684b4793ca76f0cc79c91aec3276a1b1de32be18dc6a8a61530e0d95e24ba49bd53dddd4b7ca6b81726866e3bb2a5d482667bae965b08eff2abda6f8f054972ee7322c1decacc910246446920e6af6f6aa8eaeb3f68455d9dd0b52ebf99233a3c2983ecd9ffdb9f9b1b2868de418c7fc7810061b6e51f27731039187cac723679c7a8ce95763ac575455352a89da3cb217626f3c0053008034effe259efe50d801fc6eb44781511ddaf05394a0a5f741d1f647450e924190116482382a573385975a1e45ce93241eb378719f02ba20ae6ad9ae0881ff7523a1664d5b3498149939dcbf397385c10305089474ef32bb50c1af159938b9754e1047d4dae8afe827d625afed767f24cc2e5db2e1d316218c4b8cc713fc765908704ec4d4d13c7c659a07c31b15d40c4fbeb483a75b78d5e16c5b4ca63f6144f0b4b174005436c978e4d18b65e2cc13e2d9e5abd6af7905aa182a9f52919c053496462cf9bb409b408484e7fd798fc7d6770680bbdccb6676da2c551922ead10993984160368e37d5ccb492d21d9862d87e2336f9dcfb6baddf813476d0974919e7def3e2d8f20a5d0c6df494f2c9cd06e2dbf993a3d2575f695131bd1d1b4b511c73670067a306ae44a5bf5fa4109682d2efb183f635481030edf4f037c7a19e40135f3c4b59e17b54e564b37f711ed1c248bfd415899ab94cecd4873603b681d672d7ed7ed0d71c161c0a040523edb37b6452e03eca082291b9d613b8049098b46f4dae85f403500363b2245107490353665a484b75ae7dedf507aba2a5b3db79277fc930671aa2941f7cb71c23e75bfd4f720896a1eaf47323efc8518dfe9f3384b0adc8b78aef458db559ebd8dd055cd786d364d78dcee5f57013051a7ebc307dd2c8718505eb291d15e69e97ad0be9f19a7eacdedf3fe368fb8f755605ac457ce0f4a2d21a5558d8d486265ce105d9537f43e5dcbed6e5dc242f096da944be8c7167926781f0b95b5f729c691e0f6e0efd1aa9abb7b567554cb20571f0b4ebdbad51f51ced26b8e8204ea4b504b1303576790f1d3ed612323409176c7970914dfbecba2ec10b8ddcf6d6e9bc79ab9780dd6ac8ce264c08b14a8dee9c06a1421d77a289320c55357a8e3e92e4f2570f0c998ba523e9b6eb5641543de5adb27fb55ace7ddd95c7535aeda524905b3b13cc9a266a6d97e302b2866f86c1b6531e7003eb2d629a4df7659c5857d168fb351087520e267d8b360d4d18dbbb7d97f21834ac65abe918aa61ef32477a6014866dc86cbacd7f85e9efcfa2a1bc291dee82e6f481dfcd3ddf536219835de9c149ff75ef99240590061a0abd21bc723972e68996900c6bf757b54c3e7dbfa45360878a741e290a7012ca58a4e108fa98995c5c9bc9c8c08c3ecf979169df3bc4938c82f465c92851b8c96e5e257592d34dd5d7a087ea4688b78f5bc644eaaa04a6a4f680a63612075949a096384698acfbd5a81b740b842200cc301817933a92b5654bbacde05feb33fbe1fa72556d93e7008c87150454282d283e181d7ca58d986db8a26f1ff50527c69dd43d13ddedce13fa6d82b180c100ba6fb8edbcc09fbac7a07c1e880e145d13994b89be823b72a1bab3ea45fc3e8db1e6981f236ef5995b2addac2eed16a756f0ff43a95ed7cc20d1267f2033296f287dc0512d11d325500808764bb17ba90bd181e86d65f201bceb08ae9a0d384a57a1cdd3041e715da9f292fe10f80cfff5ac3f2d578412cf0093d0d7f7222d1eb30b23c1e26cca3f282f0d9bbe268de4e8926f7401df2565deb9e6007baeaee1e44292983c438021a540e0692d8204951ba18502abeff1f6ea714f6974de6ae407853d1743a5435449aa52c83b2840bf1a94b8a75dcc57b015571386649619d54cb88a47bfe2d606e466256acfff3ca4fa48b967fbfcfef99500a07c07f5a83d98ad5a15abd622fbc2d08fe58a523284b01405f21dd77d227e7b5b3666d38067c140d1094978fb5e95e9ed9a6df5e06f99b8301ceaf2ce81a7efff60f56da66f8f957ae36859cf918742aa06d80899bd22208b863c27b3e33898c71a8ba0847d6b6dbfbb76731606f8b93298d895af1e5386aeb5c395d7ee4cca5759a420511df5d0739c949160f81af4692641a6b21f731bf61281f9d64a64c3128f6e56d5de0d6aa510d368ca7ad7f60f32df2d1aae43e4bbb8683b011c6c8cacb1176896f611303aa5bc2f789b9d24f90a67fb16cb0c936b2c7673b2ec5adfce015d693cedd06f53622995e2c741829ecb0cb843ccdec925d9ed65ce51cc49a09bebd703c96540b7252ee2de320a1aec999074c57519a72c07aba4995913500bc8a6202ae75ae274bc9b2d7955e9aa9e5c8f927b9565fb7f0814a62724eb92009c4904d4d0d16eecc26529959ebb334f3638c20ead7fa56eba21f9a59a14ef7f2106ae19bfd638c7227cff9af189f8d1b3497d7bc1798af4904aa98b6302bd11b04daf07b1550fdd5ccc5a57e9ff94d4d497c50dd5412f758620f6e239bb1dccbb6365ebdfbe1f7f4fe2b30a9f21661ed3b512e43354537fe7f35f670a0a9b36d8b9a6d172c676d50db849fc15e0746a8eafe1bba58545c3e7984b8251174259f288e9ceaa16e0363f6d6aac5dea74cc8abae082710c89cf0c30cb78e6028784c169fcb7a5fa9f1560b64306f9906c86fc4689689ae877454f1122f2be9880e207847dd9741c5a54893ca1eeaf74704bddc54ce039fb74d06696e3d86fd087207ae3ca15ca18534d6e40ac55316efb6ff61ce5facb204698bb89fb773183dd33f4ad6289ad41ed004cb5da7c6720e7d15d127560d17ad87caffde570b16cbbe8759ba5f249b53da4beb03e0d9de1fd69d5057ff216a9bd3b5ce771de93938d5a69c9386585453d3c5ad676f366a58dacf3cc8eee28135c4d32971e809b21257df29537db75f35ecee3347074ad042acf9634b4f73e76731536b78005997bbe3a720e49d7d98e9577d0722bde044468e25e7d469b05755b908bcb850d487910d5ccdfffa44da91b9adabefee85d153fbdb1bf87cb7b038744cc59673ff4a639c584f5024afd468bf7d5848c3bb5d912212e69036d103b96ad1f7a29f62286fcd8cbbfb8f6a3a924023fd1024083b9fef3d3de8ff392e72f16caa4029a41d267c609ad2f7e65b0587fdc0bd084ecc4988bd800d40c361757fbe17ec47057715a464352c6e6f9c7d53dffead52f3b7514a059b758d89db07346fdbcdbf6bdeef7d9403f88d03abd8ff3fc61d980c6f64542bbe14d1bebd73f4ef4ccec2059babd7da521fc0f6dd83a4fa23f9d3527ac768433a69b230f9679c15134f0e9473d701cb3071fb9b322ad278474b9b6c47d693d15d9b5a028339a28cff6d991e784027bd8a3a4058cd77891c1002ee03948f9e2ffb41b1bdeabb45b70d7c0faa8ca69ae727dc33aa2bba4476101fcb91ef73b476179af3ddf23bef543bf61345833d7c54831cfd0796169d118dd9097510e4249af6ae3d9f592a7e5fa54deb2ef94ee11b05da9929330aabe1c1933206e3b5e784ddafc47b28b366833250c1e06e0bd3f9e07f68c6470dd717a30708b24b5221bb72b9b0cd3f33fb7abba4f3570fb1e83d97ba2e33c244d77bd9bbc809cb1cf7c238ebd6499350731bb6ce1882115eed07d8657f250bb113012d8a7d915f3525aed0c76752563e7a7b2c93a5c0cab6aaa4b99cabf67eb4d0625b65c98d4629e6d4b7b651016b7bda6976a1ef99adface2487eb08282549e55653426d8675dd85fbecccbdcfc56eeef75bc49f50dace26839059a449ede81d11a1bba3a052a2e60255e3a16ad98790b1fbb8988b644bf6b727f8cecd071698a5e635e18ea61767dc362d25a057566db5d8f627b87fcb3e1213d90ee7099247fd385441fc3fbf5172700a5abb4f6a86d386531af3448544f83ff80fb8458d9e178e39c7c4ddf8c33fd1d09c71530ddcfd771c6d0fa44c2f8c857e5e0d0830863c4916fde72a19f87ddd217add2e0c26a95e6026f7c8b1f40fb1d0ba7d0ce90b51ac19888664657da6984b54efcaefe2e0b863218ce5a229687c7a509975b35c875be0c28ecc440c677051143896cd7ece8a2d6ba3c878beb0113a2c0566f70ce2e44a28544ec851133631e9327654c6155baba0b3287413d7badb264a28e7833150e897a7ee68728d4daca9df00d15c05d136e4661492b792d9135ff59ac0cadbe31042b01b5e5cceac6aaecd94f8860436cc1b840760d0538507d2314ab7287e0c570f0c387e7d477b93b19324fa8d5c47c28c88caf26ecbae11e5016513066c71a062aeb560a9024e3cdbc21dea9ef7bdfddcc6a9a3b215a03652877cb7dacf09eb1fe49183296781bba01666526123efce27ce7398b1961b2d4855ea2f012dd772953a6ec6bae371449464aeb3ed91e61148f5f14790d6e641062dba9ed8dbdf1f934ad3f57e10a30ed69a56bbe4b8181adf0a957c8a6b69d6e699ca308230034a244044fbde94a0279b5706da82f5e9967a12d80336186feea948c82d21717d277e4277d43ee8fb5063465cbfb56edddffad459a28cb9cfbb771b920cb1af24207d6ee0d30a1ecb47e9efac2a88ce09737d2d8a1aeae1538d5ef9e13ca608de88ba57c66bcbc64808b0cef60ac87e811554a29d9bb8f0d00d28a25e2aea9ead6e0975ba58e38b2e6d3c02a842341e8ce6e1b41a263d6fab94bd8ffae6d38bd3b2367b13d6c55eb5ed6fc05151dfd70f7d800f3aa304e35e32b90c0845fef6f77172602434d5b097034deeab68398918caa727ff8777cf8959c5755ed0a24f4187d7836bf52eff1d04bdbc42782b24ae8620483c6a093fd77f58e95d0e2ca77b3884f2e6f84163c0ac34aaa45dd2b19ee08c747de82f21068190af204b1e92d594a89413e6fcd9bbb07fa9472e2e326925cdcea63f5441f39e43cb206bfc6bcbc26f222983bc891bfe49e4b6dc70368f8d5c9c54c6407f8f66131d6ea49a98b3723ef8235ef2f4050bf35684693fa6ff632a300a6a0d39692080d2ba601ee246aecfd80fa69f615a16af3e34566df5b7e295eaf8526b18fa90e1e7b6dca46527ff0d0431e4178c4e617dbddc55daa8dd139b36ab282b4c79a4cdeb9cae1d531166cdb6a200c6a06fb8643a5053b41a59047238aa03a7fbf2eaf15b311948315a555cfc5697e280f8069f80acead3a8036b3cc5429b4b4e84266efb6d4efe4abe19aa3ed8793a5f67b33f130f0b7600627bf9490989e6ce006fb89d0f399e18a851697faa7bba13a1f4c56907e11e77b712beae962abe279b57f1c7f0c1974e68125d345203f90877ac99850832756f8cc50f79f635a9f8babbd19d050320aab3e7e9485e55767b5ff0aa7d58aabcce32bcba6bdf555815b3b47f77f4a6a134340d10d3ed034f2b517779c494ca2145c7b7839a8252dd4ab9417860b896abc88c4286eb84cf7d14c7cfde53ec50268609d09ff41bf934d9cc828cd2e4e7baa42e72c6509a9feb0238e30863a8231cd2fd3133c7d36280d3441bec0175d784d78d8048b8e79e457abd49d36911fab7c01310ee024b5a2fb3878cfd3a7b369194c3b9582aff5aa26a4720f62ac7785c112b6bab2364660cafbbb96621c158d76a1fa01c04a807e0286bd47675613f75370998d0bf7f45765d3a74a5fee2e3f2af8820cdc5176ebd16e0b2f579eda19b08c7bcd95d16b5e82e6729fd47bc915bbc5f6de6ac31b973b3fb6cb68b5006b507ffb4a7272d3789e6745fbfee294be0ca498b511c86844bb98dab84979a5e964069e393cc4b5a9a3f7f3e784015ed23f7f14663a4427b81cf8b3e3f4522f082f09f2e49791b661e5bb7eeb5c1b3fa4e9f350f470d8931026388946830ac37b18eb4dda2b03f0dde721299d0c38027e922772cc729e0669f2204f83175a467143c5084cdb8fdf68d3e55dd89f84a67ff68075369c8c03f4c857af6f401db7418810544fa5f0305b556703dedcf3b8d95ec343eb02c07b7f275baf3658991f0c18fc869d03b4b879158bb5e3436106862f52452b0a1d534c6970d0c8bfa1cf2bf3c5963bcd3b5cd714ceceef8cc563cf7441de9f9defc6f3a1344c4baeb5603cad6401cbd1fb14fcfad8210aeeb7b450daed5c69276ddfaabc6a1ae3bc4fad8e0a2f4a9c99f462100de61c5a479cf80058f8fcd2663f88af59c82c2bffb4ba5a8c8d9c39aa767ee0e84dd9a3d755539b873f36b4bf12836af32d2856bb2aaf15dd2a117ddf46ae8d188923b2e6246a8841b2e9121fc3f6c1102469df33550f6d55372ba498011b23b6205c4462793ba5a855b3ab6371c2bc72b3d18d785021b0f897deed2f27ed932035a5007f99c61b7e3199a206aa4dc9c80215b6c6d597ab606c569ac89854aef93d98ded67bcf75a7236af6c926b4c9d65c90af2bf0c017792d8dd6eeeb3fc1a54e435e019c229de71d787ea418a99ea25e3f29ba5bc68a78a09db865fbb2d95bc99fb211381ee88cef4fa0ebf899cb1309f4d194180a7f6cc4aa2b94843c27ea6c9617520d0ab04fcfd9fb3cb3c88a46a5dc49954e5c5722c2c5340888b28f5ece16ea797d216735711e9ee25c0c77321e48e614cd91269bf1f8cd1929a6f4bf499c7d55a971c7a2153aaf103abe2aa2063a8d02fbf064126da7a81274f234bcfb347c4d3a37780f39446aa20026ee46b2ddc27bd3baf97a6e667841dba439689723c297df4ce5c921e8476b15ebc50a9d6fcc12c1be18390484372fc5216bf8e6370152b0f6a0f43e78ebe7580802e2768f8ed14f4f2c99ac6df288f69c2df5dd97cca2d40920bfc94737508c48b54664bd83b85c2e03fb8929ae02a650a77b861d02288745980ae3953528e76e319edc523ae490d1203f1bcc53960e8b73739aa8d94822c278f17a38f417f642f34d8717e1548624ecad41706c34497a2e76d708fbeac36388a84dfa387ec2ea12e2b19e69a85edef6fa146dd8ff3130f803bdebcf85ca29e1d6b29fc45968614a3140dbeefc8e9b694de8b30de4d34340084da76c59855e8b6d65d20be3c0f8563db49f5054e36a7f1b08717fd167fc3715b63f1d3c677d1cd7ca6ebdc05a5b29cfe68a7e9f14553249ee83d56818e5a30d81009f8dd8448358ab2beed273bcee02a4d650e9151fe198d193a20ab6c52bfdac68f5e1a394b3ce6473fd891ddc8a0ddd121de4f57ad3f59726cab259f4bf8412f19e964d493afaa3d026c6e4cb0ba022daf88ec4ae407169eb9220d88a76730b6deeee6f9bdb3def45653ecba35f80d5b01776c15b8358dc148dde439802ad76abbaac7f436307e003f557498766f6b7ae8d75f96ee33a399b21cba1a1136b287fa6aba2055c113c089fe5b16d3440f73f69e0191c38e668e9411d37af555b9098a4c45beb8fdf2fbc7e216ce2acfa79fecda14000347fc332f06fc7d217534547c2ef335056d9b390de99f7a56485740a8ea2a51a0aa4ddb375ecaa37f388cfb87dcb2b6e8ec8efd0b6f2f3671c23197eab84cf778820c57268a72d15c3153d590718b7f93e270449f69db0041997d4017a389aae9474d12134315ba5b2408e463333d1d406f55592a537a27224ccd999a240216c842cee438463915b9f5d0ab4bcd885ad4e3af6edb257982dd5c33ef67244f708731f338564fd38172f29bbc82c24a4c6f508ddf49af795d511210a76f390c8dec4636d137e835eaeb86f7d3024d1e78c5a8ce7c53045867439eceef75ed3edbf6fca8d4c664c8d802eea9d280aa29b0d35f8c13d751cb32cf0508024dea4c1678a8274c8349a50a3deebba47dca03ec9bcbfb8bba6554db8ccf873fd3c3dfe80e02a3855091fcc4bd5eb855f2bdb80f7938d0947b549ceced2c284d0113659c830b8ce2c9d75a35114bda4fad29b5b7553937eba2bb96c8fe35c542f882f95f1cc69cea61b2e892720a8bafb7879360031a90fb5b1cf37f7bdc899cde639b65f015b32bd4322dcb510eac71fecce1836a048b15584518a1067277f2c3bf34a8211f5f2b36968e3f28d085f7a46374568d894f0bac74a2247c0e86b4813ecb00062834003bd497708854027b961bfe6be3807fed5d36d9934db9cb6b1f86155ec2cbc55e9addb03c475b69c47dadfce94666809536e823e15e7e17bc49c7f1c695d06c897a27f6a17f62051f4856086bdc43e6db8e213c9fedb706516f41e010378dcc53ad64de8d737f63e632d29f9a37ad51c16ee11a0daff69f16058aab49eaab18ed097c87e3372ca3823546748621c2a755a616fa267fa17c6bfe70994dab44d3f4f84f65b763e77bbfaada5169d6c6b1c88d38819560651d4947efd2a905576e56adf9892b04b49b7392b9117fefc1dc0309364b7c94ed285dd2f11dad376f92ef095e4141358063578de9d40739f06ac72be6edc38f4ad36267598ab63ddf59ae659c3cccbdddf11b1db39123ee45a0faccadb8d2cc8512a957f311f0a764e2634820188a57f7033cc52ad25115fc07ce6ecbe6b611b368a5d1e44c5cda09bd2887ab4a87ea72f24c4a175e27a0651cf41f58b0fc2e093e35f4aacda5faa28820fab7284aae4b025442a480a41c82c459c68a2b741b7a0f520aa4de342cec4aa00d6806e13fe5997c0282dbd9565a82edea4cd24fe1cb39a5d04d01e9c3e54e6082bd2dcc271ecb3cf75c20d1c3087e02b2587464fe3aec1e004392faed7d23e0db5287c6bd7c6e6447d2d930ace7c289cac6ccbabc19e743c1c8c1f0da22f103b5d38d12b2974d39e351dbeb42755c8d417668d996742f95630584911787969159c0b2441ec89e741eb04d73fb03468aedbc5269bca5acf855aba365fe667dfe39621babc9d4eb354b39a0b96d04ef66fb6b3f58c3b9d28082adf131d41d606042d89d86eeeb5c8503da329ff111eb3ce931fe85322473707af4da06ac21d04d952975dade1a3d313d2cf3729a4f48a38f72beb8cc3bc8451f712f1def1155f7d4a6e24e71be936170d4bb1dadd997465512f35b5b27582752980fdd61c3841c2c07ef2a7a293c3e841d737f4ff67dceae9fb036fc0947c59aaeb4fe1196eda7fd84f882077c77c0da955cbf37bb98af6e8ce6a95980dade92b02d3f38cd5c8a8aabca7219faefc767552bd0b1d5dac0f8443d42ce12508efb72fcfa19dab8d9903a0543f1a3d2c27e2626f6037cabb9b2b10a08df3bed146bbc2295940a32c9c5f48a3f0d1bb1a41740ff41751287ecb2d0cc5b29ad8ef16a304e0c850118468238dffb02c53ab3cb4b1044bd39ec64ac7ae0d31fc6124cf6c6d4276286bb8d96461df27896e948b805b8cad379235289eb11e6173ff92f2f72f8454c5bbb371225c705e2fde74330ce808fa2dd1bb3c1cc72f1d5b1338e25f25b5caa9669914a97a25a13b7ffb0c5ceb769d1cedf11a287cf1790e373db5acf6dcdeac2d8568d6bbab280dde753835fdcd0b613767caa95783617abd6015863ea31c246a115716a64914b3220fb41944f3fb84822a681680426e6ad32a975fb491c62fdedc025c0566e1ce1536fb94699f480e653a58e07f5e36144c964d3043bc98b0"; - } - function data100000_2() public pure returns (string memory) { - return "e23d45bbf42a485c31371827e14e7c14710f0ad81b37a9e8aff0c9f82c7a5d60f546ad0a309353875217c9a6aa3ab16c774ae2c24498c8ecebcc61af8f79d9e559c50cbdef6f48e640bf5ec025c970aa9a7b310dbcb4978733e298822b7dc0cbbe685ed6057588c07bb88dfc2d98e2d64ca3fb679013218dd8c51dd64a662e901186cfa6ac79fb17674dc79ce535f0d243f88a80438d4008c1b04f531c8e91528f0ef46fac95361e477ef5cc48252a4b73c18a37cf3b6cf7193480214d4129355fd546502f44e7449c2a164f45107d63f6a831996d966f884a40b60c03ad139af2af9903688e713bcfa34606ee62d45b4bdd10da0d192f83ff2bafb22f9a36c4d423ec4a9d9bed893134dc9cd6e7a5374a49b54f8158b2acb49e0e4b10d2d20857dcaef77dbd7a36205cd27a739b2e9b4281e93b4e5ba1a3466de74845d2f70ac7af2156300c45a9e9c64ac527f1abd4246ca2e4ccdc82e8032f49ad46c8ef96c117a58abfb20261c78cc7fa02ad8daec4babfce07fcf1c82fc7f66f253a30ebc836eab11738c9076791b075c1444959c00a81fad6cf5b78cf34268c522adc07a4210869c3d7aad606c4997b088349dd7c0b74ea542bbb78720176d9a1fe0841480a3e551c61dc713e2115d458911b37221c8b3639feb0e9637264069e32be1a3abea2b10e8ae4fbb5cbf1463057e861bef74f56732a59514bd166bf714f223d30462bbb39f3515fcd1075a21be27dc0d1b8cb669e9d446f6f32dcc3082204dfce8a5cd352d8cd55f5b193b54b5a1e171bd50bcd304dc16e003fbf63b128532e4c0c3e9230dc8629b35e65c850bc62402a6fdf0b89b72fae8a42aad56bc83d731444856c35607335294084c10a46284d92ef65011485ebd7c43e5403ee2361cd4a67a1032eb94203690cf7ef1599e970f15f20f486b53cac024680f92664593940b22bf90ead8235066192e91c291d8bfac19e6af05385e0acba640701359c83620f60a541e81b976bfc0ce1bece11d04f6b857a7615d5ca51849c6a40a39d841df0ce4509f2703eb6323fe71fb6f65a7307c7aa6b59702bbffb67ec9f453e2f6cf98a2e14b205cca2d796ec76fa53a6ebe4c8a329f9c7c4acddda30fe460e3cf62a34e1d22c9848a270243b5a07fc263fa18236b4df8bed8131fc6bdc2e137c9c890c2b8ece0914e0ee76c02afed33a801f36bbf3d3256f3d107be84d2417c9451e21cface0918b4be7222098d47f745515f4f1d2cb0aa2a8e5d4e78e09e29b560f71beeaf8ebe6b388edb76978a68e5bdc7c5c2bbc18c67beb27dc2ead2f66a8639c8d71ae2194da9b21246dd3974635eda722102a5f70a0b6bf7323d13eb5674b5809acc0dabe48d55e459f18918c84a3b790a410fdbdb0cdc30d3b7d1ccb8e1b1f6e006c4cf08776dfd9a27888ba05b2c4a0bed2255dce25539fefc34ed3c7926267ff74d4e01d2818c74675ac61abe63effea42d26f03821632975ba41f90c6fa8693bca3faef59d76a260861ffb94abc09271bc5339fd2d01c0e2ad4f8fdfa1d7d3bc108e97c6157b214850741f53c5f0d36c83e07755e6030f49e8da4ac40cf34ecb46c5361357488507d1969c54f87d24f5d6b1b191aa282cbac65984c3c3528c18fcbc0d6d612682696e2f56ffcbfa9d5ad434a472e4f3b3742f4751258942944302224adb75611899f2409e7610f856c03e51106f04c78672e9064a233474119d17c83c0906baae6d8561b5e6a426ce101b36724e1ea07eb22e25af48eb5fb82fd7daf4f0db4bfc05930134060b88a980f30e875e94533ad762e01645447fc03459e71452ea9a6511a52f4874713fb6e6e2e13f21605365350efe932d6f6f43aa400c9bc58e667fd49ce53baa16fecc708ca6efb0299bcd9331fb0d3a11481c763c715d1fe0b8b95e1121d4f7c182b6c8e0d690dcb436a5419eb3ea8429db173139bd5488cd453eed43d218b5639123aa8f7773d0df50a86614292653f6f109ded5a5e32b060d49d29aef25643172bc982195526d1fa1a598eaa770189207606c3098a4cd255573c936a0a45c3a67cb62cfa9af66bc5b9c92d46d4351af5732313274625243e240fdee6a428dfcbed38ef32007db2a7bf1def4976957b8a43e4d1006f7017b39141d7977abaff3f5fdca3d94ca0380234219fcf900974453e1075e2a8024af2289eac24ed49efd10b2cda31471231d73b6f00e0ccfdbbdf3aca08b3ba13b4a3b5b850a4f26e10da3fbbb7080ebb1ad2f1ab4a32a705d4ae9d15b0e15c887a0e8153ea478224a187d640b3d716b39c7d127201726bb0193dbfe395c21ec7bce1e2078fc04a7d1bee5fb081b410cd238e4a2d33148866df937cd9a5629943f7a55ae9bb0604ffaf3593db1dbbe660fa1cce77fa5c75aebfa55beacd75fd9cd81a253bb57562548db3660a0cc647cd3cd728c68b13e71ce851cab61a2814b8e842384f08182419f341e49c6bbe3396b5116ccec1e23a0af5d48c036df85b8bf18da9c1b40c96cb8378da674c3fd67da13cba16c34c171a87473adcb026555660c4b79349f7637f19eba18bc15e2523d66f751ff1fcdf3b4294ccd0c84173e63af53af28d32d9add2a7ceb7bf7cd794d3a8a5a3ade7aee135472a9a8c84138c20f9b971a95591a4cfe9dcce892f1d1fa361610ccb9477897112c9dab12eb2ca1b59e5d70781f284d703acdb2b49c2b2f4a293cd9f6948355e81263bc1adc4e9954e30f342b6a778b9fc17c29e680db0b9e0453b1790e02afb165842bd3b5720a6b691762c5cea1a574a7987bc6fc413f792590d07e7ed03f95bddb004db11051bd284a23018f20af262fe735651bc442b6ea3c04cea4b67f2312ae2816921ad821fe1891fa9893475f6790c3bb90ff0949ab0f3e7cd0dd4e6f399f7f4a5486b4a76fe4c7a199c0cee77bbe754ef1a5081c6019f2318406f105eb240a811df35092864fdb3885f28bdaccf08ab8a93e3bcf4efa2ea7678846027ce93fdf1fa7525d96e54a080995509f9e9a518e81a484cf2242bbaef5da9c8c74bb907eef0c3d2b433536067ca732ac8a3c85dc1d780f1406795db1445fd4b8f8e46318e52aad768d054351a6e9bcde54e3f100a15a7e26a179293243ab4e059bd0c2c4508847af8258945d5c4b84a251ea116f67106d932aad4a96c3bd8f569ac77656726a84481f6c135ae44d313e5935a1781005696964151240d3b19faa0d8dd51e924db45d1494bcc5c34c115a759d85c79a5de0df076120e109c63f7044d510e9d847349d45f3c67f1efa6a50b01c2a888612570e79f60c58ed83b940016e909573144ac4f416c1cfe993e945dbca79b48941508b52e882e5b740e817d04bd1a23276d16cb1c27b7c05897a44645e9ed84aa111b3d5aa961cc052f7490fbf867b96423e1dd664e33b5a1107045d7fb103d02c779f6d13373c3f93b64eb2804ff22ce0a8dcd4d888cd92ecf7cb05ee1f99cad351c533d1b9d42cfa6227ea88e38e1f540c79d8787be9ef892d729c8543fe53431ca4502d517aba3e03aa7400460b748df0d833506a58b5a92c1213a6406b70a2f32d9a2d3a9c77335c41049a5b411f0db98646e2e6da81ab52cf2d4edffae65cd9412bac58a4fbf417a1360a94b62fd71c024c69cfdd9a8657b95b3b2b513f98d2ec624a2d06b6aadea080cb75d4abc602cebee79e6fca769a1bc9344eba32361ce818b810744365bcccb5429f5d24ca2889fa18cb5a67db1b169b5025e12e83dbd0e002a5f3b0de5e912ddec0979df3d8f791cceab4b9d0fe5e0fcc9436ea5a68fac15e3571ea459563eb6f197c5ed82df7c99b529f6c72dcbfed4a5cdb7dfd6beab5630fdd1a3ea50130af87818ba352833a57434255abe160b5b99e9897da50f1c36361011855134b35b8659d0cf07962d303aeea84b8d39cbb2e0d6c7b8988a0703137be1ab0f7a3fb95d6d6822e89b60020fc09baa6cc45944d0d625699b539266407a5b1c5be7d4f524079b16f74d03fc824786e30be78dfe5fa777ad9ee6e7d07a6455cf97e1a128678e0e31a840860ca16ed9714c8deecf0b8054e6f3adc053f9d2d0e9a33c6a2611b22ff86c4484df61a2ed059732c68e4f6703ab4fdc4246cb1faa8ac44e391195e74351cc4c347068207f89de2f3d875753ba6c227a912ed048f7eb60f5dfaacaa58bc9a6190618cbe13fd1d55da5cfb0dfe29ccc4c24927fbda812c93dbe931c522da7c5c8a94f0d1d6f4c77a5160fe7f4da182aaf440f33c8258b10611e743482af685a99dfe0ec786dc9a3f5448c8cd82248b0cbd30e4cfdd6c4762f8cce1ca49bb28e6be886067da0d68951cdd29cd787d067e2e978208d50643586cecde51f0466064e46c2cd8225dd3948e3735dccf8e2f6651e4cae1c46170b1f781fb8079edef3777dcfa5ba8443798c63ea7c28d4da693fac3bdf7b5ea207c32d7292d79f81dbf16a9f740a63bc78cef2aca4b0e57600d74f56e394a1563f245b9f068572ee79e5caa748cba429e57e25955e1c974fe83ca5cfef936ee80f7594b88a2f47a3742ab9e5677decc796de00f88f783474fed428f87467a6023d65f130634d26d4be0f08379d7ac812daab8f78284f6e293553070c6fc22515675ea64af6f41aac5f374152dfa64e225b042c0c3bb1bb5767b919102a3a3b2a8511fc8187c2888ad376984f0c357f2a58a8e84e45ec9236937f71e2a9de3869a803815f955ebd41acc91a9b8180ccb05b2a059e2eecfb98b03a2c533a16f32067e13d4902a13e0072647a75117c71a4ad551ea87804da152c87eeb21794c99b1f38e1b34d119f7f6a2ce370fb8bad6a906391f486cb5707304d338f618f71c6c25fae34bd391d6eb5fea719cff2d755ec20709db5304efbe2123b1a231a309136ded9dfb68a40bc90ea327282dd16786de0d414918c2d832d9b2bac741378c4ae2189627ef02dfb5e8077a1a46e7805e4fce109ac19c6cc509400e1989b3193219278c1580555040af16dcbe31093bfecd41bcc9e954adb1767212fb4577735d07ed5126aff6f64851dafe481793be2136519489a7340195d5d29d8a70e21bce15a6f6a9811b97db5402318c056a1f8ef99a01d3342d8b2ec2de3626c69d9a82a0f034569dc195d01820d33fc53976eb3ff17bb17dd7aae69aa4fa2e0de45bb1108337b2f624553c1b903348878426bd00bcf19af6aca49982057a49d2bf6ac98bee56cef592483c255c7397644eb18fd4dac10e984c34fe5de9d996c5e79a5c3637e40c91db76e5f8f207c2c53495063adb61e85e9a920d9ef85915216f1019e96df9591c0ad96232aecd2231836d657b58413197dd3b4dbdb67eb7a6b3dfea9876e73acbd2029d804a6cc3ef7b1626dbfe6f2b5da20f9d9eab49be3893f557fd644cca77fa6c3f9c03d12fa35760b2f853d8cc3ada4cbbf725a01732b38c95b74ffc234bebbdbcade6c5038582eab509821cd883ac9411f4f1fc0f4dd5a6ee6bef266e22b6ed3d0f6d8ac9353c253a6477c106c6887d704113e587b534078eedbd7ef5841879397afea53c3a9f2bfb6b7ccec27d954da564ff524c6085fbeaff5ac786862aec682557775a0df9b1a3b59d55277d0cf19a0f5f100011568d8c60e7e70c6f53b221aa55b499174ac8775c661d3a78a1429eb2b20975a0f4b59b567df66d735848e436a48683c20dac39382da141523478fa51c04a61920369e14fbabe08af3ec67ce81381757f8441739df17d17b249798dc6b211018222d081ab416718fb1ac44c2791165cd5f950ac2e389ad5f59c8d141f5ea404e8c3c64ad66f0c2506e879e115fec0aac7e697bdd5b9b5937277b702dda72388ca35320762de23b90ca91890d54fc5fce36a99556e3578a1222ada27e8d4491ea5e3e37924224b764bcbbe302a56b663556e5a3b5ddf6548669c1d3d7eeb794b6fdc2329f9f01c72380d08157d1e40b0154a999bca2de32442031667516f9739465055e53259de3f06e8a25bd5a3fe3176fc6fc32d8a537543b09677941c5ee309f55629386bcc47803709db4f496750e63fa3e9886b490e5a730a61c4909f06c993915e63dc2185d7305a8014482076b0f8471937947cdfa80f50cb39d3065fbb55fedc9b2b6172c699a325c2fe8a0f6456a7a53427380a91599ddafeecc3e87f05f16261f6d8306d9cc91a69c970b0b22385fd6f057a5540957df932cefb88598570d3e8d40c031d9289d270e8026773c3f0ef5d9519193b3cc02ce634ca979287b1daa1dde2158d8859f1821ac8b1fa8b96356ee626d55d14c5d13ca23e5eb88e7f27e02d24a19f66f77899d3d9a57515977b9f00aaf3d2fee971ce8a7d60e9513701861be4065d5fc4a5182fc2ad8bd9e56bc32588afca5d7d68924628b4a6c0e71e1bb9453fc77f368b3602a7867f0caf9e52b41d85e1a0cc2fca8058e0d139f10060b07e1327572ef27a9eb2374fc2fd460cd723005e991fdcf077a3b7a571308478765d07397325e99eda5f7e96f8f97f387a04f518cd4695e240711785f4153d6a307997bb05a2bcf30e290fcd2e72d855a54a1d40bc922718fe0280d76a31706156b05ccf28360514c53ade049063df29d20a82d7a34fbc925d78203d2c8d98bca7708f5862d89cb69a8f81cb93c6578153d93cff5c39e016d04c1c4706b545947a3306efc3ea036fe8b6c250e50f3e903725649d1d9e09bb980d635fa313c2abdbbaba8ac9b7539b53bb299896977b9e8dcd292cec81d4fce55f9efd5e96db0ea0297c29f5985548faa31341913ab8ec8863ade633dcea9f7d07ae8d00b4161099323769147d7e50a8797600bf0655c2647319bcd76e3a498b187d129c49cf7af469641e25b313034c542b44b04a2138a6d83022b76e4c7a1ebf2a974643c640e6ccd544eda68142942ed513aa88aa53fcb05cc3293f977c433a4aa9e978c74c1e3cb2b16a02151cfcabaf1f97bf0542c10cdc8eeff34e7032d07fa736ababb7220a0a2471d67b2647bcdbf3498f1422e5e9b7d360dc06a2275dfa37f11157b24c80f2722eff6f1b680b5e3830b66dc9773df4c158dcdd77fab3014d82386887790a4d31cd2e5e41bed4bbc3f75fdb859c4d8b4839fb1e3e16756af22c7d27686aeee857339152243df80a75b2279267680e159bfec6dba0b9c2ddfe7c9eaa38402d12e9627e4d78bca92c5306babd9c84facf983261789e5c6ad4ac9711e736eec708d1a1dbd0086862634dce9e440092ad3fa1d1bab2228d55b8d88a5cee246632b7b369db8fb3f2aabe874755b5ae2da05eeff369ff0a952e00fa5441be86ec6d39c4f0feef2036f66cdf23d6c51015438dcdb3a01f708b1276edd85e4c24a798336d49240f8ad67b18f7326909266881af21d8c8b6eb0cf70d49c06661965b0facb45e6df056d9892104b77d0a0533892b9ccd68baa09142acf19ff4194e92d070e680258637024df3700acbf02b9fa5e5023b6bf938c0f4d997b0ee6df69cfd41f3819b727439d29ccc19582f7c6964bee88a1a569dcdc63a17ace5e4a2613604da9ac6cc3007764ed384e46736aaf194a7b1f795f375b792cd7bf75e791ef933cee5d2185556f7086e33df0d0776c64a530173863c5de9d3024b7e4017d85807eba287a7fe74a90d6e3567f747ecfa400e40b7635ff332f93c9512a73660c6e1c2a3e8a7440e019e5927b760413eee6387804f12c8e9799dcb356b5947ac951222bd26e7f47410a236e3cd24e4bd5fe492768e3c8f4b26f38fda0b5d2d490b3fbe5adc3c1f26e055f0dcf4d373da1a45fcdc3cf326657ab377e2b992cbddd425a2ca38b02918df78796a3863aef80166287f13e10a0e76b74764999e70a3d3df24c9916fb298c05d979daa053446be76ebbc764853cb083ac72e37279a06b03a7045ee75e151307c4eef3d2ca9b3173ec0c18fea36ed73a4d460bbffccab089c2766d5a3f0e39ee58baaa23f43e65479aedb51638953d87269a59ef00d74612b8e3e03561f0d251c5f690d84b80023cc0be6e0fe630c00a8008d5f5b4823687732978550fe63f54d8c1cac0dde05a348a7fff2cb265abcb0c874dc516ae5d902be0aeef679f910d5287041965050411330b049cefde58097dbc158eae349da7e7d5985f871e6781f535b6b4d7c72d4188f6667944861dc1ad350c288a7e43ff438407326b52555b2d681ffaeb8c117d1a030601e4169fb5ae6b8dbc4b74cdb093ffc2b9dd697b2a19e39af9b2f8489646e9092b8c57233647dd04ad76ffebefae590e10c3e9d59d0e3acf49cceb7126d63e62c2784b3448e82c51bed6e8a8447f720fd6034e078f6afe9a706d5e83bbcebfbd73f249e1d7bca6d4bdf6ac690a821196db627a64d2a182b535b582e8cfb9e3e4079269be1bf0128148e2b7f40a496465ffbd89d2986c3e4d591099553029446ffd7016b65ecb8e753d5ad885457130190d49668ffd719699ebafdbfe4bb9497ad6bb0bcf935e3285068d6422d8ad9fc953385695d80e7ec7ad6159da4661eb11d8579a3d902e0d9d19e69ee7eae9a0435f9ce2440d61b906a65c11d823ebe0c9f695f9aee77de28135703c324af7c20ceb5050629761a82e88dec264f1b6934f909d2896108e7d48711c527af219bee38e5bf0499e002e0b7ba16e06e40146cef6b94f5b0d17025ef3a454d25d6133045107837fc17a42c7375903786cb6802a7dc790928119c7bc02dfa0ac5844598fafd01a17fd23ba47c3fae5fe43c5edff1ea9b5a5e40267c76c3ba4058a919eb3d427b15d866e3e007856fe002cd8b17d91329ca3e1fafa90c65e6c38df176cf9eab11824284953bc4a3c21ea657563e2e8683d1cea734a5952eb9269c3551f2d2ecf8efa67e1fa01357462a3c74ade268860c707e9e77234bd38eecefc308a07de21aef89093c6df371e7df404f52403f20bbe8eb7c7faf0d1dc1cf27ef36e8b88673ab8416cb9b44faae673b599221038a86c94a7f75cdf85acabdda85c12757d818b2ad803c0bf094475c5b770ec5c91768a13a04b2b4ac6004bd9dc4222b985f213caffafb1d0223eade041318c0336488665690b7e8a45d38eaf0ff87b659177813c67ba4596bdc229ae41dc98a3c09f80c6262d0cb51f6acc494f056880b639c688a9bd48af3db92a0ef6087c29ad7ffa6c48b8267f89a1dd4595a85141fab1c2f5906ba10ca60ffed5bb7b307dc278c23bde359362a34d03c9fd0dde45fd05e6516d83b4374d2af0cadf783693c067e5f6208598fc349c89c5bf64b27595b490865d4f5d11bf626819c80a9688a84e85af65bb4de08a2b113a4187db3a47b13bc09acb7b05d4fcda8e86fbab94d867a16794c1df98a8e1e1feeff7af0c44cf96539110a20d429e1676672edd4b0a1f0214874b432f5b4c2f5558320ba4f534f43b50dfdeb99c4aed6037ad52b7a63bab25278c7bb2f94abb39c7302cce778f950c6ad3521e0a86b7a0611eb1d060445f4b553d21dbd4a43c1aaa1e5aa690cf9c976e13eeecadabf8c24a6dfaaeb3a03eac1ce9253da7987eadd08e65de7121bd381e090369a92ba69e03607aedc8831c829f610428ac8f7eabc7e03b87363972de78533ca87a28416282f9c8b77391100254b7f437cfa9ca8cc7cacee907fff8358f7991ef27c29c76de8f18c4e6808742c6fa49bee2d41ba367574345f5053dd58f45ad7d81cebdddf5b72f9c936d08b83f716fc49611af18b614e8fd480d30d0f42bf3f715a5f248a4e4713fe7edad8660f9251be8e4a8c2851656e73b3b42f33352430756a173c90f78328f891617f4f921dac78f5602ee221ef36d4ea65b7699501be2f0abd5981bf1269008bccc835a1c90a91b99bdb95182ac517630971773cef3e44af4e5137f0919920d9030e16f7196076b9a9cc7034cc239fd6a74d0ed49771e5aafcb09d610051544f28110f4d895c347c2f0a543bb616c2cd7876d491220350e1673dbd66c7405f49212061c6b792a728d53ebe094eff8db2a98d231a102eccbfdc4708e282fb0250f694cb3f9088438752feb4e11b333ab6067403b79d52ed667865156e5b4fa2ddaa6a04a54c24e9a92f1acb0a983c697d724650c62e5aeb11db894cd96ce4895cc5750d3c592433193bd28e822a1f2da2a96bbc8f91cad91f380222edeb754f0d633e3f16d896e1f2260a4e4df98d4c18fe903f54221214dd8c3c69e59acc6d1202d912db103a0a355ec5d5002d118484c7e883cb4b20fbb200fc46662457e425e466045f5b2b47f182563ce464e9857ac127767d1d681b2af1c02f4ead349c2615d4f5e1a8572c97f86068832f9a1f99b4d060a4185187bc5b16d79dabe9dc970f297f89f6c3933cc51459341373bb11ea62d61399c564f22442f241aae5b38ac69932aca31a2634d49d7ef2abcf83ff8dfb4e4c3847b039111d81be4dcdaf4baa9861ebd1203958b37efde0d6210287ccbff4d5e7955005f161de1526676c78d6709ef2cd2cc040e325accda4341d235b9ba6bafe4435cc7753373b424e5f11e77bec9d68bc79950e6de2bba276514760ca142d78a86346242bf0c8e1c03c004fc8efab444c5abfb32829c0fb72e4f43106eca3d785bd7653c4b3ea4d6459cfa5a0a28dbdb4f6528aa6d398f9a229a9decc98b182b8d82a06dd4c8f7710fc8a384ad46708f66af71a94eacf1d53466bb5adddf12ce94cdc19a8af5089aa972fceaae3708275d9e7dd714e59312e124a3c9f74ce0317d086366bd24c245ce51b42a807165ec423145bf38d54fc27a97d1d2111c8963fe3cf5f3d7dfd2c60014ec53bbc2942e905cc25d9bfa08b91669887ee5f1b4a7b4c77ca1055097b442b38f992185719c073364b4aaaef8bf1e752777125d1560c492df7236ea033f11786afaf842af186336d6e637ad0618b47f2ecec739a0edc55ee81e0e34667513e5757c2ad77e69896119b74af3bdf6cf4226be8532629b1fb6573739fe9fee1db7f34db432d86d4be11092ff016e1c4306b58025eda761b63b626e1d21e54de8d2675016053e29f34dbdd4e7dcba5d8b10981852275739c16d9a628cf3b766c8506e5fb61697537d56fb1e07d967323aa1c3008939d03d92cc6361b12c1ec06c9202550ec4b673d4e38b372b50a3d9f7762db2fd50d1118bf5b8bebad6a7b787ed004a49296caaaf9004b8634f707ae9fba99ec40269d2f6b08edb294910ea18bb7e9c595a6171ff4ad4f0b7c045139c66f7ca24643a63f3c805923da4c4ab86c50056eb3f836ecc0283f2095252d24d50e1903ff3aa9c09297447d2b4d8279ba17808c5d8a68286f729338f5827220a214d881437d93f67ced38c21fbd54971dcb2241e2b700c5be438a12af53dbecf1b96f0abdda144f231b7f202d49be05b8fac83748caa721cf33cb1b4bb7055d6b2a01b9cad3dbe618750c5bb3731699560bfd0464936c4db7441cff4e0cbee47fe12668f462638a55d56e1238c9456d3fe120677f1b1b892db4a7f9bcb28088bbe2dd8a6279da7439169dd954ae8f4fc65bcc0d0ee8f87260675dce7db911052ad4279b0b620dd9c4e7d29cb858ea0beca3103c80a141990f9a05545f9dd3ad6e57965d13a154755226b6d921d3b2a6e3c2ab8b6cfffeea80eb8a4551deebf45938314111188511290eeae65eaa5c3f4d56cfcd981457cc97c1ec1456cab9bdd59364ec3395b9a04cc25be773fc294b5a325103154ecffab9cea5e643ceaa4baa18f56295c527eb8600cd6605b08c2d27b531dd15bcf4ff7932d8ef6c73d8da872e0c7927ef8fe430ef020c736e693b56c74e6ef95f038a6eb24eae1d903709b50f20073ed36e1698762233f2d86aa804633487b0c7cb17e1954683e1612d351876594b19014cd10c898c6cc23b08da47f81f7d51446ab3d9a4201d2df119f2e680f9ce314ccd2ff8adfc414563c9c8cb0aae016ddadaf6d58612e4b397814fc8b95f4e749e8cdcd6199b7d97dfe7e62c95380f3afc9103dbcf45ef00f6669b1ee9b24c8a79a47d127fc7b2ab662c9cb47837b2966961e082d5bedf441283ab90b255eeed0eb7e575d823f724e70f55bdc07128b271e33c44f4e8a15d993789ad903f235fa46821c69e13bc30a2a148225c222704f11a939695282419f912e099f2c7da2d7939418217aa584a946cb1b462d8748a1c6a567f5412825c180ab6d9191ec8569be704df0600dc653dc9e7e3f592c5439513edb3e9e582d8589735316d7355ebc15b7a5e47015c97db1e7ae2c5bfef95772259282cc5d62bfc054e08d5f733b96a4038eaca83a4d070537cea2032ea76ce6a5b64442b4852fd417ed8f5fad72acbac7182e694e994965876e5576d9e277454a70370d20462a0c959e037e9c7f26b2e8996407788ff9f93fcfc9b2706fae626e849e88a9b1a7a43728fa595012a339c83c26e5396b9205379d2ea59f91bb4f4faecc03e3edf14f7bc02f847b2529adcac82226e34520674e23bd5f486575c1303a303e1c1e18bf3a635cd8156787fb615a6b4c02726406f603f3a8a1c90219acbb6e3cfe8d68d6015bb03042a555775d1bb7c0b3136723a2000e66853ade4804682ed811674ffc97705fdabafe8040e3f439c5b1179d34055df6e44bbac8cd90bb55ec74fd362cbef730f4fe9ec1ec7c2dcd68d6cb5b0c9e46536c687a187c9aa93be77acad58af2993db5aff962f9cf0c6f28724cd767f6937bba618f0ad31cf0ee62bb9e09d9d101c6ba49d81f8623196eb9c3a3804b21af576a68b7cbdd55411ed01a8accd87c81e5166a99ea6140ac0e6e29a45a6544f2c1970e6ad361637450b47872a1af7a5884815ecd2282a337c31706f114dd3421699b364fb2687ef3d30822697ecb1e661236d540689c604dd08e552e101d973073ee9eb74f75b3248ef7bff6a1e0b4b02492e451a8da1e092bae2b957cee88ce3fba5b233304a7b2e5a8da6f0736e16ade9b28f7311c7a037bbb07b0c23af8fd3c7c39f4ec06f1a72e1c803b424a64bcda97b0664ad0cf168696651a9ce50923a4d71becdf19ac1e04c9a0ac5a8ee18161559cab80deadc538e336f4aac5d45411495d2edba0e623c236dc49b08ec796bedab3ea4e5efc1434bc7b9cd1b23b7bd75c6efc63c3f1e4dcf92c21e2e0003588d5e39d6b21374fa4a38981aa0f193457c257f76fdf610e866500d1d0a4cd5855b4e9fc75d93619d6bc97c25ccee961083c57bcf4be3aad01e527164cc14775004e0b0facef0adf126c8a4cbc0c7afa0c8e36e85f01689953cf7c8321be124c52189e43892bc4c26c766a9c298d04e94d1444ed9daa7dcf2955a846df5768db528efa1bfddf1a22a3cc9d10a876b4a2dfa44aae233de1fd3be0da491ac9fad3ac01ce40eda773b116a32b297c24abfde9c23383b55edd9a738a11a4ea0a5c70ee385266b4fac12da995c9144d4200ae3badf016a146c7d31e153a4b0a62426f0f46da5d6d911e1cf6552eb4eddee42375256f76660e1b23e3d118df803da75196a658255024ff2a2f23e26d401c336e5f1e10a87594289c56848de772a656a2925707158f13e41beda7ffb7351ef7384563a5a83022d3d37b1393d5195b393de6d28de61def752d7b12116944289f0f627df0d398547189ff98bbc343c1a2c25dcba3edfa36cfbc9a55188fcc19c94fb898afc7806a1c5577b83f36c51de6ab1bd8864359624c24850f4b303baa0070cedfae8cc2f7f16a3ec532b052522ef913baded1a34ff14c55683bdfbc686f264121734cda36bcc7974c635e66c5d783a69cfd2c6f8d1b3a5b004ab6d8220213c52d16304ebef06b5ff697a43c9657e3237f733de9c461b1692e51b61c84488ed6d65e07ac2d9856f6ef8f729ec59c09db535257474f42b219fa97c7fc4f7a94f539433d6686452bc3b8dad964d5fa6cc35ca5637e1cbe98b6c600d091abe4218a8d394811612d39f3679ab02bb519e4a1b7060f669bfddb39b729c2dc4c788346d47fda6990402feac1f49d807e38d9b362310e7d9ec0fa81694d785dbfe633a4d5534c24ab5e79cbf1654fe7b28b4c862719302ebc9e8c130f0c36ea2e82eaae548579c0ccaf047d0db3f90e59ed492c3f9165d9adfbf3c6bb71c42b58691168d186a4c9e85d3c92fdab935cc894dd8f157f00fac458b1bb0f0f534310cb85a1ff447308bf012d5ea9638d6d5a4f481b805dbf2b63586a90"; - } - function data100000_3() public pure returns (string memory) { - return "217cb822b6792beb6844a8397eea9fc9c00e7b7b71ae88bd07cbccd1707566bcaf9a54827152fac53db6cabe894a4c901d2be2e5be5391bc5e29c95a037fea2d47ad50caeac201c5189295ffd92c3cb77c0c4071e5baa122d8e5f9f364885c0b0da09cda60b093d5a29f943fd45a8513eb5775120bcbb9c0ea05f481a8e037aa9b560b2aa15b6344450e307337f0defd6d610dfd409523cf08c2786f4345457a6b74e07288259470d6f4ef5ce2b823f2a7eee1b42f65ddc805181697cf9c7c099482322b7c1325a34bb7815a6243c7e03aec8686eaf0669f3f56f3af71c6e53545c125c1dc9190a8f8c815119a67292d2f71520a76e5aef1e24431cc0c09ded107bd23fb345eb944492514fdd806d88b0c70c933bd8efa673ee36f1b009d6091561412405d89795e814a6d4ac2d70dfc067a7b493299c829c34ff7e785e77e928137e58a7605ed64acffc01a75fc4ff545864ff6046b2044c1ce35fad8f61acccdb3aca3e19f1e2d4f3b3e0e6a2a13db4436688dd61ad71dc279a625bed619c783ceaf00a5249bcc96dac5615f213403ce979f914b945a21b9692d28806f0b0ba8d5556ecf7b8f1b0b5b6ddb98b43cd3dccced5c5edb15df8d21ed5f800a3a197c93f253100dbf7d555c704b88017f5c02d3658a204f5826f576c46b9ba4f71981ab5ba901d60d5a754e9ebf5119e30e407ea61b0ac1562344e97ed7328f86fc37cd54dc84447fd1fc978f8686a44509c0faa62c0c450b25211b8289e948e86050fd8bbdf4a4dfca687512a0169833c8932596e15bc6c96e3f33d03999505716bb886da855df9f0b75962d30658c95654160505d75f412b3499ff5c43e56cca99c6158d324a89d6c2364512778be0ea70bb862316e3ff532f2570092b1f4260e3c402c9b86176e74bf5faf16ee32cef4003822fbd032111f9c75138ddc0ce92187924e69a41602978df63f8012778ddb058f55155a695936946624c533df5f83244210a2779a8290ee51cc96f14c7b210637e985da2f2c3ad26f35e11fe216e64c202a77f2ea23e579227e487020b3e10df41e7f9ccccba4171a8dfe84c3dcc25ef8d764173a45a2b30b67316010539920f7f7d26e6606c3962239adaf6bbf7737c44f48e783a74d0b63e4cb177cefafae75873cb5123ac42cd3c508a51efc8d474d5ed2b0a08ba8fca3e686c8e3d67c00ed4964ee9726ee558718246da39a494834b83a29ee5a5470c9bd5f1b82f5ae872a0a918c2329fc2bafac6904065f2a43129cabdc0e366417b110661c4b2a39a953d16336b34c0811749977e9fdf699727de0cd0aa0a49ca3b35b7071bfb32c7743624dde86e5428a93af4b4e96f575ac33328358a623478198505cecbdc141fd4d2615db58cebeeac78d8db398e54f5bf3b6decdc43ebfe8ea8b48859d54a4e4f5afcd4bdb706ff8c483f5d69627607b3bbe9b00a8cf2a05528c5f7bf04aa7b6fd23c0dd5fda69dd8c184754ccbc2c4fc2c3a36f78f83fdfdffd85f9c8dc67fe99f0d238eaaaff91da9d8a030d467c2f1171778deea0849dd0950f915d93f1d5551f5652ecf3b4ab41dbf15927d4e38246665ebc0e77f50969a9e6e625ea3677f97485107a069bd52a0e7fce6305e9a47c693ddf8a0cdc3c7b8c46663a515fc46b96b7c3711e5e089d7d5d20db758c0033164eeeb7d061466cafde7384952b77fec257f187051645ec933129d9c2692924eb883a33cfc290dba78200d23cc1f6712a2d5188b7ee08d669f12b768be188c32ee53bac41e011efd5c5066b6d94e21f7903d96e6118c8b5fdc9817c4585fa69050f9a65e70303e3492197491bfc4927ad941e5e8757e12268ab1fff7ca2cabfeba0ef1b2478512bd5028416720e4fa7e87e57c164bdf301b46b0266cda26c3bf5ed8f07f98c96b77dd5d525c69567b490a9d63aebb5730c2d01d307e72528a173b7d249c475953a90ce28f1bda69181945dce526028f2cd2b17a743c7859405d866637cdea1e6a735f9bbd3f15d135c8d1222f8bc24a6523ba83af1bd831b9eeb2dfffbd3abd3cf259b626a7abf9dc874f9c4488924e8890a4c6ee9ebc57048ddc03341713fb0f38d2ac43b2a6c0b76e0435c16364b6a1fd88f761a851be26f275ae07c96d49d199d37d83ad3aa99bb83cd4a61bf879cf606e25c01b69734085fc27423e3f149ba32ac8bbe482d657fd3e01883f0dffc9910fa11d65d646efd9087607074d555c311ce3256d23af58f485c1e80c1984abd29fe8b220510896857069987e91e0a836c61b90f5c3974cfc85dbbd9cc9877c753630173e90671dfc1c3bf32b1e9a9378e822629d65d41b7ffaf990dd79314e82273f310780ec7d6719c8df3c73e6c741bc040917e1c0bd65050d0b2a914dac7977b31bc96c2fd72c72eb56f7db61eefa895c5e82f5486fc48be2c988e66980caed601917354b8f8d0cfd565a12914fdc6ba61981255736535aa25d95e923b5f9946e5401dc7d2b4d53569e91e3095390018997fe77d71956b6c86198d74869ae1fb0b72c836181e8d5b6cc2a1a0f74d6df25f5fe5f7b45145a3b6890f62d8e0f14f52bc9343fa7436e493caf65232beef58abb26259e463e9981ac83e6809f1cc2e0b426572f0d006d4185eb6a3272f027acaf27d7c7d4ff8e1a052ea37ee3587fb3c1b8030151acf2cbe98cdd3cd421b16971b69063cc5fb4e1153bbe648b3a092492049f7dee73f2555df280a68c6f98fc7d0bb486cfa35754634c26a2cb0993da4b240e6eae56560083640fcb4b257b54b0ef72aeaaa970d226554b167702261f448aa3420458a87f58e87cec0762b9b8b3d6f536b696a62a102f4752f786fef65f216b2533b14b05ff3f6bfdc31639c879e8aa035786d2c0b208b2e8115d21f8c24c8850db04af2589e39878832fb40f1a8a23daa83db8e81e808bab7b69117662af18d646937e54de5d924c945f1874ac910cf12378de6869076ef850d0c57974bf6db1bd471f4dd60329a3cc815cdc7489949b55a64e753506f1265130fd8797af19ab37742c2920d012e44393eced838f7642d38288292887db7fe1b4f8fef32ac0f3c334a72e4ccce70c70bb58e1ea712cc511c4c1b07b5689bca195a7336a35debbe0a097da7048aabb393ffe1249c1e6412073d3f3aac0decfcab0cf947f14351b5c3b886ca5107b540e30bcadede04ac426d5b347cb3e3f622aedb752cf6d8839960a3466b254971779eb68d30fa6b1b6f03d6833a4620f466639bb14f7437dbc2d6090a690e55079fb2b9b231a467f6b294b5f7bd369962e7847ddbf3513c90e56599535effb1fd2039abba8b18cdfde631b9e5eb2c65426e5824b6dba4977ed1edeb80ed13c8400dec97716b61ac75218c3857034dd925ff57549c26a1a54697a0d5d814c9bf2cbce3cee8e767589e1d400a5f914b3147c69f7faf8fbf8e5c326806fb9dff3e99bc8e79dff8f53c5a6de9e2762c1eac105fdbe238ede65ceee4c5f9dd999fef56e46cbfa47ad0ab1ed8d797789abe9da6abcb42464c5f333da965315743a474ddcfb3dc9b31ca289ecfc975b86a93538b78eeb0028b7f1a3daf73e16148d439004adffcd0313479626ba05cf29ff51cffde76ca1b68b897df1de4c44452230cf2cbb1e4cdd8b82f0b9ab0b6d606d2aefe78264c72a6c122b590ff587a1294d0c530c631f6e007149cae2da5114c1dca56eb194791cea5d1efc236a510df4284195efe13211ef585d1bbe9c9c051e62349a79188db2629339d46ad0f2f48d4f51f7b045b8aaeb81ece1ecdb948531e5a6d357d61a4aabc953a3a3b0176bdc7fe7e09709ba53b8b477eccfe6fc1dfa5d32019ed13e4e6485e6cd56880cc395d655fad1bdaf6b2b8538cd5ec7857e6532cd294f218161c4ccb174c04d9d37687260fb4643bf19470cc120fe068c4c47949a9f499774a407bfa38fb3c8f181a1b5af4a580597b079546afde4a290dcd02de97f724aad1334102a17d8da8aaa7c9719f0faa0a9e9fc54f470122b9ff6348f8709aa9566f5dc71f99b4a9bdb579c9317ca0acd7d809ae3b88e78b387a551fa6c279dfdee5ea0a683956c98aea0f5f7d10fd225ba9295493e66ab597afe8546ea6940931cb34981a8e6c4df6580ec14a6b6e5986f7283ca168d06481e5f19c70e39c748ad1125c76cc7a220d13011293e86668ed5b5a088327a4cb193b15788d84fac1cc19f7baeb91d13ca2c788425fdf47b27e69360c83ad83b0ce95870a82df40e249ec665948004295c90847e971487b5a449f13dc0fd8af7eef86316a2533a264e71ce41e29ac23cf088ede42ded02aa0c753eb0f7cc92cebc4b8e63aa2b967687b33df8b58b5d49334142a57e040b624cb59d93ef2bcc03f48f1172198634089ff209f9e638834629ea364d1565c269c718336e2fec003518467bb2d114ce9bc0e01f9946e298062be5a42b37e7bbcade2241e2c3788406caf41ad692869c336bf04c06e4c2a5b6ea0f1726ba7f01f7dc0f54e3bf70b69d099d9ac27dc4d0dea8d794d1e8295ae35984d8eb05efd064fad86bf60b2a04a22630cf9080818edc982303f08f28eb831f772378761d2be8b7b74c3062f4b7093468685ac9ec93a9f1f5142bf7d8a63a6127e15d717e530ef66798e97d3741c9f8266c29d8c0bd1acce05b151246ce9c6c3d139ba5f4db7b209e246b35aa28ee485806312e72e788528f49f080766c69b613f9881578506679b5bec901119f02fe9067cd85137693872bf903a58a153b7743fdfa08154845e0c884a63044dacd6dad816840113d722649495cb3e91d924e84dd9e568a670a8cbbad91e28c7ebf2669a8d4bed64f8818a658f4944d99dc7964d698d8ed3cdd2ecd33f9f7020332b31d6cbf4979db499aa652bd21ad20fc150a3fcb26d9f9d14916f59bdf13af3d51478208fd46c06f244326286f0b11f5f59d85f6b26ffca7afb8348102c48894e5b21ded0f74ba2823947eed35bc1f7cf14f3e25447cff1a8b3f006daea1d2257fc33429738f8b90028722bf6c0e2c4fa5efd7be1d03f3bd8174a6c6968b59be4ae8acab438a73fd943b3e574dc9d54308877afc86ba6de44d54ff38d13ca6ad23628dd44b646990e33528f3f17d0bf1f93b53ed54d155619a96aab8126caaff6fd69fd449cb1182e0c99eb534aff7b80645c82abd0d69f96731f1a5a5ed05222c38d3c7dbbcaf72d543c1c91ad2120819d4d68155e4c1fd36447327a9c504d4e16ba15d737066497f6f59f3445465521810019acc919ca2611c3db3c24409eb46377eddae77f0d0e2663526e9f1b2056a8b2516cfb98cfed004f57f8d093d6ed8e931934c13d4b5b07b718b8b045168a8f8a1229ebd4f11f7b8fe2dde5d54ba1b9ecb6370cfa476f5caacd942b557e9e59dee803ebdcd28fe4894897446e413e33d8fe8c1bbb2ba7ecbf5a56404d88403b93bba425d154b224a03fdcefd7382a1d661cc4a70fd314ee369f543efe68ee59cc5c346a5949bb267542ddec67986b357c59e346920c58f6c3f37bea998b37e347c093d064c1090a06224e530197fc7a3b3ba43e3e4785c663588474aa834b6065180473cc36319bca31d964f7274c9176b9d527ab90ff2b8beb23ec41cd4369c7fecc399d4801db3d4264c9559378ee5c480660e140f669d10097d0b7e97ee22f51f7bfc52cb06df4fff5ce0b075239663650f9133f49db6559ef66baab70e8c7a9a1070a5108f58ba0565047027613b599133b4fb329be9b62a0c80b54d35b5478b3d13c219dfd9a025912f9a7af022f15ca654d68fa1c328ae993789b554d9c9bba740061cd37963b0db10dad281162d6882b6d84d62caf3040a160e9fa6d1a2db3650ce6d3b3c63765d7256c18916ab5a4b168ce5990584cd7c344bdf2fbe5415565f241dc3a75ec7c27c5cde63d9cb463056a5c86cbbac6a3018729161f945295e934f9567f8b9e12d64a79881009e80ed46cf9b094b57cd07bd01e5d0aa28699256996ff9cca2ad66aae2bae807ca8fc6c565c8b18b113af5c69c94da9ef53c5e7ead7b144db55c78bf39e31844cac9063e068d2140e6ff29d1e3bc8258a5f59b1abc7b282847e437810fd35de4650a4d492c30ae65549f7d01c1cdbe9b0ac92f989500102bbbab38cfa1b5399222e4eeec7e63c656e86e23def8f7910fa29a02fab82803dfa89b7fe82d11bc517493272ee4ea0814f612050894a7ac3b8dcaf126cc226e38e8ca07be5220625ac926057de429a82d6a81553b7c534833226e0c73f330285094d3f82339e1f03109665d15a509cd9a3db3f3506226582ed5063d17012ad90ec57fb24c216238696d62aeb76a0aa58a1f15bb431bf6db1e48be079e21a50840edda434daa94a1ef589406c6b6f36aee3c362cb16665436b87fc040a16abf3bfb461ee225a5705b574f61417cf9eb3a23885a9ab73082a082534261c40053da8224159064691c37a45fd7846b47925c5620d93e74f0bbf13ce0ec2ae9dd2dc797baa99c72799e1eda66ddb1adc39fac3551f6868201f786a6811d70d0a45b3e3c7f0d3607dd677da04a1361fa6a57069bfc45da8941353720c5f752d0efc3aef3de3c23757bab97e0194c63391137843f7a5b6b09f15bb01326bd6be74e106f6d65782ce9616486eff4e3fa646843e4e57dd155d9784f4a0961fd5126241bc452ee4f8688be4f1f86523aa362b9c3bbf2150a6dd6b61d2000f3154760cb034a09d3d881ad8fcbf0265db4fc1dc35a3b237fe5337e2a09c95173af0ea70449bcddcdbad39fec22e3580c7c54f009b50c1a2cd85c71a50b7315f9725d7ad4359aac26c4a7b3a38702535a3477783cbae15a81fc1815230b6141199241d589ec06a7bd33d87315818fe21cceb48360c8af62dd9d02826e0174222c6ba6d426f884b306d2072b7f107b8a131cea29a446e3c9cca3ea40310fce11a094396f717d5033d22d313eae42a35fb05ccc80221936105848b0f548da83266a7a7d5433b137aed974bfd2b4ac4deec1a62628bd64a43cfce4bccfe2f895827aa1bf2effed85f7cda12ff66b86543a6a910b837b2dc087faf5022cb875f72ffcb65aa22f6e593241c27ccde53d109fba14f1203dde73d9fe9804ea58704103f78481aa54f1ba8f14f1f52fd792e2ba9ec49bedee1a23b3a06a12f470ea904eb8e8248aa49f3d9a5180ccc50a902bf00392b5ed45c13863192b5a80d33c41c6ce70e89a265871a1831ca122d145343fcb984e843a0cd3ecd3b91bfd2073eafaee4596cf01a062b70110a2d464318494e6f8f48c6443a65ad1b0d878186a5f37e083dffa3c2cf6d4e9e10d3ed1e1cde61371eec2882dced444acc216598dfc7240a8a3e84e343b969594b82840d5c941cfe2e7084f46ef0506c064f8c5824d30d8cae072ed3c18bb9f45a1c3f8abff5700e7eb6a55f3a4e511fb3d2d9d1852f8c2e1f02e7014fb03a596bdcb943f2171cca284418a6fc4e450ef792def19f9a48cfc68f02d2a5c358d45a25ad7f98a56f44c932ed2e704be63f69faef78976886315046beb55ab942989ae54c96637abad803675b04f9128d6f141bba634d755bd3ba960cd3b4280f812d41c4534df680aa0dd34dfd31b0efb1f0ed70f400e468cfafa2e4e6acbd6287daf40aa7afbe04776e3e3b98cf376fe5dfbe3d1aebb226ffa29ccb399c8b10d32805d43f75ca9224886700194931cdba114166d8a49e84daab3a793e21881c90166366309eaf01adaf08aabdecb348bf727a80fe826fc48687e17cfb3a9ab1611f8224de3190efccd4176cf952868f8bc874619dee4916f03c0348b21b310d5699e6cbdcc1ead23f0b82d3a0742382d9bb65d89167ad830308ee78ae1431779ad4218787ac706ac48f35074545181880e3132ecb7289a2bc3f7b882cc44f5e5f657fc7fb79ead36d451c5c47e58146913c7107dc5aec90e1af0552ce8f7853f466ef52a02aafa36f28e663dec5c7befe72886cc32acc8e7876934253f832b305091f287fa1947542b6e858ab3c88f826a739e46b9cb05210d6c05ca5a9b5389a493517f287318acf7b58dbd152ae2f57470fc6d5b21e69e3214cf802f0ff614cf8ae54cf8a9c3e142822956bf13a2b2654d727f451530ad5a97164d68454431183e3a3118d5a648809c9adde571a1e09eee589073b1cf290801381c7f7e80e0191d42e8933639932a921af1aa00ca8f7852fbe0c5915d0a73b3b5ce7a77ca28ad2e0c38aefa886f35b6b44ebabbbca8d7a7496cfc84b3c5ef9a3ff0336ccd58d0b76e8eede8ec4f8d4015b4bf8b294d4047ca19c8c9a53964388a7663e2d6b04384b17c7b8e97289c92e1439d1e28132e79a5a84a5e3cc5b9035e82834a1aace3117b8bff70441eaaa53156362bf3ea000e711ad23f494984b2fcf125cd3345acb30484c1cdaeb7a8b90ad76c5a4c7e50bf9a28f5324eb9f7e5055bbf6ff9a7fa824a7df2c351361e8d2641d3d208664098f0e9c96ff681d8d42c6945a82d9b6268e6b2f444cfaac7dc6fe98c631ab367869c77eed553b00da1e8866bd30d633aaf0134230c63d4151323c0b97fc2fa6f6782235cfd2002f457964200769cf48c09519db0b4c28e6e11e0892e74d73e9d9f27c1b8a8df46872b9f1d40eeee501adfff1f94c9eeeb8c37f294ba2405c829e1665b5b3ca977252894cb4ae0fa86a16e43f83b141c263d16a53c8527e468033a34435917629f258d131ee8a6743c6e283e76ecf0bc365dcc8399942fa7ff33c1a62da08ab88d885ecdc063b1b795d005953a59935d7380d9c4e93f82dfc6a99bacdb1c21554c177171f54e6ae6f058c9fb54026f1166da7d09aaa03e260f84528a4f33c9a4db2044883c975572fb14b844ff3e9e0eda561cb8bed40b4b63cb3702ea7b981aebe11e703f6be660e1c80c123b3c4e0ba0567017086ca07dfda01726ac2eaf6dd45caed89a0438efd2df2c9a3da865b30a2e54f21f8d9c286c9bd40a0ef32157359866ec6cc978bd5caf68fd2d7b6b64d8baa41178b42b27595e6ef0bd66dd8a4f0a73cbef01ed6023afa4e4e61c44cc23e7be853beac6b72be95f7191ce3f341133e8b4018e0c5e57416a3e99ca3fe7f0cee0c5372d49e6ebf3795a5cba80167c4618ee7d9a9ef916c38b2402b7c354f0c32f240825002b34de07e655f5a544a8f88585ba39907585711c8419998d64616462244d663a1c24d0a5e3f6fba674abcb321027dc5c50391492268cc760f271c41b0aa728f5ba8eedaa801ad47b5f84d11e6a9871eab417910d6d2c924b860be8444bf7dd636a62f0dd80d3b0f7f5a97b2824145919ae818659850b3ed4824a8e277c21c8e9378099354f890e5af04e6b6c0fe79a24d086a283fce8bb3f3056528d370a645d3ef467902f8eb45f3a3d42a8ed0e7ca623c33ad7f7e7781de327b24f73a5d752fc03014590ff9a25d53aced6169be0145c7426430a1a99baf58772a1e076eaba1bbb1f91c61a52cd79abb920e48a14a13082c5e473cf9099ed2b337ceeda782f8304c4bd68945fa10450a80398faed623e5888cf9d86ddc57cd6489b00a72597921181f1bbfe15da0ce20037e8e65d9e582e9d61ebdaffeacdeb3e019e80f2e4b653d8c17146be24e04c3a13c2173e17417f497be0423101af1e4ce18ca860c546a8ec0cc0f1e8fdb61b6fe8e8baf901a2be7aadeb2bec7986870ab7f3179cfc638d6b19a78794d312faa86a9d66aa5b93aeb83996a98e1453fbb235dff03f4836defeb5bba898a7fadbbc50a6417dfc12917c1cd823dbd60fcdc3bbb5888f68299660bb009075d061f3f747e4f64b6014562a8856741fdcaa413ad0594c78988ca12234742d399525bf65163b335f1e9cf084e57a75e06cdf6c9ed267a2312ee36ee59df0f0d75932c4280b842d2dfc6f40ec2ebd192281f064307cb9067f1d700a475928b7c7532760cd2b80e4c82bdc8cae1b6ccc39ceb76817ef4335609ad118b051383116bc38bbaa9756dc0d7b3944596ef04de43cf5b6bcb2e218ace63c2ee92588e5380e56f3164a80fe2bf2495e853350ae1c09b1b5e50209d52fb41a2b961af9f82e6ba4fff2adbd44b4a170339fb05af260fa25373d53ba8a8d106ac5ca49a48e53448622b81ea334322a4534cd55832fe0a0bf09abc4f11c415d34db23bcf6a43a9b196e11580151ff91ecc9c2999d867c0f63646f065d9934122b612b10eb47bef330c8213f249c3429fbf1355d581f590778a8625daafb6b6ad6fa157c87f7ec253b283faa04878fe179238cbb5529e5cf1e41fab3eb43c7f494dd18198feccc45e9e194dcf93267ee21a6d5e511c39bdaaf390f0bbc98bc928b0dfcef8150a3ae3baebe2423ceb147df4a7042197cd9062fad3254dbfb990e1a6a4b6d56e0a2d59a168cfd766666366262af6fbe7fe660b7c2d2d649fc36367846247b618c1b93349eecd9b52587ebd0e01b1cebfff1ee8ab1de9f785f277be426e4f6e290252c2f282947b5f49bbaae02cb9ca181c603f6c3956a82ff2b1fb242e9610d74f9e115da6232fa1b8cbfcbfa7663a25c3d91fd695a5f93ac89126744d6bca1b1e307da222281960b105afbbf5fe5848011ba055e38bbb906c81bcd5afcb13014123aa7439ef861ed5d5af8978212cce30ccc94d8404d6fd8871e32ee7be24196d8b0afb840c5f64aa6f705174bde4aff347cf9158eca56e750db5ff7e1c5f9dc2ffcc53db411c005246c6e986c64b246a376ca873c6928a033a152672ffdc11d23c668bbc4591c8e893794472e093b2f66eaec3ade402ec34fc04789265b15ebf668149f717d50d8dbd99b621ab07fbd94e7e69c21f238dc0a5d13975bf6e712e915919e42dc736f3d61ddc9944e764cf8c10283773a6f98fb0866d38276014fef9dc4b4b5b4613594ee656eda41d47c54748a7eaf84d60ceafe34b2135a98d26a6f56d126f986808fcf08d2a70a1f579d8c8805ad0a7168c954bcfdb7edcf0b8b3da12114c67e4bf00c890cc959e0a7e665bb6d561c3cae49e4ab3a2f526238d10dc060a33400145bfb81ad14b5ad57ef9850eecefa425404a88e29ccb553a16d48db35868cf67c09b7b818f2c047bbbd4024ede8eda2def4e0ad495b1b335962f60d42f2d960f891e9166163b46f9e81b72256677cf3eeb21902fbacb90300ee07c38980955dcf18ea4a372aac64292cc5623d559c6664bfe05a6f19bc743c8074a73a699d895777e6a2d9ee7010e48faebb308d79f9023f91371d75cbc28aab772bf81a4cf16bbfbad0fe75e4735e2eada94a68baef600b7c634b15cf3cbe0d31f20dc1667e57084b406c46c8fbce3c203346739d22d9bbd349e08f38995726edb9ce81fb3f63573a628c2e29927e2cbdf5f6b8aba65a0e43742c71812d09a71f5c329f844323d13cd01837e5812420bfff8556a1be7272e47c80c9bde3c632e57973de0eeca7d4e6d32a70d94ae1ca20dda7a08883dd961a6127de01997b23ae0a1fcd05182cafcac1dea1fd4a5a8858c87a66588e2c4985bf07cc100a8b21149784af75666d612ec6c55f7319a74f9d5f7a39d9f86f0617a2f37dbd3b0a9605f894e96fb150c31fe48c4ff673b08a35b1b30e059599910c9b2ca5fc009cb8790c6df633dbaf25505d2c59cb9cadcc3f3d117891ddc728ec6e259a478ead0be236851586872b01c5d91456ddd75139f4633d15d958e41a9cbadfd9782ebf8dc7114f4ba1b29e35abb75b5b99c5a95a4ac3951d7726ed5342571f9e92e920a77b0a26745b0d6e3a73acbeff3ce4a0956b8e0797b9babccf943c2555ddec7a77312183cc51da431b021639f1ed13805f094def3775a6055a5523e441cdf9e9c5369de6a54c72ed6339f04071f5b282a696db08122d17505d0a43bc510e43d02fb18a3bc7e9df3830b76383a3f2d5e3d4e1e313ddc4ee8d9a47de66148ec8e65caca1a14106516018cef55164ad2721dcb001957b9e76af19662e3f6fc1d0c3434df10be1ba70d724ebe1247c1e9c8e48dcf65a8655d5f85b830d4a5da89c0c94dc0c71efa4695570a7407a5d49f3be0057c08eb2d9cd545d4a924f59eba3ed13d3a78c78ee084fc964a066ade2579ba44be411eea1f7307f27e68d2e1a12cfd7adb6815ce464d66a017e203280aa97e34cdd5c637255d877aca16b7aed4ba6b7da8a2e72c4efff097d9d4b9c6eaf92edcf7b9150c084d86a99c6d21a2ff7a6fa248d061d988565bf83705d5fd68fc38c894240a3a7147e1250dd7602970430cadd18463c150dddf19666cc897ee420cab3da8cc62d685bf9da65d0a42f0353ba87624e71795ad5b2af157711e574cea00caae4994e8411a5d4e9a1cb720477cb74081661017a9a6039a87746fb87ba089c0a222b0071d49dca1022360b1ddbd9be8ba2666de6d46338a133109f532dd2251cccbf41c79ef8090567628d477b0f7168cb93cf974caf9a9c694280f1b96c27e0be2ba1060831cc94aeb4a5fc72bf225896b0518a47be4826d61f58627cee0dbe4d511e0204cabd5c8963d5f3eb84c00685bc05e7e406b9e47edc0f21369663d0f6256844549cf0fec0bb336763ceb6f60c2850f6ff60c8e002fc7e68311969017c5370150e8d7ee5fb36e05d2608317531c443b1262582cd7f72794fb3b24354d703c7c96bc435d7f91dd41ca8a3bccb31159655aa322c7f249ce3ab1081c29b753ecd13d237c0b28866eebef5f3b4d8eaed448a85fedbd6bf503693e908ce6a4e93dc9e9b27f44685096e58f9d8e5e69436d787de81d2a349023fd58fd3446f1fe38e307a61c7d21ffcc03d497c946feecf29f30b9e9aa35bb3ce580dab8a3b15e9f95db8ace4c2c1cade980c561a5aa27369dc7da60441cb3ba54b6717d0b653f9e26d8736449265ae2960d0b1d3a4c291938857749e02ac0de409675f86eb1cd6c9163943b5740f7c666ae7d738ac4b5e5e9560ca8a5ae4f899b20af77abbfabd80ca0ffd4d38d7401bd39c06ddf6070580b8ba9f1c28db2885a2c2ca67c80497d19e57b2f4ac30d4656ecf91fc71eb34dd8b55e423fca5ed5eff72b60bb20f2db76add2359ceb77d6658d281372049190d0bde64820a146a3eec706ee9b3d3a811a73a0d7022d5137b8f3ca8164e9fd53a21321bd49b3450cb997641c5fbc56a9a0f120f611db47ba7770612cfe47d97bb19176ab7cb12c1427a4098182cde6843eff14be821527b434bd584201d11c1e13ff02f792069d1327fde4693298c09289b7b35a36b70fbd4cc44f2c842ffe0946a7ea47a40f88455b5f3a21944c77c9c8b4957db2078461a17c8569b381ccb1ae8bc4bde3f244f0d91f0e8ac38118f74d81e45de855040178472d221f1f8a40b6e3adfb71d7a5bdcc341163dc922afac214b61fa653bd6c2593f8f2214c2b6edca128c1882a50f330105e4eb7ab439d6943ba4733574e0f03dc4516fcc8a01e2421943dfc32e946d41fe13a1130d4d209cd1af2a1667258d130958e3d29c0e7d14b219c1b00f856d327e0b5ee117ee00e3258b01960b7acf931d110614841ebf7e2fa6c937c65d94a60384b324dd96ef6b76697804f2442ed5c9f6bab195152a412f39a8c7b787f2007d8a3dd97f5706f8e791a5a04be43a620fa1706fd0677937ffa69d927235d7ef55567cb00664c5d4b692aca45d629ecb69b18e404802a80b3dccdc40c48321a483f97223f820e3f95dbe0bc1fd1a567f64ed7a09e799595b07fac53b0962a6259c888cf09938bb212ce80121fd7543b96cf7a20a51ad8b6f10f1212a7e7407948b99732ea2b3f36853bb0d70253e1bb5f528ece83ac43222d630ec3d19c417913631dd0c66d75f950b5c53800428f0c945de6150d13d9c38c8fe667a358120020316b76009c17691b34f515ca6b85bfaaf443dc48e688f0e09c5e8ecaeaafb656a93f4628f59601f0c91d5f56faf65f758386f5bd650dcda16499e38543ce9a4cb836cfc235d09bc601f7d91b01d982add01789ee752b09e0d923e9450ab9f6458c40f687319b28d2a6cc464f885a88220ef45054485755816c5bbf0d626e567296b9a2a37eedab1cf835436de80a91bbb4234ce01a4d57c37674b6c611fa24927d26cec430935b6e3df12ea14800d1cc5c2cb240a2ec0e1cf806e00257b06bbd6e14edf21299943b1cb69e572c67573f388f49beb0b4f3936603a1923bae3d4"; - } -} - -/// Bytecode: 106976 bytes -contract LargeContractB { - LargeContractA a; - constructor() { - a = new LargeContractA(); - } - - function data100000_1() public pure returns (string memory) { - return "6087b4d3f92e12a947116ea9f8e32d0d547fcb96cd81e646bc5e530d168cd6ede97890a57d97312cb0d499e429673ff56078c3da27028c8e2a063e01ed4088a8b557a04ba1b5e036a03cdf3a103b7c4a567480d217518df4f2a4e887c245875649ca79e6a28e835153455dfb05de578e62b94ce0095faa5fb82477e05b38946207720d91dba8698504cfdb412f4955bd3f980d063c5e44fb988c4a9555242bb332fb0c63b33d10e28fd829e36f0dc4c6ecc87b7d6d7ae22d3ef03c7b7c665cd36d910bd437d5b78e4c4485c8eb36cc72af39fac5ee09e39ade1d198696460a6cce4317f8eb0cf4b51f795edee80ca2ffe316255124fd611a0fcec138b184f6d9ce2ed22956b7517a654590adaeea6f35f3e456352290c450f72f3ba43693f0a46d971944f0525b1dfc698c1ef39089d989fd49063f907219621832fce2fad10a5c6d70b36953887656be914363998b1af7b08b47df8dc23c90766e38d52c4bdbb28fc911f386615f2c849ca641bfcf0fbda91f2207446bf59840c23fb76a119839eca26820400191f0fec781d5c365a8465d0203a84b140df4833c1a8570369209b600033db26fad2262ad89d61f2b64a3ab51be87a8646410c0ad416f0d3cedde462c20dfeade7bc291b7130ab8f5c9f67b22a2e35ccc875f231220bf42cad62e5e56cd065322f3d98d22b7efc9fbb55de58b1354024645aa6d2da4498a535f000a81e892e84e98c8dd775cbe5398040977cbdf7d004164f91f405324c3c1501196d8baec72742ac7f267061dddccf36803a27c11f4b13c72b062264394b1430c830d17f6d7c457783dc4df2032d464e0e2707929aefc9f3aee60e3088157ade6714fb6a259538146996a64bde53daaf8a1f27fd0610b5c1ba04da1f29751850fdb7841e2e5f3cf7fe34222bf7e2a0d7f182a8df61a9f27f7a838698006c6933c0a04cdd5f2c21712a0cd675a1c90d5b0a2fba2b25869f914a28a1adb1afe77fd0dc44d08f6a232832668da8de88bb63b950fc668337b40f3cd439ef46fba2510430b0ec7df0380c11828ec371c05042d9796abde6b10e1109e54acbdb79758242ef749dc94ec9f7c9219157a120eaab6419784b0a335c77f55c0829111925c0dde7878c685762591a0b7e823e2d372cd5b3bd3fd9cc660a74437a97c43578ef291bff3df0797ab7d867f4b97dae97d1030304fd989c057c8c6e0b6f66062441764d759522378a1e5849165b8474a28a579932897759eda1cb6bd005b1ccc79b0e61aa34e32f84128cae02557e66a8ef2de979315427574ab8c8464ca387c10bf982b0254d198138ec5353ea56c126849abb32ab36ad6beed63ccb7aecfdd22508f45751e6dbb632be4fb3fd5ff7638fd79ccfc617fcb4ed49c587d9b34aaa52b1ec3b304749c51534854e7bc8428a44339b38c137479948b5f68b7a0d7a6c7a09d668ac42fd35424549e78ae84d9b68bf002124619918970d310ebb00b6e1370c587976001a79ef68fb8e4d821b287cd1af78fdcfa4c6ce1789062587f8e363b0a64c07b21d75d88f760a35cbecefe96148d1ecd7b754c2b6fd81212c64544cd9e34d1f65f1f649fcc21c6564553f6425d177e11c6d53eea13e2bd07ed5746cd43e0293eeca2878cffcfc6648d841a996093347bee8f19d31b5a629c55990f8db1e780b800b702bb219ccda472b1cf3e7b7b2e6ef9cc9000d656d114d40e8cc62295865f1101628970caa8def63e0e16e715febcd86f28122d42c616665b7fc6706fae8d02b24376a796ade81b0d9d1676784d3c41fd7d0a0dc5d47dd567d8b0edc93b6d6eb2da07781475b62589e63c0cd0c9131e783b56bbc4b731440ccb0d10248481b0d1e951c7d20ba9c3e505d2fbeef9d8db2ef7a72b1c0c4ca190e8d86820584b1b0d9a96e07c1fec6aee28f69942b58a144bbfe5a34f917555bd482fb50605af0184ebf88084f39aec3386f47b4bfe18b63c784fe5d83a9c1ffcda2d317ccd1e36f6f8de65f2bec6be676c22ec72f3f30be0a4cc8b1cb1c7368e6a1770c9eb4a25b952a5a78aac0a21a47ca25ffa0a13db8f3cc53f5fb9fa8a0677cc0be7a31943bfac4a69613bc93395086c216f725783b5dfe6d47d53d13fca1dc9b35e936eb699e8ce140536dbbdf2d9af8f7ec671b9635e280e2a6bb734e05f1932fe17330af86481a00b3abc3f34bc17f40ab079d7af05ae6de6bff3a210aaad7fa519b69609e615ca2e5479d5d0e09cbd14bbada22e7dbf0d78c3b0a8b4d642941f8a9b874522c7f456cb321fc97c491f1dc8e030712a8a8f8906d4a1c67f0c4863a12464be82f04900d97415a7073716cb633972999858996651dcf8157121b7e0264462c3ea37125fdcf62b93c8156a77a27f8f8d7d49db5b23bb737315922bfd2cd80fc46a11eed81ce91e540d897d14899ec3fe4e05acf459cf105f88bcaf1ba6fa180d2e0e1c84d754279536d2395ebd0341a7c72008ec81952bd8ea0c122f462a33d712d09aa2337b304f1fd50e76a4cca539449977f925fa6a7488b50d76bb025af152b5fa6d17c7fedc00da3a604f92646a273888bbd9bf9a4c926ced5bc70bef8b91e45058903e32c507354b7a35f6905bfa9d3047085d829636a7849bfbc3d2e3394205605f8b0d7959c8844263bf0bd2d689381e84bae2c808ddbaccd7086f49847ef22c7907c6c8fd2fde4c290397e3baf0e20a6960d45f255e32e85d6020e4efe4ad28018588f2e8401628bb2f15019eb0e0bdc02ecfca0d417e075c23748cc16bb68691d808bb57abff140fe98e3689c627136483edbaa62ca0e9d69e4cb114e6a5a247fa6a13a305eb56bc9138dc47141be0919c02047e13d68649b0809e2af06e5212a223c4067bcfe0b13715a6682dd9a8ca960583abfddfa2b6cdd570bf8afb4ff7f9deb31e446ec93d640e4eaa2090091a4ebb027e6b153e0a8384cd9ccbc9f6f8be881e42f1ff681970ca5da2ebce99b5225b49cf09a87a2b363303405a94f035605877b4c876fa7e6fb2f9078858c7f6629e90d031ce9ff51976b28c2931c04a67e17d4ffe25c25fda40250d703110b48d2ba6e6e9198c52b2770db04bc444e7adb8330c6ff2174a09ed6aadcd11f29d6a0f870505da0d8684df4de71babbe4cbadd974a5b7489aa02cfa815887cfbaf26b009777a501ec5b8dc2732851966eab2241c2578a76f896b5701567c48a9ea710f97dc0d183f4ec2edb59238b7e3f558aa1ff0b1ccd89df35b26f822d1ba5caaf1841c9d40466a8cbeb5a2daa9c847db25dccaede61417bf83d0c8668ac429c0c7ba237cc40ff03c100b0aee746c1c32d402fff590ca169b08ec9da851db4e4cab04ad2e454a3ad21769c0a013f5ca6f0c5d154549f20d81272c89bd7065faa748105e75dffc4721ce046f34174f05028ccfe6e28679c2eed050643fee3dcb50dffeb413bec9103c17b7d045f1cd0ff2c2b508240e94c6e5626d2e2f1fe5142bea3d0b342bf31a727a0dffd42cc05a8dc489f9685e14b56f17818679bbd1622f2849383eb72ce6e573e7d4b39a1340afc7c7926a00b41035b00b4b5af2092629aa074e76f0184d3c60f4f8ee053338ae2e0f2351b384cf153bc2258ec42d6f4e6c6e29a0756f8feff4d7f2168e73f8b9655c823e3f4e10255c4e6ecdcd38060f32c4c942fff9fdb2e40a413249cff5626f3240445701ffe212303622267bf9cdaa5b189309aaee34f344dc6a2e3bcc206cde6295bc645f10ba11fa4fdc0988d00b28420a293f9de4509d36922bd1a15f31f94fc266f0bad01fc292fa5a2adbcd81e61feb123e2c9f0974c7cc688bcb281de193b86d4c5a08af927499439bece67c2273da45e70cd15e0ea9729a07f3b5f63257d28c2acc323a32c757f6b9c02d71bf4cf34acf4f5d643df3b6e865994f493aa60ed500095b0b4527ee26538e30d022818950e8a1c19d370acb64f9cdb77cfcf6ab102c286b1699f629f1243b59e6cb53a9d04d7bf137d71d203ed1e57568c8882cef463069fc7bd39bdcc3aa32381d441728929dad016285e36648a24c6f5611f476264aaeff61cca92e7ee29c90cbb26c48c17b3e793bcd6dbd6da208cd454f2d2a9fc4fe883a953b8d1b7c43fe075d42576dc69f73a2ceb244ea3381021c9043a30fdb988ae2786a446fed2d19f0a758e1135bc85c9b38830d770384568e2ffca2b50743ba9ddffc04234068f86f087e010bb93c5bdb697a5b2929c270cb2a615cc60ad65597c73afc9e9cba19c61db9cf9f31f90fd7cfaaa05ac5055402a4dbe72c24814de39d7eeb0e0ed694c3f1f5b79b4b23343536990feafdf1c9879afb5a23c12296357add9e2d648fe94c08e14056bc9a425ea4d2df42e38ff1cb11b35b46e136275ccdf2750b1c5927dc0290a20ce9ff4ad96a32ecb7c05b060b050c761e464dc4d42148f9ae69ea5bda72c1f02cd8c9f4547ea3650f361928abad1bf62a51f78905e58fdd91f396a9b6fe0b80f2ac062e16defd9b50a529aa40339908023cdda4bc12c628b113c6307a8211525204a4998df2083e8bf4651f95c7673854468084952f5e463d519542356061b13d028a715abb51c07ca55a1dc722843120229cca2c970c1447f3fbf5b67b26ceb83356f3d4ca2219be08d9535cc47b8aec68161bea9531d3a04a401d07b9d38c0d4bcbcd2a89b423bcdf8bc91bed8071acfee5c9e10b27bdf67da0fa6848d47fa3929e64decbe1b3aa099cb8d78fcc9669280d86d34b389e517ff26b4116c6162fecc455f6c4892f0c41faf5715ba6af4ed071d2949f05aa4782189ab776cd20823b60ee460dc76efcbbd6927ff6306c7db6ba13f9bd57e939195bd88fa054610842b9ee9958fec3c87f5279a1a05c3310fc94ac7a355e5771f1e3409dd25c9e6adebd272e42eb227dc4143d412ff8bd395cb548c4a874e544fa97e5f34876631d7989234bb67c1a05680d31f18c70c93bd3108f0a404b67d25165711274f7e2ccb2b4bcd7df8b46884913f6c0d7edde5307fb4e8e39f4624976562bffa1ae73ddf6efcd528ee91399ea26040e5906c1a979dbf656044ee5bc64576845a6ca9ac8149cc31dc4266e56fc0f50e5ab2a6f5bc774c15cd4a8924ccb1c58711ddbcfb72af448eb40a23c70ae3c75d018b3c505503e72e1c95364a6464cfc637aa516cd81a39ebb6a143122cd84481c80bd70416943e292e1498a20c2298a5c5e52ac40879884801459d92c55c34c255795f95eeeca4e713a34ed7159d698ccb502741c7ad91146d2135a848004d7e6ed10b0aa1016ed94696af50f4c8938aa176ebae27c01e856078078df7ac4f49dd8d55ca7e8901d6e48abea103b694873dacaa8e34f5558d37abe80cdf239ff38bc30ed8b2d2df48793f3382fcd3c6d65fc1fe4a5e96a0e07c1a26a05c027ea10ce1ecec845b1f12e01fe460c5da281f03188ca0065dc0bb8219aa2b0ddc7e9aa54905073a94dafaa3508b239e30f0a565b15c61db1f7d1089967648471b2d92ebfdd46884c4c5cd5cb100a4e43eeacf1b95d09192d6f2d4f173042af488db870217d46d6e7ebed42a4f0b3b56f460ba3ccd05a453258a8bf412e8bbb35f1dd4548a625e6b82c6c5f5fa3c57b6589bc101a3cdf1da12996553176721b4e184dbb54d38f52ca1aabab3ce45beca685a905be86bee909117103e8d03f2f616db1d29515c6565283c9e41a36ee195d3061058af9864b11fe1def607a348b63a324a8f4c1d1d7aeb3333dec4cf6fb77bb0d7150eaeb3306ed59bc8c6da2cf2da9f3f198d3b88d30fef4abaec2d6cd4aa4642a115cb228d8cf001eac4cbc88c9d8c45d286004c95720d600bd1e2a7c610961234dc0871f6cd11117d84cbb3ad31026dccc9b652ace3a5546a62ab39e5cde0258ea98eefb4bd51e0693c717de684df17eb5c925c5f31bb07cddea23ea932c0655c13108cc98e9a9ab19b75bc5df30fc989666a8702ddecea6076088a23959a556c38a1eb96acdcc13f2073a7b95b46c7949ee5b5aa77b345b90719d76a1a40bc82d7f75ab692efbfa04111f8cfd0f1f36071bb409dc56a8e3cdaea4171caa9e7de31a70e4f2f948855468ba47860eac761d805b28c4c884c611aa8536c2c06862c628c39266a255cb05b35d97606c6c42d8e27562b6f8f2f9a23dbc180f785ba8c11181707c9893ab441a40de2ae687e597181312639d1e1106c5a1c54ebabd1f065a352a2fa3693cbaaca9bd34d5fd9179fa0fee60111910d3cfdefad9223c81e31b5cac9346e66ecb1531ce53021210ea361bf33875844a1a30af49158d0a5ae1b7eaf6e5a12b762bf4ec930a155a1f1e949653f0ea86a0522e510039970ba9e84f5b006e2dee9f351409a7fbb102032321d7db85048d2f51856882dc86be455cd0754407fa88ec12f8e460fb96596f6cf2708fc647296eb771b0c3007ce93746a2bf1d71d692dcdaa83b72b4d4bd032e836714e13794253b66c649f28932f6bdba818759d62e79dc916c6b6309f3b7a66a3612aec9dc8a32c7029e81eb7f3d9017d8b10462a7295dd440397d276f7b8e0ae994fb9d0a4d80dbd4c6f3de0dfc7b1b96c6c647ae72244f7ba1f5758309db4720e0b89882c4c1d9213235fdc8227be4a244f18f42eb12eed05d82a867596d0195609786a17bbf22fde7018db576a88cb0e8497ba3af8361b3f48bca21b0699108e43fc08ce4ec043f9003aeadcac0c02139e94d572d65d05f52ee6f13c39f5606db1fe66bae35bc1df60e0089184dbf912a281eee7fd91c349da04df3a9fa285ab050d2f47dc254d7246b16fd96ff577ec62301a54496e68e4521e704cd04060bd4a8e2ed8cbecb370e32332e37eb09ae1be1c7a7694f40aef3f2f9c4e017b208b395c60a8b4461cf21d3e86655b9ca20137ad4e0b1f17bf2bf0245e985bd3cf227910dccf023cf934c65b9f887caa28c4ff0c48c990c252f5548a8f766a914f448848c456ae0d909d840f268542ad3de9f50c70319f88a77258f9d96264fabf6cce2f851e42aad2c1e58ec098e6cd33604960bd246c654ced59e9dc0eb3b5b34bb487c9dab22303fc47ae7011d3b6d4376eda8a63f10f2a1da78db0ee566a8ac84941f9b816a532f51cd743b10e74edac6e82a8940a9ef52197a0d9b768ec03fc5a800dac5551dc1adee179d9fe9c620daa21349010a1bcab361a37dd6a759d685aa4fef4e13f8580f2a3436d82a611cd22da2adbc93fef172b15419604bd96c8d5295d8d92d15bdb268df45b10d42b419e7ba1246a3fa7246cc15be1ae222fb46e31d5ddf9098641e9112d69aff682f52674491ef7a2e28fd0b38ba903c1d54f814da927d4e9ceb39483b3bfe316c0caf4fc67d0c0219a6fe50835eb4e3a2666f228c626921a5408fe638b3a31ab9deb0be4302ce522debb13e97ecf437f928ce19c19d0c7b297480dfe90da0c3a2b95c299ce08faf8766d49d949238275237eb88c4d38330e86456aee7939f3c70d153ef9a6952d55380b4909a78ebebfe7bea2d2fec7d666809fe661c38127435f25e7df15d98123b4010abe042f9e4d3bd17c3e768027bf4f11d9fd447a45faad3ea69e785425665ca68d975cc7ace8515fed99d6ebf0b254145f3229508bb916868daa823c30d415465d02cab15b4653cba4f8d04ad86e53f5add54f28142681abe4d8da6d669b2dd66c72de5699387ee87ff9c9d8a3705671ea267df2de3a26a6ccbd203eb6563685031753e7d40c6a1a984b71d7bc8fe55de360c9776efb7b07ab6c4145f0d6b7de4eb668a6fe6fbe160ad8cc34bca66319d4972c4dad6badc609895e5b2d625b1aee021f9d5f1f8d62d1d56d682761034a6e155fdb552af1040bbae36caccc95e33d96e9a75349742b8aafe219878398ae4eca47f4d2f021f184cd9d183d967a420a77520735b19a2f820dbf2cb0075db6c48a9c27ec4851bb388c259c15f60e5cf0b5be0870babbf91ce7743e3391110a032daccfdf54b4aeb1cbbc0fa996d6b90fa4ae0f7d38a8ac3dfaa28c986a3bc8e7be4181438bef84b27f615c7c77b052e40f8ae041a8675a264cd73c24a04770d6449b49adf799ad83e46afb1eea80208fa72694ef545bca2b58b947319834dfef6cb1176e45c1b076ea10f18ec35c61a5d6d448953787b587c12e11a701a1092937e14cda076ffbb8f312238abbd4c5701d8429aef97709dcdb7498177db43d33314a230c6983b55ccb9e8c18f31daa39c8d262e0a0cef99c220df4d81f146ba2f0f87a70cf3bef323efefe106757b3b4d4fad79db4f9aaf8d93d3ab2a4d8088531b79f15d0154d76b402da4eaf153b03271107cd2d56456d5d4665f47511c0153083983f3caaf297f7a505deeaf2c01f0cdc5c1748dbd27fd21440b50463b6008ffd64aba3879d85c5596f069130c8247dad3e0c28277c8a865d7e757b2f08af20633fdd5deeb685e61292ab54cc98160471428d55b93fc5f7305c5ddd3ea3323ee74a54f285f29ce15554275f6059cafc14665cd0a75d01b06373608c29e781ad38f0acb14357d6ffaed5cf045695bbe577a6264a267f79728cb69834b8fedb7f7b358eeca227136792fb1a5e2a7275fe8b4b64ce01e5e743e195731eb4201f876366090894f14e35274b195dfb217f43a83c6bf68c90358c68871014f618298b37a8e487b8ecb76c048fe0ecd499365a7ed68127ec2806ccfd90155b92b402a78497fcdcfd76ff8b40a0673b4419d907eec9a06417719f124e5f792e0f272de2d8429881663c7cf7191c694ff0486c784af32a52e37f1ad8d39c3170c95ba2befed0731f00a37d1440c916a7e9d732ff2f68eae62ad04184409ecd673fb2bb813cb4632698f593af06fd74828816e78174beb30ca0173aa0cfa124acdc6cc53e5c73a4700e62f1c57c744ab9065ceeaa3f1614abfd1209a60fe04421afdf589830c8c69f6287cde12eabe7519228419046bb40af0957b058c4e9b321db20b7f9b39ebafafb4c6e8358ea9e47a8f51329c013c9bcad857fb32c0716656ff566cc963ade3c059dcf9cef928fd85add0a4de50e0f561a5afe0dc74ab7346b81c1cff544d8699b276ed92eb479a3fc3d1abf8421c5286f0a704b5122deebdcc18db8a6241f90306e2d45ad0043fee0ceb769f65f2e7021bd7996f6f19521b0746fcbddf3ddc06e21a3060fc69f3832513457f7f413b68d33cc168a5cd03a2199e0b7e673ed152d0957e99a16f5a5b9a7c367586af76858d3652e6120a150b8630e7c910fea73dc288e99169a10a13ab6a175dabbbc1bb51e332de320e93aadd52b55bd9a2e7a9e65fbbfae2a00c65c66b28c6012562e687ac2058edc187f823a6418436e709ef107e349e2a68d1de7441ba23a996410588b82729f05088ba9c3a1e058ad376b822d1dae15a31446854701357872670ac1403208bd289186d9444aeb70848407100ff36193389ad6d570f8f2914593474f44cd64d6491f8f36b38ff57e5477a2832c4a150f26f8e8da14bfc06a0a66f94eb9f3896cf334a2c9af976346228e80fdba6661dda2b1a3a30d4003d2a1b983a7f22d78ca1f79ab11748ee2db4324030927f879303103bbc22189c7f7322c59af9b384946463d4bd08e532df47aa61b70340ada1f235da972b4e149798ef5d35e52a9bbe3c5ec1fec27c2189f20b89679721a738f947c4fa3e1159cbf7e16c65e5b242d9cb94842119d56c16374eb18f9fa995d453ed1717e1fa8ae765dcf96962476d622a7c3ebfaa3eb0c4821cef32160a3e6b1bbd5f159c5af24cd559290fe729b5fbfddc0e6cfe516f5420677fba9f4a8e2faa60b4a159e61f43e91c487afe5eedd9b818f5395197ebb3341f2d587c6eeac63d594e96c4e467ae0c16d6bfb881e56a5f34b8ae7478c357c3dec8951e204733514a0ebb1f4be45fc746c742e08ee3f8543c97467cf493d30173ac391fb3b454e2d4232256b3b40f1c65cc0d88ab0aa8b5ca87803402ed0d93b889635a0e1f282f1140a7d0cf26edd8edcb42277cf951d20ef0cdabad93d60d382b5ca901a29b769ae7305b0c3b8e8ae32dcf0a21522ff8862adae4af9082afaab08c56ef048393a3f7d92000cfd49161690c28c60a37b75aac38148683378ff41ec3c435113957ff29f437805a2ce76ab480a730d47b2e5eb153d30b251bd1e3ad1d4e00cb3e3ef7c7d15d1642b96f0e1a86b241b83092442770d44fd2b5345245955748de3b89691528536184d25f7f123015a6220af91424ccedc26c4e2a78b69f3847e1602ee0489515fe25db00bd11042138d84e129438b772b032b27bd562aae60fcd8163eb1ce9659be357b16428e36c8f1aff6736ce46721b39a0b4735d7ba4ce7b3a6d86282d2e1664e3a1fe97310c0a3e5efbc6bd33cc05ed2a0f42114b213036d6d1768b92156c0a915ca7991bb29b116d42d4423587a4be12347041af53f927d0382a9c1c900e23433106c71aab1aab2082fea605d69edecf2fd597249ffe38e6ec0d7cff648dffcbb75f1651e6fec0024fb1c3b39e23f18414598e339a0be089532f9848e858417c10a46cb0b733834e86acb204fd0d8d3222961756b6663bcceafedd6085cfd4452bd8d415bbc6b684fd0a97d32d4fcc8934e5834e135e7e39c17f2e74a9837e131130ca8a2ae0adeac83bf217c8a05ad62392956960db0d7055167b46b5ef8ad474c3753b20fd7f3be7f67e8189b4ba9aaa509872cfb0b1d1732d893b9cf2c002971c2fc7707fd057c531e0b500f167a8fb7a102ec10096216a27c26a56f550c80314eca105fa3d06635aa16faab26d3972b2c210794bcee5c1f8dcb7e73c27af73b79923ce41f47b9fb61b3d8054423853da58a2b12382655c146484cc1edebd7516b0e23ab78384f1e69d69f891d23a8a5ed637e70bba01c3b580fb08000798953eb5166183c205f9c97653f4039e1eecf219c2c00fb587e81d48e823558cad5574e10127c95549fc23fc0feb3d764a7eacb5d6f8205f80e16a4930b5b827eccfecda5c9cd34992dfc4b19eb9cf85e1404ed1b73ab9803bc759b981ab3af82f8680809d03417bdf5283eb2c386bc32639a8d86d13f48a752bbeb0b47ed15bf3159544deb3939483b425a82db63b9de32a2a7a7b79e44f6c6753bdefd7e939dfa281a01053bd8071968d0e7aad247e73f9a1b33169b4fa16b63749c691df238077de66738989f94511fe6b8c53026c174bca883bdde803572875b2ba02e653ee710cbb01685d9da1fb8d008b9ae7b0b958f894a13dbcebe412ed951c73ccbef967b445626043147528b08126f9f7ad263f2ab0b791b433261fe6b4ec486f102640bc528f6588f3b379f1251fd5680908a098e35823c2a1a7d69eb4c5d104ad5f08c3209aab8740d84d7c8323d73c724ba02589e8b003caabde7467fa87ded7e9ba4957c694af22b047b1102ebb3f45d16e26a86b702a5893459dba384ec95e910be49f9d15aa2009e040f67c2615e3bb28058cd57460426530506bd94a515da9e651c9fd2393cf72ac0e1d6f99cdacd2be5b37fb00ae6cf7c675bece33a3be1fbd203c9a14d2cf2dc2945c4984eeca122f8fb7083006925a5018f36fd67aceb9366885e4d9bbba6e65e2792119a0b86a79ce1761700c5e3d1ad750834bb7c2389864a3b8c47f7779da67aaf1c649071b10c28d5c00b4c065d13a048ec02af1308cdb296d8f4dca58d29ecc12e7c51b2091067ebef1eefe7ec778c119253eb239be53848aeb4372ada73341211c9635c795544f81f886e90c5f60ad4ed71ed045456d4626860402221053bb0f6d249f85ec5ef34bb22ac3627b5ee64e5aca849c7c676c7669d4e94e26efedc4449233eb5eed17c2d3bf97671ed071a4c043b7545fed8f38370ac751f034daeeb2d369332ee2afa54a1cad833e558b8130893a804869ebab530d696aa877a444c55e996522f405c3e830f27bf6f6cabd554d29cf7cb956cf15ea7c94ebf6a040a9edfc67890aa6c99cfbee18d390eafb7c89d9f855fc00bfe414c15dd7a3f9143502074029bbc0dcc52d49e13cf6ae4dbff76f29ed9138430735d2eccb36af052becc7504e6595190ce8dd876f3b0ba9401e71d552a2f72e876d3b20dd27a3a1574b52f4c236d20f5c5d3ee2d677042b37d0a8f20a9bfa3699b14e409fe8a379edf7402fdfa447d5fcd3dba3c20e301ef9f354a84f314bf78d12f162a8dc2704dbc2d54a65d40e62e15a33e0550e7ddb413e6a6ef65b9487d1737e38737a2af2e58fa4512dc550af92c72295a5fb3ad30d53209395d37be56e142d9c4113fdb6cfd720e0ed38c3072eaea8dc885018df7bbbd6cee8d3a4d097614efaa66a8b0b285c605f32956a05ed9e864d99721608476144377fa8a69c96ab78db84c5887c3cc206e94a724ca08de10aaeb6b192e17ce6e0c30b00815ca59ed55bb8268dd2e01ada515dd020e85aef6f2ddb1ba51804a87282d7a37432449c0e82afe8372ecd20256a79e055454c68bb04b70a10209b1686da2e419b89ad8a74c5098587b9fd0afbaf5e3d5029540962eb4c9939543623d1de89d57f3cbe6d31663e55ab4e672c46f4936da93766c14486040da6172d0eacb83096cf28b7cc842b34328424c83be094917c4adf0d5ecdd3f926a32fec2b612c9000071a02cb166d9fb0a920327e39467dd7583626194af986ce8c3563b4849daed27f54c8439311309edba976ed1106a4ace7edddcf87aeca3e965e3f5fe7d512d0bd9f9845727f32bb779ddc41549abaeb24c7bc085d8a2519052b5603ed245a3991e97a975709c017510f9ddf2890226eaf0c00c973331ce6846ca52502f9b5fadd24ad1dd0b73a5c19a47143571e922cbac7e230349052371c244b3f2706f0dd59963d18bb02335ac023494af49836f695157532434b3325d364e48b312cb3b91111fd1087444051355eeb962706bb36758f6180679b5663ed31988d79c45b06fa073715f4fffea99583763b677876b4b4ea1357800be404687b1df69b9a37de23e9321bd8d43e6b721de5f57ff4969419b4b0bab40cc1ab4a0c5375c17179fd786a1c92ca88a7963f143aedc4bf23e0b2063c4780a0bef53badf7d22293508b76687d8028bee44dba5fa63c17c4a1d10f791880c0d85cdfccf40fde6cf1e838b004a762376352f965ed0939019a93445b00b6755d0c119448e0a0c0ddbbd06174150e0939940ea070daa6df34b2d25e760baff4e84c972273e62c66ce8178a1ea48f73f9692bc40a0b8542a1027648cb12f0ba45d196bd2613103d7dceb46fc79ab30882a46dd66d3e977cd97a2dbbd7d49ce0cae7456a7e6758ca18d15630e82579f0c9ba950cc1a32a6941b18e1fb0ba40bc7b0056c1cf7a5806b3527601c521e3109a52846f846a7ff59d23028d4e8909e8073c7213874ee02bef6d66cd56d9c62de7e7085a23e176629fc03b176e1eba4b3861ffef08e67b0d1160c08a764dcde217698e25cfe6e11302bae4251b4b4466a149a4ad01a7deabb58b40fb8fab254a26cc02f3b8f3088b95637142a1fb171ca71d1aebf1a922e20ab3a6ab2ac068036c627582c084cfc3176f385f2ae7aa7ef3a22a236ba685488bf9de7c58f1dfd023b54e1a6c63721e8ed8cd73c2fb72e5910328c4885ccfaf7c8f3b0a778c0d913072acf346b933bf24b22290b755fd7e8d8084517fe806de8a534f4e7564e609f3b69edf98be1fcdfe14d0557235f3fc9fd9fb673ce34c008a51b5a18b5e851da92265b9e49974a303ace2c29d9e2a2426e3a50e9746e5d237d65ab9cae061bfe9dd112a1c1234561969c4d456588e327de61d96b64e1d615c5e51a5989bc32f764b5ffc5671a14c979c67a04dc21eac00565d5c765de407f5259b9ddb92b30e90ee34d26cf7c072e2384994015367368e4ea3c8c619444e32086e2cfdff8bc708fec90b44a55f72da5bf0e744332ed2ecf4bb18abdb6d90b93d96cfc6e80b1dc0765cff14da4d88be2a541fa5e359ed3ad38aea2890b60bba60b783eb19a5e17ad791baac1f2fa5d5a52d8d0f07c8fff5b672fc46a20805419d32994db3ddc2c9308a416f202aceef53d05db87c0442b10a86371117be8d1d6d097cc31837824bb068891bd898fa1f79d38ebf5ca500b4d737d17d87d7623d0e0e7cecabaa159abee1fb3e1d17287f2b65c1726df8de03501b0d259497fcb8f536ba477"; - } - function data100000_2() public pure returns (string memory) { - return "f670bfbdedbd689a27f57c948324a1b43bf21bf73e7164fb7e112f39b30d4bdeddd45d1b514c9c038c3748641b77cd2f10536d89e22ca0fcfa928d8c9830e7869963a15afd0128d64165bcbe920f9719509b3e9d405310c19c2af343b75aaafbc5ab68c2a5c0fcd49c3b35acb63000442e047b1d1fb75c745c4ae55b791ebe6bec7244e3d40c01e58f8d99457461f02aae5050ab8c999061e8133632172652655bce651e87f35941e4392cd46f39be964781f0908bab59a49e366bf04ca232cbd4076cee4122b95b29ee411113bb75bfefbdff9a97c97b5a0d9430710af9b376f751da89852f133b6fb82a29a5bd1137044734b25b7651f966c8c2b209f3725c635fe0fb213003a9ae2b63d651aaa7673d27b26d9ca749ce65f9d50df993a08af68627a023fecbacd7cb073773f96de945cae6d8dea4bad497c46662020deae765ba260d8d9af5162ff91b6b92092240149cde16d479d5caaa9501ffd70ba137e19a8ec13de8ea208dccbfadbbb409079f3e2a4181a43e745042c614b2ae8c788932a2dfd07012f66a904abf2633c29f020469dc08af3974e65307739c9f087144ba4b37d18f41e3b3623c7776488a17069bee6614ff651e749edf1ca408fc709ec04727f73d6b23e56bbf0c58d3ea7f33222e17bac0748e2b16bb8f7f48b057cb11681ec9ee0fe1e9aba98fb3d247ded0f42d9da7929bc3e41402d012f2c07544461736efaebd41ca63b3d96637123fcdd9875ed5d97598ab705f7e22a5dc47e595eb9d8a3f0284bed4dded1e3132ff10a76ea3a718ce42864630d0f2772584d3e7b193cd0a3643a76569ffd400ba4e7a27df74161b91538b0490259ae858e4dc73e82c3793a09aa2025ab4b21141244442aaa6b94d8ccffc796b42ab7f358ba761b284ddafe7954df0df1996b82434aa1dcc0787c9a9503d5c009a5d42bed5473f4ad905ad32cfb971a7a7f6f05f09fd3b942f19c2b92d8b23cfd74478b43389ebeeb5f53b11ff3102e6a311817bda0dd208fdafaae9aefe883ef9511de160f05b55ebab40814c596b81d4bdb17f13b3b0909b94a5aa0c43774e807946c72a8d759a5b1e18352dccf243663fcc1377ac79f0d92e76790dab2b0408de9294cad65147febfdb1ed5abad6a3ee17b723b3100d005f703c05e38be11648d4ed39f41fef43a85f1f1f1bda7f078d0bab5dd613d28d27f7ad2a2455589ff0621f8d078d14662c72e9b967b4ff09976b840b2cd73ae198872b5afb447b448d260fbd1bcb4d1ca757132f87553877212928dc7afbaeb94ddd32c601cb130a638d2d35d4791c8a53aa12f39060d51ca5b32eb093445b105a47631cb377f599b690f298d744472c2d644582a7a32007a8357e0ced79fe81f67e30e17b0853ccf17361af91c5b0d0c0b162f19f725a2fafc7ba9b7d90d445d66cb837c58790d4d8e0de4e582433d54d676b7c52912088324cb7230ae1c1d72233b0c9b28ee6847876c82de4111bf2a4dfd0f97fd446e64861d16e85946f57b5a887f52892715df6b50868e876b2e213cd6b389cbe46b3e1d7394671e22919765e2f97e588a26e49cc1df5d800a7c9d0dc108a75e15d888f630b78339b90fb92d8814845b01234cd96cfce2146b0efbee7cfa7cdea3c0c877173c84d507b01dfb5a32d41bbf274eda5ba9e296c6754c887c6fc39d7c3104ed1021b4e2ed2bab12b3db4688594bd1dba1d4347370e6ae4459809491b7282a29b1d0cdc311b4e947c21f21c7cf6e9271944fab051c577d304312e67207e81c7a90ad9551be34ab0733b8ce2c136e1b2abf56c853e3c6ef0c22d1ddca1f6cc595c5e4b49a8fefb77c7c144897b3cba9ae8a05ab932e7c302d5a87a04a0c4649db822880ad4e0226c63a57f483e949e26b6a300caf6a38cf43ee64d0728a75ff6177c7f4b99c987c2def4cffcf001c5cc534b43168d19f33c38ecdec7f75b1fc0ba7bc837be8f80a89ba48714615b59c0cef02809e5341719cbb23ce2cc3bb2b2a2ae2794bce2f02637175c47ed968584d09d044c1df3173fdc256429a26f87a5d5de55ec84d0d2f905f2a5ab8550bdf1bdeeec9778bfa3ac6be60fdb340bc9819151561a36dec94693c7dac769edb421c7e0fc0797e5b8e82553c6d9042b5720f9349a078bb0af8298e20504a48ced4e95010f1fe0f4238654c86c3abd650eaa53837e3bdee404583d4496c7f2a957adb263d0d41e32a6628de9956af6ee35e1d8069ccd0358274a3e8c2a2283f2d242191804090dde9be2fcf08914dad40d33e167a8e41ff1c7954540d351b5fa0555d5f8546cefbb1fe7970d73710da3b40d19a2f1bf7fe28a6e51cd2e4e28eab08f1b12321f1dc77d0161947e7d46295b36b3e787911a107e5ba62acee58000b6dd64dd466c4c03a2737b19b34a271522727c088784c9e7411764620116ef06a73baec078653c01ce10022194b1551e907dea014b8734f804027abd7c67c170b16c24c72cf586fbe81e155944403d446063d028d7a867572846d493e202fa24cc75c785ab3a4909d0a12552b2f4799c0219ce35f12c33488d0cbb5f536793ecb21c67e0d43a82946784c58cf209e15f9f9efb4f089215c2efc0ff28062d35e4d0463b35b8671d0d874de34108330a8e288c4dfefd453363fe9a6447835a48c0c657d30037f89dc780eff05c3aba2d09187b87161339ea386dd11687fec31e57178770dac31ecf4503acdb5131a62971a2abde82003f053272cb64993a80607e61d0f314d5ee1d34d26f43473c0addf949cda7ffbffa44203897a0e1e04cae1e19b253b91e7d8815b918dd2e383bdfbda7c2053c89c697aaab2e11f4758e5c96f78124016c6d46826b45383d3751972d7abff69c993122006af37f094b782414595acd802ae61c13f2a1e62ce864a81817263d98956a44ba64ed1e7b4b1804b2dd86611c50600810fd5394a8341a83dd32f245c675d90330183247c6dc08e5c801f33ac26d2b258f599d3115bd86f0de6a9f84bca6bb17b4fc6896b3bffab4e8ede23f0cd62fce3d8b495997db7dbb31a795d27acd140d5bf7a35811383de909661a9c8a58e67017451718d7f1f57dd2a2b915be0e99493e84c19174469b43ffe933a11302bbb59273e9d2da70354fc849a947aaf1eacc51e83717c2e349e4bd3b0fce58ec49f4529cdd7a171726bc42d8ddea629eb1ab9dcb5ebc5f0bb2a0431b88d0bfff096880f36f43760416a8f92262d100ccc8a935f59f359f98ec6480393fc98a32e14f9810016ab241d57c819197aa5be343ee5cbee13540213d1a0a7030d05a10a048cd067d6159f4c560eff0c84e3c1c7a20740e505cfa306c11145f99bc269b32021d324b1f333a41e930f905f9ac7fefed9415e7350d9e5638e7bd76aafebcb7d5413cb6045d3c8e45ab8d50239d24291d2288e56fb56dba9a94499ffe8247132e03d82e4002776436c89f6cd857f8fdf4fd7a1dc5309ade21a2463aa4cc6835c1fb7c75e3c7acb4372e591759acf2a32fbbaa7af253d8e67b72e3909ebca170806416a058e37d05e4f574e0c37aaf93701361fc11447912d35949b4d038411986d5e35d9a9c813bab70e2948f39957f9f1c09a5c8efb5f5cab33f83386080e8a3deb64c658c73d0c7b1de2b2e49d6a2a906550f9650ec016d1cd72dddc78698c4f19e51535fd611ff840593e2b4e3207d7ceea498f69586478fe37c84a52e0b08dd7e36534ed3938834bcb0aa32587a1ac83b6e39bf495497cfa1188f7eca4dcd3e123b74471856f26208afbd7f190c635a81b5776c6e733e61582356ddd9490f882b8e9d3ef4b100a3a528eb86350d621b1c3ca9809b1f7ebf78e00ba14bdd47e036b9d19ccd5fd24357a8ff295d066eebe95adf316d777535233334dac63a21fd52a00c55025791441e9b71d34f73333a1975369ea5c8fe46110a946c6031e3d7c57a703cc7aa5a8f8f208da882efdec86af1066bb471719f905f80f5d3a92e66623e4343b1fc1569b4b485beb47d1531259da7871cdad9694f8782543550feade52a32788c3064a77204c0c3114fd32f5cd3f03a6fca62f41bb9a16f2d9acf2a7a5a94cc9f67f86fc199dbd9f82dcd05bdc35dbf6f7a1cf8f27a0da599e74198cc28250ab8d8ccc7ab6611fb2c6865725c48f71ccc86a58eded1cdd5111e41ed542a67fde5ed04ac9cc610e8e2384df297ebc5a5712b9e271803ac9933d94780c04e6efab29a2c7c2b9615189e6be5f3c89648a6576d29802410dfd5f43aa828e6f31aee7bf0e137785ae63676cc70e1801b614105f1cb477d77eb161e561478fb5c4c964b8d700b836dfdb49a3599b9421bcdb9992585d9fc28a3e4bb5288e11af1d86933b8b4bdfc623518dc0547f127d720a9c4d01d3371ecf2734e19982881a45e99c621c6636b7c278b67b3cf1fd1f42dbbe09493d9342d9585a8707ea16be30428ea4f0275bd54882d4c8ed08847d3b93ba41158d848d307ea8129b85f6d8b68c082b775384a2a718ddceb1985edfe29b42f1f4dbfc4c5a2747b25cb04fefd49ce935120f17c58b9c3d58b8c3e3e85af5124c827606cbc31401f81450b7c52653335a52acc89997bcadec6867380a0a4c90f27f75f749ad33de73a3567fccdf3fa40624484f7aadefc258e1bf3effc4aae0e14acc83a2c91733f6600a1d990b98fa5e89a6eca7768eecd87ecf3be7492428e4c05ab5767634c45e296cb5a6a920f5372685561bcda1badcda6db3348784449eccfe06bb95e37c8d0b8c76f55af0098659af07ac7c41ad537d56c64f75cc12e5938faa76012153f93be5f8c923eb33c4374148fcb3e2f5911fba541b819e388e64a456b6d43776cbfe56231e32558b403a487a263abb22e485864cc8427c68b862339359930c532265f690335084c7b08759a0186082821a9b635cc1dcea27cddd136a715db9cf790fef8931759ba4ff6ebd86dbed9cdce9189f6b53dad21ca9107e361111a4e98cd70b07e0211851d100fc2e02d4fd768c85c123c0638d6109e422476497035262516003a55d232c018542c0a4b86dc60513d2600c79d75f3482c02294fb3ae3ca02622f7f97791fca95c8b6acea5d2a024c3ba4873a362e7327f911497c24920835ab8135e52d1b312715a31f39ac95580e9a954bbdcd87dfb96b5fd2e9b2853e30da1bdb8a9309c3403deb695a0871700829b619680df5a1b07d9a5e50c6bbb0cafecb687ee5d7449a954ca4de74f4cb41e03c368a68cf4a7db72f4fb7612a17ac55ffa6706823e38d33fef63e2d2c22c240f3242c85551ab08ee57c728b97504f0881abce35768efce20953f3809e3f72f1d14252327392732b273484323cddc0e5f93aa8d6e340af08cb4a0935f316a7e2c3376afa5275d9a16097738543f0002887df39cde07d8617ba34d3493953d2e2c0f176515f02dae0856d5303eb6009dc759923eb843897f80f47e530cc6578a3289d42f51b3d92a43bc6353dbb2de2264212222c26a8027fd08b1b4807d808b53bfba19ae55770d865bd7d325b50b2ca887df8b6333eb458154f81f7511ffa9a0b2ece3a0a370a5ec6a731a057753f8fc7739d4203cbc08b2a5d2570879eb05b5fe73fdf4993207a75ae3a470d0d2c103420e41b69d9e811195feaf3473bea4def735b300e5b18846710214a2da6c55399b5ae3e72ad2dedd232169119d4300f010793f46d28a56f112d14c4157a8a67fb4b7a28c78cdc9f4d9b278fd03512c2ab7d6ba382d05bbe3aff6d24d4a147ca43d348c0c78fe6f66670115a2ebd0283456fdb921cbb81e63627553a20ad69006cccca8eb9bb75fa7cf7bb7e03a4655a95a007e9b5575fa75be70f84f25a90c7d7d80fe4ebc65032b1b839644a2e371e23da489710ab39a54753cb46a2599b4621cf51d7378f30f87a7a8ede8bd64b13cec9b3f0740e7921b7a238c9962d403a84e26aa3e43269c63cbeb55e746377e4fb28747c19e30b18c739437130b74473dbe34f8478aa958e0fb708d2e43ab50321e1e92a458d9010901b44ee90929ef82dfdc1e760bf5d05d24ff3452c95268e429e75b589a61563939766c650962afc8aaf94d16288e27d3c19974d81e281a9e4c3ae7975e257a9005e7a257fdd31662315777d4d465de327da82b014b78b88520fd376343ea7126e4b17387c8fc4e01949bc7e6eb55a7f29392b4167b4da0ce3eb159dda5024a1a5b4cac8c51ece23f45f1d87a9228a43015fdafeca275c3fdbbe70448fa2b693f39a20a07132f19553a4b33ace68ee42805d4cb0551dab9d337b320b86598bdb3b8bfa8ca347693d4613080874f79bd03437bcfbbbc2f9b5e0b9d3fc25807f0159f766728d22fc2c0923df68a50430495858146c483c89a4926326c0672a3bab4fc557764c683564893af4fa53b22a3bce584e88b00407c928d6e41a732adf59714a36f7576eeccec5d090d0c34492c937af04c4f42b94b80bfcdbd04424cd5d4cba49e5c1b1ce3146eb69053453f0d8a5bc94ce9796a546f78be932acd889b39656a6dfa078c69bf7023b1e5942234b82dd1cf21f0663d7310de162c11dddc52e4d3e91090cd30de9c77d38bdd08c2057811f16eaf91a294edb66ebdbb4894c2421347ebf78be4eed8d36bf0d16b07283054c88a5256abf07ad49185e4298617e652f921e440fc3f55e146e3a1955048eccc23f3434bc783b0db7394d74d5621fc05e9279030c8b3697990baadc294add8327ca3644e69d6530123ca16c9d35dae6d54f1bdbbe8e262b3c046cde2070e3d8f753b344ad07c0f385a52a38a7bf83ec95031c340be5421f04a8bdd3e71483c0b2bc6b543cf0860ef903ffd7b2c1ccd86e58596ca1cb8a5825789fdd30df221137d8bb1a809f11dd06bfab38f372bfe18a24113807f532d9ef0064443ed0eeaa438d6c4ed43c16cc003779978eb4ae9cf26bf53497b8b538feda7b277db043a0937df1e481888b9ab2eef11a1a182c42b1e1c3897b5dbb1dfbd09ee256628fa646be8264b0ffca6367486bdf48841163b37ad4b07127de1382d88e937dd84d11bdd93063691680995f3349cd81e8a49a146daa38f655f574adffe006c8d46a58b189e4f5656b91133ca9803bc02576952dfbeb60c1685fa3c42cdb3989bfec4cf6d911b1de9b8145d98bcc56141a72edf07251c54badbf7da1562776b0a0372f6cb66c9a458b4b194a14dd2a061dfeb3af7e55b3d4b5be10c2c7ed9ebb177a6b71948a0bec402a5b82074d8edc322b16456415374e37fbcaaaed1d79488f0138aaac571b79f8b99d1ebc3a4a6b08c3f00baa128268ef80be3e174eaeac64b5e07e8cde2f4ea8ec84c7b8e9c66d5ad5b7d9429fb4ca45418f9cf9601e7ee9eb11a019acf80a99354f1d33dd4c8022bc88de872f4e8bc472f6c85c37697ddbc39f0066bf6c4b57e4464d5b54bb999b026879e7235857cbfd91505e7457b3014a3e21d28e0fc6d6d31d0fccf6fe9dc07affc4fce51f2fabe928b400f4e8ed86a846e62b98738c29468762a3a1993cd30d7759e275679acfcb3a0eb21d7b30dcbcd6c0b52668271937f126a2687bb8662fcff289a389478018a487251b31bbed184bd688ff65c24ee426cec84000d5a9a6838ba4881a7bd6d86e2c9e20360b0a57c398d46e32c8451a893e306d2f2a5486ee851349e14bf25e2475d88c0bbf9f577bf50c3e7c21b19e467f9bfbed1d4f958fbccf553480aa122ec77ad511499d12edb6df9351668149b827c88806373d142db825d57f337890afb6953f0d0ef16bbfeb213a45341e7c533dc29eb870ec2aed1d9aeb68dbe0750b9efb1e7a36533be533f66196de19ca5a70df4f6046ac8b88b00022178a4ba0a355b8a967ad350d2559d879b482f0aeae4d62bce230b924d5cf464e6c0a0b4b91b1606f023d9d5c1ebc1a88955d0df7cd135b9db5118afcee6dfedc2a53571dc4a26ed71e00692b5da3ff307bd1388ef6591f12283a6f0f008d898d04c3ee2c1651e9923372edc9bf0d7bd7a241e6fa1a924fe54b6d601bf85a03fb2721b611b844d2e2e451a754e94e8e979719caf4ba5803733b30097fa59ffd214de06233c8cb5c3e4ae63e05ac3ed13917b4540957fcaed5c9c57f2ca3691f663ff45c437af224b8268e4855bdf4ca4080b14692765188766384046cec70998b4aa027980e9eaaf30739b40e8441532ca3b18348437bf881517c700f61fdd949e2de578b15ebb40c22ff7f1aefe8ad526d8eb479b593cf549d0b1e87ae94c2181a78cb1cbf07ba4b6ad4a40eb016ed5d684f3f51a2c8fc97c1404f7637a3f92432fcf7921153e0097113fa8a651cf7acc9e7bc282e2e8ada5e234c416efbb29869725956dd5480c356475a588584468ebf633c5dc531212a37cc67978502be1258aa8bc737ec8e62941c0ca3f15b99c4dc547abeeae69a78a2d6d5e3facd9c894dad1ab93009569ee0590a7557c6d64a011e498018bfb30556aa33b7c8e0aa0697f284d6ec4b0226b5be3bb7a88fad71f07bc9760e17613d298071d09bc56957bee9cf0ac91cb06ce53aa58d5bb39f47b6d03f66edde800c36e68b1533054cc0d669856b0c9476ef7d34081c128b38627bdc436b54c928a2466a70a893aaf5ad4d9931db938b81b5ed8ca992b50525ade1ca8c3405394f65ef6e25b8643b97e573fa571b50cbca9daf7048180d6da437f2892e486ef990ec935c3425defc5ddb893757ceb7c652657653cadcc5bbd82ee0e85869808ece528f773e4b8e3eff1870b00371f866ca6a36544b502d8c85cc9a089d2bb1ed23eab48ee8f28362d77942af5fd41c9dc7eb98beeda1f5fa9dad03f64f1485f9126517abc909914cf95f5e75a601b216e29e5a149cfd7158d281d336e0af1599bb9ca47fadeebe71aab98e7b273e12f40c27a364652ec0943f7412fbc2b6bf2e87a127e291d9b10e7d1e5f1223d8542a5f1abad48f3df705217e0d180445a4015bd10b60bff60304754b40b09053dea66c65d3415a045c7713d0823bed0a6dc73275fff91f6df0902ebeeec0406829b8fdd8446000dd5cfa057a3cce56c51711ce98b5c0079fbde0b8950df99c666ad219619bb8436a1f918d229cc13dd81543aba967404b74f186d014fdde2d69b3ce262824dc38e752d7edd6b4f41b5231b0af163356ed038cd0d9f51e00f4fc0697939108d78e3a86f230db16a4a49445b7dde8e2187e0233915576ad1b2b81973ce186f50b57e03663fb169639a1a8977ebf5a6a1a4ef4acc3a15ed748dd50097713f7486f3835f471113939353dda5db2904073e63ddf17d4cbc69bb111eb3b643c3fc88ab0159a5d187ea24750429e569bdf9015166632569f2683bf64a0133d751e309b327d806109f55175c6e9abdf60ce1b0f204b0cd45092edd2cdf528a79625e033f57092dfb58df25a761bf091d4653896aa6ae4ec5851949cb6f88ebda9a1c117519044fb466513fde797529e828fe20841f493beb36aec962b2862dc796a504840c12de76715e0feab019271ed98311693fcad3fe85161030c9f6c9f19c45cd358b6de55115549f3d28eda6614ffe4f64614077a614e1d36cb46b4e500620c9fa502710e5adc39b6340db43c656b5496326b7610706af755b0f0a60153c3fc894785c66344a627c29315f83caf4913b3d6f31b9a6fcb55859c95e6884e5eb342c8b6d72b2677f2ef2d2e53e8451f294ca7e481877636631a68f0383f650d76a26e85d8c2cae433f20994e2b1f0f1ff7dfe5309cccf1590fbaff0ac82f7e3f35285e7e30f9983978a9d2803a82b262ce1d08401b1b9096427a9bc3b6bc1be84c7fa162e38579157d91f6e962b6e6be29a8c488169fea11b18904655ae52e65a625d973b5f473c8595769143009144c54f9bf430252cb7e512c52d016758a3c2829bebb9f0e04148bdc59361719050d26cf5de8d241398f9fbad71a58ab60ca3207f9f20a5f3573706cf2150815c4ded2509b11280a6b605d032d06e7993c6181f005f05de3e54eca450d43e13c815815401b0802ea2a6ee8ee722417308a12a2b2fe1e0dbe5e6a94298d275f9d3862d8b8bc8aa8e9f53c7782f6e8653a301a53e929d46ae91b61287e72b5a776c33e5635c030f55540fad2b97264ff6bf7f7b7982c83db9822421e46156246df2f4ccf4893b1db7c8c746a65ce5c397bdaf17ce37696b25f291692524f8921361dbddf77a8e12a3048f310d019d73d157a0b6bf9ca14b93a197fcd4bf501e6bfb14330da71b9b81a4d7c5448e2a2c72f04d41110d033bb7e85ba0af69e9c60b2e35157c6a725a3b97bba65ab59235c21ada7ce30e40cc4316124636a00d6df506e9de680514bfed1c9a9732f668c7107d488984b19f67ad6bf79caaae58db131defca11e0d0386f24b576a826ea0737d9b4507c7c855dd0b89a8b0234d7850c798b52bbbe7e643f45b21f3727c3f637a18789e82a57c57407a4f44129f36cea2906b2f111ef8305828119a4d74df4309de5b6f3568202525a9a621a4454918f70a2a4a32c66f5092dda0e22da089c5a8edfae9f93370eae91c6a67aa25924e460628d4a6b5eb2aa62dcb2744afec8c6aec540631ba2dd3a0f7eb6fad804ba3b3a0352412cea172ff2d0f9d2baf8b28747e8a657ce8a26f0e6010ad6f2ea78b33d627f61ac590dddd2209bac88ae0dfd68762d1a71ece4fce9409ccc566b9811b680ecdf8f36043649187b3bac96b2f3fb0a7fddd2d232cc0e09c3541e26f46605871855dba5af86cba70bbd3a37bd34c221805f9472e1e490197e530594706220d6f669b7144cec007d959475248866a20cffeded85f3c3258ff3b640e9a47d6ef0ff1940503575a10e817a5b6957dfe076102d1d4d5c71dc277b1b85137e1e8602bf011c40af754b4788d3d102ac9aeee36bbd47f77135ca31e7009e45b1555d3ad7fec6be46f5fe441d8c5b4c2789dad6177adaee33e2a8fb813e7f69c44d1e78fa727785ed55d9e9894b07fd41e277e76b0df6b1a7c467cda7dcd94671e2d707028fda04a5e4866bea6dd7d914b0382a616d791afd1db6824f30ed1251c1ff06bd7318e25ba2aec478acc22ebbeb8deb4c9c6a3a587af7e3b168e2f41bfa557e1c7c353a37a9d175019e01f11414162549503564c1cb5ac278ca61836939b170bcc84ddb1ef5adad054f285e0c8628483e3c66037cf1c45512e238d27580197a2f8b70d802a2f353e59913d39775f8c3e86efcaafea5b98e4cd29682e19a15fb9217a7eb467b05538205dbacdfe2765ac0073fcdf890379deae1657d46650235c3a75f4e3abdfc9ba0a23cd787f9cb6c071f5a2e46d627697483eba33da8edf9a168b58f39f7cea6cedb29bd50de3d8bbd1fd581a07a4568837d0c0cf193b649a5c69d3e1ae5bc683bd8098e029b3ca8b00ae764f172339e7e4670918ce94a989fee1d901de94f414bad15a2a35cb237d1403387c8885888e2e5f7ed7282733d71eb537ac92cd7bafc55e4a81984638a66a5f4a3c3e2516e524fde89ce2cf053390fd00f1d7ba4b3971a96869765f3b5f806b310de9d06984818f19c41ca77ee8c13501409cc99167694e1ef051cf2a8e6871c69083b17b911f83ef6308abbb8baa872ec36c35b313764cd3e637edf8f3dbf07f27a33bcab57d4412bc68a2f1b39c45a0b3c2daf55c79ccb7b124db33d295cfcf892aa28bb452fff97a77ad8563eb1753d8d635b627c567ed1544d600d65f2339e2d83215a85c6f4cfe2bfce8890e7e6ced1374670f9b6dd32eef9638897d882ebb3136b12238320acc96837b5171887fbbc228b16bacbe0b1c46a75c173aab92484df507e405504777c63582f99c0c7094bc6826dea3fb0d2a43d8ad5de1a378b377f13c264836e78fe705df4956d91613b5356c5176c98453e5b3f69b06cb5eabe3d85ac89fbdd3146b404e10c7ac642d979a6cdf0b0035bece5ab5cfd7b8a12a97cf2500149927c2730950429a10453a8d7a1030a4e3b45134b3fc0c8de125e0340701bceb0d085b057562f877574bc9a66b103674e8bbe6b75ee7c96b6671deec3ef30f05b6a6c7443e527e80a263b3e307231c9a08ef367ab24b4216bbf76402aa960da5b65be2d10fa6e6ceecc0afa77b745ff63eeefab6d2b927687d872897dad1c75bbc018fee0ad93fc7a05ad7ec56f13f5b1810b31501c4c227912526927cadd187b3288a0cb491d4d8200327658eb4c741a3e4a84ee884c73fc4454f9038c8e9d517bbe935df5b5528d57d3c3ba9348274fdce3eb487f95166890ac8cd9a15f3cbe7b039fb2c931b05ec0c2a1095bd2344dbe059ea7df22634beb0a8ab5a8ed3a72e36f6a285aa5a44907245e532ebf93af4bafc2cd82cd837057838663c31ae26a8d768c32dfc1889d6dd5deb608bc7ebca586b7118bb144816294c31c8c5299f8c8d3993e2dd6fe5d420bab0640c5d64d18a741cf3b201c27cc94f0e9a6c0ed295c6d8e162feca3668a8779e4a6aff821393e6eddf52e2f3a59d21d55becd162c2edbfe026b4d7b139453a07c024f330044f3ee2cd4fcd65397a095772f87800c574cce33b6f4cb5702a06b4a25a1c2ff2d0e0c373cbca24ccc7c71f573f374827b52b0ef09bd7c80ce2c977b7eace91e185b1339b44255f43c9807e329ddb7be2777b02d2ed3ad5aed36dd41a024d9488f6510fabbd9ae9e0c44c400154174a924ff87eb649b61beeacc5529537b8dd3b9151beb49e91aa5d26551cb1d5527aa7df80570d538588d69ded4b863d5358e52725b649764e5492c9e8340a645f6dc21643988006df33a09133cc10177dde9a2fecfe44e278cb5ddc0c654d5dbc75e3baefc65299ebfce35035a8b6d91af475056c232a1e52ff339ac4f34717892717e9cd4c10821fa387425b98bb380592403bed8f1b1d5cb185ff28fc66fa440aee20ad17f1777208036bdba2142aaeb284007ab003bafec897b974dd763269bc23936a6c301878dbb83fe6c5f10ee43a14261edee62b2d793187b0f9ee6d5bc53986ac617f98f45457af4fb1577470494ab01ac2403440684f096872fe3f2f44136ad7d667f50fca75c46f9feae75e2010d1763e3aa2103a21209525d25142b9d1b3a13e2a0676cbdd712d8f300b9d2152517d110872dd30196a2270257118cca516d0b6cc8283aedf1f5becded3e7556730c81a13d09f07d727ddaa7469654104549c85984e9b7a7947382e69116890fe94c0a02d0d33ffa30c2d60e2095f7e81552291c3f887fb880f37bb4068cadbc582c7fd0e8213175fd4a68bcfe9b208b46d8de9b5d5cbc564d532fdabf2e835d0aeaad058341df8bbf9a847aa4eaa2a96685caa31416462f904c8d010e78325488bcc1a1bd6044d980126a2e2056272831cf48f28451568b0ef103e5dfe8e3988a571b0f6e5c4c8cfaecdf52de33dd22b73307997554473980a375d4225ddc478a405f795f9fd809b498227aa5405b435678e020ac1365d5f7f01abbc75965dc523ad8f8c8a10c9311c75ea146d5f8dab67181e6ea34ca6d6c45dae50c934f104cd1a3852435f23511a028cf391e7296b5bbb09ae8dcf80c86d1a4df028dfff709e65d7c772ba79f3e48e3780595d29bae77957a44fc85a9e9ce9dc88e4b78878ccee3abaae9196c284ebe336fcd02f601800216cc6dc4637fcffd3510d35fcd31ad936d8df57752f16379f5a0696b3d9e59fb7cf9238fa3a60af12aaf5e9be377f6a0c9ce27c0912843dbea9aed1c6359f0511c9d14e177dc87fde71946d91d0016e04ef4ce8326c93c12cb7ff1ca873fce9b5831f946ad88c4b878cfc0f314e3ec7357ed4c44a0005e041a4411b5ab7e758fd36c891c02a4cd49632389e134f0c3b55a51808a525841a3aab6e9125e94f779713b05c58dbfdf2577d2ee4185dcff780571d51b46e27c2b55b545054f9e766e9bc1011f93b1ba16da03588de2bcf04194c5bb1d675b55d5d58db0c667a2a88cd08caa8962dc0e34a80c3c0ba4adfe81e95f198c20ce6fb7dfd048aea5030a76b82b31472afcd271fa387a12999622a150926ff7ab1cf91d5ad9427e8911ec0da4a18965b0e8b2ba9e92e93c7941ba167c606d3f4f1a58e438aac8fcbcaa2ca4e9d1eb5898eabbf45ffce6fe6074d59746e6d783e4b321b9d9d0c9e889f0b97f5a227577f0b7b5e5dc106828e40c11e14f099c62c46eabbef4720283"; - } - function data100000_3() public pure returns (string memory) { - return "a1e35e01d308567917e0103759fbd63dac2e57be64e3b571e66e72c98121d5fb36464b382073d81a71573c5b2d157d7a6e4dcbd361bf4b6ffd12e36e373244a9ce2fd0ed25dab7dbf963bfb6774e41e84e3695940a8081573910c062addac16d9003ff180c233afce53edc93ab5b27d57b05df2d04b1483fa20704f277ee52d7b881d6fb85241468d38b22fbc4ff4d4a64da888de876beebca92cf0b5f08d8e0322b6396de03ad2d1d9fa0213df279b000423dadc21c58aca14a3178521b2591a96cd0aedb24f88d57c3f70c48792b55a6326a61ba687dab1aabc2e7da71f19e447b9ebf9af55b6a36840b90aae47ff0d2205cbfc750d4f4ba60c0efd0f30c188e9fa08395c4f0df84346647ca56bd6ffaa3df48979ac18d9254d0238b28ccee9ad5da3af187c952996d425414900d3cc4b6e0d00287e2b222a41e534a1f40db1b1acb8abc55ab4b1d5700adebad79e91aa7da5bd78a1e342973b14b28ffdda0416e7844c8bed746a9323fa531b87af0eb9251c7e87e4b80c26e5734b5c103606b4e63cb904c11c775cb2e7aedbacfea1f23cc5c56cb2a0640b5efb65b274266a30f8c054afd3c9bfd52d42666355fbe502ee5cc651fa772375584065773dca494f8392befccd245c68022ed5e5ef25389848702a0b5d52d4e38236a9b32de27b23e27f322f608d7359c85674381a340e631ea4314715284df05490dd65594d767b54ab29e4b3cae01a4abce6f85aad8e5d14668630fbe31ddebddc38870edb5cb3b7a262bc88b08feda50329d16af747a02ae58b7ca44a5012024628083a5563a2edf9a076eb1b1880dd27987f62d834f935181e34967e09cd989cfa6ef4660be3fc967d009e24a71fdcf4f647200f9b795ff235ced40aa9e3dfac81d53c2eb3a1f19d3eb00ae806dbe5e9c29b343f5fea5bc09526ff699998815e535268ce8629342c615451dc810dcad1ff86fdb709e1b8437b8cb0dc4d37de503bc6abbf747949fda669ae497bc6b9adb53f08fefecf61b7f656f25c93e8e72bf8067031c982f0dcb0a9c42738c17b0403b1ab5e0b783a619c948eae3c627435f84489e1a53911671ab2c899cdfed235e51fb14bd6826796d0df62d5991ca4ce4d3f682f6c9714cde5d2032ef13c323142f5e4d201d6a9183a0f4932d4633605dc908cbe11d6fa669a315baabd238c601339042b4ffe2152f7404b335d248aa7cb32c89b895c23ea08251078ad284206c391710bf655a680312e11b027fca956a41caea047826c766fd2bbd89200401811942c87fbb5b4587e2582c91b9703b0e8f552c10977dbf2f5abf4b0c2ac96eff523c274429281c71cacc756adfbcca7e006c188f8f66924d40c199217680adeeb471da76c67e3ffa196f674ecb31a34ee61c205c044f1c7fd5101c2ccde8e68d2b790470fd1c456838c7d2d03503345743613aea72185cdc1eac255a1414eac7bc59fd44d3ca0e392d9265f7aaef97124ab04f2b838c231d10c5b05c38148143e5f4a7fc270aca331801e3cc29b2618d93caa0965c567682370b0de0e2f11d704a575a695d55b9662b5d8b05e42cb5f8a393c1b4f34584ce0ccd4439f82641969d30ae71666aba3dc72780e953c5ff1cb3461d9d0708b3614c287136b110f567a19340b270ff3e10120656146968c8513832ceb1d09a27165d66531dcd2566f2f8b75f2b2723daa31c71e13ed501c1a17e836b2c7aa1a0c5bcb3add707fb4abde1e9bc877ac8b286207a1d02466e42e2691fa4f2033f3c79461789fc258b24661f0fbc716c2a0907898bc5b97aac4a65e529a67e55770ea0d476d601f6fbced7f9708a9330e64c1ffa6012ce4ab08a1c6e764ddbc0c9b32ef3346d914f2d7dd11e9203bc00fbdd546e65b76d9c818724bf2f9f7fe0b6ac2d4ed0837d3842e3d1c9b33641206a3dfbd36a243e9055dd0d00d92c456380afb3aa3fb0a7f8fc4f6b6d8ac4aeffe9aaece359edcc0192500b9f9a5677e6e23561821c5a5660bcf096c8446490af8ed54dcef5c30b0f864bfd6f624a6b94e18bedb9ff361ce4099895e9fc52169c43077374ddbbe670d0c7f299cf6ee0b32c4e22122a78218853179dbcf3ca8c5923e90744c3a762345e7e3da07a26d40f9afb0ecec49fb01bb6abf58d20dca054edc7395ed2fdf33b3790b4e2756abd3414db4a92a35606b12ef349b4f7edce16868ea10ce4864eb82914c54ea1be98428201f75217ce95c360eef05657b1ee771512aa76e03b822f4e125e333923dbfda08fd174ebcc12de3d20c3b2d7843e2fd39acfce9be77aa21a6f245020918c5e67ff82e94cc0927214b3b925a73fa0444bf5a533bc2009b702ecde8c9f2d1c3b8ceebbf7b11a17d4b62d6f43a138b3c4a720158b0c264f76ba3422584b9478894ae6f6a1ecad108a158fbe03e4a14755af4476df5117f11f449c836a4cb0f18a47cd092e75b72222135978656bf00f09e2f7f9ae4eb14d44d87649eedce2a0a7e0fa0989fe69b2607cd28521b32f1a70ac90e984b13c8ca76447cd5fb53f03972a073206155fd5a1ffb7a394932eeaa6e156ac0373854f36f391d4357582045cde4433631f0d49c3c52098a3f7affaa751d0c79320c95be478d50e506551505e6942c96f895d73a0ff0baa8e2acf0340c6fed06fd5a8fdb9774f44b94791726890d43203f68eb3e503fe954510fa6ac3bd4b4781e4ed007b51f74290c8463c07168dd124fddd12adc4bd041a0d77f120f88d6163f7da87e0e83a41ae778e9b0f7fa81fff9fcf22a3461dd802132a9fdbc2c5f019e5ee95c019bbb113916dfb40ce220d5fa926bd130241642e92dfbbcb7dc4760361cc52223a2b70b868d52ed8e24be16ef4dad5946d7438276971b37c3f81db66b15e15a403f41f8b356d5f054393f4cf166eb2f912a00a6114fbcec9bc27f5d71c511c7d84466ad726647d235d87e6a49bf1d07718e439eacba28ce9985e2ce895c62716f6519cd9e0af4887bfa5f5b906c6ef4c465b0a37992c7540b82d0083c2e1e433d1c170077da8f354ba2b4c738947166452da8ab6a6cd474eecdbd1e77601cf1c778a697f2fcf7f0c341530e2e17bc5423be570cf0049ed053bb7777d92b42e193021ed74df56816bb91d83b17c0c84c5fc10fc5b621b951b307a28b1d25e8857526eeb75b673a874bd157d036227055a525088926fff4af6ad587514d219e249b94da9005efb8ff1f8038228e490db110f6b9e5e889812f848d33caddadfd1e7ccbfae012ce3587960d55b96d0fb04cd33e9d9a9652743e70483c7a515f5d106a9c36f6dd93a98727d7418935abe99a618945c11b70aa1f2cb070b28c0be18ef36baac990a1e5a97c646ecfd896ccdaa0732932637ddb461218442acbb0d5abae72f3f1662650101f1bddfbe96ad22ebbd47dab985fed08be34333bc2131ee5fff77f7bff2a91f8d44dc13ea1027498132e3d30a23cc8b1e3880b8ac84429babf92d8c5fd7a187249b5b91390c360c1d446f981703ffedeeab5fa0c6da3d081f2d7c9c0c61f2cd9d0f43e63fdb5318ba4368dac31fa0cb4c4b5af30d9d39f6986f2cff109ba1fc7fa56171f279a8b2d49c6f097f4873aa4d4291a00ca3ed99af8818159180a0fae420e17b498c7934f94f935a3cc42ce29fda48d2297e8ba6a1b8c53ca202c11b37949faf773ddb604ff4f2c7691edaf3ee70519e16c01732692547b663cd398209709d800cbbfafab7faee0d7052b12d4271454b6305eff73dfe5c5f6d43813c4a83cf316b02062ed515d68443af2c91ff91caaacff9afe336677df5e75508819854817ed662435e1257ea2eec68c9c5a7bbb683ab56a774494efe9bcf7b49bd48658ab3cb266d83ba94e07f8c1610e0e0c1b484601cf219295052251cf3ed4f8010892df9212d3df3b33e237bb49adc6aea519f1619d056d8beacf4edf759bfc2270582814ae9a17f19503eee31c53caa5455738a20b590821f40259e66761bae52bb935dc68281fced3a00fbee84300df0232b963f61ab433e333ff24deaf47490813fb8f7b20330a9e457391ffaae98ede0fdc8692000a9eb74ddc0e8b30a6323d9a0b75d7c31482e0a771667061303aa019189aa7a5068c3e3eceb62c87e62065ac5f29622d3816f6283927fb37be7c8768f8d995c80adec8ac36a5d43dcd3df762cdd82d77b089efaf87547dc8e0712ffab0d92ef5126004394479d3bd48b7c30b4624d6f7b53b002a4c27e505299c7e20460831caa1fd7d0f520618d9ea935262f61260d77cafa98867f09d21878d5bb71459c25a91906b9685944a947b290c0e1591d685920ae7d70921232829be5bf50c633c2293f6aac559bcdc60c82776a4586dc664eff534deeb74653fd74b6c5c586cf5089c5d905e7cec5bdcb30b33301aca375a2a9a60ee97f68c19d2013262530485fa8b8dc0c414c74ebfb35af8171e7387e049e8960777e52df7b284fcfb011ffb7e8413ed0a6dbe64edbbb523eb269b7a4a3b493708e980f5436a52ae6b8d603a0809fa92fdd640bf68f1fa716bcc5db1c4ab69ba6abbf83110ef03312327d75e7291771531f37ce02ace414d0f2b552251132f7b69c4eeafd9879f9256ccd73812d9a085264a568a12fa34d984f32bf2580f6d5afada032ae8392a60f3598a4bc896b48bc486a4b03b79624be6d9250f26d0c82dfad65672df968308a90797184f2334647f3b64fa176330b0f8b226cf126a8f727e063baadc5db9ebf8aa763c443aee8055f24d40d98ff8c50e699f2aa7b0c9bde3e0efb03f76fac52cfd866e7c12d38095e5c2bff92a37a373b94a55d4c46859b86dc62b851b7b9a6096ffc170e1d549776440990e522a3a8f00c115c535e13382d6a5483c4a025403f8be52d2fb31a43d5d481d96843fe140ec41f8ea924a06fbf68cacff530489a45125e67a2cad698024610baa668dea736b5f581c70b38705939f7c9c7c7ae89962c944c9e3ab305c8852ab74acfdaea584940210edf08d0e8ecd3f6087db99cf68f5d8f55f052d86b1efd84f30059ac79ca65bda43ae7dd493eb8acfdad0c6c55b14a57050c67f18ad42baa0a35ffe0264a014c38a9727d13195554dc063bb902b507d9ff76828e43acead694449338dc0c6db7ee7d6553fe0669a9236d4693b9c5b248cf8d6c458e91659a0f76c918a34d3b0a1ed53851086430d4e3fc7d7e5a23133f814624a0a01cf6efb3e1e06ff54dba9b9b903c1a9c2e85a6c048676c7fb3c87bb9ae5b3f1d2fac4ccd5c6a7e8d04e61f6f6dd73437951e803ad8054b5a88b7cff00c6da4cf65cde7290ffd70f236616a486cf428f10a0ca240b0279b6e9a238cd97fe726933a11c362469a2ceed99f371a5524ea794b4d392c9807eedb52acac021cc0872a89d99dc4cb96fb20f5f402d52ef71358aa4483a09c024b2f351978babcc0b455b97249509345f7b14b3229f6854c80f8f32de4c3003a710c22181c10e26aa9fc6948debbafef39a26f537e3bb0c3442dfe40d069ede243873733cdcd9a2075e872b0c02a701921d77b8ad7a403472496b506b7cc0dc78880ef666b87380ca96cbc8281b263d105fef787191734185b46f65962ad48de15b050bbbae4b93208723721935f546c9ccab1606ab84aed8063ec4652e9e68596fb145c9bf9f87e7c006355b96ce62e0e88a20e14b6739ac7d10e72adc6c834cc4f42b2dbd582b9426174991b6930e1c0b44fef57ab3a87a8f3bafb646a100f1f3871216ed3880455e84c92022050e0a7ac444cd6240f0682430d6a9cb90fdf9961eb13b8fd18c7a456c6d2c98dcd38b7c8b672da3c49f141e804b8678f9bc94d81d540a5cd2a890dea33f34db77e84a25c01e87b672f041d6cab485ccb63daf91531b1dd92b19d73824c6b5bc8a2940c618b7b78d8e5e0d4415134b80625b770f5df66af0704712b8d1ec0f4c0da72cdb6c073c5021ec489e4a4a213323a84e6830fe61a6747ec5f2814dfded79e7f145748024b3f6a5d244aff64645fcb0fb2608559c87775d69a7242989950a9fa652b809bece67e1ebefd118b3c5ca509c46dc0f11ccb65a176893a6a9acc08062a13727479f0ba7efc8d7816ef0fdf27ad1d4c625af9d1f78d77fe0b4f223b89f22d8c729a6cc0a79d8286405c9bd7d958e331a4290eaaee8f8423e8579d67fef205e57cc588a6e128d66083de3f4dc1a9fb6aeaec75a797fef90d44e1e31bd05ba254c03d0f164acf71aa2cc93718fed3f87a5bf468e84c5827314f8e047ea9fae8007b67b60a4138eccf1438949628ef2ad7d840b2737c501e8cb4412d7f26b142318bf307f189616680130335c6d89943398ba8248b484e91928b12aa2dea6e25f6fb7f97e820b6558cb0eeb83afd439ac46e5821e33b9a6036ffb0fe821eac95b3836275e7f447c7dbfb962b6dde19db4f6d2d6e8b5bc172d5f4093e5ab83ca913671405aca64531d795bdccad10f138bee489316c2e6afd4f08b1e95b6c3524a566c56c2b6946ea83acdc0331698ddd84f8ce9ca42bf2fcde231e7af904373ea6159cc84f9c5de647b5859b009b00bb11681ace72ef6a6dbd7eec6f6e4a2dbfec7ec6f0d1116649f6a2be9e7ccb0c25b8901cf698db5373589b9996a2183d2a58702b9211d8a05a28a58f4dc6ad2e9a3f99a5b893584b0b5f8ae4a883d359ea49b8f8ce32546b1a36acc55f78d2118747b6b5400fdc681352019b2ceafea075f4e55a562c380c3a7ee439f234b1d05754013eb54dc0d73f7d53cd0e9478d92785ec8d83ba96d9d5229a4c0114d8be0c416d2fa7186124bbbaaf6c1b1b72c446c92ecd72c05c380758e4183be80b5e23632a26dfcc55db93c7f71ac5b3a16d91d16afe0848721bf6af5bd2fc2f789b4a73c4888e7efc49dc3d6f6b5235d16a974b4d5e39bdd23488e1f1845c7da3cfca31fbcde47713e47c8037bb0d62038637cdf7299f26e7e58cbdcc2b2328ba13815010b47781e3cfaf977f5c14f763ffa67e0357fefbd2a0a7d9b9930b8802038f6252c9e442be50e3ed9c2b7a80fc769e9aee33270ff6ff7a213f2eaaddab2004ded2c1814b51070b822ecf9c0826c108e23e92dabe41a71f18fbe99a6dfdbd3809022eaf0d2289491a005a5368f13b446a0dfcc8fbef1075a851263c7470caf443f023e35779a02754b70a0cde4fbbaed185c319a5545a3fd8f56a5369fcbaf227bf3248e7c69369effbfe2431051fe93d1c11b2a020bd4b61160a452cb9f47a9b6935b1eaf097018bbc7c39dc97822f509605e0f91ac5d0aa13259ec593559e724e465e13d082603336300ffb89f19b879b8aeb1e27bee4571a3ebb9dd3793f3f0ae24bf176117c440dd996287794d14452bd52d6ba4df257a7caea44005a3506e8de6fc0b6ca8060e2577d5032954e64bb5d8438daddfb5d6f3eba29cf4fd965ab7c58ea3165e351ecf82ede85e5a53b63f2b8c446af7ee3b477fefd7d652895bad85fad8483fba84a2225f1809c9d76d7286fc48eb7b6d6dbd9020f8d872d89598b11d1a09385815af02ee369b6b80df23afb45be4391ca2904903c2b30665bedbe6fbf5677aa6e0d775b221b572e877b2efded05e914e63fa1756b6f3b610d98bb1ee4bed370a91f671106bb34d345bf9f2f3560901c0a99a9ab6427f319cc48fa1b0e14b1ce504604e5e59dfaa5d33327eb2e971ab33ea2d05c2943cad8eea13751d9d82ea47385801978708016d064333d75118481ab8da6251a16f70a52a0b22c683116ef9dc94ed5963e0d1d077d3e97219a5af0ea419570fd253af4d19947b82aa91891aa05e3dd5394524c9b1fda75cbdbcbd7b88d17c77939adeefd51a3606898e6bfebfc9ae38fa354c0767257c20e708c4a109b1d373c32290777fcbd6b72762d538580626792682dba208cae4a9b7c8f043582ad9d9fe19d015a54791ff009248995057b7955686ecb2c66b1dfc21771e1929e97fff6a38b1e903e0bed4cb5c2e6e418924f5b1f0bbff292c2ed92e7aaf5b6fa1910ec3be6cf554c651e63d808060725bfad3054fd5c41796d73125cb611942be3830c1c1249ffb22c436d479a0b696a3bfe0f2f39665cafe1ffd5a57562a6f6626d4f07da35517732b738e331cb4d6616e5d945bf815d9d160d3afb4c951c4ce2df5554c054d7539284a4485eb5cc115dabb7dc454d1566739e058683af47ee57951667ee3612f694105c2cf7e01a0ea4d100366da1c4a733a8d639b874935f9f3ff89127d059c9004e385469b77f62c72fa0550d14f5212cda7217d23abf5451abb24f33e7ced1def039d28e66d285b11896ab84ee6b424a3da49f256f31f68c5f3595428cf89a3ca550e5ac17064c71c453eabba53b69002ee58efc74270031568946b863109e67e798b0e78f7bed5a2cf0412903f5aa3294ebbb687a1ac022af9aaae8cdb819acfdf2b3b6e95f2afc8a295009b302a191aa835abd41ae93e3e19710ae9742a3603e6c599fccd4725099678a5bba93e4972f32d7882a1b5f4933459b84ae00f0930ecf7a4c1492ed6e2088a961ee2763ee91d0b738f1ed8f4706b66857bb65f14b1e47bf1ff7fabb3d7516b4e9d730fb528c504ba60004acf73ae8c1642f1bc9d843dfa9ebbc4cbf154632be4ef2d777308a7be58b88878c5a8d2b9e0343af43173ac5cb903a9c08ad9ef0ed860f650f2676ea5d4bb9b79984d602529788c7c04912aa3a45710bc44f4cba68a6d5dacf730a6bc94c00ab410135ab62413a2f702a9c2f23154799a1287a8350528b2ecb8073f8d1239941403a63d58d0566f2de41a99988e0679c97174c2dc69d9487a4f9fe8ec3ac1169771071da600a1906d88566c704e86234c2ebc92f61e7fc7a50bf31a74fffc75a4e67af0eba40cbfe6d310cbc82e88a9516b20ad115affa891244cb0edb77b7333638fa973c33973f4532f9e20f7e31060846d9159d3b0e53b4cc53188836209535ea80042dbb1b690ec9458c9391194208b3f3f5fe64e27899c1dabaf712887015249d92973acf9e0e9cb20738fa51896684d7f199fd55cb0b4ae4082f3e06726a5aa9dc35aceab8a11b945f5836826b912fb3d88aec3c138762e354b08440d41fe73439063f120366dc5cebfc9be705c2a6954ff541ab7cf5937d87ec880bcef1848835ba60e0114f72e2e0763b4c06998a8ba1b1cedac8a2843b581e28e190c0d95e09021efae34a4dade3810f2e0e40968cff6cd979536a7d107c99d8dfbe71d0da5dd40dea30f0d15ac3fff3e932f701af9334d7f080dae622befcfd46d54b15ca03af5f6b68f98ced8e9f295b2d88ac012b04e7c41537e95409f17ed8bc98dc25bb1eb961f67dc45667de80a2651fbcdec4c2458ee7e816b1b00b866199f923c18030f7b0815470fa383e23ac3e06c5c811e8e9f81a812195774bd7e86142f77b5fec76cc581d31154e80664ab42d7d496363d4815e58a5281d4385fd96502aa82fe21023ba3f487e4454622400119017cbc8b4c5381263a7b2d93593141b7989fa9dd39c1ffb9b546747ae0f4bf2fd6c3569bd75def1fd1eb6a022b3707ce429ea9a2569f8a79d00c81a57fd5e2a2c83e89cbd69a64824409ec650232496b52b23e144191898f51c338da4386ccf26a55803c92a25884eda486861c7690b0a2f9b8b389c8a2042660ea92c0bf7b8b8b7c93d1992c4ef7cd0fdf1bd65395a38814d7b9a1057162ff70e4b70dd0bd712afb04abdb203f6cc38a5eec5452381e5b70f9cba53641abf112eeec31922ecad69a0b6cfa5400cda3f402cd7386a329b781195f0a71140898fee0a7328c3b824356ffb7792f1b45dbf7dc26f12e86441389c0e5143c721833b0b5ae546e9be5def096adba5c96de99914496d2c365f26c6467001a78a888e217a7b608d67e397b04d4395168b22484065dc6f192a3780d3c05a54959b962f3d18f3dc8e00a40e430cf78586656ab0677719d6a4aaf351518d7ea9b67c5160472e73af7648c278e2dccc9752461631d4dbfcab7664ed367d10c784266aead4eb971b003ecdc7621add1b33fc785d181969b646d410899dcfeca3bd96c59cb9c18e0129098ad2c8b92fb76f7d1574500f1eaaa9e3fb493cad0de23a04a1741f8283eef72b40b305c030a0612fefd743b6b59da345ad477665ada4a9ac403ff5a70f6a63f5a1f3d2346755fa86e6b39413b364fa6c7ca18413196f095af807d6412d62ab14717e7cc897cc9e51c77dd9b707705826026ca1c7046ed017d6725877b4132ec11f2a5857b9582a48c5f4d78ed4e80f39f9f49da1fa028997c827bf0b50f2efe132b2d8689e4f54f4bce58f8e6645d500d3052c718dd54140c6344dda5f542c957867fd8322ea89e0e61364bf8c6ba59d7d1ac7a6ac6b0c16a0b39b0e574391cc7116c0d37443b2e84f4bbf092801a6d14add4877323d3b927e3b373295623168c42556271ff7605cf47d9babf7952597101717d7c79fd98b888ece0dfe8c88c9d49892d35f1f9dafad9d6c8b10c704a3f51881d37f4a7866b4d4b114c88fe5f6cbcd03c09e56129627cb9a7f62735c3fd637312254e33ac0b67d68b24419748b6c36ef510dcb15ff7558358471b95171357404d5d4e79d08886c0efad09065f6e7d262f19e6c174d2a6d88170a90f8ce86976f29036afa37e3eb2661a037ac52e857e22f12343feda0c0c796dc00de820791f1d7afbdff5c5f527c280467913b1fe6a950dce1cdb0da419a69f73bfd99ba96a82a7aa9e28af5233f74f0ff529a80262d2a94d57b227c07280484c673aab601e63e27d6a497bac9a47f7fa879632649353cf592ccd51c4ca901e5adeecb74be96cf05804270db3ac4b4622bee3bd8454eae7fcd4f2954a40ace15db01fb916328a520666deb204bbe3799730e8721c048b7d9d75f59e9ab3da3fa610ef581242a50261386a35ca3cbbc59c63c0e3be71043f1382271a0f37699704e65144c67a3fa473d4eb563bcedfca5ee95471e4c5a91baf00e467c4650048e3fdfe161df81e1f0aaecb9211881ce4d0bd8129ffc016f4413320833d3632ca38fb7cb35c5e58bc1256724a074db06d6921096b0e29b4337d1d5c9f902a9ec0a83a191696140d06e206efd302b23ee66da2c2e09fdbd071244334f8b08cec303bc354c8b4ba76f6522cbc5494fd959a6793becf2e42d03c3175b94c97e463ef6f4e9809e099b3a7e646d5c324113ef1c6eab682c5473163b6a44bcd72321ac1273dc7f4d03848584ce463d5066c07c5aba8572d1356bd87574fc3f2e1ebe91f69415abc11772831a53fbbd5315128aa7e37541b0946b427f1a7b3add207b0de351fe3f95480045aba54dfff0bffcb68c73d94d9f919d0a382e3066ee9ff9766c96491f7659330038feff8c3821ee017c58ecc5b1e1ce80cad5523aae0283dd78a4384bbfbd741e90ca690d9d83760795f2b8df26265cb555304aa2dd35bb5dc2b78c672cac9913a36c35492750e74e1504060ac155aac32a6444138a690ab522ce58a07c171d707e382de2c3d3328aea421ee2131ab5b6b64ba176c9ae2ce4ec697df3ae89e882248e5c9c1af2b2136c484b13b4e34d26833ce164aefb033060b3015f6b3cf9343a5c668f379e3a3b14dafd6bc7a89fc4c931620fe3a112985979bbeade35f7ddf17b4c3f9f42720c1bd1fdeb754146b77eeb7afa9c87eab35b1c06128a99858f047c678b1edd555137aa4c106ad0694bfd17185275ce742d9a36916f3e9530131bb6fc8c695b49847e4c6615959444bde8bf93936f1266c7296437c49a79d9e471e7f918fe077af1cb01a40a11d6b641409864b51935f1dd1f59f6a7056a1efe2f32771a23e92af96bcdfaf432f971af9bd9323c084608742aa43ba2f8969e014ba2e2ef2f4fcd4d0e628bad7643f4d519479bd579b1fef1484cc47bbd32df7abd5eb3cf56626131508c462aa99a245dae38f06c4051de6fc900bf716fece6155e1a9f9f66c1090f17884fe57b2871840d94463d410cb2078139f49fd4164fa8a8bedd2e9702e459d46ddda7de0d472ccc2d9f8f10cd4c24c168ff5adb6767f6975c509954e24ec2eff16436829f3efd69b3bd972160f338316729b8023abce91298262940d56d5b925e85745498bb13d6a6a4fe5ed511617f7fcc335fb996cf0b5114ec1f099e960da4be52f7e821a5c80eca6193a25c83abf7e3bf38df33400858b86860717c2b53c87fabd6d1bb5f9d72eed373d4e82844a86e28e48541ddef64c88bf2b2779a4386864cf2617dee5f4eb16cff56cb2215807aa50d870ec51cd1efd0b62f883271fc4a8c4b14f1fac59dd605fc522fb784b096d59504fdc717fbb77fce6abc56caccb4d36f31ec7ae7947f374bb85a1d74c198cb4c2525e6bb383b09261c177db29d3457226e0797fd33cd77c2b66279d58c35192c9efd9cdb8527b971b370bc7c2cc6c211fc97c86ee4268718bc5926353c924e54c92d6235caad129140dd71be6698fd4919a8106adc863593c34fd70ae7eab447a147f57f509a1f529836ce74629100dd7b86b881a3986af56a1110bfc2dd0422beae0ef01156acb900043ebcb3618bec23036d895d4ca820283a2065f73baf47debff52d6ebfd8aeb20db8aed59cfa352b0ded9f56db947c52ae37f01281fc3c23f8b83d86c6db4d0554f8b2dd40dc6bd18c7da4b0acac06463ea72b8b1908fa802ac7a456b9da34a1bedffd54cb1b863c85fed4001a1be605a7ac58d6d87f1c69fbda7321bd8454887ba60bf77cd419be54002dce265735ab577639830212bb1533cc12006c698180b419d67a6054ec73d1849a64d6e8a7cb2feb96d15b99d9031d47e506742d2f8e44161aa3ca7dce300a6e7c438bbda5781232e9755d65a6fa85860442b0decb3c1dc1ac8fd801f548d2bf895741efdf3d35ea44e5bd643f66d78b7c0a6fc2f256b34b5dcc6e302df3fe1eb62ed0c5d0c7fceb7783578dae119c72e8f24e52920af9a8712b3d0d0002aec20f38f75ebbe371b69d8a9379ab6e41d78772eaf84de7381e060a2e8d9beb9e8629d12f22ff4d2d9310bc90f61dd76924119371c32a4b672df4b34a420459d9077d56e249b96ab97c410ac108dd67444d8aa6f5d5b49972c931ca67feb210688f595af888b8c3adaee7fcece6d9c1eeb309eec5da87b8670a3263f651db8ee2dbe403e2679c9d22a3454877398e24febd566c5de31b1db4675f8180f41377dedc82ef43e7091814ae063fc0174ef479b77f4be6afbd495402402b51a2f42760d357070cd7eb64a1cd08263612f6f2921a579574a8a21571286c8459b7981e6a27ff8453559e21e33fc6b7a2c49539c907442719aa7ea4176e5887a94c982225774c07635f12e2b502060a4de79646f711eb4930de68ac3b7b9e546ec9f25db59c8272a6305c5f668dba572d4ca6f558df6412a5b4ac73a55c76e521c961547076affbcc51da4573a36c3d1759c53ad7ff9996d0c58a2a2be81336384a321e8905f1cfc12a1d6d5dcb9f4099c24ab71169d01ce474e7a0b8b19e3269249e2811d214de6ab9c3d88ffa3475204a849d882581b73c2512619874bfc72e616e468fe235d5b84105407ef62691d985516ec1e5435669fdcd06f272aeb1725264bd6ea6ffe17502c470e5aa685ee1f03a04728df26fdfd929184f7e0b2b53e5c9807f1c44ba8124f1d90fe1e33f91da7e7a6b89af6a43358b29c1333554a4e034245261219d840275194c7359367df73c3c01a385d338b8fccf9074101ac28d7f8d19dc51205129e74afd9ddeb3a964dbdd458645c17767ca4dcdccade3bcee0023a4feedbafc22e2c71aa9f7256a3ca80739b9b61003f73c814121126f8517a239153b64efb3b1ad8ad37a2f6a7c07d98b95c26c44e4b3b468d099806406f584dd89791078a1bb2963ec5a59d992a31719c54bcf44937dd86ac22de7df00c1de5736bc0245e3a23b68df3660187a4049fa7e56e19565dfced02da7813489b50907d80661c6a3f977c9468f94b8f11b17d84c88d323a6733b31155947991966430cb62010554600c355de1a4d84de0e32b8e705e3f84a541382af893d82928f9d262d2a71a8a3f4fc88333d744f2ef515c32c83ff03165777515f3176fb1df18860a2cef3642b90db6c924538ceb02476111e0435b881cc4730e1cd8141a4d0d39dd65fafb79a0714d75ee91edd3800bdebdbbb"; - } -} diff --git a/zk-tests/src/LargeFactoryDependencies.t.sol b/zk-tests/src/LargeFactoryDependencies.t.sol deleted file mode 100644 index 1a249692c..000000000 --- a/zk-tests/src/LargeFactoryDependencies.t.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import "forge-std/Test.sol"; -import "forge-std/Script.sol"; -import {LargeContract} from "./LargeContracts.sol"; - -// Temporarily disabled due to issues with batching - -// contract ZkLargeFactoryDependenciesTest is Test { -// function testLargeFactoryDependenciesAreDeployedInBatches() public { -// new LargeContract(); -// } -// } - -// contract ZkLargeFactoryDependenciesScript is Script { -// function run() external { -// vm.broadcast(); -// new LargeContract(); -// } -// } diff --git a/zk-tests/src/MockedModifier.t.sol b/zk-tests/src/MockedModifier.t.sol deleted file mode 100644 index 36e171574..000000000 --- a/zk-tests/src/MockedModifier.t.sol +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED - -pragma solidity ^0.8.13; -import {Test, console2 as console} from "forge-std/Test.sol"; - -contract MockInner { - // this covers an edge case that mainfests when returning >=5 items - function mockedMethod() - external - pure - returns (uint256, uint256, uint256, uint256, uint256) - { - // We fail if this function isn't mocked - assert(false); - return (0, 0, 0, 0, 0); - } -} - -contract Echoer { - MockInner internal mockInner; - - struct Foo { - uint256 foo; - } - - modifier needsMocking(uint256 n) { - //we just check that we actually mock the value (to avoid optimization) - (, , uint r, , ) = mockInner.mockedMethod(); - assert(r == n); - _; - } - - constructor(address _mockInnerAddress) { - mockInner = MockInner(_mockInnerAddress); - } - - function echo(uint256 n) external view needsMocking(42) returns (uint256) { - return n; - } - - function echo( - uint256[] memory n - ) external view needsMocking(42) returns (uint256[] memory) { - assert(n.length == 1); - return n; - } - - function echo( - Foo memory n - ) external view needsMocking(42) returns (Foo memory) { - return n; - } -} - -contract MockedModifierTest is Test { - Echoer target; - MockInner mockInner; - - function setUp() public { - mockInner = new MockInner(); - target = new Echoer(address(mockInner)); - } - - function testMockedModifierTestCanMockNumber() public { - uint256 n = 10; - - vm.mockCall( - address(mockInner), - abi.encodeWithSelector(MockInner.mockedMethod.selector), - abi.encode(0, 0, 42, 0, 0, 0) - ); - - assertEq(n, target.echo(n)); - } - - function testMockedModifierTestCanMockArray() public { - uint256[] memory n = new uint256[](1); - n[0] = 10; - - vm.mockCall( - address(mockInner), - abi.encodeWithSelector(MockInner.mockedMethod.selector), - abi.encode(0, 0, 42, 0, 0, 0) - ); - - assertEq(n, target.echo(n)); - } - - function testMockedModifierTestCanMockStruct() public { - Echoer.Foo memory n = Echoer.Foo({foo: 10}); - - vm.mockCall( - address(mockInner), - abi.encodeWithSelector(MockInner.mockedMethod.selector), - abi.encode(0, 0, 42, 0, 0, 0) - ); - - assertEq(n.foo, target.echo(n).foo); - } -} diff --git a/zk-tests/src/Ownership.t.sol b/zk-tests/src/Ownership.t.sol deleted file mode 100644 index e90f87816..000000000 --- a/zk-tests/src/Ownership.t.sol +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test} from "forge-std/Test.sol"; - -contract MyOwnable { - address public createOwner; - address public txOwner; - - constructor() { - createOwner = msg.sender; - } - - function transact() public { - txOwner = msg.sender; - } -} - -contract Delegator { - /// Retuns the current `address(this), msg.sender` as a tuple. - function transact() public view returns (address, address) { - address thisAddress = address(this); - address msgSender = msg.sender; - return (thisAddress, msgSender); - } -} - -contract ZkOwnershipTest is Test { - address OWNER_ADDRESS = address(0x11abcd); - address TX_ADDRESS = address(0x22abcd); - - function testOwnership() public { - // set owner balance to 0 to make sure deployment fails - // if it's used for payment - vm.deal(OWNER_ADDRESS, 0); - vm.prank(OWNER_ADDRESS); - MyOwnable ownable = new MyOwnable(); - - vm.deal(TX_ADDRESS, 0); - vm.prank(TX_ADDRESS); - ownable.transact(); - - assertEq(OWNER_ADDRESS, ownable.createOwner()); - assertEq(TX_ADDRESS, ownable.txOwner()); - } - - function testOwnershipDelegateCall() public { - Delegator target = new Delegator(); - address thisAddress = address(this); - address msgSender = msg.sender; - - (bool success, bytes memory data) = address(target).delegatecall( - abi.encodeWithSelector(target.transact.selector) - ); - (address thisAddressTx, address msgSenderTx) = abi.decode(data, (address, address)); - - assert(success); - assertEq(thisAddressTx, thisAddress); - assertEq(msgSenderTx, msgSender); - } -} diff --git a/zk-tests/src/SetupForkFailure.t.sol b/zk-tests/src/SetupForkFailure.t.sol deleted file mode 100644 index 39e23402c..000000000 --- a/zk-tests/src/SetupForkFailure.t.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test} from "forge-std/Test.sol"; - -contract ZkSetupForkFailureTest is Test { - uint256 constant ETH_FORK_BLOCK = 18993187; - - function setUp() public { - vm.createSelectFork( - "https://eth-mainnet.alchemyapi.io/v2/Lc7oIGYeL_QvInzI0Wiu_pOZZDEKBrdf", - ETH_FORK_BLOCK - ); - } - - // We test that the following function is called after EVM fork from zk context - function testFail_ZkSetupForkFailureExecutesTest() public pure { - assert(false); - } -} diff --git a/zk-tests/src/TokenReceiver.sol b/zk-tests/src/TokenReceiver.sol deleted file mode 100644 index efd75034d..000000000 --- a/zk-tests/src/TokenReceiver.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.0; - -interface IMyToken { - function transfer(address to, uint256 amount) external returns (bool); -} - -contract TokenReceiver { - function receiveAndHoldToken(address token, uint256 amount) external { - IMyToken(token).transfer(msg.sender, amount); - } -} diff --git a/zk-tests/src/ZkForcedRet.t.sol b/zk-tests/src/ZkForcedRet.t.sol deleted file mode 100644 index 6dedfef16..000000000 --- a/zk-tests/src/ZkForcedRet.t.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test, console2 as console} from "forge-std/Test.sol"; - -contract Number { - function one() public pure returns (uint8) { - return 1; - } - - function two() public pure returns (uint8) { - return 2; - } - - function echo(uint8 value) public pure returns (uint8) { - return value; - } -} - -/// Additionally validate the inner workings of zk-evm as the bytecode is decommitted only once. -/// When a mock is set, the bytecode is updated in zk-evm memory to simulate a "force return", which -/// could cause issues for any subsequent calls if implemented incorrectly. -contract NumberFactory { - Number inner; - - constructor(Number _inner) { - inner = _inner; - } - - function oneAndTwo() public view returns (uint8, uint8) { - return (inner.one(), inner.two()); - } - - function echoOneAndTwo() public view returns (uint8, uint8) { - return (inner.echo(1), inner.echo(2)); - } -} - -/// A simple scenario to ensure that the "forced return" functionality of zk-evm works as intended. -contract ZkRetTest is Test { - function testZkForcedRetOverrideWorks() public { - Number inner = new Number(); - NumberFactory target = new NumberFactory(inner); - vm.mockCall( - address(inner), - abi.encodeWithSelector(inner.one.selector), - abi.encode(42) - ); - - (uint8 mockedOne, uint8 two) = target.oneAndTwo(); - - assertEq(42, mockedOne); - - assertEq(2, two); - } - - function testZkForcedRetOverrideWorksWithConstructorArgs() public { - Number inner = new Number(); - NumberFactory target = new NumberFactory(inner); - vm.mockCall( - address(inner), - abi.encodeWithSelector(inner.echo.selector, 1), - abi.encode(42) - ); - - (uint8 mockedOne, uint8 two) = target.echoOneAndTwo(); - - assertEq(42, mockedOne); - - assertEq(2, two); - } -} diff --git a/zk-tests/test.sh b/zk-tests/test.sh deleted file mode 100755 index 312b093ba..000000000 --- a/zk-tests/test.sh +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env bash - -# Fail fast and on piped commands -set -o pipefail -e - -REPO_ROOT=".." -SOLC_VERSION=${SOLC_VERSION:-"v0.8.26"} -SOLC="solc-${SOLC_VERSION}" -FORGE="${REPO_ROOT}/target/release/forge" -CAST="${REPO_ROOT}/target/release/cast" -ERA_TEST_NODE_VERSION="v0.1.0-alpha.25" -ERA_TEST_NODE_PID=0 -RPC_URL="http://localhost:8011" -PRIVATE_KEY="0x3d3cbc973389cb26f657686445bcc75662b415b656078503592ac8c1abb8810e" - -function cleanup() { - echo "Cleaning up..." - stop_era_test_node - rm -f "./${SOLC}" -} - -function success() { - echo '' - echo '=================================' - printf "\e[32m> [SUCCESS]\e[0m\n" - echo '=================================' - echo '' - cleanup - exit 0 -} - -function fail() { - echo "Displaying run.log..." - echo '' - echo '==================================' - printf "\e[31m> [FAILURE]\e[0m %s\n" "$1" - echo '==================================' - echo '' - cleanup - exit 1 -} - -function download_solc() { - case "$(uname -s)" in - Darwin*) arch=macos ;; - *) arch=static-linux ;; - esac - if [ ! -x "${SOLC}" ]; then - wget --quiet -O "${SOLC}" "https://github.com/ethereum/solidity/releases/download/${1}/solc-${arch}" - chmod +x "${SOLC}" - fi -} - -function download_era_test_node() { - local arch - case "$(uname -s)" in - Darwin*) arch="apple-darwin" ;; - *) arch="unknown-linux-gnu" ;; - esac - wget --quiet -O "era_test_node.tar.gz" "https://github.com/matter-labs/era-test-node/releases/download/${1}/era_test_node-${1}-x86_64-${arch}.tar.gz" - tar -xvf "era_test_node.tar.gz" && rm "era_test_node.tar.gz" - chmod +x "era_test_node" -} - - -function wait_for_build() { - local timeout=$1 - while ! [ -x "${FORGE}" ]; do - ((timeout--)) - if [ $timeout -le 0 ]; then - echo "Build timed out waiting for binary to be created." - exit 1 - fi - sleep 1 - done -} - -# We want this to fail-fast and hence are put on separate lines -# See https://unix.stackexchange.com/questions/312631/bash-script-with-set-e-doesnt-stop-on-command -function build_forge() { - echo "Building ${1}..." - cargo build --release --manifest-path="${1}/Cargo.toml" - wait_for_build 30 -} - -function stop_era_test_node() { - echo "Stopping era-test-node..." - if [ ${ERA_TEST_NODE_PID} -ne 0 ]; then - kill -9 "${ERA_TEST_NODE_PID}" - fi; - ERA_TEST_NODE_PID=0 - sleep 3 -} - -function start_era_test_node() { - echo "Starting era-test-node..." - ./era_test_node run & - ERA_TEST_NODE_PID=$! - sleep 3 -} - -trap cleanup ERR - -echo "Solc: ${SOLC_VERSION}" -echo "forge binary: ${FORGE}" -echo "era-test-node: ${ERA_TEST_NODE_VERSION}" - -# Download solc -download_solc "${SOLC_VERSION}" - -# Download era test node -download_era_test_node "${ERA_TEST_NODE_VERSION}" - -# Check for necessary tools -command -v cargo &>/dev/null || { - echo "cargo not found, exiting" - exit 1 -} -command -v git &>/dev/null || { - echo "git not found, exiting" - exit 1 -} - -build_forge "${REPO_ROOT}" - -"${FORGE}" install transmissions11/solmate Openzeppelin/openzeppelin-contracts --no-commit - -start_era_test_node - -echo "Running tests..." -RUST_LOG=warn "${FORGE}" test --use "./${SOLC}" --chain 300 -vvv --zk-compile || fail "forge test failed" - -echo "Running tests with '--zk-startup'..." -RUST_LOG=warn "${FORGE}" test --use "./${SOLC}" --chain 300 -vvv --zk-startup || fail "forge test --zk-startup failed" - -echo "Running script..." -RUST_LOG=warn "${FORGE}" script ./script/Deploy.s.sol:DeployScript --broadcast --private-key "$PRIVATE_KEY" --chain 260 --gas-estimate-multiplier 310 --rpc-url "$RPC_URL" --use "./${SOLC}" --slow -vvv --zk-compile || fail "forge script failed" -RUST_LOG=warn "${FORGE}" script ./script/Deploy.s.sol:DeployScript --broadcast --private-key "$PRIVATE_KEY" --chain 260 --gas-estimate-multiplier 310 --rpc-url "$RPC_URL" --use "./${SOLC}" --slow -vvv --zk-compile || fail "forge script failed on 2nd deploy" - -# Temporarily disabled -# echo "Running factory deps script..." -# RUST_LOG=warn "${FORGE}" script ./src/LargeFactoryDependencies.t.sol:ZkLargeFactoryDependenciesScript --broadcast --private-key "$PRIVATE_KEY" --chain 260 --gas-estimate-multiplier 310 --rpc-url "$RPC_URL" --use "./${SOLC}" --slow -vvv --zk-startup || fail "forge script failed" - -echo "Running NFT script" -RUST_LOG=warn "${FORGE}" script ./script/NFT.s.sol:MyScript --broadcast --private-key $PRIVATE_KEY --rpc-url $RPC_URL --use 0.8.26 --zk-startup || fail "forge script failed" - -echo "Running Proxy script" -RUST_LOG=warn "${FORGE}" script ./script/Proxy.s.sol:ProxyScript --broadcast --private-key $PRIVATE_KEY --rpc-url $RPC_URL --use 0.8.26 --zk-startup || fail "forge proxy script failed" - -# Deploy ERC20 -echo "Deploying MyToken..." -MYTOKEN_DEPLOYMENT=$(RUST_LOG=warn "${FORGE}" create ./src/ERC20.sol:MyToken --rpc-url $RPC_URL --private-key $PRIVATE_KEY --use 0.8.26 --zk-startup) || fail "forge script failed" -MYTOKEN_ADDRESS=$(echo $MYTOKEN_DEPLOYMENT | awk '/Deployed to:/ {for (i=1; i<=NF; i++) if ($i == "to:") print $(i+1)}') -echo "MyToken deployed at: $MYTOKEN_ADDRESS" - -# Deploy TokenReceiver -echo "Deploying TokenReceiver..." -TOKENRECEIVER_DEPLOYMENT=$(RUST_LOG=warn "${FORGE}" create ./src/TokenReceiver.sol:TokenReceiver --rpc-url $RPC_URL --private-key $PRIVATE_KEY --use "./${SOLC}" --zk-startup) || fail "forge script failed" -TOKENRECEIVER_ADDRESS=$(echo $TOKENRECEIVER_DEPLOYMENT | awk '/Deployed to:/ {for (i=1; i<=NF; i++) if ($i == "to:") print $(i+1)}') -echo "TokenReceiver deployed at: $TOKENRECEIVER_ADDRESS" - -# Wait for deployments to be mined -sleep 10 - -# Interact: Transfer tokens from MyToken to TokenReceiver -echo "Transferring tokens from MyToken to TokenReceiver..." -AMOUNT="1" # 1 token, for example -TRANSACTION=$("${CAST}" send --rpc-url $RPC_URL --private-key $PRIVATE_KEY $MYTOKEN_ADDRESS "transfer(address,uint256)" $TOKENRECEIVER_ADDRESS $AMOUNT) - -# Assert that the transaction was committed looking for the transaction hash "transactionHash" keyword -echo "Transaction: ${TRANSACTION}" -echo "Checking transaction status..." -echo "${TRANSACTION}" | grep -q "transactionHash" || fail "Transaction failed" -stop_era_test_node - -success