diff --git a/Cargo.lock b/Cargo.lock index dd083d6b9..6ab189a71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -712,13 +712,12 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.2.1" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d4d23bcc79e27423727b36823d86233aad06dfea531837b038394d11e9928" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" dependencies = [ "concurrent-queue", - "event-listener 5.3.0", - "event-listener-strategy 0.5.1", + "event-listener-strategy 0.5.2", "futures-core", "pin-project-lite 0.2.14", ] @@ -1479,7 +1478,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel 2.2.1", + "async-channel 2.3.1", "async-lock 3.3.0", "async-task", "fastrand 2.0.2", @@ -4636,9 +4635,9 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332f51cb23d20b0de8458b86580878211da09bcd4503cb579c225b3d124cabb3" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ "event-listener 5.3.0", "pin-project-lite 0.2.14", @@ -20245,6 +20244,7 @@ dependencies = [ "pallet-ismp-rpc", "parity-scale-codec", "rust_socketio 0.6.0", + "sc-service", "serde", "serde_json", "sp-core 28.0.0", @@ -20272,6 +20272,7 @@ dependencies = [ "ismp-sync-committee", "pallet-ismp", "serde", + "sp-core 28.0.0", "substrate-state-machine", "tesseract-evm", "tesseract-primitives", @@ -20305,6 +20306,7 @@ dependencies = [ "ismp", "ismp-solidity-abi", "ismp-sync-committee", + "ismp-testsuite", "jsonrpsee 0.21.0", "log", "mmr-primitives", @@ -20338,6 +20340,7 @@ dependencies = [ "ismp-solidity-abi", "pallet-ismp", "percentage", + "sc-service", "sp-core 21.0.0", "tesseract-primitives", "tokio", @@ -20386,7 +20389,7 @@ dependencies = [ "parity-scale-codec", "parking_lot 0.12.2", "serde", - "sp-core 21.0.0", + "sp-core 28.0.0", "substrate-state-machine", "subxt", "subxt-utils", diff --git a/docs/pages/evm/integration.mdx b/docs/pages/evm/integration.mdx index ba805227e..3bb4d7274 100644 --- a/docs/pages/evm/integration.mdx +++ b/docs/pages/evm/integration.mdx @@ -32,16 +32,16 @@ HyperUSD (FeeToken): [`0x6df8dE86458D15a3Be3A6B907e6aE6B7af352452`](https://cont | Network | `HandlerV1` | `IsmpHost` | |:-------------------|:--------------|:-----| -|Ethereum Sepolia | [`0x12122B8E2E1e24345161A2433fF2d91Fca123FAe`](https://sepolia.etherscan.io/address/0x12122B8E2E1e24345161A2433fF2d91Fca123FAe) | [`0x705ba08d072f26bB92C8f71B7E37a3c7aEA5Ecb1`](https://sepolia.etherscan.io/address/0x705ba08d072f26bB92C8f71B7E37a3c7aEA5Ecb1) | -|Arbitrum Sepolia | [`0x3F50392A707B1b77500485b4539C96f3A4311798`](https://sepolia.arbiscan.io/address/0x3F50392A707B1b77500485b4539C96f3A4311798) | [`0xba4deE7C228cB81DB2f7a05CA27444d9a20f4A41`](https://sepolia.arbiscan.io/address/0xba4deE7C228cB81DB2f7a05CA27444d9a20f4A41) | -|Optimism Sepolia | [`0xBE5Ea8A28D5AB4e96532c85F078d83E138EC8d44`](https://sepolia-optimism.etherscan.io/address/0xBE5Ea8A28D5AB4e96532c85F078d83E138EC8d44) | [`0x98A6A9c780D7d54aEF9aBd08c55C9ADc17de48A0`](https://sepolia-optimism.etherscan.io/address/0x98A6A9c780D7d54aEF9aBd08c55C9ADc17de48A0) | -|Base Sepolia | [`0xD61AA09E97cdFF33CCd7f7Da463b95caf6DB79f5`](https://sepolia.basescan.org/address/0xD61AA09E97cdFF33CCd7f7Da463b95caf6DB79f5) | [`0x75Df12dc3e0a32f69DD0F7470dE4eFF5D75C72b0`](https://sepolia.basescan.org/address/0x75Df12dc3e0a32f69DD0F7470dE4eFF5D75C72b0) | -|Bsc Testnet | [`0x13463B01CE69F8B5279c5922D38EB1073503e87b`](https://testnet.bscscan.com/address/0x13463B01CE69F8B5279c5922D38EB1073503e87b) | [`0x1488f22baf2027D6e28D79b6F38EB2CfdfE48d62`](https://testnet.bscscan.com/address/0x1488f22baf2027D6e28D79b6F38EB2CfdfE48d62) | +|Ethereum Sepolia | [`0x7fa6f643A1a522D35058FEE753DA027d25Ea601f`](https://sepolia.etherscan.io/address/0x7fa6f643A1a522D35058FEE753DA027d25Ea601f) | [`0xbDFa473d7E483e088348e071480B624A248b2fC4`](https://sepolia.etherscan.io/address/0xbDFa473d7E483e088348e071480B624A248b2fC4) | +|Arbitrum Sepolia | [`0xc31cc2Fd516a90188a3ECA5cbd757E21DDa84c7b`](https://sepolia.arbiscan.io/address/0xc31cc2Fd516a90188a3ECA5cbd757E21DDa84c7b) | [`0xC98976841a69Ce52d4D17B286A1698963E847982`](https://sepolia.arbiscan.io/address/0xC98976841a69Ce52d4D17B286A1698963E847982) | +|Optimism Sepolia | [`0x6DbcA7CAEBd47D377E230ec3EFaBDdf0A7afA395`](https://sepolia-optimism.etherscan.io/address/0x6DbcA7CAEBd47D377E230ec3EFaBDdf0A7afA395) | [`0x0D811D581D615AA44A36aa638825403F9b434E18`](https://sepolia-optimism.etherscan.io/address/0x0D811D581D615AA44A36aa638825403F9b434E18) | +|Base Sepolia | [`0xCF98639715DA2cDb81C18C51713Cb146455252d0`](https://sepolia.basescan.org/address/0xCF98639715DA2cDb81C18C51713Cb146455252d0) | [`0x7FaBb96851517583eA7df7d6e9Dd28afc2fA38f5`](https://sepolia.basescan.org/address/0x7FaBb96851517583eA7df7d6e9Dd28afc2fA38f5) | +|Bsc Testnet | [`0xBA82A7c413BfbE26ee025DA221088319b895A8E6`](https://testnet.bscscan.com/address/0xBA82A7c413BfbE26ee025DA221088319b895A8E6) | [`0xE6bd95737DD35Fd0e5f134771A832405671f06e9`](https://testnet.bscscan.com/address/0xE6bd95737DD35Fd0e5f134771A832405671f06e9) | -PingModule: [`0xb51d235CF4461D17FEA88733fed1865873c8D686`](https://contractscan.xyz/contract/0xb51d235CF4461D17FEA88733fed1865873c8D686) +PingModule: [`0x9Cc29770F3d643F4094Ee591f3D2E3c98C349761`](https://contractscan.xyz/contract/0x9Cc29770F3d643F4094Ee591f3D2E3c98C349761) -TokenGateway: [`0xD79B936FEe38e86D4b98818773781fa33DB6d945`](https://contractscan.xyz/contract/0xD79B936FEe38e86D4b98818773781fa33DB6d945) +TokenGateway: [`0x08BB29A013469F543575a958ff460Ea6E0510e83`](https://contractscan.xyz/contract/0x08BB29A013469F543575a958ff460Ea6E0510e83) -TokenFaucet: [`0x71FDAa6d246ac7059874580246c608307831970d`](https://contractscan.xyz/contract/0x71FDAa6d246ac7059874580246c608307831970d) +TokenFaucet: [`0x5DB219e4A535E211a70DA94BaFa291Fc1a51f865`](https://contractscan.xyz/contract/0x5DB219e4A535E211a70DA94BaFa291Fc1a51f865) -HyperUSD (FeeToken): [`0xe189D60BCc6114C7cd4F0B9a94C826FAe9D9b078`](https://contractscan.xyz/contract/0xe189D60BCc6114C7cd4F0B9a94C826FAe9D9b078) +HyperUSD (FeeToken): [`0x6B0e814557b15D67db6F0F147702d209DBEd8D1A`](https://contractscan.xyz/contract/0x6B0e814557b15D67db6F0F147702d209DBEd8D1A) diff --git a/docs/pages/network/relayer.mdx b/docs/pages/network/relayer.mdx index a47271718..4ef51177d 100644 --- a/docs/pages/network/relayer.mdx +++ b/docs/pages/network/relayer.mdx @@ -125,22 +125,22 @@ delivery_endpoints = [ # Here you'll declare a new chain entry for every chain you want to support. # eg ethereum [ethereum] -# configuration type can be "evm" or "substrate" +# configuration type can be either "evm" or "substrate" type = "evm" # State machine identifier for the this evm chain. The possible values: -# - { Ethereum = "ExecutionLayer" } # Ethereum L1 -# - { Ethereum = "Arbitrum" } -# - { Ethereum = "Optimism" } -# - { Ethereum = "Base" } -# - "Bsc" # Binance smart chain -state_machine = "Bsc" +# state_machine = { Ethereum = "ExecutionLayer" } # Ethereum L1 +# state_machine = { Ethereum = "Arbitrum" } +# state_machine = { Ethereum = "Optimism" } +# state_machine = { Ethereum = "Base" } +# state_machine = "Bsc" # Binance smart chain +state_machine = { Ethereum = "ExecutionLayer" } # http(s) rpc urls for evm based chains # Multiple rpc endpoints supported for increased reliability rpc_urls = ["http://127.0.0.1:8545", ""] # The consensus state identifier for this chain on hyperbridge. # For Ethereum and it's L2s this will be "ETH0", for BSC this will be "BSC0". consensus_state_id = "ETH0" -# etherscan api key for querying the state machine's native token price. +# Etherscan api key for querying the state machine's native token price. # Do not that ethereum and all it's L2's use ETH as the native token # So they can all share the same key gotten from etherscan. # diff --git a/evm/abi/src/generated/evm_host.rs b/evm/abi/src/generated/evm_host.rs index efa23a472..6294c2252 100644 --- a/evm/abi/src/generated/evm_host.rs +++ b/evm/abi/src/generated/evm_host.rs @@ -278,6 +278,7 @@ pub mod evm_host { ), ::ethers::core::abi::ethabi::ParamType::Uint(64usize), ::ethers::core::abi::ethabi::ParamType::Address, + ::ethers::core::abi::ethabi::ParamType::Uint(256usize), ], ), internal_type: ::core::option::Option::Some( @@ -1893,13 +1894,13 @@ pub mod evm_host { .method_hash([184, 243, 232, 245], (post,)) .expect("method not found (this should never happen)") } - ///Calls the contract's `dispatch` (0xd0dd5904) function + ///Calls the contract's `dispatch` (0xdab0feae) function pub fn dispatch_with_get( &self, get: DispatchGet, ) -> ::ethers::contract::builders::ContractCall { self.0 - .method_hash([208, 221, 89, 4], (get,)) + .method_hash([218, 176, 254, 174], (get,)) .expect("method not found (this should never happen)") } ///Calls the contract's `dispatchIncoming` (0x4e9b74ec) function @@ -2764,7 +2765,7 @@ pub mod evm_host { pub post: DispatchPost, } ///Container type for all input parameters for the `dispatch` function with signature - /// `dispatch((bytes,uint64,bytes[],uint64,address))` and selector `0xd0dd5904` + /// `dispatch((bytes,uint64,bytes[],uint64,address,uint256))` and selector `0xdab0feae` #[derive( Clone, ::ethers::contract::EthCall, @@ -2775,7 +2776,7 @@ pub mod evm_host { Eq, Hash, )] - #[ethcall(name = "dispatch", abi = "dispatch((bytes,uint64,bytes[],uint64,address))")] + #[ethcall(name = "dispatch", abi = "dispatch((bytes,uint64,bytes[],uint64,address,uint256))")] pub struct DispatchWithGetCall { pub get: DispatchGet, } @@ -4002,7 +4003,7 @@ pub mod evm_host { pub commitment: [u8; 32], } ///Container type for all return fields from the `dispatch` function with signature - /// `dispatch((bytes,uint64,bytes[],uint64,address))` and selector `0xd0dd5904` + /// `dispatch((bytes,uint64,bytes[],uint64,address,uint256))` and selector `0xdab0feae` #[derive( Clone, ::ethers::contract::EthAbiType, @@ -4225,7 +4226,7 @@ pub mod evm_host { Hash, )] pub struct UnStakingPeriodReturn(pub ::ethers::core::types::U256); - ///`DispatchGet(bytes,uint64,bytes[],uint64,address)` + ///`DispatchGet(bytes,uint64,bytes[],uint64,address,uint256)` #[derive( Clone, ::ethers::contract::EthAbiType, @@ -4242,6 +4243,7 @@ pub mod evm_host { pub keys: ::std::vec::Vec<::ethers::core::types::Bytes>, pub timeout: u64, pub sender: ::ethers::core::types::Address, + pub fee: ::ethers::core::types::U256, } ///`DispatchPost(bytes,bytes,bytes,uint64,uint256,address)` #[derive( diff --git a/evm/abi/src/generated/host_manager.rs b/evm/abi/src/generated/host_manager.rs index 51fab4c6e..055de0265 100644 --- a/evm/abi/src/generated/host_manager.rs +++ b/evm/abi/src/generated/host_manager.rs @@ -254,12 +254,12 @@ pub mod host_manager { pub static HOSTMANAGER_ABI: ::ethers::contract::Lazy<::ethers::core::abi::Abi> = ::ethers::contract::Lazy::new(__abi); #[rustfmt::skip] - const __BYTECODE: &[u8] = b"`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`@Qa\x14X8\x03\x80a\x14X\x839\x81\x01`@\x81\x90Ra\0/\x91a\0\x83V[\x80Q`\0\x80T`\x01`\x01`\xA0\x1B\x03\x19\x90\x81\x16`\x01`\x01`\xA0\x1B\x03\x93\x84\x16\x17\x90\x91U` \x90\x92\x01Q`\x01\x80T\x90\x93\x16\x91\x16\x17\x90Ua\0\xEBV[\x80Q`\x01`\x01`\xA0\x1B\x03\x81\x16\x81\x14a\0~W`\0\x80\xFD[\x91\x90PV[`\0`@\x82\x84\x03\x12\x15a\0\x95W`\0\x80\xFD[`@\x80Q\x90\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\0\xC5WcNH{q`\xE0\x1B`\0R`A`\x04R`$`\0\xFD[`@Ra\0\xD1\x83a\0gV[\x81Ra\0\xDF` \x84\x01a\0gV[` \x82\x01R\x93\x92PPPV[a\x13^\x80a\0\xFA`\09`\0\xF3\xFE`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`\x046\x10a\0\x88W`\x005`\xE0\x1C\x80c\xB5\xA9\x82K\x11a\0[W\x80c\xB5\xA9\x82K\x14a\0\xD6W\x80c\xBC\r\xD4G\x14a\0\xE9W\x80c\xC4\x92\xE4&\x14a\0\xFCW\x80c\xCF\xF0\xAB\x96\x14a\x01\nW`\0\x80\xFD[\x80c\x0B\xC3{\xAB\x14a\0\x8DW\x80c\x0E\x83$\xA2\x14a\0\xA2W\x80c\x0F\xEE2\xCE\x14a\0\xB5W\x80c\xB2\xA0\x1B\xF5\x14a\0\xC8W[`\0\x80\xFD[a\0\xA0a\0\x9B6`\x04a\t\nV[a\x01]V[\0[a\0\xA0a\0\xB06`\x04a\t]V[a\x01\xB9V[a\0\xA0a\0\xC36`\x04a\t\x7FV[a\x02`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01`\0`@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x02\xFBW=`\0\x80>=`\0\xFD[PPPP`@Q=`\0\x82>`\x1F=\x90\x81\x01`\x1F\x19\x16\x82\x01`@Ra\x03#\x91\x90\x81\x01\x90a\x0E\x14V[a\x03-\x83\x80a\x0E\x8AV[\x80\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x93\x92\x91\x90\x81\x81R` \x01\x83\x83\x80\x82\x847`\0\x92\x01\x91\x90\x91RP\x92\x93\x92PPa\x05\xF8\x90PV[a\x03\xADW`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`\x14`$\x82\x01Rs\x15[\x98]]\x1A\x1B\xDC\x9A^\x99Y\x08\x1C\x99\\]Y\\\xDD`b\x1B`D\x82\x01R`d\x01a\x01\xB0V[`\0a\x03\xBC`\xC0\x83\x01\x83a\x0E\x8AV[`\0\x81\x81\x10a\x03\xCDWa\x03\xCDa\x0E\xD7V[\x91\x90\x91\x015`\xF8\x1C\x90P`\x01\x81\x11\x15a\x03\xE8Wa\x03\xE8a\x0E\xEDV[\x90P`\0\x81`\x01\x81\x11\x15a\x03\xFEWa\x03\xFEa\x0E\xEDV[\x03a\x04\xA1W`\0a\x04\x12`\xC0\x84\x01\x84a\x0E\x8AV[a\x04 \x91`\x01\x90\x82\x90a\x0F\x03V[\x81\x01\x90a\x04-\x91\x90a\x0F-V[`\x01T`@Qc=`\0\xFD[PPPPPPPPV[`\x01\x81`\x01\x81\x11\x15a\x04\xB5Wa\x04\xB5a\x0E\xEDV[\x03a\x05\x15W`\0a\x04\xC9`\xC0\x84\x01\x84a\x0E\x8AV[a\x04\xD7\x91`\x01\x90\x82\x90a\x0F\x03V[\x81\x01\x90a\x04\xE4\x91\x90a\x10@V[`\x01T`@Qc\x03\xCB\x07\xF5`\xE0\x1B\x81R\x91\x92P`\x01`\x01`\xA0\x1B\x03\x16\x90c\x03\xCB\x07\xF5\x90a\x04i\x90\x84\x90`\x04\x01a\x12\x1BV[`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`\x0E`$\x82\x01Rm*\xB75\xB77\xBB\xB7\x100\xB1\xBA4\xB7\xB7`\x91\x1B`D\x82\x01R`d\x01a\x01\xB0V[`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`$\x80\x82\x01R\x7FIsmpModule doesn't emit Get requ`D\x82\x01Rcests`\xE0\x1B`d\x82\x01R`\x84\x01a\x01\xB0V[`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`%`$\x82\x01R\x7FIsmpModule doesn't emit Post req`D\x82\x01Rduests`\xD8\x1B`d\x82\x01R`\x84\x01a\x01\xB0V[`\0\x81Q\x83Q\x14a\x06\x0BWP`\0a\x06\x1FV[P\x81Q` \x82\x81\x01\x82\x90 \x90\x84\x01\x91\x90\x91 \x14[\x92\x91PPV[cNH{q`\xE0\x1B`\0R`A`\x04R`$`\0\xFD[`@Q`\xE0\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06]Wa\x06]a\x06%V[`@R\x90V[`@\x80Q\x90\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06]Wa\x06]a\x06%V[`@Qa\x01\x80\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06]Wa\x06]a\x06%V[`@Q`\x1F\x82\x01`\x1F\x19\x16\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06\xD0Wa\x06\xD0a\x06%V[`@R\x91\x90PV[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\x06\xF1Wa\x06\xF1a\x06%V[P`\x1F\x01`\x1F\x19\x16` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\x07\x10W`\0\x80\xFD[\x815a\x07#a\x07\x1E\x82a\x06\xD8V[a\x06\xA8V[\x81\x81R\x84` \x83\x86\x01\x01\x11\x15a\x078W`\0\x80\xFD[\x81` \x85\x01` \x83\x017`\0\x91\x81\x01` \x01\x91\x90\x91R\x93\x92PPPV[\x805`\x01`\x01`@\x1B\x03\x81\x16\x81\x14a\x07lW`\0\x80\xFD[\x91\x90PV[`\0`\xE0\x82\x84\x03\x12\x15a\x07\x83W`\0\x80\xFD[a\x07\x8Ba\x06;V[\x90P\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x07\xA4W`\0\x80\xFD[a\x07\xB0\x85\x83\x86\x01a\x06\xFFV[\x83R` \x84\x015\x91P\x80\x82\x11\x15a\x07\xC6W`\0\x80\xFD[a\x07\xD2\x85\x83\x86\x01a\x06\xFFV[` \x84\x01Ra\x07\xE3`@\x85\x01a\x07UV[`@\x84\x01R``\x84\x015\x91P\x80\x82\x11\x15a\x07\xFCW`\0\x80\xFD[a\x08\x08\x85\x83\x86\x01a\x06\xFFV[``\x84\x01R`\x80\x84\x015\x91P\x80\x82\x11\x15a\x08!W`\0\x80\xFD[a\x08-\x85\x83\x86\x01a\x06\xFFV[`\x80\x84\x01Ra\x08>`\xA0\x85\x01a\x07UV[`\xA0\x84\x01R`\xC0\x84\x015\x91P\x80\x82\x11\x15a\x08WW`\0\x80\xFD[Pa\x08d\x84\x82\x85\x01a\x06\xFFV[`\xC0\x83\x01RP\x92\x91PPV[`\0``\x82\x84\x03\x12\x15a\x08\x82W`\0\x80\xFD[`@Q``\x81\x01`\x01`\x01`@\x1B\x03\x82\x82\x10\x81\x83\x11\x17\x15a\x08\xA5Wa\x08\xA5a\x06%V[\x81`@R\x82\x93P\x845\x91P\x80\x82\x11\x15a\x08\xBDW`\0\x80\xFD[a\x08\xC9\x86\x83\x87\x01a\x07qV[\x83R` \x85\x015\x91P\x80\x82\x11\x15a\x08\xDFW`\0\x80\xFD[Pa\x08\xEC\x85\x82\x86\x01a\x06\xFFV[` \x83\x01RPa\x08\xFE`@\x84\x01a\x07UV[`@\x82\x01RP\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\t\x1CW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\t2W`\0\x80\xFD[a\t>\x84\x82\x85\x01a\x08pV[\x94\x93PPPPV[\x805`\x01`\x01`\xA0\x1B\x03\x81\x16\x81\x14a\x07lW`\0\x80\xFD[`\0` \x82\x84\x03\x12\x15a\toW`\0\x80\xFD[a\tx\x82a\tFV[\x93\x92PPPV[`\0` \x82\x84\x03\x12\x15a\t\x91W`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\t\xA7W`\0\x80\xFD[\x82\x01`@\x81\x85\x03\x12\x15a\txW`\0\x80\xFD[`\0` \x82\x84\x03\x12\x15a\t\xCBW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\t\xE2W`\0\x80\xFD[\x90\x83\x01\x90`@\x82\x86\x03\x12\x15a\t\xF6W`\0\x80\xFD[a\t\xFEa\x06cV[\x825\x82\x81\x11\x15a\n\rW`\0\x80\xFD[a\n\x19\x87\x82\x86\x01a\x08pV[\x82RPa\n(` \x84\x01a\tFV[` \x82\x01R\x95\x94PPPPPV[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\nOWa\nOa\x06%V[P`\x05\x1B` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\njW`\0\x80\xFD[\x815` a\nza\x07\x1E\x83a\n6V[\x82\x81R`\x05\x92\x90\x92\x1B\x84\x01\x81\x01\x91\x81\x81\x01\x90\x86\x84\x11\x15a\n\x99W`\0\x80\xFD[\x82\x86\x01[\x84\x81\x10\x15a\n\xD8W\x805`\x01`\x01`@\x1B\x03\x81\x11\x15a\n\xBCW`\0\x80\x81\xFD[a\n\xCA\x89\x86\x83\x8B\x01\x01a\x06\xFFV[\x84RP\x91\x83\x01\x91\x83\x01a\n\x9DV[P\x96\x95PPPPPPV[`\0`\xE0\x82\x84\x03\x12\x15a\n\xF5W`\0\x80\xFD[a\n\xFDa\x06;V[\x90P\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x0B\x16W`\0\x80\xFD[a\x0B\"\x85\x83\x86\x01a\x06\xFFV[\x83R` \x84\x015\x91P\x80\x82\x11\x15a\x0B8W`\0\x80\xFD[a\x0BD\x85\x83\x86\x01a\x06\xFFV[` \x84\x01Ra\x0BU`@\x85\x01a\x07UV[`@\x84\x01R``\x84\x015\x91P\x80\x82\x11\x15a\x0BnW`\0\x80\xFD[a\x0Bz\x85\x83\x86\x01a\x06\xFFV[``\x84\x01Ra\x0B\x8B`\x80\x85\x01a\x07UV[`\x80\x84\x01R`\xA0\x84\x015\x91P\x80\x82\x11\x15a\x0B\xA4W`\0\x80\xFD[Pa\x0B\xB1\x84\x82\x85\x01a\nYV[`\xA0\x83\x01RPa\x0B\xC3`\xC0\x83\x01a\x07UV[`\xC0\x82\x01R\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x0B\xE0W`\0\x80\xFD[`\x01`\x01`@\x1B\x03\x80\x835\x11\x15a\x0B\xF6W`\0\x80\xFD[\x825\x83\x01`@\x81\x86\x03\x12\x15a\x0C\nW`\0\x80\xFD[a\x0C\x12a\x06cV[\x82\x825\x11\x15a\x0C W`\0\x80\xFD[\x815\x82\x01`@\x81\x88\x03\x12\x15a\x0C4W`\0\x80\xFD[a\x0C\x84\x82\x85\x01a\x07qV[`\0` \x82\x84\x03\x12\x15a\r\xAEW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\r\xC4W`\0\x80\xFD[a\t>\x84\x82\x85\x01a\n\xE3V[`\0\x825`\xDE\x19\x836\x03\x01\x81\x12a\r\xE6W`\0\x80\xFD[\x91\x90\x91\x01\x92\x91PPV[`\0[\x83\x81\x10\x15a\x0E\x0BW\x81\x81\x01Q\x83\x82\x01R` \x01a\r\xF3V[PP`\0\x91\x01RV[`\0` \x82\x84\x03\x12\x15a\x0E&W`\0\x80\xFD[\x81Q`\x01`\x01`@\x1B\x03\x81\x11\x15a\x0E`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01`\0`@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x02\xFBW=`\0\x80>=`\0\xFD[PPPP`@Q=`\0\x82>`\x1F=\x90\x81\x01`\x1F\x19\x16\x82\x01`@Ra\x03#\x91\x90\x81\x01\x90a\x0E\x14V[a\x03-\x83\x80a\x0E\x8AV[\x80\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x93\x92\x91\x90\x81\x81R` \x01\x83\x83\x80\x82\x847`\0\x92\x01\x91\x90\x91RP\x92\x93\x92PPa\x05\xF8\x90PV[a\x03\xADW`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`\x14`$\x82\x01Rs\x15[\x98]]\x1A\x1B\xDC\x9A^\x99Y\x08\x1C\x99\\]Y\\\xDD`b\x1B`D\x82\x01R`d\x01a\x01\xB0V[`\0a\x03\xBC`\xC0\x83\x01\x83a\x0E\x8AV[`\0\x81\x81\x10a\x03\xCDWa\x03\xCDa\x0E\xD7V[\x91\x90\x91\x015`\xF8\x1C\x90P`\x01\x81\x11\x15a\x03\xE8Wa\x03\xE8a\x0E\xEDV[\x90P`\0\x81`\x01\x81\x11\x15a\x03\xFEWa\x03\xFEa\x0E\xEDV[\x03a\x04\xA1W`\0a\x04\x12`\xC0\x84\x01\x84a\x0E\x8AV[a\x04 \x91`\x01\x90\x82\x90a\x0F\x03V[\x81\x01\x90a\x04-\x91\x90a\x0F-V[`\x01T`@Qc=`\0\xFD[PPPPPPPPV[`\x01\x81`\x01\x81\x11\x15a\x04\xB5Wa\x04\xB5a\x0E\xEDV[\x03a\x05\x15W`\0a\x04\xC9`\xC0\x84\x01\x84a\x0E\x8AV[a\x04\xD7\x91`\x01\x90\x82\x90a\x0F\x03V[\x81\x01\x90a\x04\xE4\x91\x90a\x10@V[`\x01T`@Qc\x03\xCB\x07\xF5`\xE0\x1B\x81R\x91\x92P`\x01`\x01`\xA0\x1B\x03\x16\x90c\x03\xCB\x07\xF5\x90a\x04i\x90\x84\x90`\x04\x01a\x12\x1BV[`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`\x0E`$\x82\x01Rm*\xB75\xB77\xBB\xB7\x100\xB1\xBA4\xB7\xB7`\x91\x1B`D\x82\x01R`d\x01a\x01\xB0V[`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`$\x80\x82\x01R\x7FIsmpModule doesn't emit Get requ`D\x82\x01Rcests`\xE0\x1B`d\x82\x01R`\x84\x01a\x01\xB0V[`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`%`$\x82\x01R\x7FIsmpModule doesn't emit Post req`D\x82\x01Rduests`\xD8\x1B`d\x82\x01R`\x84\x01a\x01\xB0V[`\0\x81Q\x83Q\x14a\x06\x0BWP`\0a\x06\x1FV[P\x81Q` \x82\x81\x01\x82\x90 \x90\x84\x01\x91\x90\x91 \x14[\x92\x91PPV[cNH{q`\xE0\x1B`\0R`A`\x04R`$`\0\xFD[`@Q`\xE0\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06]Wa\x06]a\x06%V[`@R\x90V[`@\x80Q\x90\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06]Wa\x06]a\x06%V[`@Qa\x01\x80\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06]Wa\x06]a\x06%V[`@Q`\x1F\x82\x01`\x1F\x19\x16\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06\xD0Wa\x06\xD0a\x06%V[`@R\x91\x90PV[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\x06\xF1Wa\x06\xF1a\x06%V[P`\x1F\x01`\x1F\x19\x16` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\x07\x10W`\0\x80\xFD[\x815a\x07#a\x07\x1E\x82a\x06\xD8V[a\x06\xA8V[\x81\x81R\x84` \x83\x86\x01\x01\x11\x15a\x078W`\0\x80\xFD[\x81` \x85\x01` \x83\x017`\0\x91\x81\x01` \x01\x91\x90\x91R\x93\x92PPPV[\x805`\x01`\x01`@\x1B\x03\x81\x16\x81\x14a\x07lW`\0\x80\xFD[\x91\x90PV[`\0`\xE0\x82\x84\x03\x12\x15a\x07\x83W`\0\x80\xFD[a\x07\x8Ba\x06;V[\x90P\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x07\xA4W`\0\x80\xFD[a\x07\xB0\x85\x83\x86\x01a\x06\xFFV[\x83R` \x84\x015\x91P\x80\x82\x11\x15a\x07\xC6W`\0\x80\xFD[a\x07\xD2\x85\x83\x86\x01a\x06\xFFV[` \x84\x01Ra\x07\xE3`@\x85\x01a\x07UV[`@\x84\x01R``\x84\x015\x91P\x80\x82\x11\x15a\x07\xFCW`\0\x80\xFD[a\x08\x08\x85\x83\x86\x01a\x06\xFFV[``\x84\x01R`\x80\x84\x015\x91P\x80\x82\x11\x15a\x08!W`\0\x80\xFD[a\x08-\x85\x83\x86\x01a\x06\xFFV[`\x80\x84\x01Ra\x08>`\xA0\x85\x01a\x07UV[`\xA0\x84\x01R`\xC0\x84\x015\x91P\x80\x82\x11\x15a\x08WW`\0\x80\xFD[Pa\x08d\x84\x82\x85\x01a\x06\xFFV[`\xC0\x83\x01RP\x92\x91PPV[`\0``\x82\x84\x03\x12\x15a\x08\x82W`\0\x80\xFD[`@Q``\x81\x01`\x01`\x01`@\x1B\x03\x82\x82\x10\x81\x83\x11\x17\x15a\x08\xA5Wa\x08\xA5a\x06%V[\x81`@R\x82\x93P\x845\x91P\x80\x82\x11\x15a\x08\xBDW`\0\x80\xFD[a\x08\xC9\x86\x83\x87\x01a\x07qV[\x83R` \x85\x015\x91P\x80\x82\x11\x15a\x08\xDFW`\0\x80\xFD[Pa\x08\xEC\x85\x82\x86\x01a\x06\xFFV[` \x83\x01RPa\x08\xFE`@\x84\x01a\x07UV[`@\x82\x01RP\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\t\x1CW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\t2W`\0\x80\xFD[a\t>\x84\x82\x85\x01a\x08pV[\x94\x93PPPPV[\x805`\x01`\x01`\xA0\x1B\x03\x81\x16\x81\x14a\x07lW`\0\x80\xFD[`\0` \x82\x84\x03\x12\x15a\toW`\0\x80\xFD[a\tx\x82a\tFV[\x93\x92PPPV[`\0` \x82\x84\x03\x12\x15a\t\x91W`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\t\xA7W`\0\x80\xFD[\x82\x01`@\x81\x85\x03\x12\x15a\txW`\0\x80\xFD[`\0` \x82\x84\x03\x12\x15a\t\xCBW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\t\xE2W`\0\x80\xFD[\x90\x83\x01\x90`@\x82\x86\x03\x12\x15a\t\xF6W`\0\x80\xFD[a\t\xFEa\x06cV[\x825\x82\x81\x11\x15a\n\rW`\0\x80\xFD[a\n\x19\x87\x82\x86\x01a\x08pV[\x82RPa\n(` \x84\x01a\tFV[` \x82\x01R\x95\x94PPPPPV[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\nOWa\nOa\x06%V[P`\x05\x1B` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\njW`\0\x80\xFD[\x815` a\nza\x07\x1E\x83a\n6V[\x82\x81R`\x05\x92\x90\x92\x1B\x84\x01\x81\x01\x91\x81\x81\x01\x90\x86\x84\x11\x15a\n\x99W`\0\x80\xFD[\x82\x86\x01[\x84\x81\x10\x15a\n\xD8W\x805`\x01`\x01`@\x1B\x03\x81\x11\x15a\n\xBCW`\0\x80\x81\xFD[a\n\xCA\x89\x86\x83\x8B\x01\x01a\x06\xFFV[\x84RP\x91\x83\x01\x91\x83\x01a\n\x9DV[P\x96\x95PPPPPPV[`\0`\xE0\x82\x84\x03\x12\x15a\n\xF5W`\0\x80\xFD[a\n\xFDa\x06;V[\x90P\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x0B\x16W`\0\x80\xFD[a\x0B\"\x85\x83\x86\x01a\x06\xFFV[\x83R` \x84\x015\x91P\x80\x82\x11\x15a\x0B8W`\0\x80\xFD[a\x0BD\x85\x83\x86\x01a\x06\xFFV[` \x84\x01Ra\x0BU`@\x85\x01a\x07UV[`@\x84\x01R``\x84\x015\x91P\x80\x82\x11\x15a\x0BnW`\0\x80\xFD[a\x0Bz\x85\x83\x86\x01a\x06\xFFV[``\x84\x01Ra\x0B\x8B`\x80\x85\x01a\x07UV[`\x80\x84\x01R`\xA0\x84\x015\x91P\x80\x82\x11\x15a\x0B\xA4W`\0\x80\xFD[Pa\x0B\xB1\x84\x82\x85\x01a\nYV[`\xA0\x83\x01RPa\x0B\xC3`\xC0\x83\x01a\x07UV[`\xC0\x82\x01R\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x0B\xE0W`\0\x80\xFD[`\x01`\x01`@\x1B\x03\x80\x835\x11\x15a\x0B\xF6W`\0\x80\xFD[\x825\x83\x01`@\x81\x86\x03\x12\x15a\x0C\nW`\0\x80\xFD[a\x0C\x12a\x06cV[\x82\x825\x11\x15a\x0C W`\0\x80\xFD[\x815\x82\x01`@\x81\x88\x03\x12\x15a\x0C4W`\0\x80\xFD[a\x0C\x84\x82\x85\x01a\x07qV[`\0` \x82\x84\x03\x12\x15a\r\xAEW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\r\xC4W`\0\x80\xFD[a\t>\x84\x82\x85\x01a\n\xE3V[`\0\x825`\xDE\x19\x836\x03\x01\x81\x12a\r\xE6W`\0\x80\xFD[\x91\x90\x91\x01\x92\x91PPV[`\0[\x83\x81\x10\x15a\x0E\x0BW\x81\x81\x01Q\x83\x82\x01R` \x01a\r\xF3V[PP`\0\x91\x01RV[`\0` \x82\x84\x03\x12\x15a\x0E&W`\0\x80\xFD[\x81Q`\x01`\x01`@\x1B\x03\x81\x11\x15a\x0E`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01`\0`@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x02\xFBW=`\0\x80>=`\0\xFD[PPPP`@Q=`\0\x82>`\x1F=\x90\x81\x01`\x1F\x19\x16\x82\x01`@Ra\x03#\x91\x90\x81\x01\x90a\x0E\x14V[a\x03-\x83\x80a\x0E\x8AV[\x80\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x93\x92\x91\x90\x81\x81R` \x01\x83\x83\x80\x82\x847`\0\x92\x01\x91\x90\x91RP\x92\x93\x92PPa\x05\xF8\x90PV[a\x03\xADW`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`\x14`$\x82\x01Rs\x15[\x98]]\x1A\x1B\xDC\x9A^\x99Y\x08\x1C\x99\\]Y\\\xDD`b\x1B`D\x82\x01R`d\x01a\x01\xB0V[`\0a\x03\xBC`\xC0\x83\x01\x83a\x0E\x8AV[`\0\x81\x81\x10a\x03\xCDWa\x03\xCDa\x0E\xD7V[\x91\x90\x91\x015`\xF8\x1C\x90P`\x01\x81\x11\x15a\x03\xE8Wa\x03\xE8a\x0E\xEDV[\x90P`\0\x81`\x01\x81\x11\x15a\x03\xFEWa\x03\xFEa\x0E\xEDV[\x03a\x04\xA1W`\0a\x04\x12`\xC0\x84\x01\x84a\x0E\x8AV[a\x04 \x91`\x01\x90\x82\x90a\x0F\x03V[\x81\x01\x90a\x04-\x91\x90a\x0F-V[`\x01T`@Qc=`\0\xFD[PPPPPPPPV[`\x01\x81`\x01\x81\x11\x15a\x04\xB5Wa\x04\xB5a\x0E\xEDV[\x03a\x05\x15W`\0a\x04\xC9`\xC0\x84\x01\x84a\x0E\x8AV[a\x04\xD7\x91`\x01\x90\x82\x90a\x0F\x03V[\x81\x01\x90a\x04\xE4\x91\x90a\x10@V[`\x01T`@Qc\x03\xCB\x07\xF5`\xE0\x1B\x81R\x91\x92P`\x01`\x01`\xA0\x1B\x03\x16\x90c\x03\xCB\x07\xF5\x90a\x04i\x90\x84\x90`\x04\x01a\x12\x1BV[`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`\x0E`$\x82\x01Rm*\xB75\xB77\xBB\xB7\x100\xB1\xBA4\xB7\xB7`\x91\x1B`D\x82\x01R`d\x01a\x01\xB0V[`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`$\x80\x82\x01R\x7FIsmpModule doesn't emit Get requ`D\x82\x01Rcests`\xE0\x1B`d\x82\x01R`\x84\x01a\x01\xB0V[`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`%`$\x82\x01R\x7FIsmpModule doesn't emit Post req`D\x82\x01Rduests`\xD8\x1B`d\x82\x01R`\x84\x01a\x01\xB0V[`\0\x81Q\x83Q\x14a\x06\x0BWP`\0a\x06\x1FV[P\x81Q` \x82\x81\x01\x82\x90 \x90\x84\x01\x91\x90\x91 \x14[\x92\x91PPV[cNH{q`\xE0\x1B`\0R`A`\x04R`$`\0\xFD[`@Q`\xE0\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06]Wa\x06]a\x06%V[`@R\x90V[`@\x80Q\x90\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06]Wa\x06]a\x06%V[`@Qa\x01\x80\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06]Wa\x06]a\x06%V[`@Q`\x1F\x82\x01`\x1F\x19\x16\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06\xD0Wa\x06\xD0a\x06%V[`@R\x91\x90PV[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\x06\xF1Wa\x06\xF1a\x06%V[P`\x1F\x01`\x1F\x19\x16` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\x07\x10W`\0\x80\xFD[\x815a\x07#a\x07\x1E\x82a\x06\xD8V[a\x06\xA8V[\x81\x81R\x84` \x83\x86\x01\x01\x11\x15a\x078W`\0\x80\xFD[\x81` \x85\x01` \x83\x017`\0\x91\x81\x01` \x01\x91\x90\x91R\x93\x92PPPV[\x805`\x01`\x01`@\x1B\x03\x81\x16\x81\x14a\x07lW`\0\x80\xFD[\x91\x90PV[`\0`\xE0\x82\x84\x03\x12\x15a\x07\x83W`\0\x80\xFD[a\x07\x8Ba\x06;V[\x90P\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x07\xA4W`\0\x80\xFD[a\x07\xB0\x85\x83\x86\x01a\x06\xFFV[\x83R` \x84\x015\x91P\x80\x82\x11\x15a\x07\xC6W`\0\x80\xFD[a\x07\xD2\x85\x83\x86\x01a\x06\xFFV[` \x84\x01Ra\x07\xE3`@\x85\x01a\x07UV[`@\x84\x01R``\x84\x015\x91P\x80\x82\x11\x15a\x07\xFCW`\0\x80\xFD[a\x08\x08\x85\x83\x86\x01a\x06\xFFV[``\x84\x01R`\x80\x84\x015\x91P\x80\x82\x11\x15a\x08!W`\0\x80\xFD[a\x08-\x85\x83\x86\x01a\x06\xFFV[`\x80\x84\x01Ra\x08>`\xA0\x85\x01a\x07UV[`\xA0\x84\x01R`\xC0\x84\x015\x91P\x80\x82\x11\x15a\x08WW`\0\x80\xFD[Pa\x08d\x84\x82\x85\x01a\x06\xFFV[`\xC0\x83\x01RP\x92\x91PPV[`\0``\x82\x84\x03\x12\x15a\x08\x82W`\0\x80\xFD[`@Q``\x81\x01`\x01`\x01`@\x1B\x03\x82\x82\x10\x81\x83\x11\x17\x15a\x08\xA5Wa\x08\xA5a\x06%V[\x81`@R\x82\x93P\x845\x91P\x80\x82\x11\x15a\x08\xBDW`\0\x80\xFD[a\x08\xC9\x86\x83\x87\x01a\x07qV[\x83R` \x85\x015\x91P\x80\x82\x11\x15a\x08\xDFW`\0\x80\xFD[Pa\x08\xEC\x85\x82\x86\x01a\x06\xFFV[` \x83\x01RPa\x08\xFE`@\x84\x01a\x07UV[`@\x82\x01RP\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\t\x1CW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\t2W`\0\x80\xFD[a\t>\x84\x82\x85\x01a\x08pV[\x94\x93PPPPV[\x805`\x01`\x01`\xA0\x1B\x03\x81\x16\x81\x14a\x07lW`\0\x80\xFD[`\0` \x82\x84\x03\x12\x15a\toW`\0\x80\xFD[a\tx\x82a\tFV[\x93\x92PPPV[`\0` \x82\x84\x03\x12\x15a\t\x91W`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\t\xA7W`\0\x80\xFD[\x82\x01`@\x81\x85\x03\x12\x15a\txW`\0\x80\xFD[`\0` \x82\x84\x03\x12\x15a\t\xCBW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\t\xE2W`\0\x80\xFD[\x90\x83\x01\x90`@\x82\x86\x03\x12\x15a\t\xF6W`\0\x80\xFD[a\t\xFEa\x06cV[\x825\x82\x81\x11\x15a\n\rW`\0\x80\xFD[a\n\x19\x87\x82\x86\x01a\x08pV[\x82RPa\n(` \x84\x01a\tFV[` \x82\x01R\x95\x94PPPPPV[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\nOWa\nOa\x06%V[P`\x05\x1B` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\njW`\0\x80\xFD[\x815` a\nza\x07\x1E\x83a\n6V[\x82\x81R`\x05\x92\x90\x92\x1B\x84\x01\x81\x01\x91\x81\x81\x01\x90\x86\x84\x11\x15a\n\x99W`\0\x80\xFD[\x82\x86\x01[\x84\x81\x10\x15a\n\xD8W\x805`\x01`\x01`@\x1B\x03\x81\x11\x15a\n\xBCW`\0\x80\x81\xFD[a\n\xCA\x89\x86\x83\x8B\x01\x01a\x06\xFFV[\x84RP\x91\x83\x01\x91\x83\x01a\n\x9DV[P\x96\x95PPPPPPV[`\0`\xE0\x82\x84\x03\x12\x15a\n\xF5W`\0\x80\xFD[a\n\xFDa\x06;V[\x90P\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x0B\x16W`\0\x80\xFD[a\x0B\"\x85\x83\x86\x01a\x06\xFFV[\x83R` \x84\x015\x91P\x80\x82\x11\x15a\x0B8W`\0\x80\xFD[a\x0BD\x85\x83\x86\x01a\x06\xFFV[` \x84\x01Ra\x0BU`@\x85\x01a\x07UV[`@\x84\x01R``\x84\x015\x91P\x80\x82\x11\x15a\x0BnW`\0\x80\xFD[a\x0Bz\x85\x83\x86\x01a\x06\xFFV[``\x84\x01Ra\x0B\x8B`\x80\x85\x01a\x07UV[`\x80\x84\x01R`\xA0\x84\x015\x91P\x80\x82\x11\x15a\x0B\xA4W`\0\x80\xFD[Pa\x0B\xB1\x84\x82\x85\x01a\nYV[`\xA0\x83\x01RPa\x0B\xC3`\xC0\x83\x01a\x07UV[`\xC0\x82\x01R\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x0B\xE0W`\0\x80\xFD[`\x01`\x01`@\x1B\x03\x80\x835\x11\x15a\x0B\xF6W`\0\x80\xFD[\x825\x83\x01`@\x81\x86\x03\x12\x15a\x0C\nW`\0\x80\xFD[a\x0C\x12a\x06cV[\x82\x825\x11\x15a\x0C W`\0\x80\xFD[\x815\x82\x01`@\x81\x88\x03\x12\x15a\x0C4W`\0\x80\xFD[a\x0C\x84\x82\x85\x01a\x07qV[`\0` \x82\x84\x03\x12\x15a\r\xAEW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\r\xC4W`\0\x80\xFD[a\t>\x84\x82\x85\x01a\n\xE3V[`\0\x825`\xDE\x19\x836\x03\x01\x81\x12a\r\xE6W`\0\x80\xFD[\x91\x90\x91\x01\x92\x91PPV[`\0[\x83\x81\x10\x15a\x0E\x0BW\x81\x81\x01Q\x83\x82\x01R` \x01a\r\xF3V[PP`\0\x91\x01RV[`\0` \x82\x84\x03\x12\x15a\x0E&W`\0\x80\xFD[\x81Q`\x01`\x01`@\x1B\x03\x81\x11\x15a\x0E`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01`\0`@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x02\xFBW=`\0\x80>=`\0\xFD[PPPP`@Q=`\0\x82>`\x1F=\x90\x81\x01`\x1F\x19\x16\x82\x01`@Ra\x03#\x91\x90\x81\x01\x90a\x0E\x14V[a\x03-\x83\x80a\x0E\x8AV[\x80\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x93\x92\x91\x90\x81\x81R` \x01\x83\x83\x80\x82\x847`\0\x92\x01\x91\x90\x91RP\x92\x93\x92PPa\x05\xF8\x90PV[a\x03\xADW`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`\x14`$\x82\x01Rs\x15[\x98]]\x1A\x1B\xDC\x9A^\x99Y\x08\x1C\x99\\]Y\\\xDD`b\x1B`D\x82\x01R`d\x01a\x01\xB0V[`\0a\x03\xBC`\xC0\x83\x01\x83a\x0E\x8AV[`\0\x81\x81\x10a\x03\xCDWa\x03\xCDa\x0E\xD7V[\x91\x90\x91\x015`\xF8\x1C\x90P`\x01\x81\x11\x15a\x03\xE8Wa\x03\xE8a\x0E\xEDV[\x90P`\0\x81`\x01\x81\x11\x15a\x03\xFEWa\x03\xFEa\x0E\xEDV[\x03a\x04\xA1W`\0a\x04\x12`\xC0\x84\x01\x84a\x0E\x8AV[a\x04 \x91`\x01\x90\x82\x90a\x0F\x03V[\x81\x01\x90a\x04-\x91\x90a\x0F-V[`\x01T`@Qc=`\0\xFD[PPPPPPPPV[`\x01\x81`\x01\x81\x11\x15a\x04\xB5Wa\x04\xB5a\x0E\xEDV[\x03a\x05\x15W`\0a\x04\xC9`\xC0\x84\x01\x84a\x0E\x8AV[a\x04\xD7\x91`\x01\x90\x82\x90a\x0F\x03V[\x81\x01\x90a\x04\xE4\x91\x90a\x10@V[`\x01T`@Qc\x03\xCB\x07\xF5`\xE0\x1B\x81R\x91\x92P`\x01`\x01`\xA0\x1B\x03\x16\x90c\x03\xCB\x07\xF5\x90a\x04i\x90\x84\x90`\x04\x01a\x12\x1BV[`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`\x0E`$\x82\x01Rm*\xB75\xB77\xBB\xB7\x100\xB1\xBA4\xB7\xB7`\x91\x1B`D\x82\x01R`d\x01a\x01\xB0V[`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`$\x80\x82\x01R\x7FIsmpModule doesn't emit Get requ`D\x82\x01Rcests`\xE0\x1B`d\x82\x01R`\x84\x01a\x01\xB0V[`@QbF\x1B\xCD`\xE5\x1B\x81R` `\x04\x82\x01R`%`$\x82\x01R\x7FIsmpModule doesn't emit Post req`D\x82\x01Rduests`\xD8\x1B`d\x82\x01R`\x84\x01a\x01\xB0V[`\0\x81Q\x83Q\x14a\x06\x0BWP`\0a\x06\x1FV[P\x81Q` \x82\x81\x01\x82\x90 \x90\x84\x01\x91\x90\x91 \x14[\x92\x91PPV[cNH{q`\xE0\x1B`\0R`A`\x04R`$`\0\xFD[`@Q`\xE0\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06]Wa\x06]a\x06%V[`@R\x90V[`@\x80Q\x90\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06]Wa\x06]a\x06%V[`@Qa\x01\x80\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06]Wa\x06]a\x06%V[`@Q`\x1F\x82\x01`\x1F\x19\x16\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x06\xD0Wa\x06\xD0a\x06%V[`@R\x91\x90PV[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\x06\xF1Wa\x06\xF1a\x06%V[P`\x1F\x01`\x1F\x19\x16` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\x07\x10W`\0\x80\xFD[\x815a\x07#a\x07\x1E\x82a\x06\xD8V[a\x06\xA8V[\x81\x81R\x84` \x83\x86\x01\x01\x11\x15a\x078W`\0\x80\xFD[\x81` \x85\x01` \x83\x017`\0\x91\x81\x01` \x01\x91\x90\x91R\x93\x92PPPV[\x805`\x01`\x01`@\x1B\x03\x81\x16\x81\x14a\x07lW`\0\x80\xFD[\x91\x90PV[`\0`\xE0\x82\x84\x03\x12\x15a\x07\x83W`\0\x80\xFD[a\x07\x8Ba\x06;V[\x90P\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x07\xA4W`\0\x80\xFD[a\x07\xB0\x85\x83\x86\x01a\x06\xFFV[\x83R` \x84\x015\x91P\x80\x82\x11\x15a\x07\xC6W`\0\x80\xFD[a\x07\xD2\x85\x83\x86\x01a\x06\xFFV[` \x84\x01Ra\x07\xE3`@\x85\x01a\x07UV[`@\x84\x01R``\x84\x015\x91P\x80\x82\x11\x15a\x07\xFCW`\0\x80\xFD[a\x08\x08\x85\x83\x86\x01a\x06\xFFV[``\x84\x01R`\x80\x84\x015\x91P\x80\x82\x11\x15a\x08!W`\0\x80\xFD[a\x08-\x85\x83\x86\x01a\x06\xFFV[`\x80\x84\x01Ra\x08>`\xA0\x85\x01a\x07UV[`\xA0\x84\x01R`\xC0\x84\x015\x91P\x80\x82\x11\x15a\x08WW`\0\x80\xFD[Pa\x08d\x84\x82\x85\x01a\x06\xFFV[`\xC0\x83\x01RP\x92\x91PPV[`\0``\x82\x84\x03\x12\x15a\x08\x82W`\0\x80\xFD[`@Q``\x81\x01`\x01`\x01`@\x1B\x03\x82\x82\x10\x81\x83\x11\x17\x15a\x08\xA5Wa\x08\xA5a\x06%V[\x81`@R\x82\x93P\x845\x91P\x80\x82\x11\x15a\x08\xBDW`\0\x80\xFD[a\x08\xC9\x86\x83\x87\x01a\x07qV[\x83R` \x85\x015\x91P\x80\x82\x11\x15a\x08\xDFW`\0\x80\xFD[Pa\x08\xEC\x85\x82\x86\x01a\x06\xFFV[` \x83\x01RPa\x08\xFE`@\x84\x01a\x07UV[`@\x82\x01RP\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\t\x1CW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\t2W`\0\x80\xFD[a\t>\x84\x82\x85\x01a\x08pV[\x94\x93PPPPV[\x805`\x01`\x01`\xA0\x1B\x03\x81\x16\x81\x14a\x07lW`\0\x80\xFD[`\0` \x82\x84\x03\x12\x15a\toW`\0\x80\xFD[a\tx\x82a\tFV[\x93\x92PPPV[`\0` \x82\x84\x03\x12\x15a\t\x91W`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\t\xA7W`\0\x80\xFD[\x82\x01`@\x81\x85\x03\x12\x15a\txW`\0\x80\xFD[`\0` \x82\x84\x03\x12\x15a\t\xCBW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\t\xE2W`\0\x80\xFD[\x90\x83\x01\x90`@\x82\x86\x03\x12\x15a\t\xF6W`\0\x80\xFD[a\t\xFEa\x06cV[\x825\x82\x81\x11\x15a\n\rW`\0\x80\xFD[a\n\x19\x87\x82\x86\x01a\x08pV[\x82RPa\n(` \x84\x01a\tFV[` \x82\x01R\x95\x94PPPPPV[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\nOWa\nOa\x06%V[P`\x05\x1B` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\njW`\0\x80\xFD[\x815` a\nza\x07\x1E\x83a\n6V[\x82\x81R`\x05\x92\x90\x92\x1B\x84\x01\x81\x01\x91\x81\x81\x01\x90\x86\x84\x11\x15a\n\x99W`\0\x80\xFD[\x82\x86\x01[\x84\x81\x10\x15a\n\xD8W\x805`\x01`\x01`@\x1B\x03\x81\x11\x15a\n\xBCW`\0\x80\x81\xFD[a\n\xCA\x89\x86\x83\x8B\x01\x01a\x06\xFFV[\x84RP\x91\x83\x01\x91\x83\x01a\n\x9DV[P\x96\x95PPPPPPV[`\0`\xE0\x82\x84\x03\x12\x15a\n\xF5W`\0\x80\xFD[a\n\xFDa\x06;V[\x90P\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x0B\x16W`\0\x80\xFD[a\x0B\"\x85\x83\x86\x01a\x06\xFFV[\x83R` \x84\x015\x91P\x80\x82\x11\x15a\x0B8W`\0\x80\xFD[a\x0BD\x85\x83\x86\x01a\x06\xFFV[` \x84\x01Ra\x0BU`@\x85\x01a\x07UV[`@\x84\x01R``\x84\x015\x91P\x80\x82\x11\x15a\x0BnW`\0\x80\xFD[a\x0Bz\x85\x83\x86\x01a\x06\xFFV[``\x84\x01Ra\x0B\x8B`\x80\x85\x01a\x07UV[`\x80\x84\x01R`\xA0\x84\x015\x91P\x80\x82\x11\x15a\x0B\xA4W`\0\x80\xFD[Pa\x0B\xB1\x84\x82\x85\x01a\nYV[`\xA0\x83\x01RPa\x0B\xC3`\xC0\x83\x01a\x07UV[`\xC0\x82\x01R\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x0B\xE0W`\0\x80\xFD[`\x01`\x01`@\x1B\x03\x80\x835\x11\x15a\x0B\xF6W`\0\x80\xFD[\x825\x83\x01`@\x81\x86\x03\x12\x15a\x0C\nW`\0\x80\xFD[a\x0C\x12a\x06cV[\x82\x825\x11\x15a\x0C W`\0\x80\xFD[\x815\x82\x01`@\x81\x88\x03\x12\x15a\x0C4W`\0\x80\xFD[a\x0C\x84\x82\x85\x01a\x07qV[`\0` \x82\x84\x03\x12\x15a\r\xAEW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\r\xC4W`\0\x80\xFD[a\t>\x84\x82\x85\x01a\n\xE3V[`\0\x825`\xDE\x19\x836\x03\x01\x81\x12a\r\xE6W`\0\x80\xFD[\x91\x90\x91\x01\x92\x91PPV[`\0[\x83\x81\x10\x15a\x0E\x0BW\x81\x81\x01Q\x83\x82\x01R` \x01a\r\xF3V[PP`\0\x91\x01RV[`\0` \x82\x84\x03\x12\x15a\x0E&W`\0\x80\xFD[\x81Q`\x01`\x01`@\x1B\x03\x81\x11\x15a\x0E = ::ethers::contract::Lazy::new(__abi); #[rustfmt::skip] - const __BYTECODE: &[u8] = b"`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`@Qa\x1D*8\x03\x80a\x1D*\x839\x81\x01`@\x81\x90Ra\0/\x91a\0TV[`\x01\x80T`\x01`\x01`\xA0\x1B\x03\x19\x16`\x01`\x01`\xA0\x1B\x03\x92\x90\x92\x16\x91\x90\x91\x17\x90Ua\0\x84V[`\0` \x82\x84\x03\x12\x15a\0fW`\0\x80\xFD[\x81Q`\x01`\x01`\xA0\x1B\x03\x81\x16\x81\x14a\0}W`\0\x80\xFD[\x93\x92PPPV[a\x1C\x97\x80a\0\x93`\09`\0\xF3\xFE`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`\x046\x10a\0\xCFW`\x005`\xE0\x1C\x80cr5N\x9B\x11a\0\x8CW\x80c\xBC\r\xD4G\x11a\0fW\x80c\xBC\r\xD4G\x14a\x01\x94W\x80c\xC4\x92\xE4&\x14a\x01\xA7W\x80c\xD5\xF6\xEE\xFD\x14a\x01\xBAW\x80c\xF47\xBCY\x14a\x01\xCDW`\0\x80\xFD[\x80cr5N\x9B\x14a\x01[W\x80c\xB2\xA0\x1B\xF5\x14a\x01nW\x80c\xB5\xA9\x82K\x14a\x01\x81W`\0\x80\xFD[\x80c\x0B\xC3{\xAB\x14a\0\xD4W\x80c\x0E\x83$\xA2\x14a\0\xE9W\x80c\x0F\xEE2\xCE\x14a\0\xFCW\x80cJi.\x06\x14a\x01\x0FW\x80cM\r\x9C;\x14a\x01\"W\x80cp\xC5GO\x14a\x01HW[`\0\x80\xFD[a\0\xE7a\0\xE26`\x04a\x12#V[a\x01\xE8V[\0[a\0\xE7a\0\xF76`\x04a\x12\x82V[a\x02?V[a\0\xE7a\x01\n6`\x04a\x12\x9FV[a\x02\x8CV[a\0\xE7a\x01\x1D6`\x04a\x13\"V[a\x02\xF6V[a\x015a\x0106`\x04a\x12#V[a\x07TV[`@Q\x90\x81R` \x01[`@Q\x80\x91\x03\x90\xF3[a\x015a\x01V6`\x04a\x13\xCCV[a\x08\x04V[a\0\xE7a\x01i6`\x04a\x14\0V[a\n\xB7V[a\0\xE7a\x01|6`\x04a\x14\x19V[a\x0B\xD1V[a\0\xE7a\x01\x8F6`\x04a\x16\x11V[a\x0C(V[a\0\xE7a\x01\xA26`\x04a\x13\xCCV[a\x0C\x7FV[a\0\xE7a\x01\xB56`\x04a\x17\xB9V[a\x0C\xD6V[a\x015a\x01\xC86`\x04a\x17\xB9V[a\r-V[`\0T`@Q`\x01`\x01`\xA0\x1B\x03\x90\x91\x16\x81R` \x01a\x01?V[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x02\x13W`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7Fhv\xFA>\xCC}\x82\x1F!]\x82\x12B\xCB\xBE\x1F\x0E0\xA0\n\x85\xC2\"\xD6\x92\xA7\x96\x8F\xD3\xAF\xF1\x0B\x90`\0\x90\xA1PV[`\x01T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x02jW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`\0\x80T`\x01`\x01`\xA0\x1B\x03\x19\x16`\x01`\x01`\xA0\x1B\x03\x92\x90\x92\x16\x91\x90\x91\x17\x90UV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x02\xB7W`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[\x80Q`\xC0\x01Q`@Q\x7F\xFB\x08{?\xFB\xBB\x0F\xC9\"\xDC\xCF\x87%\x08g\x1Av\x05\x85\x94#\xEB\x90\xEB\x01LV\xFD\xBA\x14\x84\xDC\x91a\x02\xEB\x91a\x18=V[`@Q\x80\x91\x03\x90\xA1PV[`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xF47\xBCY`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01`\0`@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x03JW=`\0\x80>=`\0\xFD[PPPP`@Q=`\0\x82>`\x1F=\x90\x81\x01`\x1F\x19\x16\x82\x01`@Ra\x03r\x91\x90\x81\x01\x90a\x18PV[`@Q` \x01a\x03\x82\x91\x90a\x18\xC6V[`@\x80Q`\x1F\x19\x81\x84\x03\x01\x81R\x82\x82R`\0\x80Tcd\x1Dr\x9D`\xE0\x1B\x85R\x92Q\x91\x94P\x92`\x01`\x01`\xA0\x1B\x03\x90\x92\x16\x91cd\x1Dr\x9D\x91`\x04\x80\x83\x01\x92` \x92\x91\x90\x82\x90\x03\x01\x81\x86Z\xFA\x15\x80\x15a\x03\xDCW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x04\0\x91\x90a\x18\xF9V[\x90P`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16cdxF\xA5`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x04VW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x04z\x91\x90a\x19\x12V[\x90P`\0\x84``\x01Q\x84Q\x84a\x04\x90\x91\x90a\x19EV[\x86`\x80\x01Qa\x04\x9F\x91\x90a\x19\\V[a\x04\xA9\x91\x90a\x19EV[`@Qc#\xB8r\xDD`\xE0\x1B\x81R3`\x04\x82\x01R0`$\x82\x01R`D\x81\x01\x82\x90R\x90\x91P`\x01`\x01`\xA0\x1B\x03\x83\x16\x90c#\xB8r\xDD\x90`d\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x04\xFFW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x05#\x91\x90a\x19oV[P`\0T`@Qc\t^\xA7\xB3`\xE0\x1B\x81R`\x01`\x01`\xA0\x1B\x03\x91\x82\x16`\x04\x82\x01R`$\x81\x01\x83\x90R\x90\x83\x16\x90c\t^\xA7\xB3\x90`D\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x05wW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x05\x9B\x91\x90a\x19oV[P`\0[\x85``\x01Q\x81\x10\x15a\x07LW`\0`@Q\x80`\xC0\x01`@R\x80\x88`\0\x01Q\x81R` \x01\x88` \x01Q`@Q` \x01a\x05\xEF\x91\x90``\x91\x90\x91\x1Bk\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x81R`\x14\x01\x90V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x81R` \x01`\0\x80T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xF47\xBCY`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01`\0`@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x06TW=`\0\x80>=`\0\xFD[PPPP`@Q=`\0\x82>`\x1F=\x90\x81\x01`\x1F\x19\x16\x82\x01`@Ra\x06|\x91\x90\x81\x01\x90a\x18PV[`@Q` \x01a\x06\x8C\x91\x90a\x18\xC6V[`@\x80Q`\x1F\x19\x81\x84\x03\x01\x81R\x91\x81R\x90\x82R\x89\x81\x01Q`\x01`\x01`@\x1B\x03\x16` \x83\x01R`\x80\x8A\x01Q\x82\x82\x01R2``\x90\x92\x01\x91\x90\x91R`\0T\x90Qc\xB8\xF3\xE8\xF5`\xE0\x1B\x81R\x91\x92P`\x01`\x01`\xA0\x1B\x03\x16\x90c\xB8\xF3\xE8\xF5\x90a\x06\xF4\x90\x84\x90`\x04\x01a\x19\x91V[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x07\x13W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x077\x91\x90a\x18\xF9V[PP\x80\x80a\x07D\x90a\x1A%V[\x91PPa\x05\x9FV[PPPPPPV[`@\x80Q`\xA0\x81\x01\x82R\x82Q\x81R` \x80\x84\x01Q\x90\x82\x01R\x82\x82\x01Q`\x01`\x01`@\x1B\x03\x16\x81\x83\x01R`\0``\x82\x01\x81\x90R2`\x80\x83\x01R\x80T\x92Qc\x94H\x08\x05`\xE0\x1B\x81R\x90\x92`\x01`\x01`\xA0\x1B\x03\x16\x90c\x94H\x08\x05\x90a\x07\xBA\x90\x84\x90`\x04\x01a\x1A>V[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x07\xD9W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x07\xFD\x91\x90a\x18\xF9V[\x93\x92PPPV[`\0\x80T`@\x80Qcd\x1Dr\x9D`\xE0\x1B\x81R\x90Q\x83\x92`\x01`\x01`\xA0\x1B\x03\x16\x91cd\x1Dr\x9D\x91`\x04\x80\x83\x01\x92` \x92\x91\x90\x82\x90\x03\x01\x81\x86Z\xFA\x15\x80\x15a\x08NW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x08r\x91\x90a\x18\xF9V[\x90P`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16cdxF\xA5`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x08\xC8W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x08\xEC\x91\x90a\x19\x12V[\x90P`\0\x84`\xC0\x01QQ\x83a\t\x01\x91\x90a\x19EV[`@Qc#\xB8r\xDD`\xE0\x1B\x81R3`\x04\x82\x01R0`$\x82\x01R`D\x81\x01\x82\x90R\x90\x91P`\x01`\x01`\xA0\x1B\x03\x83\x16\x90c#\xB8r\xDD\x90`d\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\tWW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\t{\x91\x90a\x19oV[P`\0T`@Qc\t^\xA7\xB3`\xE0\x1B\x81R`\x01`\x01`\xA0\x1B\x03\x91\x82\x16`\x04\x82\x01R`$\x81\x01\x83\x90R\x90\x83\x16\x90c\t^\xA7\xB3\x90`D\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\t\xCFW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\t\xF3\x91\x90a\x19oV[P`@\x80Q`\xC0\x80\x82\x01\x83R` \x80\x89\x01Q\x83R`\x80\x80\x8A\x01Q\x91\x84\x01\x91\x90\x91R\x90\x88\x01Q\x82\x84\x01R`\xA0\x80\x89\x01Q`\x01`\x01`@\x1B\x03\x16``\x84\x01R`\0\x91\x83\x01\x82\x90R2\x90\x83\x01RT\x91Qc\xB8\xF3\xE8\xF5`\xE0\x1B\x81R\x90\x91`\x01`\x01`\xA0\x1B\x03\x16\x90c\xB8\xF3\xE8\xF5\x90a\nj\x90\x84\x90`\x04\x01a\x19\x91V[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\n\x89W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\n\xAD\x91\x90a\x18\xF9V[\x96\x95PPPPPPV[`\0`@Q\x80`\xC0\x01`@R\x80a\n\xCD\x84a\r\xA2V[\x81R` \x01`@Q\x80`@\x01`@R\x80`\x08\x81R` \x01g\x1A\\\xDB\\\x0BX\\\xDD`\xC2\x1B\x81RP\x81R` \x01`@Q\x80`@\x01`@R\x80`\x0E\x81R` \x01mhello from evm`\x90\x1B\x81RP\x81R` \x01`\0`\x01`\x01`@\x1B\x03\x16\x81R` \x01`\0\x81R` \x012`\x01`\x01`\xA0\x1B\x03\x16\x81RP\x90P`\0\x80T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xB8\xF3\xE8\xF5\x82`@Q\x82c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01a\x0B\x89\x91\x90a\x19\x91V[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x0B\xA8W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0B\xCC\x91\x90a\x18\xF9V[PPPV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x0B\xFCW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\xD7\xDC\x99\xAF\xB6\xC309\xCE\xA4PZ\x9E,\xAB4q\xD3Y\xCE\xBE\x02\x1E\xC1'\xDC\x94\xDD\xD3Y\xD3\xC5\x90`\0\x90\xA1PV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x0CSW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\xCB\xCB\xCAfM\xFE\xB9$\xCC\xD8P\xA0\x08h\x13\x0B\xFB\x1D\xF1W\t\x9A\x06\xF9)h\"\xCB{\xC3\xAD\x01\x90`\0\x90\xA1PV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x0C\xAAW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\xBB\xF4\x8AR\xB8>\xBC=\x9E9\xF0\x92\xA8\xB9\xB7\xE5o\x1D\xD0\xDCC\x8B\xEF@\xDC}\x92\x99Bp\xA5\x9F\x90`\0\x90\xA1PV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\r\x01W`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\x83\xE6 %\xE4\xBCXu\x16\xD0\xBC1^2\x9E\xAC\x0Cf6(T\xFE\xB7\xCDA5\xEF\x81C\xBA\x15\xF9\x90`\0\x90\xA1PV[`@\x80Q`\xA0\x80\x82\x01\x83R` \x80\x85\x01Q\x83R`\xC0\x85\x01Q`\x01`\x01`@\x1B\x03\x90\x81\x16\x91\x84\x01\x91\x90\x91R\x90\x84\x01Q\x82\x84\x01R`\x80\x80\x85\x01Q\x90\x91\x16``\x83\x01R3\x90\x82\x01R`\0\x80T\x92Qc47VA`\xE2\x1B\x81R\x90\x92`\x01`\x01`\xA0\x1B\x03\x16\x90c\xD0\xDDY\x04\x90a\x07\xBA\x90\x84\x90`\x04\x01a\x1BoV[``a\r\xAD\x82a\r\xD3V[`@Q` \x01a\r\xBD\x91\x90a\x1C2V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x90P\x91\x90PV[```\0a\r\xE0\x83a\x0EfV[`\x01\x01\x90P`\0\x81`\x01`\x01`@\x1B\x03\x81\x11\x15a\r\xFFWa\r\xFFa\x0F?V[`@Q\x90\x80\x82R\x80`\x1F\x01`\x1F\x19\x16` \x01\x82\x01`@R\x80\x15a\x0E)W` \x82\x01\x81\x806\x837\x01\x90P[P\x90P\x81\x81\x01` \x01[`\0\x19\x01o\x18\x18\x99\x19\x9A\x1A\x9B\x1B\x9C\x1C\xB0\xB11\xB22\xB3`\x81\x1B`\n\x86\x06\x1A\x81S`\n\x85\x04\x94P\x84a\x0E3W[P\x93\x92PPPV[`\0\x80r\x18O\x03\xE9?\xF9\xF4\xDA\xA7\x97\xEDn8\xEDd\xBFj\x1F\x01`@\x1B\x83\x10a\x0E\xA5Wr\x18O\x03\xE9?\xF9\xF4\xDA\xA7\x97\xEDn8\xEDd\xBFj\x1F\x01`@\x1B\x83\x04\x92P`@\x01[m\x04\xEE-mA[\x85\xAC\xEF\x81\0\0\0\0\x83\x10a\x0E\xD1Wm\x04\xEE-mA[\x85\xAC\xEF\x81\0\0\0\0\x83\x04\x92P` \x01[f#\x86\xF2o\xC1\0\0\x83\x10a\x0E\xEFWf#\x86\xF2o\xC1\0\0\x83\x04\x92P`\x10\x01[c\x05\xF5\xE1\0\x83\x10a\x0F\x07Wc\x05\xF5\xE1\0\x83\x04\x92P`\x08\x01[a'\x10\x83\x10a\x0F\x1BWa'\x10\x83\x04\x92P`\x04\x01[`d\x83\x10a\x0F-W`d\x83\x04\x92P`\x02\x01[`\n\x83\x10a\x0F9W`\x01\x01[\x92\x91PPV[cNH{q`\xE0\x1B`\0R`A`\x04R`$`\0\xFD[`@Q`\xE0\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x0FwWa\x0Fwa\x0F?V[`@R\x90V[`@\x80Q\x90\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x0FwWa\x0Fwa\x0F?V[`@Q`\xA0\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x0FwWa\x0Fwa\x0F?V[`@Q`\x1F\x82\x01`\x1F\x19\x16\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x0F\xE9Wa\x0F\xE9a\x0F?V[`@R\x91\x90PV[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\x10\nWa\x10\na\x0F?V[P`\x1F\x01`\x1F\x19\x16` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\x10)W`\0\x80\xFD[\x815a\x10\xCC}\x82\x1F!]\x82\x12B\xCB\xBE\x1F\x0E0\xA0\n\x85\xC2\"\xD6\x92\xA7\x96\x8F\xD3\xAF\xF1\x0B\x90`\0\x90\xA1PV[`\x01T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x02\x9AW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`\0\x80T`\x01`\x01`\xA0\x1B\x03\x19\x16`\x01`\x01`\xA0\x1B\x03\x92\x90\x92\x16\x91\x90\x91\x17\x90UV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x02\xE7W`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[\x80Q`\xC0\x01Q`@Q\x7F\xFB\x08{?\xFB\xBB\x0F\xC9\"\xDC\xCF\x87%\x08g\x1Av\x05\x85\x94#\xEB\x90\xEB\x01LV\xFD\xBA\x14\x84\xDC\x91a\x03\x1B\x91a\x1FdV[`@Q\x80\x91\x03\x90\xA1\x80Q\x80Q`\x02\x90\x81\x90a\x036\x90\x82a\x1F\xF7V[P` \x82\x01Q`\x01\x82\x01\x90a\x03K\x90\x82a\x1F\xF7V[P`@\x82\x01Q`\x02\x82\x01\x80Tg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16`\x01`\x01`@\x1B\x03\x90\x92\x16\x91\x90\x91\x17\x90U``\x82\x01Q`\x03\x82\x01\x90a\x03\x87\x90\x82a\x1F\xF7V[P`\x80\x82\x01Q`\x04\x82\x01\x90a\x03\x9C\x90\x82a\x1F\xF7V[P`\xA0\x82\x01Q`\x05\x82\x01\x80Tg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16`\x01`\x01`@\x1B\x03\x90\x92\x16\x91\x90\x91\x17\x90U`\xC0\x82\x01Q`\x06\x82\x01\x90a\x03\xD8\x90\x82a\x1F\xF7V[PPPPV[`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xF47\xBCY`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01`\0`@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x042W=`\0\x80>=`\0\xFD[PPPP`@Q=`\0\x82>`\x1F=\x90\x81\x01`\x1F\x19\x16\x82\x01`@Ra\x04Z\x91\x90\x81\x01\x90a \xB6V[`@Q` \x01a\x04j\x91\x90a!#V[`@\x80Q`\x1F\x19\x81\x84\x03\x01\x81R\x82\x82R`\0\x80Tcd\x1Dr\x9D`\xE0\x1B\x85R\x92Q\x91\x94P\x92`\x01`\x01`\xA0\x1B\x03\x90\x92\x16\x91cd\x1Dr\x9D\x91`\x04\x80\x83\x01\x92` \x92\x91\x90\x82\x90\x03\x01\x81\x86Z\xFA\x15\x80\x15a\x04\xC4W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x04\xE8\x91\x90a!VV[\x90P`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16cdxF\xA5`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x05>W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x05b\x91\x90a!oV[\x90P`\0\x84``\x01Q\x84Q\x84a\x05x\x91\x90a!\xA2V[\x86`\x80\x01Qa\x05\x87\x91\x90a!\xB9V[a\x05\x91\x91\x90a!\xA2V[`@Qc#\xB8r\xDD`\xE0\x1B\x81R3`\x04\x82\x01R0`$\x82\x01R`D\x81\x01\x82\x90R\x90\x91P`\x01`\x01`\xA0\x1B\x03\x83\x16\x90c#\xB8r\xDD\x90`d\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x05\xE7W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x06\x0B\x91\x90a!\xCCV[P`\0T`@Qc\t^\xA7\xB3`\xE0\x1B\x81R`\x01`\x01`\xA0\x1B\x03\x91\x82\x16`\x04\x82\x01R`$\x81\x01\x83\x90R\x90\x83\x16\x90c\t^\xA7\xB3\x90`D\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x06_W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x06\x83\x91\x90a!\xCCV[P`\0[\x85``\x01Q\x81\x10\x15a\x084W`\0`@Q\x80`\xC0\x01`@R\x80\x88`\0\x01Q\x81R` \x01\x88` \x01Q`@Q` \x01a\x06\xD7\x91\x90``\x91\x90\x91\x1Bk\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x81R`\x14\x01\x90V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x81R` \x01`\0\x80T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xF47\xBCY`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01`\0`@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x07=`\0\xFD[PPPP`@Q=`\0\x82>`\x1F=\x90\x81\x01`\x1F\x19\x16\x82\x01`@Ra\x07d\x91\x90\x81\x01\x90a \xB6V[`@Q` \x01a\x07t\x91\x90a!#V[`@\x80Q`\x1F\x19\x81\x84\x03\x01\x81R\x91\x81R\x90\x82R\x89\x81\x01Q`\x01`\x01`@\x1B\x03\x16` \x83\x01R`\x80\x8A\x01Q\x82\x82\x01R2``\x90\x92\x01\x91\x90\x91R`\0T\x90Qc\xB8\xF3\xE8\xF5`\xE0\x1B\x81R\x91\x92P`\x01`\x01`\xA0\x1B\x03\x16\x90c\xB8\xF3\xE8\xF5\x90a\x07\xDC\x90\x84\x90`\x04\x01a!\xEEV[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x07\xFBW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x08\x1F\x91\x90a!VV[PP\x80\x80a\x08,\x90a\"\x82V[\x91PPa\x06\x87V[PPPPPPV[`\0\x80T`@\x80Qcd\x1Dr\x9D`\xE0\x1B\x81R\x90Q\x83\x92`\x01`\x01`\xA0\x1B\x03\x16\x91cd\x1Dr\x9D\x91`\x04\x80\x83\x01\x92` \x92\x91\x90\x82\x90\x03\x01\x81\x86Z\xFA\x15\x80\x15a\x08\x86W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x08\xAA\x91\x90a!VV[\x90P`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16cdxF\xA5`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\t\0W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\t$\x91\x90a!oV[\x90P`\0\x84` \x01QQ\x83a\t9\x91\x90a!\xA2V[`@Qc#\xB8r\xDD`\xE0\x1B\x81R3`\x04\x82\x01R0`$\x82\x01R`D\x81\x01\x82\x90R\x90\x91P`\x01`\x01`\xA0\x1B\x03\x83\x16\x90c#\xB8r\xDD\x90`d\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\t\x8FW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\t\xB3\x91\x90a!\xCCV[P`\0T`@Qc\t^\xA7\xB3`\xE0\x1B\x81R`\x01`\x01`\xA0\x1B\x03\x91\x82\x16`\x04\x82\x01R`$\x81\x01\x83\x90R\x90\x83\x16\x90c\t^\xA7\xB3\x90`D\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\n\x07W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\n+\x91\x90a!\xCCV[P`@\x80Q`\xA0\x81\x01\x82R\x86Q\x81R` \x80\x88\x01Q\x90\x82\x01R\x86\x82\x01Q`\x01`\x01`@\x1B\x03\x16\x81\x83\x01R`\0``\x82\x01\x81\x90R2`\x80\x83\x01RT\x91Qc\x94H\x08\x05`\xE0\x1B\x81R\x90\x91`\x01`\x01`\xA0\x1B\x03\x16\x90c\x94H\x08\x05\x90a\n\x91\x90\x84\x90`\x04\x01a\"\x9BV[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\n\xB0W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\n\xD4\x91\x90a!VV[\x96\x95PPPPPPV[`\0\x80T`@\x80Qcd\x1Dr\x9D`\xE0\x1B\x81R\x90Q\x83\x92`\x01`\x01`\xA0\x1B\x03\x16\x91cd\x1Dr\x9D\x91`\x04\x80\x83\x01\x92` \x92\x91\x90\x82\x90\x03\x01\x81\x86Z\xFA\x15\x80\x15a\x0B(W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0BL\x91\x90a!VV[\x90P`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16cdxF\xA5`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x0B\xA2W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0B\xC6\x91\x90a!oV[\x90P`\0\x84`\xC0\x01QQ\x83a\x0B\xDB\x91\x90a!\xA2V[`@Qc#\xB8r\xDD`\xE0\x1B\x81R3`\x04\x82\x01R0`$\x82\x01R`D\x81\x01\x82\x90R\x90\x91P`\x01`\x01`\xA0\x1B\x03\x83\x16\x90c#\xB8r\xDD\x90`d\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x0C1W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0CU\x91\x90a!\xCCV[P`\0T`@Qc\t^\xA7\xB3`\xE0\x1B\x81R`\x01`\x01`\xA0\x1B\x03\x91\x82\x16`\x04\x82\x01R`$\x81\x01\x83\x90R\x90\x83\x16\x90c\t^\xA7\xB3\x90`D\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x0C\xA9W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0C\xCD\x91\x90a!\xCCV[P`@\x80Q`\xC0\x80\x82\x01\x83R` \x80\x89\x01Q\x83R`\x80\x80\x8A\x01Q\x91\x84\x01\x91\x90\x91R\x90\x88\x01Q\x82\x84\x01R`\xA0\x80\x89\x01Q`\x01`\x01`@\x1B\x03\x16``\x84\x01R`\0\x91\x83\x01\x82\x90R2\x90\x83\x01RT\x91Qc\xB8\xF3\xE8\xF5`\xE0\x1B\x81R\x90\x91`\x01`\x01`\xA0\x1B\x03\x16\x90c\xB8\xF3\xE8\xF5\x90a\n\x91\x90\x84\x90`\x04\x01a!\xEEV[`\0`@Q\x80`\xC0\x01`@R\x80a\rZ\x84a\x14\rV[\x81R` \x01`@Q\x80`@\x01`@R\x80`\x08\x81R` \x01g\x1A\\\xDB\\\x0BX\\\xDD`\xC2\x1B\x81RP\x81R` \x01`@Q\x80`@\x01`@R\x80`\x0E\x81R` \x01mhello from evm`\x90\x1B\x81RP\x81R` \x01`\0`\x01`\x01`@\x1B\x03\x16\x81R` \x01`\0\x81R` \x012`\x01`\x01`\xA0\x1B\x03\x16\x81RP\x90P`\0\x80T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xB8\xF3\xE8\xF5\x82`@Q\x82c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01a\x0E\x16\x91\x90a!\xEEV[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x0E5W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0EY\x91\x90a!VV[PPPV[a\x0E\xB0`@Q\x80`\xE0\x01`@R\x80``\x81R` \x01``\x81R` \x01`\0`\x01`\x01`@\x1B\x03\x16\x81R` \x01``\x81R` \x01``\x81R` \x01`\0`\x01`\x01`@\x1B\x03\x16\x81R` \x01``\x81RP\x90V[`\x02`@Q\x80`\xE0\x01`@R\x90\x81`\0\x82\x01\x80Ta\x0E\xCD\x90a\x1FwV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0E\xF9\x90a\x1FwV[\x80\x15a\x0FFW\x80`\x1F\x10a\x0F\x1BWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0FFV[\x82\x01\x91\x90`\0R` `\0 \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0F)W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81R` \x01`\x01\x82\x01\x80Ta\x0F_\x90a\x1FwV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0F\x8B\x90a\x1FwV[\x80\x15a\x0F\xD8W\x80`\x1F\x10a\x0F\xADWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0F\xD8V[\x82\x01\x91\x90`\0R` `\0 \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0F\xBBW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPP\x91\x83RPP`\x02\x82\x01T`\x01`\x01`@\x1B\x03\x16` \x82\x01R`\x03\x82\x01\x80T`@\x90\x92\x01\x91a\x10\x08\x90a\x1FwV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x104\x90a\x1FwV[\x80\x15a\x10\x81W\x80`\x1F\x10a\x10VWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x10\x81V[\x82\x01\x91\x90`\0R` `\0 \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x10dW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81R` \x01`\x04\x82\x01\x80Ta\x10\x9A\x90a\x1FwV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x10\xC6\x90a\x1FwV[\x80\x15a\x11\x13W\x80`\x1F\x10a\x10\xE8Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x11\x13V[\x82\x01\x91\x90`\0R` `\0 \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x10\xF6W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPP\x91\x83RPP`\x05\x82\x01T`\x01`\x01`@\x1B\x03\x16` \x82\x01R`\x06\x82\x01\x80T`@\x90\x92\x01\x91a\x11C\x90a\x1FwV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x11o\x90a\x1FwV[\x80\x15a\x11\xBCW\x80`\x1F\x10a\x11\x91Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x11\xBCV[\x82\x01\x91\x90`\0R` `\0 \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x11\x9FW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP\x90P\x90V[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x11\xF5W`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\xD7\xDC\x99\xAF\xB6\xC309\xCE\xA4PZ\x9E,\xAB4q\xD3Y\xCE\xBE\x02\x1E\xC1'\xDC\x94\xDD\xD3Y\xD3\xC5\x90`\0\x90\xA1PV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x12LW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\xCB\xCB\xCAfM\xFE\xB9$\xCC\xD8P\xA0\x08h\x13\x0B\xFB\x1D\xF1W\t\x9A\x06\xF9)h\"\xCB{\xC3\xAD\x01\x90`\0\x90\xA1PV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x12\xA3W`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\xBB\xF4\x8AR\xB8>\xBC=\x9E9\xF0\x92\xA8\xB9\xB7\xE5o\x1D\xD0\xDCC\x8B\xEF@\xDC}\x92\x99Bp\xA5\x9F\x90`\0\x90\xA1PV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x12\xFAW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\x83\xE6 %\xE4\xBCXu\x16\xD0\xBC1^2\x9E\xAC\x0Cf6(T\xFE\xB7\xCDA5\xEF\x81C\xBA\x15\xF9\x90`\0\x90\xA1PV[`\0\x80`@Q\x80`\xC0\x01`@R\x80\x84` \x01Q\x81R` \x01\x84`\xC0\x01Q`\x01`\x01`@\x1B\x03\x16\x81R` \x01\x84`\xA0\x01Q\x81R` \x01\x84`\x80\x01Q`\x01`\x01`@\x1B\x03\x16\x81R` \x013`\x01`\x01`\xA0\x1B\x03\x16\x81R` \x01`\0\x81RP\x90P`\0\x80T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xDA\xB0\xFE\xAE\x82`@Q\x82c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01a\x13\xC3\x91\x90a#\x10V[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x13\xE2W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x14\x06\x91\x90a!VV[\x93\x92PPPV[``a\x14\x18\x82a\x14>V[`@Q` \x01a\x14(\x91\x90a#\xE0V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x90P\x91\x90PV[```\0a\x14K\x83a\x14\xD0V[`\x01\x01\x90P`\0\x81`\x01`\x01`@\x1B\x03\x81\x11\x15a\x14jWa\x14ja\x15\xA9V[`@Q\x90\x80\x82R\x80`\x1F\x01`\x1F\x19\x16` \x01\x82\x01`@R\x80\x15a\x14\x94W` \x82\x01\x81\x806\x837\x01\x90P[P\x90P\x81\x81\x01` \x01[`\0\x19\x01o\x18\x18\x99\x19\x9A\x1A\x9B\x1B\x9C\x1C\xB0\xB11\xB22\xB3`\x81\x1B`\n\x86\x06\x1A\x81S`\n\x85\x04\x94P\x84a\x14\x9EWP\x93\x92PPPV[`\0\x80r\x18O\x03\xE9?\xF9\xF4\xDA\xA7\x97\xEDn8\xEDd\xBFj\x1F\x01`@\x1B\x83\x10a\x15\x0FWr\x18O\x03\xE9?\xF9\xF4\xDA\xA7\x97\xEDn8\xEDd\xBFj\x1F\x01`@\x1B\x83\x04\x92P`@\x01[m\x04\xEE-mA[\x85\xAC\xEF\x81\0\0\0\0\x83\x10a\x15;Wm\x04\xEE-mA[\x85\xAC\xEF\x81\0\0\0\0\x83\x04\x92P` \x01[f#\x86\xF2o\xC1\0\0\x83\x10a\x15YWf#\x86\xF2o\xC1\0\0\x83\x04\x92P`\x10\x01[c\x05\xF5\xE1\0\x83\x10a\x15qWc\x05\xF5\xE1\0\x83\x04\x92P`\x08\x01[a'\x10\x83\x10a\x15\x85Wa'\x10\x83\x04\x92P`\x04\x01[`d\x83\x10a\x15\x97W`d\x83\x04\x92P`\x02\x01[`\n\x83\x10a\x15\xA3W`\x01\x01[\x92\x91PPV[cNH{q`\xE0\x1B`\0R`A`\x04R`$`\0\xFD[`@Q`\xE0\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x15\xE1Wa\x15\xE1a\x15\xA9V[`@R\x90V[`@\x80Q\x90\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x15\xE1Wa\x15\xE1a\x15\xA9V[`@Q`\xA0\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x15\xE1Wa\x15\xE1a\x15\xA9V[`@Q`\x1F\x82\x01`\x1F\x19\x16\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x16SWa\x16Sa\x15\xA9V[`@R\x91\x90PV[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\x16tWa\x16ta\x15\xA9V[P`\x1F\x01`\x1F\x19\x16` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\x16\x93W`\0\x80\xFD[\x815a\x16\xA6a\x16\xA1\x82a\x16[V[a\x16+V[\x81\x81R\x84` \x83\x86\x01\x01\x11\x15a\x16\xBBW`\0\x80\xFD[\x81` \x85\x01` \x83\x017`\0\x91\x81\x01` \x01\x91\x90\x91R\x93\x92PPPV[\x805`\x01`\x01`@\x1B\x03\x81\x16\x81\x14a\x16\xEFW`\0\x80\xFD[\x91\x90PV[`\0`\xE0\x82\x84\x03\x12\x15a\x17\x06W`\0\x80\xFD[a\x17\x0Ea\x15\xBFV[\x90P\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x17'W`\0\x80\xFD[a\x173\x85\x83\x86\x01a\x16\x82V[\x83R` \x84\x015\x91P\x80\x82\x11\x15a\x17IW`\0\x80\xFD[a\x17U\x85\x83\x86\x01a\x16\x82V[` \x84\x01Ra\x17f`@\x85\x01a\x16\xD8V[`@\x84\x01R``\x84\x015\x91P\x80\x82\x11\x15a\x17\x7FW`\0\x80\xFD[a\x17\x8B\x85\x83\x86\x01a\x16\x82V[``\x84\x01R`\x80\x84\x015\x91P\x80\x82\x11\x15a\x17\xA4W`\0\x80\xFD[a\x17\xB0\x85\x83\x86\x01a\x16\x82V[`\x80\x84\x01Ra\x17\xC1`\xA0\x85\x01a\x16\xD8V[`\xA0\x84\x01R`\xC0\x84\x015\x91P\x80\x82\x11\x15a\x17\xDAW`\0\x80\xFD[Pa\x17\xE7\x84\x82\x85\x01a\x16\x82V[`\xC0\x83\x01RP\x92\x91PPV[`\0``\x82\x84\x03\x12\x15a\x18\x05W`\0\x80\xFD[`@Q``\x81\x01`\x01`\x01`@\x1B\x03\x82\x82\x10\x81\x83\x11\x17\x15a\x18(Wa\x18(a\x15\xA9V[\x81`@R\x82\x93P\x845\x91P\x80\x82\x11\x15a\x18@W`\0\x80\xFD[a\x18L\x86\x83\x87\x01a\x16\xF4V[\x83R` \x85\x015\x91P\x80\x82\x11\x15a\x18bW`\0\x80\xFD[Pa\x18o\x85\x82\x86\x01a\x16\x82V[` \x83\x01RPa\x18\x81`@\x84\x01a\x16\xD8V[`@\x82\x01RP\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x18\x9FW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\x18\xB5W`\0\x80\xFD[a\x18\xC1\x84\x82\x85\x01a\x17\xF3V[\x94\x93PPPPV[`\x01`\x01`\xA0\x1B\x03\x81\x16\x81\x14a\x18\xDEW`\0\x80\xFD[PV[\x805a\x16\xEF\x81a\x18\xC9V[`\0` \x82\x84\x03\x12\x15a\x18\xFEW`\0\x80\xFD[\x815a\x14\x06\x81a\x18\xC9V[`\0` \x82\x84\x03\x12\x15a\x19\x1BW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x192W`\0\x80\xFD[\x90\x83\x01\x90`@\x82\x86\x03\x12\x15a\x19FW`\0\x80\xFD[a\x19Na\x15\xE7V[\x825\x82\x81\x11\x15a\x19]W`\0\x80\xFD[a\x19i\x87\x82\x86\x01a\x16\xF4V[\x82RP` \x83\x015\x92Pa\x19|\x83a\x18\xC9V[` \x81\x01\x92\x90\x92RP\x93\x92PPPV[`\0` \x82\x84\x03\x12\x15a\x19\x9EW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x19\xB5W`\0\x80\xFD[\x90\x83\x01\x90`\xA0\x82\x86\x03\x12\x15a\x19\xC9W`\0\x80\xFD[a\x19\xD1a\x16\tV[\x825\x82\x81\x11\x15a\x19\xE0W`\0\x80\xFD[a\x19\xEC\x87\x82\x86\x01a\x16\x82V[\x82RP` \x83\x015\x91Pa\x19\xFF\x82a\x18\xC9V[\x81` \x82\x01Ra\x1A\x11`@\x84\x01a\x16\xD8V[`@\x82\x01R``\x83\x015``\x82\x01R`\x80\x83\x015`\x80\x82\x01R\x80\x93PPPP\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x1AHW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\x1A^W`\0\x80\xFD[a\x18\xC1\x84\x82\x85\x01a\x16\xF4V[`\0` \x82\x84\x03\x12\x15a\x1A|W`\0\x80\xFD[P5\x91\x90PV[`\0[\x83\x81\x10\x15a\x1A\x9EW\x81\x81\x01Q\x83\x82\x01R` \x01a\x1A\x86V[PP`\0\x91\x01RV[`\0\x81Q\x80\x84Ra\x1A\xBF\x81` \x86\x01` \x86\x01a\x1A\x83V[`\x1F\x01`\x1F\x19\x16\x92\x90\x92\x01` \x01\x92\x91PPV[`\0\x81Q`\xE0\x84Ra\x1A\xE8`\xE0\x85\x01\x82a\x1A\xA7V[\x90P` \x83\x01Q\x84\x82\x03` \x86\x01Ra\x1B\x01\x82\x82a\x1A\xA7V[\x91PP`@\x83\x01Q`\x01`\x01`@\x1B\x03\x80\x82\x16`@\x87\x01R``\x85\x01Q\x91P\x85\x83\x03``\x87\x01Ra\x1B2\x83\x83a\x1A\xA7V[\x92P`\x80\x85\x01Q\x91P\x85\x83\x03`\x80\x87\x01Ra\x1BM\x83\x83a\x1A\xA7V[\x92P\x80`\xA0\x86\x01Q\x16`\xA0\x87\x01RPP`\xC0\x83\x01Q\x84\x82\x03`\xC0\x86\x01Ra\x1Bt\x82\x82a\x1A\xA7V[\x95\x94PPPPPV[` \x81R`\0a\x14\x06` \x83\x01\x84a\x1A\xD3V[`\0` \x82\x84\x03\x12\x15a\x1B\xA2W`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x1B\xB9W`\0\x80\xFD[\x90\x83\x01\x90`@\x82\x86\x03\x12\x15a\x1B\xCDW`\0\x80\xFD[a\x1B\xD5a\x15\xE7V[\x825\x82\x81\x11\x15a\x1B\xE4W`\0\x80\xFD[a\x19i\x87\x82\x86\x01a\x17\xF3V[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\x1C\tWa\x1C\ta\x15\xA9V[P`\x05\x1B` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\x1C$W`\0\x80\xFD[\x815` a\x1C4a\x16\xA1\x83a\x1B\xF0V[\x82\x81R`\x05\x92\x90\x92\x1B\x84\x01\x81\x01\x91\x81\x81\x01\x90\x86\x84\x11\x15a\x1CSW`\0\x80\xFD[\x82\x86\x01[\x84\x81\x10\x15a\x1C\x92W\x805`\x01`\x01`@\x1B\x03\x81\x11\x15a\x1CvW`\0\x80\x81\xFD[a\x1C\x84\x89\x86\x83\x8B\x01\x01a\x16\x82V[\x84RP\x91\x83\x01\x91\x83\x01a\x1CWV[P\x96\x95PPPPPPV[`\0`\xE0\x82\x84\x03\x12\x15a\x1C\xAFW`\0\x80\xFD[a\x1C\xB7a\x15\xBFV[\x90P\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x1C\xD0W`\0\x80\xFD[a\x1C\xDC\x85\x83\x86\x01a\x16\x82V[\x83R` \x84\x015\x91P\x80\x82\x11\x15a\x1C\xF2W`\0\x80\xFD[a\x1C\xFE\x85\x83\x86\x01a\x16\x82V[` \x84\x01Ra\x1D\x0F`@\x85\x01a\x16\xD8V[`@\x84\x01R``\x84\x015\x91P\x80\x82\x11\x15a\x1D(W`\0\x80\xFD[a\x1D4\x85\x83\x86\x01a\x16\x82V[``\x84\x01Ra\x1DE`\x80\x85\x01a\x16\xD8V[`\x80\x84\x01R`\xA0\x84\x015\x91P\x80\x82\x11\x15a\x1D^W`\0\x80\xFD[Pa\x1Dk\x84\x82\x85\x01a\x1C\x13V[`\xA0\x83\x01RPa\x1D}`\xC0\x83\x01a\x16\xD8V[`\xC0\x82\x01R\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x1D\x9AW`\0\x80\xFD[`\x01`\x01`@\x1B\x03\x80\x835\x11\x15a\x1D\xB0W`\0\x80\xFD[\x825\x83\x01`@\x81\x86\x03\x12\x15a\x1D\xC4W`\0\x80\xFD[a\x1D\xCCa\x15\xE7V[\x82\x825\x11\x15a\x1D\xDAW`\0\x80\xFD[\x815\x82\x01`@\x81\x88\x03\x12\x15a\x1D\xEEW`\0\x80\xFD[a\x1D\xF6a\x15\xE7V[\x84\x825\x11\x15a\x1E\x04W`\0\x80\xFD[a\x1E\x11\x88\x835\x84\x01a\x1C\x9DV[\x81R\x84` \x83\x015\x11\x15a\x1E$W`\0\x80\xFD[` \x82\x015\x82\x01\x91P\x87`\x1F\x83\x01\x12a\x1E\xCC}\x82\x1F!]\x82\x12B\xCB\xBE\x1F\x0E0\xA0\n\x85\xC2\"\xD6\x92\xA7\x96\x8F\xD3\xAF\xF1\x0B\x90`\0\x90\xA1PV[`\x01T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x02jW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`\0\x80T`\x01`\x01`\xA0\x1B\x03\x19\x16`\x01`\x01`\xA0\x1B\x03\x92\x90\x92\x16\x91\x90\x91\x17\x90UV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x02\xB7W`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[\x80Q`\xC0\x01Q`@Q\x7F\xFB\x08{?\xFB\xBB\x0F\xC9\"\xDC\xCF\x87%\x08g\x1Av\x05\x85\x94#\xEB\x90\xEB\x01LV\xFD\xBA\x14\x84\xDC\x91a\x02\xEB\x91a\x18=V[`@Q\x80\x91\x03\x90\xA1PV[`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xF47\xBCY`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01`\0`@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x03JW=`\0\x80>=`\0\xFD[PPPP`@Q=`\0\x82>`\x1F=\x90\x81\x01`\x1F\x19\x16\x82\x01`@Ra\x03r\x91\x90\x81\x01\x90a\x18PV[`@Q` \x01a\x03\x82\x91\x90a\x18\xC6V[`@\x80Q`\x1F\x19\x81\x84\x03\x01\x81R\x82\x82R`\0\x80Tcd\x1Dr\x9D`\xE0\x1B\x85R\x92Q\x91\x94P\x92`\x01`\x01`\xA0\x1B\x03\x90\x92\x16\x91cd\x1Dr\x9D\x91`\x04\x80\x83\x01\x92` \x92\x91\x90\x82\x90\x03\x01\x81\x86Z\xFA\x15\x80\x15a\x03\xDCW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x04\0\x91\x90a\x18\xF9V[\x90P`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16cdxF\xA5`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x04VW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x04z\x91\x90a\x19\x12V[\x90P`\0\x84``\x01Q\x84Q\x84a\x04\x90\x91\x90a\x19EV[\x86`\x80\x01Qa\x04\x9F\x91\x90a\x19\\V[a\x04\xA9\x91\x90a\x19EV[`@Qc#\xB8r\xDD`\xE0\x1B\x81R3`\x04\x82\x01R0`$\x82\x01R`D\x81\x01\x82\x90R\x90\x91P`\x01`\x01`\xA0\x1B\x03\x83\x16\x90c#\xB8r\xDD\x90`d\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x04\xFFW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x05#\x91\x90a\x19oV[P`\0T`@Qc\t^\xA7\xB3`\xE0\x1B\x81R`\x01`\x01`\xA0\x1B\x03\x91\x82\x16`\x04\x82\x01R`$\x81\x01\x83\x90R\x90\x83\x16\x90c\t^\xA7\xB3\x90`D\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x05wW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x05\x9B\x91\x90a\x19oV[P`\0[\x85``\x01Q\x81\x10\x15a\x07LW`\0`@Q\x80`\xC0\x01`@R\x80\x88`\0\x01Q\x81R` \x01\x88` \x01Q`@Q` \x01a\x05\xEF\x91\x90``\x91\x90\x91\x1Bk\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x81R`\x14\x01\x90V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x81R` \x01`\0\x80T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xF47\xBCY`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01`\0`@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x06TW=`\0\x80>=`\0\xFD[PPPP`@Q=`\0\x82>`\x1F=\x90\x81\x01`\x1F\x19\x16\x82\x01`@Ra\x06|\x91\x90\x81\x01\x90a\x18PV[`@Q` \x01a\x06\x8C\x91\x90a\x18\xC6V[`@\x80Q`\x1F\x19\x81\x84\x03\x01\x81R\x91\x81R\x90\x82R\x89\x81\x01Q`\x01`\x01`@\x1B\x03\x16` \x83\x01R`\x80\x8A\x01Q\x82\x82\x01R2``\x90\x92\x01\x91\x90\x91R`\0T\x90Qc\xB8\xF3\xE8\xF5`\xE0\x1B\x81R\x91\x92P`\x01`\x01`\xA0\x1B\x03\x16\x90c\xB8\xF3\xE8\xF5\x90a\x06\xF4\x90\x84\x90`\x04\x01a\x19\x91V[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x07\x13W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x077\x91\x90a\x18\xF9V[PP\x80\x80a\x07D\x90a\x1A%V[\x91PPa\x05\x9FV[PPPPPPV[`@\x80Q`\xA0\x81\x01\x82R\x82Q\x81R` \x80\x84\x01Q\x90\x82\x01R\x82\x82\x01Q`\x01`\x01`@\x1B\x03\x16\x81\x83\x01R`\0``\x82\x01\x81\x90R2`\x80\x83\x01R\x80T\x92Qc\x94H\x08\x05`\xE0\x1B\x81R\x90\x92`\x01`\x01`\xA0\x1B\x03\x16\x90c\x94H\x08\x05\x90a\x07\xBA\x90\x84\x90`\x04\x01a\x1A>V[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x07\xD9W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x07\xFD\x91\x90a\x18\xF9V[\x93\x92PPPV[`\0\x80T`@\x80Qcd\x1Dr\x9D`\xE0\x1B\x81R\x90Q\x83\x92`\x01`\x01`\xA0\x1B\x03\x16\x91cd\x1Dr\x9D\x91`\x04\x80\x83\x01\x92` \x92\x91\x90\x82\x90\x03\x01\x81\x86Z\xFA\x15\x80\x15a\x08NW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x08r\x91\x90a\x18\xF9V[\x90P`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16cdxF\xA5`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x08\xC8W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x08\xEC\x91\x90a\x19\x12V[\x90P`\0\x84`\xC0\x01QQ\x83a\t\x01\x91\x90a\x19EV[`@Qc#\xB8r\xDD`\xE0\x1B\x81R3`\x04\x82\x01R0`$\x82\x01R`D\x81\x01\x82\x90R\x90\x91P`\x01`\x01`\xA0\x1B\x03\x83\x16\x90c#\xB8r\xDD\x90`d\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\tWW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\t{\x91\x90a\x19oV[P`\0T`@Qc\t^\xA7\xB3`\xE0\x1B\x81R`\x01`\x01`\xA0\x1B\x03\x91\x82\x16`\x04\x82\x01R`$\x81\x01\x83\x90R\x90\x83\x16\x90c\t^\xA7\xB3\x90`D\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\t\xCFW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\t\xF3\x91\x90a\x19oV[P`@\x80Q`\xC0\x80\x82\x01\x83R` \x80\x89\x01Q\x83R`\x80\x80\x8A\x01Q\x91\x84\x01\x91\x90\x91R\x90\x88\x01Q\x82\x84\x01R`\xA0\x80\x89\x01Q`\x01`\x01`@\x1B\x03\x16``\x84\x01R`\0\x91\x83\x01\x82\x90R2\x90\x83\x01RT\x91Qc\xB8\xF3\xE8\xF5`\xE0\x1B\x81R\x90\x91`\x01`\x01`\xA0\x1B\x03\x16\x90c\xB8\xF3\xE8\xF5\x90a\nj\x90\x84\x90`\x04\x01a\x19\x91V[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\n\x89W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\n\xAD\x91\x90a\x18\xF9V[\x96\x95PPPPPPV[`\0`@Q\x80`\xC0\x01`@R\x80a\n\xCD\x84a\r\xA2V[\x81R` \x01`@Q\x80`@\x01`@R\x80`\x08\x81R` \x01g\x1A\\\xDB\\\x0BX\\\xDD`\xC2\x1B\x81RP\x81R` \x01`@Q\x80`@\x01`@R\x80`\x0E\x81R` \x01mhello from evm`\x90\x1B\x81RP\x81R` \x01`\0`\x01`\x01`@\x1B\x03\x16\x81R` \x01`\0\x81R` \x012`\x01`\x01`\xA0\x1B\x03\x16\x81RP\x90P`\0\x80T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xB8\xF3\xE8\xF5\x82`@Q\x82c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01a\x0B\x89\x91\x90a\x19\x91V[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x0B\xA8W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0B\xCC\x91\x90a\x18\xF9V[PPPV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x0B\xFCW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\xD7\xDC\x99\xAF\xB6\xC309\xCE\xA4PZ\x9E,\xAB4q\xD3Y\xCE\xBE\x02\x1E\xC1'\xDC\x94\xDD\xD3Y\xD3\xC5\x90`\0\x90\xA1PV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x0CSW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\xCB\xCB\xCAfM\xFE\xB9$\xCC\xD8P\xA0\x08h\x13\x0B\xFB\x1D\xF1W\t\x9A\x06\xF9)h\"\xCB{\xC3\xAD\x01\x90`\0\x90\xA1PV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x0C\xAAW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\xBB\xF4\x8AR\xB8>\xBC=\x9E9\xF0\x92\xA8\xB9\xB7\xE5o\x1D\xD0\xDCC\x8B\xEF@\xDC}\x92\x99Bp\xA5\x9F\x90`\0\x90\xA1PV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\r\x01W`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\x83\xE6 %\xE4\xBCXu\x16\xD0\xBC1^2\x9E\xAC\x0Cf6(T\xFE\xB7\xCDA5\xEF\x81C\xBA\x15\xF9\x90`\0\x90\xA1PV[`@\x80Q`\xA0\x80\x82\x01\x83R` \x80\x85\x01Q\x83R`\xC0\x85\x01Q`\x01`\x01`@\x1B\x03\x90\x81\x16\x91\x84\x01\x91\x90\x91R\x90\x84\x01Q\x82\x84\x01R`\x80\x80\x85\x01Q\x90\x91\x16``\x83\x01R3\x90\x82\x01R`\0\x80T\x92Qc47VA`\xE2\x1B\x81R\x90\x92`\x01`\x01`\xA0\x1B\x03\x16\x90c\xD0\xDDY\x04\x90a\x07\xBA\x90\x84\x90`\x04\x01a\x1BoV[``a\r\xAD\x82a\r\xD3V[`@Q` \x01a\r\xBD\x91\x90a\x1C2V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x90P\x91\x90PV[```\0a\r\xE0\x83a\x0EfV[`\x01\x01\x90P`\0\x81`\x01`\x01`@\x1B\x03\x81\x11\x15a\r\xFFWa\r\xFFa\x0F?V[`@Q\x90\x80\x82R\x80`\x1F\x01`\x1F\x19\x16` \x01\x82\x01`@R\x80\x15a\x0E)W` \x82\x01\x81\x806\x837\x01\x90P[P\x90P\x81\x81\x01` \x01[`\0\x19\x01o\x18\x18\x99\x19\x9A\x1A\x9B\x1B\x9C\x1C\xB0\xB11\xB22\xB3`\x81\x1B`\n\x86\x06\x1A\x81S`\n\x85\x04\x94P\x84a\x0E3W[P\x93\x92PPPV[`\0\x80r\x18O\x03\xE9?\xF9\xF4\xDA\xA7\x97\xEDn8\xEDd\xBFj\x1F\x01`@\x1B\x83\x10a\x0E\xA5Wr\x18O\x03\xE9?\xF9\xF4\xDA\xA7\x97\xEDn8\xEDd\xBFj\x1F\x01`@\x1B\x83\x04\x92P`@\x01[m\x04\xEE-mA[\x85\xAC\xEF\x81\0\0\0\0\x83\x10a\x0E\xD1Wm\x04\xEE-mA[\x85\xAC\xEF\x81\0\0\0\0\x83\x04\x92P` \x01[f#\x86\xF2o\xC1\0\0\x83\x10a\x0E\xEFWf#\x86\xF2o\xC1\0\0\x83\x04\x92P`\x10\x01[c\x05\xF5\xE1\0\x83\x10a\x0F\x07Wc\x05\xF5\xE1\0\x83\x04\x92P`\x08\x01[a'\x10\x83\x10a\x0F\x1BWa'\x10\x83\x04\x92P`\x04\x01[`d\x83\x10a\x0F-W`d\x83\x04\x92P`\x02\x01[`\n\x83\x10a\x0F9W`\x01\x01[\x92\x91PPV[cNH{q`\xE0\x1B`\0R`A`\x04R`$`\0\xFD[`@Q`\xE0\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x0FwWa\x0Fwa\x0F?V[`@R\x90V[`@\x80Q\x90\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x0FwWa\x0Fwa\x0F?V[`@Q`\xA0\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x0FwWa\x0Fwa\x0F?V[`@Q`\x1F\x82\x01`\x1F\x19\x16\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x0F\xE9Wa\x0F\xE9a\x0F?V[`@R\x91\x90PV[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\x10\nWa\x10\na\x0F?V[P`\x1F\x01`\x1F\x19\x16` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\x10)W`\0\x80\xFD[\x815a\x10\xCC}\x82\x1F!]\x82\x12B\xCB\xBE\x1F\x0E0\xA0\n\x85\xC2\"\xD6\x92\xA7\x96\x8F\xD3\xAF\xF1\x0B\x90`\0\x90\xA1PV[`\x01T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x02\x9AW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`\0\x80T`\x01`\x01`\xA0\x1B\x03\x19\x16`\x01`\x01`\xA0\x1B\x03\x92\x90\x92\x16\x91\x90\x91\x17\x90UV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x02\xE7W`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[\x80Q`\xC0\x01Q`@Q\x7F\xFB\x08{?\xFB\xBB\x0F\xC9\"\xDC\xCF\x87%\x08g\x1Av\x05\x85\x94#\xEB\x90\xEB\x01LV\xFD\xBA\x14\x84\xDC\x91a\x03\x1B\x91a\x1FdV[`@Q\x80\x91\x03\x90\xA1\x80Q\x80Q`\x02\x90\x81\x90a\x036\x90\x82a\x1F\xF7V[P` \x82\x01Q`\x01\x82\x01\x90a\x03K\x90\x82a\x1F\xF7V[P`@\x82\x01Q`\x02\x82\x01\x80Tg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16`\x01`\x01`@\x1B\x03\x90\x92\x16\x91\x90\x91\x17\x90U``\x82\x01Q`\x03\x82\x01\x90a\x03\x87\x90\x82a\x1F\xF7V[P`\x80\x82\x01Q`\x04\x82\x01\x90a\x03\x9C\x90\x82a\x1F\xF7V[P`\xA0\x82\x01Q`\x05\x82\x01\x80Tg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16`\x01`\x01`@\x1B\x03\x90\x92\x16\x91\x90\x91\x17\x90U`\xC0\x82\x01Q`\x06\x82\x01\x90a\x03\xD8\x90\x82a\x1F\xF7V[PPPPV[`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xF47\xBCY`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01`\0`@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x042W=`\0\x80>=`\0\xFD[PPPP`@Q=`\0\x82>`\x1F=\x90\x81\x01`\x1F\x19\x16\x82\x01`@Ra\x04Z\x91\x90\x81\x01\x90a \xB6V[`@Q` \x01a\x04j\x91\x90a!#V[`@\x80Q`\x1F\x19\x81\x84\x03\x01\x81R\x82\x82R`\0\x80Tcd\x1Dr\x9D`\xE0\x1B\x85R\x92Q\x91\x94P\x92`\x01`\x01`\xA0\x1B\x03\x90\x92\x16\x91cd\x1Dr\x9D\x91`\x04\x80\x83\x01\x92` \x92\x91\x90\x82\x90\x03\x01\x81\x86Z\xFA\x15\x80\x15a\x04\xC4W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x04\xE8\x91\x90a!VV[\x90P`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16cdxF\xA5`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x05>W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x05b\x91\x90a!oV[\x90P`\0\x84``\x01Q\x84Q\x84a\x05x\x91\x90a!\xA2V[\x86`\x80\x01Qa\x05\x87\x91\x90a!\xB9V[a\x05\x91\x91\x90a!\xA2V[`@Qc#\xB8r\xDD`\xE0\x1B\x81R3`\x04\x82\x01R0`$\x82\x01R`D\x81\x01\x82\x90R\x90\x91P`\x01`\x01`\xA0\x1B\x03\x83\x16\x90c#\xB8r\xDD\x90`d\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x05\xE7W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x06\x0B\x91\x90a!\xCCV[P`\0T`@Qc\t^\xA7\xB3`\xE0\x1B\x81R`\x01`\x01`\xA0\x1B\x03\x91\x82\x16`\x04\x82\x01R`$\x81\x01\x83\x90R\x90\x83\x16\x90c\t^\xA7\xB3\x90`D\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x06_W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x06\x83\x91\x90a!\xCCV[P`\0[\x85``\x01Q\x81\x10\x15a\x084W`\0`@Q\x80`\xC0\x01`@R\x80\x88`\0\x01Q\x81R` \x01\x88` \x01Q`@Q` \x01a\x06\xD7\x91\x90``\x91\x90\x91\x1Bk\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x81R`\x14\x01\x90V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x81R` \x01`\0\x80T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xF47\xBCY`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01`\0`@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x07=`\0\xFD[PPPP`@Q=`\0\x82>`\x1F=\x90\x81\x01`\x1F\x19\x16\x82\x01`@Ra\x07d\x91\x90\x81\x01\x90a \xB6V[`@Q` \x01a\x07t\x91\x90a!#V[`@\x80Q`\x1F\x19\x81\x84\x03\x01\x81R\x91\x81R\x90\x82R\x89\x81\x01Q`\x01`\x01`@\x1B\x03\x16` \x83\x01R`\x80\x8A\x01Q\x82\x82\x01R2``\x90\x92\x01\x91\x90\x91R`\0T\x90Qc\xB8\xF3\xE8\xF5`\xE0\x1B\x81R\x91\x92P`\x01`\x01`\xA0\x1B\x03\x16\x90c\xB8\xF3\xE8\xF5\x90a\x07\xDC\x90\x84\x90`\x04\x01a!\xEEV[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x07\xFBW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x08\x1F\x91\x90a!VV[PP\x80\x80a\x08,\x90a\"\x82V[\x91PPa\x06\x87V[PPPPPPV[`\0\x80T`@\x80Qcd\x1Dr\x9D`\xE0\x1B\x81R\x90Q\x83\x92`\x01`\x01`\xA0\x1B\x03\x16\x91cd\x1Dr\x9D\x91`\x04\x80\x83\x01\x92` \x92\x91\x90\x82\x90\x03\x01\x81\x86Z\xFA\x15\x80\x15a\x08\x86W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x08\xAA\x91\x90a!VV[\x90P`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16cdxF\xA5`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\t\0W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\t$\x91\x90a!oV[\x90P`\0\x84` \x01QQ\x83a\t9\x91\x90a!\xA2V[`@Qc#\xB8r\xDD`\xE0\x1B\x81R3`\x04\x82\x01R0`$\x82\x01R`D\x81\x01\x82\x90R\x90\x91P`\x01`\x01`\xA0\x1B\x03\x83\x16\x90c#\xB8r\xDD\x90`d\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\t\x8FW=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\t\xB3\x91\x90a!\xCCV[P`\0T`@Qc\t^\xA7\xB3`\xE0\x1B\x81R`\x01`\x01`\xA0\x1B\x03\x91\x82\x16`\x04\x82\x01R`$\x81\x01\x83\x90R\x90\x83\x16\x90c\t^\xA7\xB3\x90`D\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\n\x07W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\n+\x91\x90a!\xCCV[P`@\x80Q`\xA0\x81\x01\x82R\x86Q\x81R` \x80\x88\x01Q\x90\x82\x01R\x86\x82\x01Q`\x01`\x01`@\x1B\x03\x16\x81\x83\x01R`\0``\x82\x01\x81\x90R2`\x80\x83\x01RT\x91Qc\x94H\x08\x05`\xE0\x1B\x81R\x90\x91`\x01`\x01`\xA0\x1B\x03\x16\x90c\x94H\x08\x05\x90a\n\x91\x90\x84\x90`\x04\x01a\"\x9BV[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\n\xB0W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\n\xD4\x91\x90a!VV[\x96\x95PPPPPPV[`\0\x80T`@\x80Qcd\x1Dr\x9D`\xE0\x1B\x81R\x90Q\x83\x92`\x01`\x01`\xA0\x1B\x03\x16\x91cd\x1Dr\x9D\x91`\x04\x80\x83\x01\x92` \x92\x91\x90\x82\x90\x03\x01\x81\x86Z\xFA\x15\x80\x15a\x0B(W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0BL\x91\x90a!VV[\x90P`\0\x80`\0\x90T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16cdxF\xA5`@Q\x81c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01` `@Q\x80\x83\x03\x81\x86Z\xFA\x15\x80\x15a\x0B\xA2W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0B\xC6\x91\x90a!oV[\x90P`\0\x84`\xC0\x01QQ\x83a\x0B\xDB\x91\x90a!\xA2V[`@Qc#\xB8r\xDD`\xE0\x1B\x81R3`\x04\x82\x01R0`$\x82\x01R`D\x81\x01\x82\x90R\x90\x91P`\x01`\x01`\xA0\x1B\x03\x83\x16\x90c#\xB8r\xDD\x90`d\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x0C1W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0CU\x91\x90a!\xCCV[P`\0T`@Qc\t^\xA7\xB3`\xE0\x1B\x81R`\x01`\x01`\xA0\x1B\x03\x91\x82\x16`\x04\x82\x01R`$\x81\x01\x83\x90R\x90\x83\x16\x90c\t^\xA7\xB3\x90`D\x01` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x0C\xA9W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0C\xCD\x91\x90a!\xCCV[P`@\x80Q`\xC0\x80\x82\x01\x83R` \x80\x89\x01Q\x83R`\x80\x80\x8A\x01Q\x91\x84\x01\x91\x90\x91R\x90\x88\x01Q\x82\x84\x01R`\xA0\x80\x89\x01Q`\x01`\x01`@\x1B\x03\x16``\x84\x01R`\0\x91\x83\x01\x82\x90R2\x90\x83\x01RT\x91Qc\xB8\xF3\xE8\xF5`\xE0\x1B\x81R\x90\x91`\x01`\x01`\xA0\x1B\x03\x16\x90c\xB8\xF3\xE8\xF5\x90a\n\x91\x90\x84\x90`\x04\x01a!\xEEV[`\0`@Q\x80`\xC0\x01`@R\x80a\rZ\x84a\x14\rV[\x81R` \x01`@Q\x80`@\x01`@R\x80`\x08\x81R` \x01g\x1A\\\xDB\\\x0BX\\\xDD`\xC2\x1B\x81RP\x81R` \x01`@Q\x80`@\x01`@R\x80`\x0E\x81R` \x01mhello from evm`\x90\x1B\x81RP\x81R` \x01`\0`\x01`\x01`@\x1B\x03\x16\x81R` \x01`\0\x81R` \x012`\x01`\x01`\xA0\x1B\x03\x16\x81RP\x90P`\0\x80T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xB8\xF3\xE8\xF5\x82`@Q\x82c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01a\x0E\x16\x91\x90a!\xEEV[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x0E5W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x0EY\x91\x90a!VV[PPPV[a\x0E\xB0`@Q\x80`\xE0\x01`@R\x80``\x81R` \x01``\x81R` \x01`\0`\x01`\x01`@\x1B\x03\x16\x81R` \x01``\x81R` \x01``\x81R` \x01`\0`\x01`\x01`@\x1B\x03\x16\x81R` \x01``\x81RP\x90V[`\x02`@Q\x80`\xE0\x01`@R\x90\x81`\0\x82\x01\x80Ta\x0E\xCD\x90a\x1FwV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0E\xF9\x90a\x1FwV[\x80\x15a\x0FFW\x80`\x1F\x10a\x0F\x1BWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0FFV[\x82\x01\x91\x90`\0R` `\0 \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0F)W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81R` \x01`\x01\x82\x01\x80Ta\x0F_\x90a\x1FwV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x0F\x8B\x90a\x1FwV[\x80\x15a\x0F\xD8W\x80`\x1F\x10a\x0F\xADWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x0F\xD8V[\x82\x01\x91\x90`\0R` `\0 \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x0F\xBBW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPP\x91\x83RPP`\x02\x82\x01T`\x01`\x01`@\x1B\x03\x16` \x82\x01R`\x03\x82\x01\x80T`@\x90\x92\x01\x91a\x10\x08\x90a\x1FwV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x104\x90a\x1FwV[\x80\x15a\x10\x81W\x80`\x1F\x10a\x10VWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x10\x81V[\x82\x01\x91\x90`\0R` `\0 \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x10dW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81R` \x01`\x04\x82\x01\x80Ta\x10\x9A\x90a\x1FwV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x10\xC6\x90a\x1FwV[\x80\x15a\x11\x13W\x80`\x1F\x10a\x10\xE8Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x11\x13V[\x82\x01\x91\x90`\0R` `\0 \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x10\xF6W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPP\x91\x83RPP`\x05\x82\x01T`\x01`\x01`@\x1B\x03\x16` \x82\x01R`\x06\x82\x01\x80T`@\x90\x92\x01\x91a\x11C\x90a\x1FwV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x11o\x90a\x1FwV[\x80\x15a\x11\xBCW\x80`\x1F\x10a\x11\x91Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x11\xBCV[\x82\x01\x91\x90`\0R` `\0 \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x11\x9FW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x81RPP\x90P\x90V[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x11\xF5W`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\xD7\xDC\x99\xAF\xB6\xC309\xCE\xA4PZ\x9E,\xAB4q\xD3Y\xCE\xBE\x02\x1E\xC1'\xDC\x94\xDD\xD3Y\xD3\xC5\x90`\0\x90\xA1PV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x12LW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\xCB\xCB\xCAfM\xFE\xB9$\xCC\xD8P\xA0\x08h\x13\x0B\xFB\x1D\xF1W\t\x9A\x06\xF9)h\"\xCB{\xC3\xAD\x01\x90`\0\x90\xA1PV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x12\xA3W`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\xBB\xF4\x8AR\xB8>\xBC=\x9E9\xF0\x92\xA8\xB9\xB7\xE5o\x1D\xD0\xDCC\x8B\xEF@\xDC}\x92\x99Bp\xA5\x9F\x90`\0\x90\xA1PV[`\0T`\x01`\x01`\xA0\x1B\x03\x163\x14a\x12\xFAW`@QcQ\xAB\x8D\xE5`\xE0\x1B\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[`@Q\x7F\x83\xE6 %\xE4\xBCXu\x16\xD0\xBC1^2\x9E\xAC\x0Cf6(T\xFE\xB7\xCDA5\xEF\x81C\xBA\x15\xF9\x90`\0\x90\xA1PV[`\0\x80`@Q\x80`\xC0\x01`@R\x80\x84` \x01Q\x81R` \x01\x84`\xC0\x01Q`\x01`\x01`@\x1B\x03\x16\x81R` \x01\x84`\xA0\x01Q\x81R` \x01\x84`\x80\x01Q`\x01`\x01`@\x1B\x03\x16\x81R` \x013`\x01`\x01`\xA0\x1B\x03\x16\x81R` \x01`\0\x81RP\x90P`\0\x80T\x90a\x01\0\n\x90\x04`\x01`\x01`\xA0\x1B\x03\x16`\x01`\x01`\xA0\x1B\x03\x16c\xDA\xB0\xFE\xAE\x82`@Q\x82c\xFF\xFF\xFF\xFF\x16`\xE0\x1B\x81R`\x04\x01a\x13\xC3\x91\x90a#\x10V[` `@Q\x80\x83\x03\x81`\0\x87Z\xF1\x15\x80\x15a\x13\xE2W=`\0\x80>=`\0\xFD[PPPP`@Q=`\x1F\x19`\x1F\x82\x01\x16\x82\x01\x80`@RP\x81\x01\x90a\x14\x06\x91\x90a!VV[\x93\x92PPPV[``a\x14\x18\x82a\x14>V[`@Q` \x01a\x14(\x91\x90a#\xE0V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x90P\x91\x90PV[```\0a\x14K\x83a\x14\xD0V[`\x01\x01\x90P`\0\x81`\x01`\x01`@\x1B\x03\x81\x11\x15a\x14jWa\x14ja\x15\xA9V[`@Q\x90\x80\x82R\x80`\x1F\x01`\x1F\x19\x16` \x01\x82\x01`@R\x80\x15a\x14\x94W` \x82\x01\x81\x806\x837\x01\x90P[P\x90P\x81\x81\x01` \x01[`\0\x19\x01o\x18\x18\x99\x19\x9A\x1A\x9B\x1B\x9C\x1C\xB0\xB11\xB22\xB3`\x81\x1B`\n\x86\x06\x1A\x81S`\n\x85\x04\x94P\x84a\x14\x9EWP\x93\x92PPPV[`\0\x80r\x18O\x03\xE9?\xF9\xF4\xDA\xA7\x97\xEDn8\xEDd\xBFj\x1F\x01`@\x1B\x83\x10a\x15\x0FWr\x18O\x03\xE9?\xF9\xF4\xDA\xA7\x97\xEDn8\xEDd\xBFj\x1F\x01`@\x1B\x83\x04\x92P`@\x01[m\x04\xEE-mA[\x85\xAC\xEF\x81\0\0\0\0\x83\x10a\x15;Wm\x04\xEE-mA[\x85\xAC\xEF\x81\0\0\0\0\x83\x04\x92P` \x01[f#\x86\xF2o\xC1\0\0\x83\x10a\x15YWf#\x86\xF2o\xC1\0\0\x83\x04\x92P`\x10\x01[c\x05\xF5\xE1\0\x83\x10a\x15qWc\x05\xF5\xE1\0\x83\x04\x92P`\x08\x01[a'\x10\x83\x10a\x15\x85Wa'\x10\x83\x04\x92P`\x04\x01[`d\x83\x10a\x15\x97W`d\x83\x04\x92P`\x02\x01[`\n\x83\x10a\x15\xA3W`\x01\x01[\x92\x91PPV[cNH{q`\xE0\x1B`\0R`A`\x04R`$`\0\xFD[`@Q`\xE0\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x15\xE1Wa\x15\xE1a\x15\xA9V[`@R\x90V[`@\x80Q\x90\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x15\xE1Wa\x15\xE1a\x15\xA9V[`@Q`\xA0\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x15\xE1Wa\x15\xE1a\x15\xA9V[`@Q`\x1F\x82\x01`\x1F\x19\x16\x81\x01`\x01`\x01`@\x1B\x03\x81\x11\x82\x82\x10\x17\x15a\x16SWa\x16Sa\x15\xA9V[`@R\x91\x90PV[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\x16tWa\x16ta\x15\xA9V[P`\x1F\x01`\x1F\x19\x16` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\x16\x93W`\0\x80\xFD[\x815a\x16\xA6a\x16\xA1\x82a\x16[V[a\x16+V[\x81\x81R\x84` \x83\x86\x01\x01\x11\x15a\x16\xBBW`\0\x80\xFD[\x81` \x85\x01` \x83\x017`\0\x91\x81\x01` \x01\x91\x90\x91R\x93\x92PPPV[\x805`\x01`\x01`@\x1B\x03\x81\x16\x81\x14a\x16\xEFW`\0\x80\xFD[\x91\x90PV[`\0`\xE0\x82\x84\x03\x12\x15a\x17\x06W`\0\x80\xFD[a\x17\x0Ea\x15\xBFV[\x90P\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x17'W`\0\x80\xFD[a\x173\x85\x83\x86\x01a\x16\x82V[\x83R` \x84\x015\x91P\x80\x82\x11\x15a\x17IW`\0\x80\xFD[a\x17U\x85\x83\x86\x01a\x16\x82V[` \x84\x01Ra\x17f`@\x85\x01a\x16\xD8V[`@\x84\x01R``\x84\x015\x91P\x80\x82\x11\x15a\x17\x7FW`\0\x80\xFD[a\x17\x8B\x85\x83\x86\x01a\x16\x82V[``\x84\x01R`\x80\x84\x015\x91P\x80\x82\x11\x15a\x17\xA4W`\0\x80\xFD[a\x17\xB0\x85\x83\x86\x01a\x16\x82V[`\x80\x84\x01Ra\x17\xC1`\xA0\x85\x01a\x16\xD8V[`\xA0\x84\x01R`\xC0\x84\x015\x91P\x80\x82\x11\x15a\x17\xDAW`\0\x80\xFD[Pa\x17\xE7\x84\x82\x85\x01a\x16\x82V[`\xC0\x83\x01RP\x92\x91PPV[`\0``\x82\x84\x03\x12\x15a\x18\x05W`\0\x80\xFD[`@Q``\x81\x01`\x01`\x01`@\x1B\x03\x82\x82\x10\x81\x83\x11\x17\x15a\x18(Wa\x18(a\x15\xA9V[\x81`@R\x82\x93P\x845\x91P\x80\x82\x11\x15a\x18@W`\0\x80\xFD[a\x18L\x86\x83\x87\x01a\x16\xF4V[\x83R` \x85\x015\x91P\x80\x82\x11\x15a\x18bW`\0\x80\xFD[Pa\x18o\x85\x82\x86\x01a\x16\x82V[` \x83\x01RPa\x18\x81`@\x84\x01a\x16\xD8V[`@\x82\x01RP\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x18\x9FW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\x18\xB5W`\0\x80\xFD[a\x18\xC1\x84\x82\x85\x01a\x17\xF3V[\x94\x93PPPPV[`\x01`\x01`\xA0\x1B\x03\x81\x16\x81\x14a\x18\xDEW`\0\x80\xFD[PV[\x805a\x16\xEF\x81a\x18\xC9V[`\0` \x82\x84\x03\x12\x15a\x18\xFEW`\0\x80\xFD[\x815a\x14\x06\x81a\x18\xC9V[`\0` \x82\x84\x03\x12\x15a\x19\x1BW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x192W`\0\x80\xFD[\x90\x83\x01\x90`@\x82\x86\x03\x12\x15a\x19FW`\0\x80\xFD[a\x19Na\x15\xE7V[\x825\x82\x81\x11\x15a\x19]W`\0\x80\xFD[a\x19i\x87\x82\x86\x01a\x16\xF4V[\x82RP` \x83\x015\x92Pa\x19|\x83a\x18\xC9V[` \x81\x01\x92\x90\x92RP\x93\x92PPPV[`\0` \x82\x84\x03\x12\x15a\x19\x9EW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x19\xB5W`\0\x80\xFD[\x90\x83\x01\x90`\xA0\x82\x86\x03\x12\x15a\x19\xC9W`\0\x80\xFD[a\x19\xD1a\x16\tV[\x825\x82\x81\x11\x15a\x19\xE0W`\0\x80\xFD[a\x19\xEC\x87\x82\x86\x01a\x16\x82V[\x82RP` \x83\x015\x91Pa\x19\xFF\x82a\x18\xC9V[\x81` \x82\x01Ra\x1A\x11`@\x84\x01a\x16\xD8V[`@\x82\x01R``\x83\x015``\x82\x01R`\x80\x83\x015`\x80\x82\x01R\x80\x93PPPP\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x1AHW`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x81\x11\x15a\x1A^W`\0\x80\xFD[a\x18\xC1\x84\x82\x85\x01a\x16\xF4V[`\0` \x82\x84\x03\x12\x15a\x1A|W`\0\x80\xFD[P5\x91\x90PV[`\0[\x83\x81\x10\x15a\x1A\x9EW\x81\x81\x01Q\x83\x82\x01R` \x01a\x1A\x86V[PP`\0\x91\x01RV[`\0\x81Q\x80\x84Ra\x1A\xBF\x81` \x86\x01` \x86\x01a\x1A\x83V[`\x1F\x01`\x1F\x19\x16\x92\x90\x92\x01` \x01\x92\x91PPV[`\0\x81Q`\xE0\x84Ra\x1A\xE8`\xE0\x85\x01\x82a\x1A\xA7V[\x90P` \x83\x01Q\x84\x82\x03` \x86\x01Ra\x1B\x01\x82\x82a\x1A\xA7V[\x91PP`@\x83\x01Q`\x01`\x01`@\x1B\x03\x80\x82\x16`@\x87\x01R``\x85\x01Q\x91P\x85\x83\x03``\x87\x01Ra\x1B2\x83\x83a\x1A\xA7V[\x92P`\x80\x85\x01Q\x91P\x85\x83\x03`\x80\x87\x01Ra\x1BM\x83\x83a\x1A\xA7V[\x92P\x80`\xA0\x86\x01Q\x16`\xA0\x87\x01RPP`\xC0\x83\x01Q\x84\x82\x03`\xC0\x86\x01Ra\x1Bt\x82\x82a\x1A\xA7V[\x95\x94PPPPPV[` \x81R`\0a\x14\x06` \x83\x01\x84a\x1A\xD3V[`\0` \x82\x84\x03\x12\x15a\x1B\xA2W`\0\x80\xFD[\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x1B\xB9W`\0\x80\xFD[\x90\x83\x01\x90`@\x82\x86\x03\x12\x15a\x1B\xCDW`\0\x80\xFD[a\x1B\xD5a\x15\xE7V[\x825\x82\x81\x11\x15a\x1B\xE4W`\0\x80\xFD[a\x19i\x87\x82\x86\x01a\x17\xF3V[`\0`\x01`\x01`@\x1B\x03\x82\x11\x15a\x1C\tWa\x1C\ta\x15\xA9V[P`\x05\x1B` \x01\x90V[`\0\x82`\x1F\x83\x01\x12a\x1C$W`\0\x80\xFD[\x815` a\x1C4a\x16\xA1\x83a\x1B\xF0V[\x82\x81R`\x05\x92\x90\x92\x1B\x84\x01\x81\x01\x91\x81\x81\x01\x90\x86\x84\x11\x15a\x1CSW`\0\x80\xFD[\x82\x86\x01[\x84\x81\x10\x15a\x1C\x92W\x805`\x01`\x01`@\x1B\x03\x81\x11\x15a\x1CvW`\0\x80\x81\xFD[a\x1C\x84\x89\x86\x83\x8B\x01\x01a\x16\x82V[\x84RP\x91\x83\x01\x91\x83\x01a\x1CWV[P\x96\x95PPPPPPV[`\0`\xE0\x82\x84\x03\x12\x15a\x1C\xAFW`\0\x80\xFD[a\x1C\xB7a\x15\xBFV[\x90P\x815`\x01`\x01`@\x1B\x03\x80\x82\x11\x15a\x1C\xD0W`\0\x80\xFD[a\x1C\xDC\x85\x83\x86\x01a\x16\x82V[\x83R` \x84\x015\x91P\x80\x82\x11\x15a\x1C\xF2W`\0\x80\xFD[a\x1C\xFE\x85\x83\x86\x01a\x16\x82V[` \x84\x01Ra\x1D\x0F`@\x85\x01a\x16\xD8V[`@\x84\x01R``\x84\x015\x91P\x80\x82\x11\x15a\x1D(W`\0\x80\xFD[a\x1D4\x85\x83\x86\x01a\x16\x82V[``\x84\x01Ra\x1DE`\x80\x85\x01a\x16\xD8V[`\x80\x84\x01R`\xA0\x84\x015\x91P\x80\x82\x11\x15a\x1D^W`\0\x80\xFD[Pa\x1Dk\x84\x82\x85\x01a\x1C\x13V[`\xA0\x83\x01RPa\x1D}`\xC0\x83\x01a\x16\xD8V[`\xC0\x82\x01R\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x1D\x9AW`\0\x80\xFD[`\x01`\x01`@\x1B\x03\x80\x835\x11\x15a\x1D\xB0W`\0\x80\xFD[\x825\x83\x01`@\x81\x86\x03\x12\x15a\x1D\xC4W`\0\x80\xFD[a\x1D\xCCa\x15\xE7V[\x82\x825\x11\x15a\x1D\xDAW`\0\x80\xFD[\x815\x82\x01`@\x81\x88\x03\x12\x15a\x1D\xEEW`\0\x80\xFD[a\x1D\xF6a\x15\xE7V[\x84\x825\x11\x15a\x1E\x04W`\0\x80\xFD[a\x1E\x11\x88\x835\x84\x01a\x1C\x9DV[\x81R\x84` \x83\x015\x11\x15a\x1E$W`\0\x80\xFD[` \x82\x015\x82\x01\x91P\x87`\x1F\x83\x01\x12a\x1E ::ethers::contract::builders::ContractCall { + self.0 + .method_hash([136, 217, 241, 112], ()) + .expect("method not found (this should never happen)") + } ///Calls the contract's `setIsmpHost` (0x0e8324a2) function pub fn set_ismp_host( &self, @@ -1205,6 +1237,20 @@ pub mod ping_module { pub struct PingCall { pub ping_message: PingMessage, } + ///Container type for all input parameters for the `previousPostRequest` function with + /// signature `previousPostRequest()` and selector `0x88d9f170` + #[derive( + Clone, + ::ethers::contract::EthCall, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[ethcall(name = "previousPostRequest", abi = "previousPostRequest()")] + pub struct PreviousPostRequestCall; ///Container type for all input parameters for the `setIsmpHost` function with signature /// `setIsmpHost(address)` and selector `0x0e8324a2` #[derive( @@ -1236,6 +1282,7 @@ pub mod ping_module { OnPostResponse(OnPostResponseCall), OnPostResponseTimeout(OnPostResponseTimeoutCall), Ping(PingCall), + PreviousPostRequest(PreviousPostRequestCall), SetIsmpHost(SetIsmpHostCall), } impl ::ethers::core::abi::AbiDecode for PingModuleCalls { @@ -1293,6 +1340,11 @@ pub mod ping_module { if let Ok(decoded) = ::decode(data) { return Ok(Self::Ping(decoded)); } + if let Ok(decoded) = + ::decode(data) + { + return Ok(Self::PreviousPostRequest(decoded)); + } if let Ok(decoded) = ::decode(data) { return Ok(Self::SetIsmpHost(decoded)); } @@ -1319,6 +1371,8 @@ pub mod ping_module { Self::OnPostResponseTimeout(element) => ::ethers::core::abi::AbiEncode::encode(element), Self::Ping(element) => ::ethers::core::abi::AbiEncode::encode(element), + Self::PreviousPostRequest(element) => + ::ethers::core::abi::AbiEncode::encode(element), Self::SetIsmpHost(element) => ::ethers::core::abi::AbiEncode::encode(element), } } @@ -1338,6 +1392,7 @@ pub mod ping_module { Self::OnPostResponse(element) => ::core::fmt::Display::fmt(element, f), Self::OnPostResponseTimeout(element) => ::core::fmt::Display::fmt(element, f), Self::Ping(element) => ::core::fmt::Display::fmt(element, f), + Self::PreviousPostRequest(element) => ::core::fmt::Display::fmt(element, f), Self::SetIsmpHost(element) => ::core::fmt::Display::fmt(element, f), } } @@ -1402,6 +1457,11 @@ pub mod ping_module { Self::Ping(value) } } + impl ::core::convert::From for PingModuleCalls { + fn from(value: PreviousPostRequestCall) -> Self { + Self::PreviousPostRequest(value) + } + } impl ::core::convert::From for PingModuleCalls { fn from(value: SetIsmpHostCall) -> Self { Self::SetIsmpHost(value) @@ -1460,6 +1520,19 @@ pub mod ping_module { Hash, )] pub struct HostReturn(pub ::ethers::core::types::Address); + ///Container type for all return fields from the `previousPostRequest` function with signature + /// `previousPostRequest()` and selector `0x88d9f170` + #[derive( + Clone, + ::ethers::contract::EthAbiType, + ::ethers::contract::EthAbiCodec, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + pub struct PreviousPostRequestReturn(pub PostRequest); ///`PingMessage(bytes,address,uint64,uint256,uint256)` #[derive( Clone, diff --git a/evm/examples/PingModule.sol b/evm/examples/PingModule.sol index e897485a0..d44983c1b 100644 --- a/evm/examples/PingModule.sol +++ b/evm/examples/PingModule.sol @@ -52,6 +52,7 @@ contract PingModule is IIsmpModule { address internal _host; address internal _admin; + PostRequest private _request; constructor(address admin) { _admin = admin; @@ -61,12 +62,22 @@ contract PingModule is IIsmpModule { _host = hostAddr; } + function previousPostRequest() public view returns (PostRequest memory) { + return _request; + } + // returns the current ismp host set function host() public view returns (address) { return _host; } function dispatchPostResponse(PostResponse memory response) public returns (bytes32) { + uint256 perByteFee = IIsmpHost(_host).perByteFee(); + address feeToken = IIsmpHost(_host).feeToken(); + uint256 fee = perByteFee * response.response.length; + + IERC20(feeToken).transferFrom(msg.sender, address(this), fee); + IERC20(feeToken).approve(_host, fee); DispatchPostResponse memory post = DispatchPostResponse({ request: response.request, response: response.response, @@ -103,7 +114,8 @@ contract PingModule is IIsmpModule { height: request.height, keys: request.keys, timeout: request.timeoutTimestamp, - sender: msg.sender + sender: msg.sender, + fee: 0 }); return IDispatcher(_host).dispatch(get); @@ -149,6 +161,7 @@ contract PingModule is IIsmpModule { function onAccept(IncomingPostRequest memory incoming) external onlyIsmpHost { emit PostReceived(string(incoming.request.body)); + _request = incoming.request; } function onPostResponse(IncomingPostResponse memory) external onlyIsmpHost { diff --git a/evm/lib/ismp-solidity b/evm/lib/ismp-solidity index 2daf64382..7702f39a2 160000 --- a/evm/lib/ismp-solidity +++ b/evm/lib/ismp-solidity @@ -1 +1 @@ -Subproject commit 2daf64382eaf9b78dab7fd21f6b915ca7297434e +Subproject commit 7702f39a21c0621fb130f18910043981f17aeacf diff --git a/evm/script/DeployPing.s.sol b/evm/script/DeployPing.s.sol index 4761306a7..9752240ba 100644 --- a/evm/script/DeployPing.s.sol +++ b/evm/script/DeployPing.s.sol @@ -8,7 +8,7 @@ import {ERC6160Ext20} from "ERC6160/tokens/ERC6160Ext20.sol"; import {PingModule} from "../examples/PingModule.sol"; contract DeployScript is Script { - bytes32 public salt = keccak256(bytes("gargantua-v1000000")); + bytes32 private salt = keccak256(bytes(vm.envString("VERSION"))); address public SEPOLIA_HOST = vm.envAddress("SEPOLIA_HOST"); address public ARB_SEPOLIA_HOST = vm.envAddress("ARB_SEPOLIA_HOST"); diff --git a/evm/src/hosts/EvmHost.sol b/evm/src/hosts/EvmHost.sol index dc46fe3bc..8b2d717ac 100644 --- a/evm/src/hosts/EvmHost.sol +++ b/evm/src/hosts/EvmHost.sol @@ -532,9 +532,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { { // if we're on mainnet, then consensus state can only be initialized once. // and updated subsequently by either consensus proofs or cross-chain governance - require( - chainId() == block.chainid ? _consensusState.equals(new bytes(0)) : true, "Unauthorized action" - ); + require(chainId() == block.chainid ? _consensusState.equals(new bytes(0)) : true, "Unauthorized action"); _consensusState = state; _consensusUpdateTimestamp = block.timestamp; @@ -545,7 +543,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { } /** - * @dev Dispatch an incoming post request to destination module + * @dev Dispatch an incoming POST request to destination module * @param request - post request */ function dispatchIncoming(PostRequest memory request, address relayer) external onlyHandler { @@ -576,15 +574,17 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { } /** - * @dev Dispatch an incoming post response to source module + * @dev Dispatch an incoming POST response to source module * @param response - post response */ function dispatchIncoming(PostResponse memory response, address relayer) external onlyHandler { address origin = _bytesToAddress(response.request.from); // replay protection - bytes32 commitment = response.request.hash(); - _responseReceipts[commitment] = ResponseReceipt({relayer: relayer, responseCommitment: response.hash()}); + bytes32 requestCommitment = response.request.hash(); + bytes32 responseCommitment = response.hash(); + _responseReceipts[requestCommitment] = + ResponseReceipt({relayer: relayer, responseCommitment: responseCommitment}); (bool success,) = address(origin).call( abi.encodeWithSelector(IIsmpModule.onPostResponse.selector, IncomingPostResponse(response, relayer)) @@ -592,14 +592,14 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { if (!success) { // so that it can be retried - delete _responseReceipts[commitment]; + delete _responseReceipts[requestCommitment]; return; } - emit PostResponseHandled({commitment: commitment, relayer: relayer}); + emit PostResponseHandled({commitment: responseCommitment, relayer: relayer}); } /** - * @dev Dispatch an incoming get response to source module + * @dev Dispatch an incoming GET response to source module * @param response - get response */ function dispatchIncoming(GetResponse memory response, address relayer) external onlyHandler { @@ -620,16 +620,11 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { return; } - FeeMetadata memory meta = _requestCommitments[response.request.hash()]; - if (meta.fee > 0) { - // pay the relayer their fee - IERC20(feeToken()).transfer(relayer, meta.fee); - } emit PostResponseHandled({commitment: commitment, relayer: relayer}); } /** - * @dev Dispatch an incoming get timeout to the source module + * @dev Dispatch an incoming GET timeout to the source module * @param request - get request */ function dispatchIncoming(GetRequest memory request, FeeMetadata memory meta, bytes32 commitment) @@ -648,15 +643,11 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { return; } - if (meta.fee > 0) { - // refund relayer fee - IERC20(feeToken()).transfer(meta.sender, meta.fee); - } emit GetRequestTimeoutHandled({commitment: commitment, dest: request.dest}); } /** - * @dev Dispatch an incoming post timeout to the source module + * @dev Dispatch an incoming POST timeout to the source module * @param request - post timeout */ function dispatchIncoming(PostRequest memory request, FeeMetadata memory meta, bytes32 commitment) @@ -684,7 +675,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { } /** - * @dev Dispatch an incoming post response timeout to the source module + * @dev Dispatch an incoming POST response timeout to the source module * @param response - timed-out post response */ function dispatchIncoming(PostResponse memory response, FeeMetadata memory meta, bytes32 commitment) @@ -752,10 +743,14 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { } /** - * @dev Dispatch a get request to the hyperbridge + * @dev Dispatch a GET request to the hyperbridge * @param get - get request */ function dispatch(DispatchGet memory get) external returns (bytes32 commitment) { + if (get.fee > 0) { + IERC20(feeToken()).transferFrom(_msgSender(), address(this), get.fee); + } + // adjust the timeout uint64 timeout = get.timeout == 0 ? 0 : uint64(this.timestamp()) + uint64(Math.max(_hostParams.defaultTimeout, get.timeout)); @@ -772,7 +767,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { // make the commitment commitment = request.hash(); - _requestCommitments[commitment] = FeeMetadata({sender: get.sender, fee: 0}); + _requestCommitments[commitment] = FeeMetadata({sender: get.sender, fee: get.fee}); emit GetRequestEvent( request.source, request.dest, @@ -785,7 +780,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { } /** - * @dev Dispatch a response to the hyperbridge + * @dev Dispatch a POST response to the hyperbridge * @param post - post response */ function dispatch(DispatchPostResponse memory post) external returns (bytes32 commitment) { @@ -800,6 +795,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { // check that request has not already been responed to require(!_responded[receipt], "EvmHost: Duplicate Response"); + // collect fees uint256 fee = (_hostParams.perByteFee * post.response.length) + post.fee; IERC20(feeToken()).transferFrom(_msgSender(), address(this), fee); @@ -807,6 +803,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { uint64 timeout = post.timeout == 0 ? 0 : uint64(this.timestamp()) + uint64(Math.max(_hostParams.defaultTimeout, post.timeout)); + PostResponse memory response = PostResponse({request: post.request, response: post.response, timeoutTimestamp: timeout}); commitment = response.hash(); diff --git a/modules/hyperclient/src/testing.rs b/modules/hyperclient/src/testing.rs index bc9e3a60d..954cc3934 100644 --- a/modules/hyperclient/src/testing.rs +++ b/modules/hyperclient/src/testing.rs @@ -35,16 +35,16 @@ use ismp_solidity_abi::{ }; use std::sync::Arc; -const OP_HOST: H160 = H160(hex!("98A6A9c780D7d54aEF9aBd08c55C9ADc17de48A0")); -const OP_HANDLER: H160 = H160(hex!("BE5Ea8A28D5AB4e96532c85F078d83E138EC8d44")); +const OP_HOST: H160 = H160(hex!("0D811D581D615AA44A36aa638825403F9b434E18")); +const OP_HANDLER: H160 = H160(hex!("6DbcA7CAEBd47D377E230ec3EFaBDdf0A7afA395")); -const SEPOLIA_HOST: H160 = H160(hex!("705ba08d072f26bB92C8f71B7E37a3c7aEA5Ecb1")); -const SEPOLIA_HANDLER: H160 = H160(hex!("12122B8E2E1e24345161A2433fF2d91Fca123FAe")); +const SEPOLIA_HOST: H160 = H160(hex!("bDFa473d7E483e088348e071480B624A248b2fC4")); +const SEPOLIA_HANDLER: H160 = H160(hex!("7fa6f643A1a522D35058FEE753DA027d25Ea601f")); -const BSC_HOST: H160 = H160(hex!("1488f22baf2027D6e28D79b6F38EB2CfdfE48d62")); -const BSC_HANDLER: H160 = H160(hex!("13463B01CE69F8B5279c5922D38EB1073503e87b")); +const BSC_HOST: H160 = H160(hex!("E6bd95737DD35Fd0e5f134771A832405671f06e9")); +const BSC_HANDLER: H160 = H160(hex!("BA82A7c413BfbE26ee025DA221088319b895A8E6")); -const PING_MODULE: H160 = H160(hex!("b51d235CF4461D17FEA88733fed1865873c8D686")); +const PING_MODULE: H160 = H160(hex!("9Cc29770F3d643F4094Ee591f3D2E3c98C349761")); pub async fn subscribe_to_request_status() -> Result<(), anyhow::Error> { tracing::info!("\n\n\n\nStarting request status subscription\n\n\n\n"); diff --git a/modules/ismp/clients/sync-committee/evm-common/src/lib.rs b/modules/ismp/clients/sync-committee/evm-common/src/lib.rs index ee1078148..00886add9 100644 --- a/modules/ismp/clients/sync-committee/evm-common/src/lib.rs +++ b/modules/ismp/clients/sync-committee/evm-common/src/lib.rs @@ -22,7 +22,9 @@ extern crate alloc; use alloc::collections::BTreeMap; use ethabi::ethereum_types::{H160, H256}; use ismp::{ - consensus::StateCommitment, error::Error, host::IsmpHost, messaging::Proof, + consensus::StateCommitment, + error::Error, + messaging::{Keccak256, Proof}, router::RequestResponse, }; @@ -37,7 +39,7 @@ pub mod types; pub mod utils; pub use utils::*; -pub fn verify_membership( +pub fn verify_membership( item: RequestResponse, root: StateCommitment, proof: &Proof, @@ -64,7 +66,7 @@ pub fn verify_membership( Ok(()) } -pub fn verify_state_proof( +pub fn verify_state_proof( keys: Vec>, root: StateCommitment, proof: &Proof, diff --git a/modules/ismp/clients/sync-committee/evm-common/src/types.rs b/modules/ismp/clients/sync-committee/evm-common/src/types.rs index 181a850eb..8ee9097ad 100644 --- a/modules/ismp/clients/sync-committee/evm-common/src/types.rs +++ b/modules/ismp/clients/sync-committee/evm-common/src/types.rs @@ -21,11 +21,11 @@ use codec::{Decode, Encode}; use ethabi::ethereum_types::H256; use hash256_std_hasher::Hash256StdHasher; use hash_db::Hasher; -use ismp::host::IsmpHost; +use ismp::messaging::Keccak256; -pub struct KeccakHasher(core::marker::PhantomData); +pub struct KeccakHasher(core::marker::PhantomData); -impl Hasher for KeccakHasher { +impl Hasher for KeccakHasher { type Out = H256; type StdHasher = Hash256StdHasher; const LENGTH: usize = 32; diff --git a/modules/ismp/clients/sync-committee/evm-common/src/utils.rs b/modules/ismp/clients/sync-committee/evm-common/src/utils.rs index 605fa0e4b..7f10bc28c 100644 --- a/modules/ismp/clients/sync-committee/evm-common/src/utils.rs +++ b/modules/ismp/clients/sync-committee/evm-common/src/utils.rs @@ -31,8 +31,8 @@ use ismp::{ ConsensusStateId, IntermediateState, StateCommitment, StateMachineHeight, StateMachineId, }, error::Error, - host::{IsmpHost, StateMachine}, - messaging::{hash_request, hash_response, Proof}, + host::StateMachine, + messaging::{hash_request, hash_response, Keccak256, Proof}, router::RequestResponse, }; use trie_db::{DBValue, Trie, TrieDBBuilder}; @@ -67,7 +67,7 @@ pub fn decode_evm_state_proof(proof: &Proof) -> Result { Ok(evm_state_proof) } -pub fn req_res_to_key(item: RequestResponse) -> Vec> { +pub fn req_res_to_key(item: RequestResponse) -> Vec> { let mut keys = vec![]; match item { RequestResponse::Request(requests) => @@ -95,7 +95,7 @@ pub fn req_res_to_key(item: RequestResponse) -> Vec> { keys } -pub fn req_res_receipt_keys(item: RequestResponse) -> Vec> { +pub fn req_res_receipt_keys(item: RequestResponse) -> Vec> { let mut keys = vec![]; match item { RequestResponse::Request(requests) => @@ -132,7 +132,7 @@ pub(super) fn to_bytes_32(bytes: &[u8]) -> Result<[u8; 32], Error> { Ok(array) } -pub fn get_contract_storage_root( +pub fn get_contract_storage_root( contract_account_proof: Vec>, contract_address: &[u8], root: H256, @@ -152,14 +152,14 @@ pub fn get_contract_storage_root( Ok(contract_account.storage_root.0.into()) } -pub fn derive_map_key(mut key: Vec, slot: u64) -> H256 { +pub fn derive_map_key(mut key: Vec, slot: u64) -> H256 { let mut bytes = [0u8; 32]; U256::from(slot).to_big_endian(&mut bytes); key.extend_from_slice(&bytes); H::keccak256(H::keccak256(&key).0.as_slice()) } -pub fn derive_map_key_with_offset(mut key: Vec, slot: u64, offset: u64) -> H256 { +pub fn derive_map_key_with_offset(mut key: Vec, slot: u64, offset: u64) -> H256 { let mut bytes = [0u8; 32]; U256::from(slot).to_big_endian(&mut bytes); key.extend_from_slice(&bytes); @@ -170,7 +170,7 @@ pub fn derive_map_key_with_offset(mut key: Vec, slot: u64, offs H::keccak256(&bytes) } -pub fn derive_unhashed_map_key(mut key: Vec, slot: u64) -> H256 { +pub fn derive_unhashed_map_key(mut key: Vec, slot: u64) -> H256 { let mut bytes = [0u8; 32]; U256::from(slot).to_big_endian(&mut bytes); key.extend_from_slice(&bytes); @@ -184,7 +184,7 @@ pub fn add_off_set_to_map_key(key: &[u8], offset: u64) -> H256 { H256(bytes) } -pub fn derive_array_item_key(slot: u64, index: u64, offset: u64) -> Vec { +pub fn derive_array_item_key(slot: u64, index: u64, offset: u64) -> Vec { let mut bytes = [0u8; 32]; U256::from(slot).to_big_endian(&mut bytes); @@ -199,7 +199,7 @@ pub fn derive_array_item_key(slot: u64, index: u64, offset: u64) -> H::keccak256(&pos).0.to_vec() } -pub fn get_values_from_proof( +pub fn get_values_from_proof( keys: Vec>, root: H256, proof: Vec>, @@ -215,7 +215,7 @@ pub fn get_values_from_proof( Ok(values) } -pub fn get_value_from_proof( +pub fn get_value_from_proof( key: Vec, root: H256, proof: Vec>, diff --git a/modules/ismp/testsuite/src/mocks.rs b/modules/ismp/testsuite/src/mocks.rs index 77e8e7acc..51efe65cf 100644 --- a/modules/ismp/testsuite/src/mocks.rs +++ b/modules/ismp/testsuite/src/mocks.rs @@ -481,3 +481,14 @@ impl IsmpDispatcher for Host { Ok(hash) } } + +pub struct Keccak256Hasher; + +impl ismp::messaging::Keccak256 for Keccak256Hasher { + fn keccak256(bytes: &[u8]) -> H256 + where + Self: Sized, + { + sp_core::keccak_256(bytes).into() + } +} diff --git a/tesseract/config/Cargo.toml b/tesseract/config/Cargo.toml index 638d1c751..e0dcefb7c 100644 --- a/tesseract/config/Cargo.toml +++ b/tesseract/config/Cargo.toml @@ -15,3 +15,4 @@ ismp-sync-committee = { workspace = true, default-features = true } anyhow = { workspace = true, default-features = true } serde = { workspace = true, default-features = true, features = ["derive"] } substrate-state-machine = { workspace = true, default-features = true } +sp-core = { workspace = true } diff --git a/tesseract/evm/Cargo.toml b/tesseract/evm/Cargo.toml index 618e1882f..f99064527 100644 --- a/tesseract/evm/Cargo.toml +++ b/tesseract/evm/Cargo.toml @@ -26,7 +26,7 @@ sp-core = { workspace = true, features = ["full_crypto"] } log = "0.4.19" ethers = { workspace = true, features = ["rustls"] } ethabi = { version = "18.0.0", features = ["rlp", "full-serde"], default-features = false } -tokio = { workspace = true, features = ["macros", "sync"] } +tokio = { workspace = true, features = ["macros", "sync", "time"] } tokio-stream = { workspace = true } frame-support = { workspace = true, default-features = true } reqwest-retry = "0.3.0" @@ -49,6 +49,7 @@ tesseract-primitives = { workspace = true, default-features = true } debounced = { git= "https://github.com/polytope-labs/debounced", branch = "main"} merkle-mountain-range = { workspace = true, default-features = true } +ismp-testsuite = { workspace = true, default-features = true } reconnecting-jsonrpsee-ws-client = { workspace = true, default-features = true } jsonrpsee = { version = "0.21", features = ["ws-client"]} pallet-ismp-host-executive = { workspace = true, default-features = true } diff --git a/tesseract/evm/src/lib.rs b/tesseract/evm/src/lib.rs index 97088a246..fae1af1db 100644 --- a/tesseract/evm/src/lib.rs +++ b/tesseract/evm/src/lib.rs @@ -27,8 +27,6 @@ use tesseract_primitives::IsmpProvider; pub mod abi; mod gas_oracle; -#[cfg(any(feature = "testing", test))] -pub mod mock; pub mod provider; #[cfg(test)] diff --git a/tesseract/evm/src/mock.rs b/tesseract/evm/src/mock.rs deleted file mode 100644 index 00171c601..000000000 --- a/tesseract/evm/src/mock.rs +++ /dev/null @@ -1,327 +0,0 @@ -use ethabi::ethereum_types::H256; -use ismp::{ - consensus::{ - ConsensusClient, ConsensusClientId, ConsensusStateId, StateCommitment, StateMachineHeight, - StateMachineId, - }, - error::Error, - host::StateMachine, - router::{IsmpRouter, PostResponse, Request, Response}, -}; -use std::time::Duration; - -pub struct Host; - -impl ismp::host::IsmpHost for Host { - fn host_state_machine(&self) -> StateMachine { - todo!() - } - - fn latest_commitment_height(&self, _id: StateMachineId) -> Result { - todo!() - } - - fn state_machine_commitment( - &self, - _height: StateMachineHeight, - ) -> Result { - todo!() - } - - fn consensus_update_time( - &self, - _consensus_state_id: ConsensusStateId, - ) -> Result { - todo!() - } - - fn state_machine_update_time( - &self, - _state_machine_height: StateMachineHeight, - ) -> Result { - todo!() - } - - fn consensus_client_id( - &self, - _consensus_state_id: ConsensusStateId, - ) -> Option { - todo!() - } - - fn consensus_state(&self, _consensus_state_id: ConsensusStateId) -> Result, Error> { - todo!() - } - - fn timestamp(&self) -> Duration { - todo!() - } - - fn is_consensus_client_frozen( - &self, - _consensus_state_id: ConsensusStateId, - ) -> Result<(), Error> { - todo!() - } - - fn request_commitment(&self, _req: H256) -> Result<(), Error> { - todo!() - } - - fn response_commitment(&self, _req: H256) -> Result<(), Error> { - todo!() - } - - fn next_nonce(&self) -> u64 { - todo!() - } - - fn request_receipt(&self, _req: &Request) -> Option<()> { - todo!() - } - - fn response_receipt(&self, _res: &Response) -> Option<()> { - todo!() - } - - fn store_consensus_state_id( - &self, - _consensus_state_id: ConsensusStateId, - _client_id: ConsensusClientId, - ) -> Result<(), Error> { - todo!() - } - - fn store_consensus_state( - &self, - _consensus_state_id: ConsensusStateId, - _consensus_state: Vec, - ) -> Result<(), Error> { - todo!() - } - - fn store_unbonding_period( - &self, - _consensus_state_id: ConsensusStateId, - _period: u64, - ) -> Result<(), Error> { - todo!() - } - - fn store_consensus_update_time( - &self, - _consensus_state_id: ConsensusStateId, - _timestamp: Duration, - ) -> Result<(), Error> { - todo!() - } - - fn delete_request_receipt(&self, _req: &Request) -> Result, Error> { - todo!() - } - - fn delete_response_receipt(&self, _res: &Response) -> Result, Error> { - todo!() - } - - fn store_state_machine_update_time( - &self, - _state_machine_height: StateMachineHeight, - _timestamp: Duration, - ) -> Result<(), Error> { - todo!() - } - - fn store_state_machine_commitment( - &self, - _height: StateMachineHeight, - _state: StateCommitment, - ) -> Result<(), Error> { - todo!() - } - - fn freeze_consensus_client(&self, _consensus_state_id: ConsensusStateId) -> Result<(), Error> { - todo!() - } - - fn store_latest_commitment_height(&self, _height: StateMachineHeight) -> Result<(), Error> { - todo!() - } - - fn delete_request_commitment(&self, _req: &Request) -> Result, Error> { - todo!() - } - - fn delete_response_commitment(&self, _res: &PostResponse) -> Result, Error> { - todo!() - } - - fn store_request_receipt(&self, _req: &Request, _signer: &Vec) -> Result<(), Error> { - todo!() - } - - fn store_response_receipt(&self, _req: &Response, _signer: &Vec) -> Result<(), Error> { - todo!() - } - - fn consensus_client(&self, _id: ConsensusClientId) -> Result, Error> { - todo!() - } - - fn challenge_period(&self, _consensus_state_id: ConsensusStateId) -> Option { - todo!() - } - - fn store_challenge_period( - &self, - _consensus_state_id: ConsensusStateId, - _period: u64, - ) -> Result<(), Error> { - todo!() - } - - fn unbonding_period(&self, _consensus_state_id: ConsensusStateId) -> Option { - todo!() - } - - fn ismp_router(&self) -> Box { - todo!() - } - - fn allowed_proxy(&self) -> Option { - todo!() - } - - fn consensus_clients(&self) -> Vec> { - todo!() - } - - fn delete_state_commitment(&self, _height: StateMachineHeight) -> Result<(), Error> { - todo!() - } - - fn store_request_commitment(&self, _req: &Request, _meta: Vec) -> Result<(), Error> { - todo!() - } - - fn store_response_commitment(&self, _res: &PostResponse, _meta: Vec) -> Result<(), Error> { - todo!() - } -} - -impl ismp::messaging::Keccak256 for Host { - fn keccak256(bytes: &[u8]) -> H256 - where - Self: Sized, - { - sp_core::keccak_256(bytes).into() - } -} - -#[cfg(test)] -mod tests { - use std::sync::Arc; - - use crate::{ - abi::{erc_20::Erc20, PingMessage, PingModule}, - SecretKey, - }; - use anyhow::Context; - use ethers::{ - prelude::{LocalWallet, MiddlewareBuilder, Signer}, - providers::{Http, Middleware, Provider, ProviderExt}, - }; - use futures::TryStreamExt; - use hex_literal::hex; - use ismp::host::{Ethereum, StateMachine}; - use ismp_solidity_abi::evm_host::EvmHost; - use primitive_types::{H160, U256}; - use sp_core::Pair; - - #[tokio::test] - #[ignore] - async fn test_ping() -> anyhow::Result<()> { - dotenv::dotenv().ok(); - let op_url = std::env::var("OP_URL").expect("OP_URL was missing in env variables"); - let base_url = std::env::var("BASE_URL").expect("BASE_URL was missing in env variables"); - let arb_url = std::env::var("ARB_URL").expect("ARB_URL was missing in env variables"); - let geth_url = std::env::var("GETH_URL").expect("GETH_URL was missing in env variables"); - let bsc_url = std::env::var("BSC_URL").expect("BSC_URL was missing in env variables"); - - let signing_key = - std::env::var("SIGNING_KEY").expect("SIGNING_KEY was missing in env variables"); - - let ping_addr = H160(hex!("b51d235CF4461D17FEA88733fed1865873c8D686")); - - let chains = vec![ - (StateMachine::Ethereum(Ethereum::ExecutionLayer), geth_url), - (StateMachine::Ethereum(Ethereum::Arbitrum), arb_url), - (StateMachine::Ethereum(Ethereum::Optimism), op_url), - (StateMachine::Ethereum(Ethereum::Base), base_url), - (StateMachine::Bsc, bsc_url), - ]; - - let stream = futures::stream::iter(chains.clone().into_iter().map(Ok::<_, anyhow::Error>)); - - stream - .try_for_each_concurrent(None, |(chain, url)| { - let chains_clone = chains.clone(); - let signing_key = signing_key.clone(); - async move { - let signer = - sp_core::ecdsa::Pair::from_seed_slice(&hex::decode(signing_key).unwrap())?; - let provider = Arc::new(Provider::::try_connect(&url).await?); - let signer = - LocalWallet::from(SecretKey::from_slice(signer.seed().as_slice())?) - .with_chain_id(provider.get_chainid().await?.low_u64()); - let client = Arc::new(provider.with_signer(signer)); - let ping = PingModule::new(ping_addr.clone(), client.clone()); - - let host_addr = ping.host().await.context(format!("Error in {chain:?}"))?; - dbg!((&chain, &host_addr)); - - let host = EvmHost::new(host_addr, client.clone()); - let erc_20 = Erc20::new( - host.fee_token().await.context(format!("Error in {chain:?}"))?, - client.clone(), - ); - let call = erc_20.approve(ping_addr, U256::max_value()); - let gas = call.estimate_gas().await.context(format!("Error in {chain:?}"))?; - call.gas(gas) - .send() - .await - .context(format!("Failed to send approval for {ping_addr} in {chain:?}"))? - .await - .context(format!("Failed to approve {ping_addr} in {chain:?}"))?; - - for (chain, _) in chains_clone.iter().filter(|(c, _)| chain != *c) { - for _ in 0..2 { - let call = ping.ping(PingMessage { - dest: chain.to_string().as_bytes().to_vec().into(), - module: ping_addr.clone().into(), - timeout: 10 * 60 * 60, - fee: U256::from(30_000_000_000_000_000_000u128), - count: U256::from(100), - }); - let gas = call - .estimate_gas() - .await - .context(format!("Failed to estimate gas in {chain:?}"))?; - let call = call.gas(gas); - let Ok(tx) = call.send().await else { continue }; - let receipt = tx - .await - .context(format!("Failed to execute ping message on {chain:?}"))?; - - assert!(receipt.is_some()); - } - } - - Ok(()) - } - }) - .await?; - - Ok(()) - } -} diff --git a/tesseract/evm/src/provider.rs b/tesseract/evm/src/provider.rs index 110ea8544..5f455df72 100644 --- a/tesseract/evm/src/provider.rs +++ b/tesseract/evm/src/provider.rs @@ -32,7 +32,7 @@ use ethers::{ GethDebugTracerConfig, GethDebugTracerType, GethDebugTracingOptions, Log, }, }; -use futures::stream::FuturesOrdered; +use futures::{stream::FuturesOrdered, FutureExt}; use ismp::{ consensus::{StateCommitment, StateMachineHeight}, host::{Ethereum, StateMachine}, @@ -46,7 +46,6 @@ use tesseract_primitives::{ BoxStream, EstimateGasReturnParams, Hasher, IsmpProvider, Query, Signature, StateMachineUpdated, StateProofQueryType, TxReceipt, }; -use tokio::time; #[async_trait::async_trait] impl IsmpProvider for EvmClient { @@ -491,19 +490,15 @@ impl IsmpProvider for EvmClient { &self, _counterparty_state_id: StateMachineId, ) -> Result, Error> { - use futures::StreamExt; - let initial_height = self.client.get_block_number().await?.low_u64(); - let (tx, rx) = tokio::sync::mpsc::channel(64); + let (tx, recv) = tokio::sync::mpsc::channel(256); let client = self.clone(); let poll_interval = self.config.poll_interval.unwrap_or(10); - tokio::spawn(async move { - let interval = time::interval(Duration::from_secs(poll_interval)); let mut latest_height = initial_height; - let mut interval_stream = tokio_stream::wrappers::IntervalStream::new(interval); let state_machine = client.state_machine; - while let Some(_) = interval_stream.next().await { + loop { + tokio::time::sleep(Duration::from_secs(poll_interval)).await; // wait for an update with a greater height let block_number = match client.client.get_block_number().await { Ok(number) => number.low_u64(), @@ -555,16 +550,15 @@ impl IsmpProvider for EvmClient { if let Some(event) = event { if let Err(err) = tx.send(Ok(event.clone())).await { - log::error!(target: "tesseract", "Failed to send state machine update over channel on {state_machine:?} \n {err:?}"); + log::trace!(target: "tesseract", "Failed to send state machine update over channel on {state_machine:?}->{:?} \n {err:?}", _counterparty_state_id.state_id); + return }; } latest_height = block_number; } - }); - - let stream = tokio_stream::wrappers::ReceiverStream::new(rx); + }.boxed()); - Ok(Box::pin(stream)) + Ok(Box::pin(tokio_stream::wrappers::ReceiverStream::new(recv))) } async fn submit(&self, messages: Vec) -> Result, Error> { diff --git a/tesseract/evm/src/test.rs b/tesseract/evm/src/test.rs index fc8f0cdc9..6d5456426 100644 --- a/tesseract/evm/src/test.rs +++ b/tesseract/evm/src/test.rs @@ -1,6 +1,6 @@ -use crate::{mock::Host, EvmClient, EvmConfig}; +use crate::{EvmClient, EvmConfig}; use codec::Decode; -use ethers::prelude::Middleware; +use ethers::providers::Middleware; use evm_common::{ get_contract_storage_root, get_value_from_proof, types::EvmStateProof, verify_membership, }; @@ -12,6 +12,7 @@ use ismp::{ router::{Post, RequestResponse}, }; use ismp_solidity_abi::evm_host::EvmHost; +use ismp_testsuite::mocks::{Host, Keccak256Hasher}; use primitive_types::H160; use std::str::FromStr; use tesseract_primitives::{IsmpProvider, Query}; @@ -84,12 +85,15 @@ async fn test_ismp_state_proof() { let proof = client.query_requests_proof(at, vec![query]).await.unwrap(); let evm_state_proof = EvmStateProof::decode(&mut &*proof).unwrap(); - let contract_root = - get_contract_storage_root::(evm_state_proof.contract_proof, &ISMP_HOST.0, state_root) - .unwrap(); + let contract_root = get_contract_storage_root::( + evm_state_proof.contract_proof, + &ISMP_HOST.0, + state_root, + ) + .unwrap(); let key = sp_core::keccak_256(&client.request_commitment_key(query.commitment).1 .0).to_vec(); - let value = get_value_from_proof::( + let value = get_value_from_proof::( key.clone(), contract_root, evm_state_proof.storage_proof.get(&key).unwrap().clone(), @@ -102,7 +106,7 @@ async fn test_ismp_state_proof() { assert_eq!(request_meta.sender.0, decoded_address.0); - verify_membership::( + verify_membership::( RequestResponse::Request(vec![req]), StateCommitment { timestamp: 0, overlay_root: None, state_root }, &Proof { diff --git a/tesseract/messaging/Cargo.toml b/tesseract/messaging/Cargo.toml index e1ab37d26..8e5bcb5ef 100644 --- a/tesseract/messaging/Cargo.toml +++ b/tesseract/messaging/Cargo.toml @@ -22,3 +22,4 @@ pallet-ismp = { workspace = true, default-features = true } transaction-fees = { workspace = true } tesseract-primitives = { workspace = true } ismp-solidity-abi = { workspace = true, default-features = true } +sc-service = { workspace = true } diff --git a/tesseract/messaging/src/lib.rs b/tesseract/messaging/src/lib.rs index b9e9f9aad..73ce3ee2d 100644 --- a/tesseract/messaging/src/lib.rs +++ b/tesseract/messaging/src/lib.rs @@ -19,6 +19,7 @@ mod events; mod retries; use anyhow::anyhow; +use sc_service::TaskManager; use std::{collections::HashMap, sync::Arc}; use tokio::sync::mpsc::{Receiver, Sender}; @@ -26,7 +27,7 @@ use crate::{ events::{filter_events, translate_events_to_messages, Event}, retries::retry_unprofitable_messages, }; -use futures::StreamExt; +use futures::{FutureExt, StreamExt}; use ismp::{consensus::StateMachineHeight, host::StateMachine}; use tesseract_primitives::{ @@ -43,46 +44,67 @@ pub async fn relay( coprocessor: StateMachine, tx_payment: Arc, client_map: HashMap>, + task_manager: &TaskManager, ) -> Result<(), anyhow::Error> where A: IsmpProvider + Clone + HyperbridgeClaim + 'static, { let (sender, receiver) = tokio::sync::mpsc::channel::>(64); - let task_a = { + { let chain_a = Arc::new(chain_a.clone()); let chain_b = chain_b.clone(); let client_map = client_map.clone(); let tx_payment = tx_payment.clone(); let config = config.clone(); let sender = sender.clone(); - Box::pin(handle_notification( - chain_a, - chain_b, - tx_payment, - config, - coprocessor, - client_map, - sender, - )) - }; + let name = format!("messaging-{}-{}", chain_a.name(), chain_b.name()); + task_manager.spawn_essential_handle().spawn_blocking( + Box::leak(Box::new(name.clone())), + "messaging", + async move { + let res = handle_notification( + chain_a, + chain_b, + tx_payment, + config, + coprocessor, + client_map, + sender, + ) + .await; + tracing::error!(target: "tesseract", "{name} has terminated with result {res:?}") + } + .boxed(), + ) + } - let task_b = { + { let chain_a = Arc::new(chain_a.clone()); let chain_b = chain_b.clone(); let client_map = client_map.clone(); let tx_payment = tx_payment.clone(); let config = config.clone(); let sender = sender.clone(); - Box::pin(handle_notification( - chain_b, - chain_a, - tx_payment, - config, - coprocessor, - client_map, - sender, - )) - }; + let name = format!("messaging-{}-{}", chain_b.name(), chain_a.name()); + task_manager.spawn_essential_handle().spawn_blocking( + Box::leak(Box::new(name.clone())), + "messaging", + async move { + let res = handle_notification( + chain_b, + chain_a, + tx_payment, + config, + coprocessor, + client_map, + sender, + ) + .await; + tracing::error!(target: "tesseract", "{name} has terminated with result {res:?}") + } + .boxed(), + ); + } // Fee accumulation background task { @@ -90,11 +112,18 @@ where let dest = chain_b.clone(); let client_map = client_map.clone(); let tx_payment = tx_payment.clone(); - - tokio::spawn(async move { - fee_accumulation(receiver, dest, hyperbridge, client_map, tx_payment).await - }) - }; + let name = format!("fee-acc-{}-{}", dest.name(), hyperbridge.name()); + task_manager.spawn_essential_handle().spawn_blocking( + Box::leak(Box::new(name.clone())), + "fees", + async move { + let res = + fee_accumulation(receiver, dest, hyperbridge, client_map, tx_payment).await; + tracing::error!("{name} terminated with result {res:?}"); + } + .boxed(), + ); + } // Spawn retries for unprofitable messages { @@ -104,30 +133,27 @@ where let tx_payment = tx_payment.clone(); let config = config.clone(); let sender = sender.clone(); - tokio::spawn(async move { - retry_unprofitable_messages( - dest, - hyperbridge, - client_map, - tx_payment, - config, - coprocessor, - sender, - ) - .await - }); + let name = format!("retries-{}-{}", dest.name(), hyperbridge.name()); + task_manager.spawn_essential_handle().spawn_blocking( + Box::leak(Box::new(name.clone())), + "messaging", + async move { + let res = retry_unprofitable_messages( + dest, + hyperbridge, + client_map, + tx_payment, + config, + coprocessor, + sender, + ) + .await; + tracing::error!("{name} terminated with result {res:?}"); + } + .boxed(), + ); } - // if one task completes, abort the other - tokio::select! { - result_a = task_a => { - result_a? - } - result_b = task_b => { - result_b? - } - }; - Ok(()) } @@ -325,64 +351,58 @@ async fn fee_accumulation { - let entry = groups.entry(query.source_chain).or_insert(vec![]); - entry.push(*receipt); - }, - TxReceipt::Response { query, .. } => { - let entry = groups.entry(query.source_chain).or_insert(vec![]); - entry.push(*receipt); - }, - }); - // Wait for destination chain's state machine update on hyperbridge - tracing::info!( - "Fee accumulation for {} messages submitted to {:?} has started", - receipts.len(), - dest.state_machine_id().state_id - ); - let dest_height = match wait_for_state_machine_update( - dest.state_machine_id(), - hyperbridge.clone(), - delivery_height, - ) - .await - { - Ok(height) => height, - Err(err) => { - tracing::error!("An error occurred while waiting for a state machine update, auto fee accumulation failed, Receipts have been stored in the db you can try again manually \n{err:?}"); - if let Err(err) = tx_payment.store_messages(receipts).await { - tracing::error!( - "Failed to store some delivered messages to database: {err:?}" - ) - } - return; - }, - }; + let hyperbridge = Arc::new(hyperbridge.clone()); - let stream = futures::stream::iter(groups); - stream.for_each_concurrent(None, |(source, receipts)| { + // Group receipts by source chain; + // Query latest state machine height of source on hyperbridge + // Get height at which messages were delivered to destination + // Wait for state machine update on hyperbridge + // Generate proofs + // Observe challenge period + // Submit proof + let mut groups = HashMap::new(); + let delivery_height = receipts + .iter() + .max_by(|a, b| a.height().cmp(&b.height())) + .map(|tx| tx.height()) + .expect("Infallible"); + receipts.iter().for_each(|receipt| match receipt { + TxReceipt::Request { query, .. } => { + let entry = groups.entry(query.source_chain).or_insert(vec![]); + entry.push(*receipt); + }, + TxReceipt::Response { query, .. } => { + let entry = groups.entry(query.source_chain).or_insert(vec![]); + entry.push(*receipt); + }, + }); + + // Wait for destination chain's state machine update on hyperbridge + tracing::info!( + "Fee accumulation for {} messages submitted to {:?} has started", + receipts.len(), + dest.state_machine_id().state_id + ); + let dest_height = match wait_for_state_machine_update( + dest.state_machine_id(), + hyperbridge.clone(), + delivery_height, + ) + .await + { + Ok(height) => height, + Err(err) => { + tracing::error!("An error occurred while waiting for a state machine update, auto fee accumulation failed, Receipts have been stored in the db you can try again manually \n{err:?}"); + if let Err(err) = tx_payment.store_messages(receipts).await { + tracing::error!("Failed to store some delivered messages to database: {err:?}") + } + continue; + }, + }; + + let stream = futures::stream::iter(groups); + stream.for_each_concurrent(None, |(source, receipts)| { let hyperbridge = hyperbridge.clone(); let source_chain = client_map.get(&source).cloned(); let dest = dest.clone(); @@ -416,8 +436,6 @@ async fn fee_accumulation(()) } diff --git a/tesseract/primitives/src/config.rs b/tesseract/primitives/src/config.rs index e63d2f9f1..ac04e8ffb 100644 --- a/tesseract/primitives/src/config.rs +++ b/tesseract/primitives/src/config.rs @@ -23,16 +23,6 @@ use serde::{Deserialize, Serialize}; pub struct RelayerConfig { /// Modules we're interested in relaying pub module_filter: Option>, - /// Relay consensus messages - pub consensus: Option, - /// Consensus stream timeout - pub consensus_stream_timeout: Option, - /// Relay messages - pub messaging: Option, - /// Fisherman protocol - pub fisherman: Option, - /// Challenege period to be set on consensus states - pub challenge_period: Option, /// Minimum profit percentage. e.g. 5 -> 5%, 10 -> 10% pub minimum_profit_percentage: u32, /// How frequently to initiate withdrawals in seconds. diff --git a/tesseract/primitives/src/lib.rs b/tesseract/primitives/src/lib.rs index a16f6b9d9..954fcc0f9 100644 --- a/tesseract/primitives/src/lib.rs +++ b/tesseract/primitives/src/lib.rs @@ -435,6 +435,11 @@ pub async fn wait_for_state_machine_update( hyperbridge: Arc, height: u64, ) -> anyhow::Result { + let latest_height = hyperbridge.query_latest_height(state_id).await?.into(); + if latest_height >= height { + return Ok(latest_height); + } + let mut stream = hyperbridge.state_machine_update_notification(state_id).await?; while let Some(res) = stream.next().await { diff --git a/tesseract/relayer/Cargo.toml b/tesseract/relayer/Cargo.toml index 361e05b4c..ee26c110d 100644 --- a/tesseract/relayer/Cargo.toml +++ b/tesseract/relayer/Cargo.toml @@ -37,11 +37,12 @@ json = { version = "1.0.112", package = "serde_json" } toml = "0.7.4" async-trait = "0.1.77" clap = { version = "4.3.5", features = ["derive"] } -tokio = { workspace = true, features = ["macros", "rt-multi-thread", "fs"] } +tokio = { workspace = true, features = ["full"] } rust_socketio = { version = "0.6.0", features = ["async"] } tracing-indicatif = "0.3.6" tracing = "0.1.40" console-subscriber = { version = "0.2.0", optional = true } +sc-service = { workspace = true } [dev-dependencies] divide_range = "0.1.1" diff --git a/tesseract/relayer/src/cli.rs b/tesseract/relayer/src/cli.rs index 268ccbc0a..e76f028ec 100644 --- a/tesseract/relayer/src/cli.rs +++ b/tesseract/relayer/src/cli.rs @@ -23,6 +23,7 @@ use ethers::prelude::H160; use futures::FutureExt; use ismp::host::StateMachine; use rust_socketio::asynchronous::ClientBuilder; +use sc_service::TaskManager; use sp_core::{ecdsa, ByteArray, Pair}; use std::{collections::HashMap, sync::Arc}; use telemetry_server::Message; @@ -54,69 +55,78 @@ impl Cli { let config = HyperbridgeConfig::parse_conf(&self.config).await?; let HyperbridgeConfig { hyperbridge: hyperbridge_config, relayer, .. } = config.clone(); - let mut processes = vec![]; let mut metadata = vec![]; - if relayer.messaging.unwrap_or(true) { - if relayer.minimum_profit_percentage == 0 { - log::warn!("Setting the minimum_profit_percentage=0 is not reccomended in live environments!"); - } - let tx_payment = Arc::new( - TransactionPayment::initialize(&self.db) - .await - .map_err(|err| anyhow!("Error initializing database: {err:?}"))?, + let tokio_handle = tokio::runtime::Handle::current(); + let mut task_manager = TaskManager::new(tokio_handle, None)?; + + if relayer.minimum_profit_percentage == 0 { + log::warn!( + "Setting the minimum_profit_percentage=0 is not reccomended in live environments!" ); - // Add hyperbridge to the client map - let hyperbridge = - SubstrateClient::::new(hyperbridge_config.clone()).await?; - let mut clients = - create_client_map(config.clone(), Arc::new(hyperbridge.clone())).await?; - clients.insert(hyperbridge.state_machine_id().state_id, Arc::new(hyperbridge.clone())); + } + let tx_payment = Arc::new( + TransactionPayment::initialize(&self.db) + .await + .map_err(|err| anyhow!("Error initializing database: {err:?}"))?, + ); + // Add hyperbridge to the client map + let hyperbridge = + SubstrateClient::::new(hyperbridge_config.clone()).await?; + let mut clients = create_client_map(config.clone(), Arc::new(hyperbridge.clone())).await?; + clients.insert(hyperbridge.state_machine_id().state_id, Arc::new(hyperbridge.clone())); + + if config.relayer.delivery_endpoints.is_empty() { + log::warn!( + "Delivery endpoints not specified in relayer config, will deliver to all chains." + ); + } - if config.relayer.delivery_endpoints.is_empty() { - log::warn!("Delivery endpoints not specified in relayer config, will deliver to all chains."); + // messaging tasks + for (state_machine, client) in &clients { + // If the delivery endpoint is not empty then we only spawn tasks for chains + // explicitly mentioned in the config + if !config.relayer.delivery_endpoints.is_empty() && + !config.relayer.delivery_endpoints.contains(&state_machine) + { + continue; } - // messaging tasks - for (state_machine, client) in &clients { - // If the delivery endpoint is not empty then we only spawn tasks for chains - // explicitly mentioned in the config - if !config.relayer.delivery_endpoints.is_empty() && - !config.relayer.delivery_endpoints.contains(&state_machine) - { - continue; - } - - let mut new_hyperbridge = - SubstrateClient::::new(hyperbridge_config.clone()) - .await?; - new_hyperbridge.set_latest_finalized_height(client.clone()).await?; - - let coprocessor = hyperbridge_config.state_machine; - processes.push(tokio::spawn(tesseract_messaging::relay( - new_hyperbridge, - client.clone(), - relayer.clone(), - coprocessor, - tx_payment.clone(), - clients.clone(), - ))); - - metadata.push(( - state_machine.clone(), - H160::from_slice(&client.address().as_slice()[..20]), - )); - } + let mut new_hyperbridge = + SubstrateClient::::new(hyperbridge_config.clone()).await?; + new_hyperbridge.set_latest_finalized_height(client.clone()).await?; - tokio::spawn(fees::auto_withdraw( - hyperbridge, + let coprocessor = hyperbridge_config.state_machine; + + tesseract_messaging::relay( + new_hyperbridge, + client.clone(), + relayer.clone(), + coprocessor, + tx_payment.clone(), clients.clone(), - config.relayer.clone(), - tx_payment, - )); + &task_manager, + ) + .await?; - log::info!("💬 Initialized messaging tasks"); + metadata.push(( + state_machine.clone(), + H160::from_slice(&client.address().as_slice()[..20]), + )); } + task_manager.spawn_essential_handle().spawn( + "auto-withdraw", + "fees", + async move { + let _ = + fees::auto_withdraw(hyperbridge, clients, config.relayer.clone(), tx_payment) + .await; + } + .boxed(), + ); + + log::info!("💬 Initialized messaging tasks"); + let socket = { if let Some(key) = option_env!("TELEMETRY_SECRET_KEY") { let bytes = hex::decode(key)?; @@ -150,11 +160,7 @@ impl Cli { } }; - let (_result, _index, tasks) = futures::future::select_all(processes).await; - - for task in tasks { - task.abort(); - } + task_manager.future().await?; if let Some(socket) = socket { socket.disconnect().await?; diff --git a/tesseract/relayer/src/fees.rs b/tesseract/relayer/src/fees.rs index 6711f85e9..ff363b954 100644 --- a/tesseract/relayer/src/fees.rs +++ b/tesseract/relayer/src/fees.rs @@ -49,7 +49,6 @@ impl AccumulateFees { pub async fn accumulate_fees(&self, config_path: String, db: String) -> anyhow::Result<()> { logging::animated_logs()?; let config = HyperbridgeConfig::parse_conf(&config_path).await?; - let HyperbridgeConfig { hyperbridge: hyperbridge_config, .. } = config.clone(); let hyperbridge = tesseract_substrate::SubstrateClient::::new( @@ -504,6 +503,7 @@ mod tests { let home = env!("HOME"); let path = format!("{home}/consensus.toml"); dbg!(&path); + let config = HyperbridgeConfig::parse_conf(&path).await?; let hyperbridge = SubstrateClient::::new(config.hyperbridge.clone()).await?; diff --git a/tesseract/substrate/Cargo.toml b/tesseract/substrate/Cargo.toml index d0f5741be..403bd695c 100644 --- a/tesseract/substrate/Cargo.toml +++ b/tesseract/substrate/Cargo.toml @@ -13,9 +13,9 @@ parking_lot = "0.12.1" hex-literal = { version = "0.4.1" } subxt = { version = "0.30.1", features = ["substrate-compat"] } codec = { package = "parity-scale-codec", version = "3.2.2", features = ["derive"] } -sp-core = { version = "21.0.0", features = ["full_crypto"] } +sp-core = { workspace = true, features = ["full_crypto"] } log = "0.4.19" -tokio = { workspace = true } +tokio = { workspace = true, features = ["sync", "time"] } tokio-stream = { workspace = true } zstd-safe = { version = "7.1.0" } diff --git a/tesseract/substrate/src/calls.rs b/tesseract/substrate/src/calls.rs index 4f27f6f94..85dab871f 100644 --- a/tesseract/substrate/src/calls.rs +++ b/tesseract/substrate/src/calls.rs @@ -19,14 +19,17 @@ use pallet_ismp_relayer::{ }; use sp_core::{ storage::{ChildInfo, StorageData, StorageKey}, - Pair, U256, + U256, }; use std::{collections::BTreeMap, sync::Arc}; use subxt::{ config::{ extrinsic_params::BaseExtrinsicParamsBuilder, polkadot::PlainTip, ExtrinsicParams, Header, }, - ext::sp_runtime::{traits::IdentifyAccount, MultiSignature, MultiSigner}, + ext::{ + sp_core::{crypto, Pair}, + sp_runtime::{traits::IdentifyAccount, MultiSignature, MultiSigner}, + }, rpc_params, tx::TxPayload, utils::AccountId32, @@ -50,13 +53,8 @@ where C::Header: Send + Sync, >::OtherParams: Default + Send + Sync + From>, - C::AccountId: From - + Into - + Encode - + Clone - + 'static - + Send - + Sync, + C::AccountId: + From + Into + Encode + Clone + 'static + Send + Sync, C::Signature: From + Send + Sync, { pub async fn create_consensus_state( @@ -98,13 +96,8 @@ where C::Header: Send + Sync, >::OtherParams: Default + Send + Sync + From>, - C::AccountId: From - + Into - + Encode - + Clone - + 'static - + Send - + Sync, + C::AccountId: + From + Into + Encode + Clone + 'static + Send + Sync, C::Signature: From + Send + Sync, { async fn available_amount( @@ -125,7 +118,7 @@ where let compressed_call_len = zstd_safe::compress(&mut buffer[..], &encoded_call, 3) .map_err(|_| anyhow!("Call compression failed"))?; // If compression saving is less than 15% submit the uncompressed call - if (uncompressed_len.saturating_sub(compressed_call_len) * 100 / uncompressed_len) < 15usize + if (uncompressed_len.saturating_sub(compressed_call_len) * 100 / uncompressed_len) < 20usize { send_unsigned_extrinsic(&self.client, extrinsic, true).await?; } else { diff --git a/tesseract/substrate/src/extrinsic.rs b/tesseract/substrate/src/extrinsic.rs index dbff83cc0..fdcbc15fc 100644 --- a/tesseract/substrate/src/extrinsic.rs +++ b/tesseract/substrate/src/extrinsic.rs @@ -17,10 +17,12 @@ use anyhow::{anyhow, Context}; use codec::Encode; -use sp_core::{sr25519, Pair}; use subxt::{ config::{extrinsic_params::BaseExtrinsicParamsBuilder, polkadot::PlainTip, ExtrinsicParams}, - ext::sp_runtime::{traits::IdentifyAccount, MultiSignature, MultiSigner}, + ext::{ + sp_core::{crypto, sr25519, Pair}, + sp_runtime::{traits::IdentifyAccount, MultiSignature, MultiSigner}, + }, rpc::types::DryRunResult, tx::{Signer, TxPayload}, Error, Metadata, OnlineClient, @@ -84,8 +86,7 @@ pub struct InMemorySigner { impl InMemorySigner where T::Signature: From + Send + Sync, - T::AccountId: - From + Into + Clone + 'static + Send + Sync, + T::AccountId: From + Into + Clone + 'static + Send + Sync, { pub fn new(pair: sr25519::Pair) -> Self { InMemorySigner { diff --git a/tesseract/substrate/src/lib.rs b/tesseract/substrate/src/lib.rs index dbef35f14..d9892c368 100644 --- a/tesseract/substrate/src/lib.rs +++ b/tesseract/substrate/src/lib.rs @@ -24,7 +24,7 @@ use pallet_ismp::child_trie::{ use tesseract_primitives::IsmpProvider; use serde::{Deserialize, Serialize}; -use sp_core::{bytes::from_hex, sr25519, Pair, H256}; +use subxt::ext::sp_core::{bytes::from_hex, crypto, sr25519, Pair, H256}; use substrate_state_machine::HashAlgorithm; use subxt::{ @@ -89,8 +89,7 @@ where >::OtherParams: Default + Send + Sync + From>, C::Signature: From + Send + Sync, - C::AccountId: - From + Into + Clone + 'static + Send + Sync, + C::AccountId: From + Into + Clone + 'static + Send + Sync, { pub async fn new(config: SubstrateConfig) -> Result { let max_rpc_payload_size = config.max_rpc_payload_size.unwrap_or(300u32 * 1024 * 1024); diff --git a/tesseract/substrate/src/provider.rs b/tesseract/substrate/src/provider.rs index d4478191e..1e2a1dc4d 100644 --- a/tesseract/substrate/src/provider.rs +++ b/tesseract/substrate/src/provider.rs @@ -19,7 +19,7 @@ use std::{collections::HashMap, sync::Arc, time::Duration}; use anyhow::{anyhow, Error}; use codec::{Decode, Encode}; -use futures::stream::FuturesOrdered; +use futures::{stream::FuturesOrdered, FutureExt}; use hex_literal::hex; use ismp::{ consensus::{ @@ -38,21 +38,24 @@ use pallet_ismp::{ use pallet_ismp_host_executive::HostParam; use pallet_ismp_relayer::withdrawal::Signature; use pallet_ismp_rpc::BlockNumberOrHash; -use sp_core::{ +use subxt::ext::sp_core::{ storage::{ChildInfo, StorageData, StorageKey}, Pair, H160, H256, U256, }; + use substrate_state_machine::{StateMachineProof, SubstrateStateProof}; use subxt::{ config::{ extrinsic_params::BaseExtrinsicParamsBuilder, polkadot::PlainTip, ExtrinsicParams, Header, }, - ext::sp_runtime::{traits::IdentifyAccount, MultiSignature, MultiSigner}, + ext::{ + sp_core::crypto::AccountId32, + sp_runtime::{traits::IdentifyAccount, MultiSignature, MultiSigner}, + }, rpc::types::DryRunResult, rpc_params, tx::TxPayload, }; -use tokio::time; use tesseract_primitives::{ BoxStream, EstimateGasReturnParams, IsmpProvider, Query, StateMachineUpdated, @@ -75,7 +78,7 @@ where C::Header: Send + Sync, >::OtherParams: Default + Send + Sync + From>, - C::AccountId: From + Into + Clone + Send + Sync, + C::AccountId: From + Into + Clone + Send + Sync, C::Signature: From + Send + Sync, { async fn query_consensus_state( @@ -357,15 +360,13 @@ where &self, counterparty_state_id: StateMachineId, ) -> Result, anyhow::Error> { - use futures::StreamExt; - let interval = time::interval(Duration::from_secs(10)); let client = self.clone(); - let (tx, recv) = tokio::sync::mpsc::channel(64); - tokio::spawn(async move { - let mut interval_stream = tokio_stream::wrappers::IntervalStream::new(interval); + let (tx, recv) = tokio::sync::mpsc::channel(256); + tokio::task::spawn(async move { let mut latest_height = client.initial_height; let state_machine = client.state_machine; - while let Some(_) = interval_stream.next().await { + loop { + tokio::time::sleep(Duration::from_secs(10)).await; let header = match client.client.rpc().finalized_head().await { Ok(hash) => match client.client.rpc().header(Some(hash)).await { Ok(Some(header)) => header, @@ -432,7 +433,8 @@ where match event { Some(event) => { if let Err(err) = tx.send(Ok(event.clone())).await { - log::error!(target: "tesseract", "Failed to send state machine update over channel on {state_machine:?} \n {err:?}"); + log::trace!(target: "tesseract", "Failed to send state machine update over channel on {state_machine:?} - {:?} \n {err:?}", counterparty_state_id.state_id); + return }; }, None => {}, @@ -440,11 +442,9 @@ where latest_height = header.number().into(); } - }); - - let stream = tokio_stream::wrappers::ReceiverStream::new(recv); + }.boxed()); - Ok(Box::pin(stream)) + Ok(Box::pin(tokio_stream::wrappers::ReceiverStream::new(recv))) } async fn submit(&self, messages: Vec) -> Result, anyhow::Error> { @@ -466,7 +466,7 @@ where .map_err(|_| anyhow!("Call compression failed"))?; // If compression saving is less than 15% submit the uncompressed call if (uncompressed_len.saturating_sub(compressed_call_len) * 100 / uncompressed_len) < - 15usize + 20usize { log::trace!(target: "tesseract", "Submitting uncompressed call: compressed:{}kb, uncompressed:{}kb", compressed_call_len / 1000, uncompressed_len / 1000); futs.push(send_unsigned_extrinsic(&self.client, extrinsic, false))