From 742ed6262b35fa0f6e882ee312e7778ab81c80d9 Mon Sep 17 00:00:00 2001 From: Web3 Philosopher Date: Thu, 13 Jun 2024 19:39:00 +0100 Subject: [PATCH] [EVM] Audit Fixes (#237) --- .github/workflows/hyperclient.yml | 3 +- docs/fixTrailingSlash.js | 1 + evm/abi/src/conversions.rs | 5 + evm/abi/src/generated/evm_host.rs | 711 +++++++++++++++++- evm/abi/src/generated/handler.rs | 435 ++++++++++- evm/abi/src/generated/host_manager.rs | 4 +- .../src/tests/host_manager.rs | 2 + evm/lib/ERC6160 | 2 +- evm/script/DeployGateway.s.sol | 2 +- evm/script/DeployIsmp.s.sol | 2 +- evm/src/consensus/Header.sol | 10 +- evm/src/consensus/ZkBeefy.sol | 4 +- .../consensus/verifiers/PolkadotVerifier.sol | 44 +- evm/src/hosts/EvmHost.sol | 121 ++- evm/src/modules/CallDispatcher.sol | 2 +- evm/src/modules/HandlerV1.sol | 100 ++- evm/src/modules/TokenFaucet.sol | 2 +- evm/src/modules/TokenGateway.sol | 85 ++- evm/test/EvmHostTest.sol | 12 +- evm/test/HostManagerTest.sol | 18 +- evm/test/TokenGatewayTest.sol | 8 +- parachain/node/src/command.rs | 4 +- 22 files changed, 1411 insertions(+), 166 deletions(-) diff --git a/.github/workflows/hyperclient.yml b/.github/workflows/hyperclient.yml index 6c11c58af..81d10e860 100644 --- a/.github/workflows/hyperclient.yml +++ b/.github/workflows/hyperclient.yml @@ -25,10 +25,9 @@ jobs: rustup target add wasm32-unknown-unknown - name: Build and Publish - working-directory: modules/client + working-directory: modules/hyperclient env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - INDEXER_URL: ${{ secrets.INDEXER_URL }} run: | wasm-pack build --release --no-default-features --features=wasm cd pkg diff --git a/docs/fixTrailingSlash.js b/docs/fixTrailingSlash.js index c0bcadf4d..7154e6c1c 100644 --- a/docs/fixTrailingSlash.js +++ b/docs/fixTrailingSlash.js @@ -18,6 +18,7 @@ import { glob } from "glob"; if (await fs.pathExists(filePathCopy)) { } else { await fs.copyFile(filePath, filePathCopy); + await fs.rm(filePath); } }), ); diff --git a/evm/abi/src/conversions.rs b/evm/abi/src/conversions.rs index 8ae52d710..08ffd25d0 100644 --- a/evm/abi/src/conversions.rs +++ b/evm/abi/src/conversions.rs @@ -366,6 +366,11 @@ impl TryFrom for ismp::events::Event { }, fisherman: vetoed.fisherman.as_bytes().to_vec(), })), + EvmHostEvents::HostFrozenFilter(_) | + EvmHostEvents::HostUnfrozenFilter(_) | + EvmHostEvents::HostParamsUpdatedFilter(_) | + EvmHostEvents::PostResponseFundedFilter(_) | + EvmHostEvents::RequestFundedFilter(_) => Err(anyhow!("Unsupported Event!"))?, } } } diff --git a/evm/abi/src/generated/evm_host.rs b/evm/abi/src/generated/evm_host.rs index 6294c2252..4479761dc 100644 --- a/evm/abi/src/generated/evm_host.rs +++ b/evm/abi/src/generated/evm_host.rs @@ -1486,6 +1486,93 @@ pub mod evm_host { }, ], ), + ( + ::std::borrow::ToOwned::to_owned("HostFrozen"), + ::std::vec![ + ::ethers::core::abi::ethabi::Event { + name: ::std::borrow::ToOwned::to_owned("HostFrozen"), + inputs: ::std::vec![], + anonymous: false, + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("HostParamsUpdated"), + ::std::vec![ + ::ethers::core::abi::ethabi::Event { + name: ::std::borrow::ToOwned::to_owned("HostParamsUpdated"), + inputs: ::std::vec![ + ::ethers::core::abi::ethabi::EventParam { + name: ::std::borrow::ToOwned::to_owned("oldParams"), + kind: ::ethers::core::abi::ethabi::ParamType::Tuple( + ::std::vec![ + ::ethers::core::abi::ethabi::ParamType::Uint(256usize), + ::ethers::core::abi::ethabi::ParamType::Uint(256usize), + ::ethers::core::abi::ethabi::ParamType::Address, + ::ethers::core::abi::ethabi::ParamType::Address, + ::ethers::core::abi::ethabi::ParamType::Address, + ::ethers::core::abi::ethabi::ParamType::Address, + ::ethers::core::abi::ethabi::ParamType::Uint(256usize), + ::ethers::core::abi::ethabi::ParamType::Uint(256usize), + ::ethers::core::abi::ethabi::ParamType::Address, + ::ethers::core::abi::ethabi::ParamType::Array( + ::std::boxed::Box::new( + ::ethers::core::abi::ethabi::ParamType::Uint(256usize), + ), + ), + ::ethers::core::abi::ethabi::ParamType::Array( + ::std::boxed::Box::new( + ::ethers::core::abi::ethabi::ParamType::Address, + ), + ), + ::ethers::core::abi::ethabi::ParamType::Bytes, + ], + ), + indexed: false, + }, + ::ethers::core::abi::ethabi::EventParam { + name: ::std::borrow::ToOwned::to_owned("newParams"), + kind: ::ethers::core::abi::ethabi::ParamType::Tuple( + ::std::vec![ + ::ethers::core::abi::ethabi::ParamType::Uint(256usize), + ::ethers::core::abi::ethabi::ParamType::Uint(256usize), + ::ethers::core::abi::ethabi::ParamType::Address, + ::ethers::core::abi::ethabi::ParamType::Address, + ::ethers::core::abi::ethabi::ParamType::Address, + ::ethers::core::abi::ethabi::ParamType::Address, + ::ethers::core::abi::ethabi::ParamType::Uint(256usize), + ::ethers::core::abi::ethabi::ParamType::Uint(256usize), + ::ethers::core::abi::ethabi::ParamType::Address, + ::ethers::core::abi::ethabi::ParamType::Array( + ::std::boxed::Box::new( + ::ethers::core::abi::ethabi::ParamType::Uint(256usize), + ), + ), + ::ethers::core::abi::ethabi::ParamType::Array( + ::std::boxed::Box::new( + ::ethers::core::abi::ethabi::ParamType::Address, + ), + ), + ::ethers::core::abi::ethabi::ParamType::Bytes, + ], + ), + indexed: false, + }, + ], + anonymous: false, + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("HostUnfrozen"), + ::std::vec![ + ::ethers::core::abi::ethabi::Event { + name: ::std::borrow::ToOwned::to_owned("HostUnfrozen"), + inputs: ::std::vec![], + anonymous: false, + }, + ], + ), ( ::std::borrow::ToOwned::to_owned("PostRequestEvent"), ::std::vec![ @@ -1662,6 +1749,31 @@ pub mod evm_host { }, ], ), + ( + ::std::borrow::ToOwned::to_owned("PostResponseFunded"), + ::std::vec![ + ::ethers::core::abi::ethabi::Event { + name: ::std::borrow::ToOwned::to_owned("PostResponseFunded"), + inputs: ::std::vec![ + ::ethers::core::abi::ethabi::EventParam { + name: ::std::borrow::ToOwned::to_owned("commitment"), + kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( + 32usize, + ), + indexed: false, + }, + ::ethers::core::abi::ethabi::EventParam { + name: ::std::borrow::ToOwned::to_owned("newFee"), + kind: ::ethers::core::abi::ethabi::ParamType::Uint( + 256usize, + ), + indexed: false, + }, + ], + anonymous: false, + }, + ], + ), ( ::std::borrow::ToOwned::to_owned("PostResponseHandled"), ::std::vec![ @@ -1712,6 +1824,31 @@ pub mod evm_host { }, ], ), + ( + ::std::borrow::ToOwned::to_owned("RequestFunded"), + ::std::vec![ + ::ethers::core::abi::ethabi::Event { + name: ::std::borrow::ToOwned::to_owned("RequestFunded"), + inputs: ::std::vec![ + ::ethers::core::abi::ethabi::EventParam { + name: ::std::borrow::ToOwned::to_owned("commitment"), + kind: ::ethers::core::abi::ethabi::ParamType::FixedBytes( + 32usize, + ), + indexed: false, + }, + ::ethers::core::abi::ethabi::EventParam { + name: ::std::borrow::ToOwned::to_owned("newFee"), + kind: ::ethers::core::abi::ethabi::ParamType::Uint( + 256usize, + ), + indexed: false, + }, + ], + anonymous: false, + }, + ], + ), ( ::std::borrow::ToOwned::to_owned("StateCommitmentVetoed"), ::std::vec![ @@ -1779,7 +1916,109 @@ pub mod evm_host { ], ), ]), - errors: ::std::collections::BTreeMap::new(), + errors: ::core::convert::From::from([ + ( + ::std::borrow::ToOwned::to_owned("DuplicateResponse"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned("DuplicateResponse"), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("InvalidAddressLength"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned( + "InvalidAddressLength", + ), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("InvalidHostManagerAddress"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned( + "InvalidHostManagerAddress", + ), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("MaxFishermanCountExceeded"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned( + "MaxFishermanCountExceeded", + ), + inputs: ::std::vec![ + ::ethers::core::abi::ethabi::Param { + name: ::std::borrow::ToOwned::to_owned("provided"), + kind: ::ethers::core::abi::ethabi::ParamType::Uint( + 256usize, + ), + internal_type: ::core::option::Option::Some( + ::std::borrow::ToOwned::to_owned("uint256"), + ), + }, + ], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("UnauthorizedAccount"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned( + "UnauthorizedAccount", + ), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("UnauthorizedAction"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned("UnauthorizedAction"), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("UnauthorizedResponse"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned( + "UnauthorizedResponse", + ), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("UnknownRequest"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned("UnknownRequest"), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("UnknownResponse"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned("UnknownResponse"), + inputs: ::std::vec![], + }, + ], + ), + ]), receive: false, fallback: false, } @@ -2215,6 +2454,24 @@ pub mod evm_host { > { self.0.event() } + ///Gets the contract's `HostFrozen` event + pub fn host_frozen_filter( + &self, + ) -> ::ethers::contract::builders::Event<::std::sync::Arc, M, HostFrozenFilter> { + self.0.event() + } + ///Gets the contract's `HostParamsUpdated` event + pub fn host_params_updated_filter( + &self, + ) -> ::ethers::contract::builders::Event<::std::sync::Arc, M, HostParamsUpdatedFilter> { + self.0.event() + } + ///Gets the contract's `HostUnfrozen` event + pub fn host_unfrozen_filter( + &self, + ) -> ::ethers::contract::builders::Event<::std::sync::Arc, M, HostUnfrozenFilter> { + self.0.event() + } ///Gets the contract's `PostRequestEvent` event pub fn post_request_event_filter( &self, @@ -2243,6 +2500,12 @@ pub mod evm_host { ) -> ::ethers::contract::builders::Event<::std::sync::Arc, M, PostResponseEventFilter> { self.0.event() } + ///Gets the contract's `PostResponseFunded` event + pub fn post_response_funded_filter( + &self, + ) -> ::ethers::contract::builders::Event<::std::sync::Arc, M, PostResponseFundedFilter> { + self.0.event() + } ///Gets the contract's `PostResponseHandled` event pub fn post_response_handled_filter( &self, @@ -2260,6 +2523,12 @@ pub mod evm_host { > { self.0.event() } + ///Gets the contract's `RequestFunded` event + pub fn request_funded_filter( + &self, + ) -> ::ethers::contract::builders::Event<::std::sync::Arc, M, RequestFundedFilter> { + self.0.event() + } ///Gets the contract's `StateCommitmentVetoed` event pub fn state_commitment_vetoed_filter( &self, @@ -2286,6 +2555,324 @@ pub mod evm_host { Self::new(contract.address(), contract.client()) } } + ///Custom Error type `DuplicateResponse` with signature `DuplicateResponse()` and selector + /// `0x276d57d8` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "DuplicateResponse", abi = "DuplicateResponse()")] + pub struct DuplicateResponse; + ///Custom Error type `InvalidAddressLength` with signature `InvalidAddressLength()` and + /// selector `0xcc2cec02` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "InvalidAddressLength", abi = "InvalidAddressLength()")] + pub struct InvalidAddressLength; + ///Custom Error type `InvalidHostManagerAddress` with signature `InvalidHostManagerAddress()` + /// and selector `0x5168b54e` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "InvalidHostManagerAddress", abi = "InvalidHostManagerAddress()")] + pub struct InvalidHostManagerAddress; + ///Custom Error type `MaxFishermanCountExceeded` with signature + /// `MaxFishermanCountExceeded(uint256)` and selector `0x67797238` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "MaxFishermanCountExceeded", abi = "MaxFishermanCountExceeded(uint256)")] + pub struct MaxFishermanCountExceeded { + pub provided: ::ethers::core::types::U256, + } + ///Custom Error type `UnauthorizedAccount` with signature `UnauthorizedAccount()` and selector + /// `0xa97ff08a` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "UnauthorizedAccount", abi = "UnauthorizedAccount()")] + pub struct UnauthorizedAccount; + ///Custom Error type `UnauthorizedAction` with signature `UnauthorizedAction()` and selector + /// `0x843800fa` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "UnauthorizedAction", abi = "UnauthorizedAction()")] + pub struct UnauthorizedAction; + ///Custom Error type `UnauthorizedResponse` with signature `UnauthorizedResponse()` and + /// selector `0x850dc39c` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "UnauthorizedResponse", abi = "UnauthorizedResponse()")] + pub struct UnauthorizedResponse; + ///Custom Error type `UnknownRequest` with signature `UnknownRequest()` and selector + /// `0x6d080297` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "UnknownRequest", abi = "UnknownRequest()")] + pub struct UnknownRequest; + ///Custom Error type `UnknownResponse` with signature `UnknownResponse()` and selector + /// `0x950a5b24` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "UnknownResponse", abi = "UnknownResponse()")] + pub struct UnknownResponse; + ///Container type for all of the contract's custom errors + #[derive(Clone, ::ethers::contract::EthAbiType, Debug, PartialEq, Eq, Hash)] + pub enum EvmHostErrors { + DuplicateResponse(DuplicateResponse), + InvalidAddressLength(InvalidAddressLength), + InvalidHostManagerAddress(InvalidHostManagerAddress), + MaxFishermanCountExceeded(MaxFishermanCountExceeded), + UnauthorizedAccount(UnauthorizedAccount), + UnauthorizedAction(UnauthorizedAction), + UnauthorizedResponse(UnauthorizedResponse), + UnknownRequest(UnknownRequest), + UnknownResponse(UnknownResponse), + /// The standard solidity revert string, with selector + /// Error(string) -- 0x08c379a0 + RevertString(::std::string::String), + } + impl ::ethers::core::abi::AbiDecode for EvmHostErrors { + fn decode( + data: impl AsRef<[u8]>, + ) -> ::core::result::Result { + let data = data.as_ref(); + if let Ok(decoded) = + <::std::string::String as ::ethers::core::abi::AbiDecode>::decode(data) + { + return Ok(Self::RevertString(decoded)); + } + if let Ok(decoded) = ::decode(data) + { + return Ok(Self::DuplicateResponse(decoded)); + } + if let Ok(decoded) = + ::decode(data) + { + return Ok(Self::InvalidAddressLength(decoded)); + } + if let Ok(decoded) = + ::decode(data) + { + return Ok(Self::InvalidHostManagerAddress(decoded)); + } + if let Ok(decoded) = + ::decode(data) + { + return Ok(Self::MaxFishermanCountExceeded(decoded)); + } + if let Ok(decoded) = + ::decode(data) + { + return Ok(Self::UnauthorizedAccount(decoded)); + } + if let Ok(decoded) = + ::decode(data) + { + return Ok(Self::UnauthorizedAction(decoded)); + } + if let Ok(decoded) = + ::decode(data) + { + return Ok(Self::UnauthorizedResponse(decoded)); + } + if let Ok(decoded) = ::decode(data) { + return Ok(Self::UnknownRequest(decoded)); + } + if let Ok(decoded) = ::decode(data) { + return Ok(Self::UnknownResponse(decoded)); + } + Err(::ethers::core::abi::Error::InvalidData.into()) + } + } + impl ::ethers::core::abi::AbiEncode for EvmHostErrors { + fn encode(self) -> ::std::vec::Vec { + match self { + Self::DuplicateResponse(element) => ::ethers::core::abi::AbiEncode::encode(element), + Self::InvalidAddressLength(element) => + ::ethers::core::abi::AbiEncode::encode(element), + Self::InvalidHostManagerAddress(element) => + ::ethers::core::abi::AbiEncode::encode(element), + Self::MaxFishermanCountExceeded(element) => + ::ethers::core::abi::AbiEncode::encode(element), + Self::UnauthorizedAccount(element) => + ::ethers::core::abi::AbiEncode::encode(element), + Self::UnauthorizedAction(element) => + ::ethers::core::abi::AbiEncode::encode(element), + Self::UnauthorizedResponse(element) => + ::ethers::core::abi::AbiEncode::encode(element), + Self::UnknownRequest(element) => ::ethers::core::abi::AbiEncode::encode(element), + Self::UnknownResponse(element) => ::ethers::core::abi::AbiEncode::encode(element), + Self::RevertString(s) => ::ethers::core::abi::AbiEncode::encode(s), + } + } + } + impl ::ethers::contract::ContractRevert for EvmHostErrors { + fn valid_selector(selector: [u8; 4]) -> bool { + match selector { + [0x08, 0xc3, 0x79, 0xa0] => true, + _ if selector == + ::selector() => + true, + _ if selector == + ::selector() => + true, + _ if selector == + ::selector() => + true, + _ if selector == + ::selector() => + true, + _ if selector == + ::selector() => + true, + _ if selector == + ::selector() => + true, + _ if selector == + ::selector() => + true, + _ if selector == ::selector() => + true, + _ if selector == ::selector() => + true, + _ => false, + } + } + } + impl ::core::fmt::Display for EvmHostErrors { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + match self { + Self::DuplicateResponse(element) => ::core::fmt::Display::fmt(element, f), + Self::InvalidAddressLength(element) => ::core::fmt::Display::fmt(element, f), + Self::InvalidHostManagerAddress(element) => ::core::fmt::Display::fmt(element, f), + Self::MaxFishermanCountExceeded(element) => ::core::fmt::Display::fmt(element, f), + Self::UnauthorizedAccount(element) => ::core::fmt::Display::fmt(element, f), + Self::UnauthorizedAction(element) => ::core::fmt::Display::fmt(element, f), + Self::UnauthorizedResponse(element) => ::core::fmt::Display::fmt(element, f), + Self::UnknownRequest(element) => ::core::fmt::Display::fmt(element, f), + Self::UnknownResponse(element) => ::core::fmt::Display::fmt(element, f), + Self::RevertString(s) => ::core::fmt::Display::fmt(s, f), + } + } + } + impl ::core::convert::From<::std::string::String> for EvmHostErrors { + fn from(value: String) -> Self { + Self::RevertString(value) + } + } + impl ::core::convert::From for EvmHostErrors { + fn from(value: DuplicateResponse) -> Self { + Self::DuplicateResponse(value) + } + } + impl ::core::convert::From for EvmHostErrors { + fn from(value: InvalidAddressLength) -> Self { + Self::InvalidAddressLength(value) + } + } + impl ::core::convert::From for EvmHostErrors { + fn from(value: InvalidHostManagerAddress) -> Self { + Self::InvalidHostManagerAddress(value) + } + } + impl ::core::convert::From for EvmHostErrors { + fn from(value: MaxFishermanCountExceeded) -> Self { + Self::MaxFishermanCountExceeded(value) + } + } + impl ::core::convert::From for EvmHostErrors { + fn from(value: UnauthorizedAccount) -> Self { + Self::UnauthorizedAccount(value) + } + } + impl ::core::convert::From for EvmHostErrors { + fn from(value: UnauthorizedAction) -> Self { + Self::UnauthorizedAction(value) + } + } + impl ::core::convert::From for EvmHostErrors { + fn from(value: UnauthorizedResponse) -> Self { + Self::UnauthorizedResponse(value) + } + } + impl ::core::convert::From for EvmHostErrors { + fn from(value: UnknownRequest) -> Self { + Self::UnknownRequest(value) + } + } + impl ::core::convert::From for EvmHostErrors { + fn from(value: UnknownResponse) -> Self { + Self::UnknownResponse(value) + } + } #[derive( Clone, ::ethers::contract::EthEvent, @@ -2350,6 +2937,48 @@ pub mod evm_host { Eq, Hash, )] + #[ethevent(name = "HostFrozen", abi = "HostFrozen()")] + pub struct HostFrozenFilter; + #[derive( + Clone, + ::ethers::contract::EthEvent, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[ethevent( + name = "HostParamsUpdated", + abi = "HostParamsUpdated((uint256,uint256,address,address,address,address,uint256,uint256,address,uint256[],address[],bytes),(uint256,uint256,address,address,address,address,uint256,uint256,address,uint256[],address[],bytes))" + )] + pub struct HostParamsUpdatedFilter { + pub old_params: HostParams, + pub new_params: HostParams, + } + #[derive( + Clone, + ::ethers::contract::EthEvent, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[ethevent(name = "HostUnfrozen", abi = "HostUnfrozen()")] + pub struct HostUnfrozenFilter; + #[derive( + Clone, + ::ethers::contract::EthEvent, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] #[ethevent( name = "PostRequestEvent", abi = "PostRequestEvent(bytes,bytes,bytes,bytes,uint256,uint256,bytes,uint256)" @@ -2435,6 +3064,21 @@ pub mod evm_host { Eq, Hash, )] + #[ethevent(name = "PostResponseFunded", abi = "PostResponseFunded(bytes32,uint256)")] + pub struct PostResponseFundedFilter { + pub commitment: [u8; 32], + pub new_fee: ::ethers::core::types::U256, + } + #[derive( + Clone, + ::ethers::contract::EthEvent, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] #[ethevent(name = "PostResponseHandled", abi = "PostResponseHandled(bytes32,address)")] pub struct PostResponseHandledFilter { pub commitment: [u8; 32], @@ -2468,6 +3112,21 @@ pub mod evm_host { Eq, Hash, )] + #[ethevent(name = "RequestFunded", abi = "RequestFunded(bytes32,uint256)")] + pub struct RequestFundedFilter { + pub commitment: [u8; 32], + pub new_fee: ::ethers::core::types::U256, + } + #[derive( + Clone, + ::ethers::contract::EthEvent, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] #[ethevent( name = "StateCommitmentVetoed", abi = "StateCommitmentVetoed(bytes,uint256,(uint256,bytes32,bytes32),address)" @@ -2499,12 +3158,17 @@ pub mod evm_host { GetRequestEventFilter(GetRequestEventFilter), GetRequestHandledFilter(GetRequestHandledFilter), GetRequestTimeoutHandledFilter(GetRequestTimeoutHandledFilter), + HostFrozenFilter(HostFrozenFilter), + HostParamsUpdatedFilter(HostParamsUpdatedFilter), + HostUnfrozenFilter(HostUnfrozenFilter), PostRequestEventFilter(PostRequestEventFilter), PostRequestHandledFilter(PostRequestHandledFilter), PostRequestTimeoutHandledFilter(PostRequestTimeoutHandledFilter), PostResponseEventFilter(PostResponseEventFilter), + PostResponseFundedFilter(PostResponseFundedFilter), PostResponseHandledFilter(PostResponseHandledFilter), PostResponseTimeoutHandledFilter(PostResponseTimeoutHandledFilter), + RequestFundedFilter(RequestFundedFilter), StateCommitmentVetoedFilter(StateCommitmentVetoedFilter), StateMachineUpdatedFilter(StateMachineUpdatedFilter), } @@ -2521,6 +3185,15 @@ pub mod evm_host { if let Ok(decoded) = GetRequestTimeoutHandledFilter::decode_log(log) { return Ok(EvmHostEvents::GetRequestTimeoutHandledFilter(decoded)); } + if let Ok(decoded) = HostFrozenFilter::decode_log(log) { + return Ok(EvmHostEvents::HostFrozenFilter(decoded)); + } + if let Ok(decoded) = HostParamsUpdatedFilter::decode_log(log) { + return Ok(EvmHostEvents::HostParamsUpdatedFilter(decoded)); + } + if let Ok(decoded) = HostUnfrozenFilter::decode_log(log) { + return Ok(EvmHostEvents::HostUnfrozenFilter(decoded)); + } if let Ok(decoded) = PostRequestEventFilter::decode_log(log) { return Ok(EvmHostEvents::PostRequestEventFilter(decoded)); } @@ -2533,12 +3206,18 @@ pub mod evm_host { if let Ok(decoded) = PostResponseEventFilter::decode_log(log) { return Ok(EvmHostEvents::PostResponseEventFilter(decoded)); } + if let Ok(decoded) = PostResponseFundedFilter::decode_log(log) { + return Ok(EvmHostEvents::PostResponseFundedFilter(decoded)); + } if let Ok(decoded) = PostResponseHandledFilter::decode_log(log) { return Ok(EvmHostEvents::PostResponseHandledFilter(decoded)); } if let Ok(decoded) = PostResponseTimeoutHandledFilter::decode_log(log) { return Ok(EvmHostEvents::PostResponseTimeoutHandledFilter(decoded)); } + if let Ok(decoded) = RequestFundedFilter::decode_log(log) { + return Ok(EvmHostEvents::RequestFundedFilter(decoded)); + } if let Ok(decoded) = StateCommitmentVetoedFilter::decode_log(log) { return Ok(EvmHostEvents::StateCommitmentVetoedFilter(decoded)); } @@ -2555,14 +3234,19 @@ pub mod evm_host { Self::GetRequestHandledFilter(element) => ::core::fmt::Display::fmt(element, f), Self::GetRequestTimeoutHandledFilter(element) => ::core::fmt::Display::fmt(element, f), + Self::HostFrozenFilter(element) => ::core::fmt::Display::fmt(element, f), + Self::HostParamsUpdatedFilter(element) => ::core::fmt::Display::fmt(element, f), + Self::HostUnfrozenFilter(element) => ::core::fmt::Display::fmt(element, f), Self::PostRequestEventFilter(element) => ::core::fmt::Display::fmt(element, f), Self::PostRequestHandledFilter(element) => ::core::fmt::Display::fmt(element, f), Self::PostRequestTimeoutHandledFilter(element) => ::core::fmt::Display::fmt(element, f), Self::PostResponseEventFilter(element) => ::core::fmt::Display::fmt(element, f), + Self::PostResponseFundedFilter(element) => ::core::fmt::Display::fmt(element, f), Self::PostResponseHandledFilter(element) => ::core::fmt::Display::fmt(element, f), Self::PostResponseTimeoutHandledFilter(element) => ::core::fmt::Display::fmt(element, f), + Self::RequestFundedFilter(element) => ::core::fmt::Display::fmt(element, f), Self::StateCommitmentVetoedFilter(element) => ::core::fmt::Display::fmt(element, f), Self::StateMachineUpdatedFilter(element) => ::core::fmt::Display::fmt(element, f), } @@ -2583,6 +3267,21 @@ pub mod evm_host { Self::GetRequestTimeoutHandledFilter(value) } } + impl ::core::convert::From for EvmHostEvents { + fn from(value: HostFrozenFilter) -> Self { + Self::HostFrozenFilter(value) + } + } + impl ::core::convert::From for EvmHostEvents { + fn from(value: HostParamsUpdatedFilter) -> Self { + Self::HostParamsUpdatedFilter(value) + } + } + impl ::core::convert::From for EvmHostEvents { + fn from(value: HostUnfrozenFilter) -> Self { + Self::HostUnfrozenFilter(value) + } + } impl ::core::convert::From for EvmHostEvents { fn from(value: PostRequestEventFilter) -> Self { Self::PostRequestEventFilter(value) @@ -2603,6 +3302,11 @@ pub mod evm_host { Self::PostResponseEventFilter(value) } } + impl ::core::convert::From for EvmHostEvents { + fn from(value: PostResponseFundedFilter) -> Self { + Self::PostResponseFundedFilter(value) + } + } impl ::core::convert::From for EvmHostEvents { fn from(value: PostResponseHandledFilter) -> Self { Self::PostResponseHandledFilter(value) @@ -2613,6 +3317,11 @@ pub mod evm_host { Self::PostResponseTimeoutHandledFilter(value) } } + impl ::core::convert::From for EvmHostEvents { + fn from(value: RequestFundedFilter) -> Self { + Self::RequestFundedFilter(value) + } + } impl ::core::convert::From for EvmHostEvents { fn from(value: StateCommitmentVetoedFilter) -> Self { Self::StateCommitmentVetoedFilter(value) diff --git a/evm/abi/src/generated/handler.rs b/evm/abi/src/generated/handler.rs index 69c0def1f..c68dd7ac4 100644 --- a/evm/abi/src/generated/handler.rs +++ b/evm/abi/src/generated/handler.rs @@ -430,7 +430,106 @@ pub mod handler { ), ]), events: ::std::collections::BTreeMap::new(), - errors: ::std::collections::BTreeMap::new(), + errors: ::core::convert::From::from([ + ( + ::std::borrow::ToOwned::to_owned("ChallengePeriodNotElapsed"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned( + "ChallengePeriodNotElapsed", + ), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("ConsensusClientExpired"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned( + "ConsensusClientExpired", + ), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("DuplicateMessage"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned("DuplicateMessage"), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("HostFrozen"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned("HostFrozen"), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("InvalidMessageDestination"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned( + "InvalidMessageDestination", + ), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("InvalidProof"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned("InvalidProof"), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("MessageNotTimedOut"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned("MessageNotTimedOut"), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("MessageTimedOut"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned("MessageTimedOut"), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("StateCommitmentNotFound"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned( + "StateCommitmentNotFound", + ), + inputs: ::std::vec![], + }, + ], + ), + ( + ::std::borrow::ToOwned::to_owned("UnknownMessage"), + ::std::vec![ + ::ethers::core::abi::ethabi::AbiError { + name: ::std::borrow::ToOwned::to_owned("UnknownMessage"), + inputs: ::std::vec![], + }, + ], + ), + ]), receive: false, fallback: false, } @@ -545,6 +644,340 @@ pub mod handler { Self::new(contract.address(), contract.client()) } } + ///Custom Error type `ChallengePeriodNotElapsed` with signature `ChallengePeriodNotElapsed()` + /// and selector `0x048c9699` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "ChallengePeriodNotElapsed", abi = "ChallengePeriodNotElapsed()")] + pub struct ChallengePeriodNotElapsed; + ///Custom Error type `ConsensusClientExpired` with signature `ConsensusClientExpired()` and + /// selector `0x40dc5c30` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "ConsensusClientExpired", abi = "ConsensusClientExpired()")] + pub struct ConsensusClientExpired; + ///Custom Error type `DuplicateMessage` with signature `DuplicateMessage()` and selector + /// `0x2ad4ae2e` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "DuplicateMessage", abi = "DuplicateMessage()")] + pub struct DuplicateMessage; + ///Custom Error type `HostFrozen` with signature `HostFrozen()` and selector `0xe36afbb8` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "HostFrozen", abi = "HostFrozen()")] + pub struct HostFrozen; + ///Custom Error type `InvalidMessageDestination` with signature `InvalidMessageDestination()` + /// and selector `0x90d4c209` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "InvalidMessageDestination", abi = "InvalidMessageDestination()")] + pub struct InvalidMessageDestination; + ///Custom Error type `InvalidProof` with signature `InvalidProof()` and selector `0x09bde339` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "InvalidProof", abi = "InvalidProof()")] + pub struct InvalidProof; + ///Custom Error type `MessageNotTimedOut` with signature `MessageNotTimedOut()` and selector + /// `0x91d1ba5e` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "MessageNotTimedOut", abi = "MessageNotTimedOut()")] + pub struct MessageNotTimedOut; + ///Custom Error type `MessageTimedOut` with signature `MessageTimedOut()` and selector + /// `0x1676f4b3` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "MessageTimedOut", abi = "MessageTimedOut()")] + pub struct MessageTimedOut; + ///Custom Error type `StateCommitmentNotFound` with signature `StateCommitmentNotFound()` and + /// selector `0xa75caa56` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "StateCommitmentNotFound", abi = "StateCommitmentNotFound()")] + pub struct StateCommitmentNotFound; + ///Custom Error type `UnknownMessage` with signature `UnknownMessage()` and selector + /// `0xf058bfd9` + #[derive( + Clone, + ::ethers::contract::EthError, + ::ethers::contract::EthDisplay, + Default, + Debug, + PartialEq, + Eq, + Hash, + )] + #[etherror(name = "UnknownMessage", abi = "UnknownMessage()")] + pub struct UnknownMessage; + ///Container type for all of the contract's custom errors + #[derive(Clone, ::ethers::contract::EthAbiType, Debug, PartialEq, Eq, Hash)] + pub enum HandlerErrors { + ChallengePeriodNotElapsed(ChallengePeriodNotElapsed), + ConsensusClientExpired(ConsensusClientExpired), + DuplicateMessage(DuplicateMessage), + HostFrozen(HostFrozen), + InvalidMessageDestination(InvalidMessageDestination), + InvalidProof(InvalidProof), + MessageNotTimedOut(MessageNotTimedOut), + MessageTimedOut(MessageTimedOut), + StateCommitmentNotFound(StateCommitmentNotFound), + UnknownMessage(UnknownMessage), + /// The standard solidity revert string, with selector + /// Error(string) -- 0x08c379a0 + RevertString(::std::string::String), + } + impl ::ethers::core::abi::AbiDecode for HandlerErrors { + fn decode( + data: impl AsRef<[u8]>, + ) -> ::core::result::Result { + let data = data.as_ref(); + if let Ok(decoded) = + <::std::string::String as ::ethers::core::abi::AbiDecode>::decode(data) + { + return Ok(Self::RevertString(decoded)); + } + if let Ok(decoded) = + ::decode(data) + { + return Ok(Self::ChallengePeriodNotElapsed(decoded)); + } + if let Ok(decoded) = + ::decode(data) + { + return Ok(Self::ConsensusClientExpired(decoded)); + } + if let Ok(decoded) = ::decode(data) + { + return Ok(Self::DuplicateMessage(decoded)); + } + if let Ok(decoded) = ::decode(data) { + return Ok(Self::HostFrozen(decoded)); + } + if let Ok(decoded) = + ::decode(data) + { + return Ok(Self::InvalidMessageDestination(decoded)); + } + if let Ok(decoded) = ::decode(data) { + return Ok(Self::InvalidProof(decoded)); + } + if let Ok(decoded) = + ::decode(data) + { + return Ok(Self::MessageNotTimedOut(decoded)); + } + if let Ok(decoded) = ::decode(data) { + return Ok(Self::MessageTimedOut(decoded)); + } + if let Ok(decoded) = + ::decode(data) + { + return Ok(Self::StateCommitmentNotFound(decoded)); + } + if let Ok(decoded) = ::decode(data) { + return Ok(Self::UnknownMessage(decoded)); + } + Err(::ethers::core::abi::Error::InvalidData.into()) + } + } + impl ::ethers::core::abi::AbiEncode for HandlerErrors { + fn encode(self) -> ::std::vec::Vec { + match self { + Self::ChallengePeriodNotElapsed(element) => + ::ethers::core::abi::AbiEncode::encode(element), + Self::ConsensusClientExpired(element) => + ::ethers::core::abi::AbiEncode::encode(element), + Self::DuplicateMessage(element) => ::ethers::core::abi::AbiEncode::encode(element), + Self::HostFrozen(element) => ::ethers::core::abi::AbiEncode::encode(element), + Self::InvalidMessageDestination(element) => + ::ethers::core::abi::AbiEncode::encode(element), + Self::InvalidProof(element) => ::ethers::core::abi::AbiEncode::encode(element), + Self::MessageNotTimedOut(element) => + ::ethers::core::abi::AbiEncode::encode(element), + Self::MessageTimedOut(element) => ::ethers::core::abi::AbiEncode::encode(element), + Self::StateCommitmentNotFound(element) => + ::ethers::core::abi::AbiEncode::encode(element), + Self::UnknownMessage(element) => ::ethers::core::abi::AbiEncode::encode(element), + Self::RevertString(s) => ::ethers::core::abi::AbiEncode::encode(s), + } + } + } + impl ::ethers::contract::ContractRevert for HandlerErrors { + fn valid_selector(selector: [u8; 4]) -> bool { + match selector { + [0x08, 0xc3, 0x79, 0xa0] => true, + _ if selector == + ::selector() => + true, + _ if selector == + ::selector() => + true, + _ if selector == ::selector() => + true, + _ if selector == ::selector() => true, + _ if selector == + ::selector() => + true, + _ if selector == ::selector() => true, + _ if selector == + ::selector() => + true, + _ if selector == ::selector() => + true, + _ if selector == + ::selector() => + true, + _ if selector == ::selector() => + true, + _ => false, + } + } + } + impl ::core::fmt::Display for HandlerErrors { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + match self { + Self::ChallengePeriodNotElapsed(element) => ::core::fmt::Display::fmt(element, f), + Self::ConsensusClientExpired(element) => ::core::fmt::Display::fmt(element, f), + Self::DuplicateMessage(element) => ::core::fmt::Display::fmt(element, f), + Self::HostFrozen(element) => ::core::fmt::Display::fmt(element, f), + Self::InvalidMessageDestination(element) => ::core::fmt::Display::fmt(element, f), + Self::InvalidProof(element) => ::core::fmt::Display::fmt(element, f), + Self::MessageNotTimedOut(element) => ::core::fmt::Display::fmt(element, f), + Self::MessageTimedOut(element) => ::core::fmt::Display::fmt(element, f), + Self::StateCommitmentNotFound(element) => ::core::fmt::Display::fmt(element, f), + Self::UnknownMessage(element) => ::core::fmt::Display::fmt(element, f), + Self::RevertString(s) => ::core::fmt::Display::fmt(s, f), + } + } + } + impl ::core::convert::From<::std::string::String> for HandlerErrors { + fn from(value: String) -> Self { + Self::RevertString(value) + } + } + impl ::core::convert::From for HandlerErrors { + fn from(value: ChallengePeriodNotElapsed) -> Self { + Self::ChallengePeriodNotElapsed(value) + } + } + impl ::core::convert::From for HandlerErrors { + fn from(value: ConsensusClientExpired) -> Self { + Self::ConsensusClientExpired(value) + } + } + impl ::core::convert::From for HandlerErrors { + fn from(value: DuplicateMessage) -> Self { + Self::DuplicateMessage(value) + } + } + impl ::core::convert::From for HandlerErrors { + fn from(value: HostFrozen) -> Self { + Self::HostFrozen(value) + } + } + impl ::core::convert::From for HandlerErrors { + fn from(value: InvalidMessageDestination) -> Self { + Self::InvalidMessageDestination(value) + } + } + impl ::core::convert::From for HandlerErrors { + fn from(value: InvalidProof) -> Self { + Self::InvalidProof(value) + } + } + impl ::core::convert::From for HandlerErrors { + fn from(value: MessageNotTimedOut) -> Self { + Self::MessageNotTimedOut(value) + } + } + impl ::core::convert::From for HandlerErrors { + fn from(value: MessageTimedOut) -> Self { + Self::MessageTimedOut(value) + } + } + impl ::core::convert::From for HandlerErrors { + fn from(value: StateCommitmentNotFound) -> Self { + Self::StateCommitmentNotFound(value) + } + } + impl ::core::convert::From for HandlerErrors { + fn from(value: UnknownMessage) -> Self { + Self::UnknownMessage(value) + } + } ///Container type for all input parameters for the `handleConsensus` function with signature /// `handleConsensus(address,bytes)` and selector `0xbb1689be` #[derive( diff --git a/evm/abi/src/generated/host_manager.rs b/evm/abi/src/generated/host_manager.rs index c27fe7d65..ab08f7acf 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\x0EdG\xBD\xB6!dsolcC\0\x08\x11\x003"; /// The bytecode of the contract. pub static HOSTMANAGER_BYTECODE: ::ethers::core::types::Bytes = ::ethers::core::types::Bytes::from_static(__BYTECODE); #[rustfmt::skip] - const __DEPLOYED_BYTECODE: &[u8] = b"`\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\x0EdG\xBD\xB6!dsolcC\0\x08\x11\x003"; /// The deployed bytecode of the contract. pub static HOSTMANAGER_DEPLOYED_BYTECODE: ::ethers::core::types::Bytes = ::ethers::core::types::Bytes::from_static(__DEPLOYED_BYTECODE); diff --git a/evm/integration-tests/src/tests/host_manager.rs b/evm/integration-tests/src/tests/host_manager.rs index 88dd529a2..33a5a0f9e 100644 --- a/evm/integration-tests/src/tests/host_manager.rs +++ b/evm/integration-tests/src/tests/host_manager.rs @@ -126,9 +126,11 @@ async fn test_host_manager_set_host_params() -> Result<(), anyhow::Error> { let base_dir = env::current_dir()?.parent().unwrap().display().to_string(); let mut runner = Runner::new(PathBuf::from(&base_dir)); let mut contract = runner.deploy("HostManagerTest").await; + let destination = contract.call::<_, H160>("module", ()).await?; let params = EvmHostParamsAbi { challengePeriod: U256::from(5_000_000u128).into(), + hostManager: destination.0.into(), ..Default::default() }; diff --git a/evm/lib/ERC6160 b/evm/lib/ERC6160 index 31179de88..aac89cf94 160000 --- a/evm/lib/ERC6160 +++ b/evm/lib/ERC6160 @@ -1 +1 @@ -Subproject commit 31179de886fec2ac4a158f40453c4f69d08d64c7 +Subproject commit aac89cf94f0bf43957d8097e9b768be5e0ed8a45 diff --git a/evm/script/DeployGateway.s.sol b/evm/script/DeployGateway.s.sol index 1d97945a2..18e46b628 100644 --- a/evm/script/DeployGateway.s.sol +++ b/evm/script/DeployGateway.s.sol @@ -60,7 +60,7 @@ contract DeployScript is Script { uint256 paraId = vm.envUint("PARA_ID"); ERC6160Ext20 feeToken = new ERC6160Ext20{salt: salt}(admin, "Hyperbridge USD", "USD.h"); - feeToken.mint(0x276b41950829E5A7B179ba03B758FaaE9A8d7C41, 1000000000 * 1e18, ""); + feeToken.mint(0x276b41950829E5A7B179ba03B758FaaE9A8d7C41, 1000000000 * 1e18); // grant the token faucet TokenFaucet faucet = new TokenFaucet{salt: salt}(address(feeToken)); diff --git a/evm/script/DeployIsmp.s.sol b/evm/script/DeployIsmp.s.sol index 542f5db48..2fbaf4806 100644 --- a/evm/script/DeployIsmp.s.sol +++ b/evm/script/DeployIsmp.s.sol @@ -49,7 +49,7 @@ contract DeployScript is Script { ERC6160Ext20 feeToken = new ERC6160Ext20{salt: salt}(admin, "Hyper USD", "USD.h"); // mint $1b to the dispatcher for tests - feeToken.mint(pingDispatcher, 1000000000 * 1e18, ""); + feeToken.mint(pingDispatcher, 1000000000 * 1e18); // consensus client // PolkadotVerifier verifier = new PolkadotVerifier(); diff --git a/evm/src/consensus/Header.sol b/evm/src/consensus/Header.sol index 0aab474f4..742f97114 100644 --- a/evm/src/consensus/Header.sol +++ b/evm/src/consensus/Header.sol @@ -51,6 +51,10 @@ library HeaderImpl { /// Slot duration in milliseconds uint256 public constant SLOT_DURATION = 12000; + error TimestampNotFound(); + error ChildTrieRootNotFound(); + error MmrRootHashNotFound(); + // Extracts the `StateCommitment` from the provided header. function stateCommitment(Header calldata self) public pure returns (StateCommitment memory) { bytes32 mmrRoot; @@ -70,9 +74,9 @@ library HeaderImpl { } // sanity check - require(timestamp != 0, "timestamp not found!"); - require(childTrieRoot != bytes32(0), "Child trie commitment not found"); - require(mmrRoot != bytes32(0), "Mmr root commitment not found"); + if (timestamp == 0) revert TimestampNotFound(); + if (childTrieRoot == bytes32(0)) revert ChildTrieRootNotFound(); + if (mmrRoot == bytes32(0)) revert MmrRootHashNotFound(); return StateCommitment({timestamp: timestamp, overlayRoot: mmrRoot, stateRoot: childTrieRoot}); } diff --git a/evm/src/consensus/ZkBeefy.sol b/evm/src/consensus/ZkBeefy.sol index 3aed9759b..a0f1640d8 100644 --- a/evm/src/consensus/ZkBeefy.sol +++ b/evm/src/consensus/ZkBeefy.sol @@ -60,6 +60,8 @@ contract ZkBeefyV1 is IConsensusClient { // Authorized paraId. uint256 private _paraId; + error UnknownParaId(); + constructor(uint256 paraId, IVerifier verifier) { _paraId = paraId; _verifier = verifier; @@ -181,7 +183,7 @@ contract ZkBeefyV1 is IConsensusClient { Node[] memory leaves = new Node[](1); Parachain memory para = proof.parachain; if (para.id != _paraId) { - revert("Unknown paraId"); + revert UnknownParaId(); } Header memory header = Codec.DecodeHeader(para.header); diff --git a/evm/src/consensus/verifiers/PolkadotVerifier.sol b/evm/src/consensus/verifiers/PolkadotVerifier.sol index b79506ccd..7e6c38e2e 100644 --- a/evm/src/consensus/verifiers/PolkadotVerifier.sol +++ b/evm/src/consensus/verifiers/PolkadotVerifier.sol @@ -6,7 +6,7 @@ pragma solidity >=0.8.4; import {IVerifier} from "./IVerifier.sol"; library UltraVerificationKey { - function verificationKeyHash() internal pure returns(bytes32) { + function verificationKeyHash() internal pure returns (bytes32) { return 0xf757c19b393ceb134ad37434ebf3b0b75316871ab05edfca7f48ee708404900a; } @@ -854,7 +854,6 @@ abstract contract BaseUltraVerifier is IVerifier { * root_1 *= ω * root_2 *= ω */ - let input := calldataload(public_inputs_ptr) valid_inputs := and(valid_inputs, lt(input, p_clone)) let temp := addmod(input, gamma, p_clone) @@ -920,7 +919,6 @@ abstract contract BaseUltraVerifier is IVerifier { * l_end_denominator = accumulating_root^2 * work_root * zeta - 1 * Note: l_end_denominator term contains a term \omega^5 to cut out 5 roots of unity from vanishing poly */ - let zeta := mload(C_ZETA_LOC) // compute zeta^n, where n is a power of 2 @@ -1254,7 +1252,6 @@ abstract contract BaseUltraVerifier is IVerifier { * the next gate. Then we can treat (q_arith - 1) as a simulated q_6 selector and scale q_m to handle (q_arith - 3) at * product. */ - let w1q1 := mulmod(mload(W1_EVAL_LOC), mload(Q1_EVAL_LOC), p) let w2q2 := mulmod(mload(W2_EVAL_LOC), mload(Q2_EVAL_LOC), p) let w3q3 := mulmod(mload(W3_EVAL_LOC), mload(Q3_EVAL_LOC), p) @@ -1447,37 +1444,14 @@ abstract contract BaseUltraVerifier is IVerifier { mulmod(x_diff, x_diff, p), p ), - addmod( - sub( - p, - addmod(y2_sqr, y1_sqr, p) - ), - addmod(y1y2, y1y2, p), - p - ), + addmod(sub(p, addmod(y2_sqr, y1_sqr, p)), addmod(y1y2, y1y2, p), p), p ) x_add_identity := - mulmod( - mulmod( - x_add_identity, - addmod( - 1, - sub(p, mload(QM_EVAL_LOC)), - p - ), - p - ), - mload(C_ALPHA_BASE_LOC), - p - ) + mulmod(mulmod(x_add_identity, addmod(1, sub(p, mload(QM_EVAL_LOC)), p), p), mload(C_ALPHA_BASE_LOC), p) // q_elliptic * (x3 + x2 + x1)(x2 - x1)(x2 - x1) - y2^2 - y1^2 + 2(y2y1)*q_sign = 0 - let y1_plus_y3 := addmod( - mload(Y1_EVAL_LOC), - mload(Y3_EVAL_LOC), - p - ) + let y1_plus_y3 := addmod(mload(Y1_EVAL_LOC), mload(Y3_EVAL_LOC), p) let y_diff := addmod(mulmod(mload(Y2_EVAL_LOC), mload(QSIGN_LOC), p), sub(p, mload(Y1_EVAL_LOC)), p) let y_add_identity := addmod( @@ -1585,7 +1559,6 @@ abstract contract BaseUltraVerifier is IVerifier { * non_native_field_gate_3 = (limb_subproduct + w_4 - (w_3_omega + w_4_omega)) * q_m * non_native_field_identity = (non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3) * q_2 */ - let limb_subproduct := addmod( mulmod(mload(W1_EVAL_LOC), mload(W2_OMEGA_EVAL_LOC), p), @@ -1705,7 +1678,6 @@ abstract contract BaseUltraVerifier is IVerifier { * * memory_record_check -= w_4; */ - let memory_record_check := mulmod(mload(W3_EVAL_LOC), mload(C_ETA_LOC), p) memory_record_check := addmod(memory_record_check, mload(W2_EVAL_LOC), p) memory_record_check := mulmod(memory_record_check, mload(C_ETA_LOC), p) @@ -1789,7 +1761,6 @@ abstract contract BaseUltraVerifier is IVerifier { * RAM_consistency_check_identity *= alpha; * RAM_consistency_check_identity += access_check; */ - let access_type := addmod(mload(W4_EVAL_LOC), sub(p, partial_record_check), p) let access_check := mulmod(access_type, addmod(access_type, sub(p, 1), p), p) let next_gate_access_type_is_boolean := @@ -2773,7 +2744,12 @@ contract PolkadotVerifier is BaseUltraVerifier { return UltraVerificationKey.verificationKeyHash(); } - function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) internal pure virtual override(BaseUltraVerifier) { + function loadVerificationKey(uint256 vk, uint256 _omegaInverseLoc) + internal + pure + virtual + override(BaseUltraVerifier) + { UltraVerificationKey.loadVerificationKey(vk, _omegaInverseLoc); } } diff --git a/evm/src/hosts/EvmHost.sol b/evm/src/hosts/EvmHost.sol index 94517c813..eff994922 100644 --- a/evm/src/hosts/EvmHost.sol +++ b/evm/src/hosts/EvmHost.sol @@ -18,6 +18,7 @@ import {Context} from "openzeppelin/utils/Context.sol"; import {Math} from "openzeppelin/utils/math/Math.sol"; import {Strings} from "openzeppelin/utils/Strings.sol"; import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; +import {SafeERC20} from "openzeppelin/token/ERC20/utils/SafeERC20.sol"; import {Bytes} from "solidity-merkle-trees/trie/Bytes.sol"; import {IIsmpModule, IncomingPostRequest, IncomingPostResponse, IncomingGetResponse} from "ismp/IIsmpModule.sol"; @@ -205,10 +206,44 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { uint256 timeoutTimestamp ); + // Emitted when a POST or GET request is funded + event RequestFunded(bytes32 commitment, uint256 newFee); + + // Emitted when a POST response is funded + event PostResponseFunded(bytes32 commitment, uint256 newFee); + + // Emitted when the host has now been frozen + event HostFrozen(); + + // Emitted when the host is unfrozen + event HostUnfrozen(); + + // Emitted when the host params is updated + event HostParamsUpdated(HostParams oldParams, HostParams newParams); + + // Account is unauthorized to perform requested action + error UnauthorizedAccount(); + // Provided address didn't fit address type size + error InvalidAddressLength(); + // Provided request was unknown + error UnknownRequest(); + // Provided response was unknown + error UnknownResponse(); + // Action breaks protocol invariants and is therefore unauthorized + error UnauthorizedAction(); + // Application is attempting to respond to a request it did not receive + error UnauthorizedResponse(); + // Response has already been provided for this request + error DuplicateResponse(); + // Cannot exceed max fishermen count + error MaxFishermanCountExceeded(uint256 provided); + // Host manager address was zero or not a contract + error InvalidHostManagerAddress(); + // only permits fishermen modifier onlyFishermen() { if (!_fishermen[_msgSender()]) { - revert("EvmHost: Account is not in the fishermen set"); + revert UnauthorizedAccount(); } _; } @@ -216,7 +251,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { // only permits the admin modifier onlyAdmin() { if (_msgSender() != _hostParams.admin) { - revert("EvmHost: Account is not the admin"); + revert UnauthorizedAccount(); } _; } @@ -224,7 +259,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { // only permits the IHandler contract modifier onlyHandler() { if (_msgSender() != address(_hostParams.handler)) { - revert("EvmHost: Account is not the handler"); + revert UnauthorizedAccount(); } _; } @@ -232,7 +267,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { // only permits the HostManager contract modifier onlyManager() { if (_msgSender() != _hostParams.hostManager) { - revert("EvmHost: Account is not the Manager contract"); + revert UnauthorizedAccount(); } _; } @@ -406,11 +441,11 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { */ function setHostParamsAdmin(HostParams memory params) public onlyAdmin { if (chainId() == block.chainid) { - revert("Cannot set params on mainnet"); + revert UnauthorizedAction(); } uint256 whitelistLength = params.stateMachineWhitelist.length; - for (uint256 i = 0; i < whitelistLength; i++) { + for (uint256 i = 0; i < whitelistLength; ++i) { delete _latestStateMachineHeight[params.stateMachineWhitelist[i]]; } updateHostParamsInternal(params); @@ -421,22 +456,37 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { * @param params, the new host params. */ function updateHostParamsInternal(HostParams memory params) private { + // check if the provided host manager is a contract + if (params.hostManager == address(0) || address(params.hostManager).code.length == 0) { + revert InvalidHostManagerAddress(); + } + + // we can only have a maximum of 100 fishermen + uint256 newFishermenLength = params.fishermen.length; + if (newFishermenLength > 100) { + revert MaxFishermanCountExceeded(newFishermenLength); + } + // delete old fishermen uint256 fishermenLength = _hostParams.fishermen.length; - for (uint256 i = 0; i < fishermenLength; i++) { + for (uint256 i = 0; i < fishermenLength; ++i) { delete _fishermen[_hostParams.fishermen[i]]; } + + // safe to emit here because invariants have already been checked + // and don't want to store a temp variable for the old params + emit HostParamsUpdated({oldParams: _hostParams, newParams: params}); + _hostParams = params; // add new fishermen if any - uint256 newFishermenLength = params.fishermen.length; - for (uint256 i = 0; i < newFishermenLength; i++) { + for (uint256 i = 0; i < newFishermenLength; ++i) { _fishermen[params.fishermen[i]] = true; } // add whitelisted state machines uint256 whitelistLength = params.stateMachineWhitelist.length; - for (uint256 i = 0; i < whitelistLength; i++) { + for (uint256 i = 0; i < whitelistLength; ++i) { // create if it doesn't already exist if (_latestStateMachineHeight[params.stateMachineWhitelist[i]] == 0) { _latestStateMachineHeight[params.stateMachineWhitelist[i]] = 1; @@ -449,9 +499,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { * @param params, the parameters for withdrawal */ function withdraw(WithdrawParams memory params) external onlyManager { - if (!IERC20(feeToken()).transfer(params.beneficiary, params.amount)) { - revert("Host has an insufficient balance"); - } + SafeERC20.safeTransfer(IERC20(feeToken()), params.beneficiary, params.amount); } /** @@ -532,6 +580,12 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { */ function setFrozenState(bool newState) public onlyAdmin { _frozen = newState; + + if (newState) { + emit HostFrozen(); + } else { + emit HostUnfrozen(); + } } /** @@ -542,8 +596,8 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { public onlyAdmin { - // if we're on mainnet, then consensus state can only be initialized once. - // and updated subsequently by either consensus proofs or cross-chain governance + // if we're on mainnet, then consensus state can only be initialized once + // and updated subsequently through consensus proofs require(chainId() == block.chainid ? _consensusState.equals(new bytes(0)) : true, "Unauthorized action"); _consensusState = state; @@ -679,9 +733,8 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { return; } - if (meta.fee > 0) { - // refund relayer fee - IERC20(feeToken()).transfer(meta.sender, meta.fee); + if (meta.fee != 0) { + SafeERC20.safeTransfer(IERC20(feeToken()), meta.sender, meta.fee); } emit PostRequestTimeoutHandled({commitment: commitment, dest: request.dest}); } @@ -710,9 +763,9 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { return; } - if (meta.fee > 0) { + if (meta.fee != 0) { // refund relayer fee - IERC20(feeToken()).transfer(meta.sender, meta.fee); + SafeERC20.safeTransfer(IERC20(feeToken()), meta.sender, meta.fee); } emit PostResponseTimeoutHandled({commitment: commitment, dest: response.request.source}); } @@ -723,7 +776,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { */ function dispatch(DispatchPost memory post) external returns (bytes32 commitment) { uint256 fee = (_hostParams.perByteFee * post.body.length) + post.fee; - IERC20(feeToken()).transferFrom(_msgSender(), address(this), fee); + SafeERC20.safeTransferFrom(IERC20(feeToken()), _msgSender(), address(this), fee); // adjust the timeout uint64 timeout = post.timeout == 0 @@ -759,8 +812,8 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { * @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); + if (get.fee != 0) { + SafeERC20.safeTransferFrom(IERC20(feeToken()), _msgSender(), address(this), get.fee); } // adjust the timeout @@ -800,22 +853,22 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { // known request? if (_requestReceipts[receipt] == address(0)) { - revert("EvmHost: Unknown request"); + revert UnknownRequest(); } // check that the authorized application is issuing this response if (_bytesToAddress(post.request.to) != _msgSender()) { - revert("EvmHost: Unauthorized Response"); + revert UnauthorizedResponse(); } // check that request has not already been responed to if (_responded[receipt]) { - revert("EvmHost: Duplicate Response"); + revert DuplicateResponse(); } // collect fees uint256 fee = (_hostParams.perByteFee * post.response.length) + post.fee; - IERC20(feeToken()).transferFrom(_msgSender(), address(this), fee); + SafeERC20.safeTransferFrom(IERC20(feeToken()), _msgSender(), address(this), fee); // adjust the timeout uint64 timeout = post.timeout == 0 @@ -856,12 +909,14 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { FeeMetadata memory metadata = _requestCommitments[commitment]; if (metadata.sender == address(0)) { - revert("Unknown request"); + revert UnknownRequest(); } - IERC20(feeToken()).transferFrom(_msgSender(), address(this), amount); + SafeERC20.safeTransferFrom(IERC20(feeToken()), _msgSender(), address(this), amount); metadata.fee += amount; _requestCommitments[commitment] = metadata; + + emit RequestFunded({commitment: commitment, newFee: metadata.fee}); } /** @@ -876,12 +931,14 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { FeeMetadata memory metadata = _responseCommitments[commitment]; if (metadata.sender == address(0)) { - revert("Unknown request"); + revert UnknownResponse(); } - IERC20(feeToken()).transferFrom(_msgSender(), address(this), amount); + SafeERC20.safeTransferFrom(IERC20(feeToken()), _msgSender(), address(this), amount); metadata.fee += amount; _responseCommitments[commitment] = metadata; + + emit PostResponseFunded({commitment: commitment, newFee: metadata.fee}); } /** @@ -904,7 +961,7 @@ abstract contract EvmHost is IIsmpHost, IHostManager, Context { */ function _bytesToAddress(bytes memory _bytes) private pure returns (address addr) { if (_bytes.length != 20) { - revert("Invalid address length"); + revert InvalidAddressLength(); } assembly { addr := mload(add(_bytes, 20)) diff --git a/evm/src/modules/CallDispatcher.sol b/evm/src/modules/CallDispatcher.sol index fa497c5f9..fa0fcd7e4 100644 --- a/evm/src/modules/CallDispatcher.sol +++ b/evm/src/modules/CallDispatcher.sol @@ -28,7 +28,7 @@ contract CallDispatcher is ICallDispatcher { if (size > 0) { (success, result) = target.call(params.data); - require(success, string(result)); + if (!success) revert(string(result)); return (result, success); } } diff --git a/evm/src/modules/HandlerV1.sol b/evm/src/modules/HandlerV1.sol index 637a85fe8..ea7cf78df 100644 --- a/evm/src/modules/HandlerV1.sol +++ b/evm/src/modules/HandlerV1.sol @@ -47,8 +47,30 @@ contract HandlerV1 is IHandler, Context { using Message for GetRequest; // using Message for GetResponse; + // The cosensus client has now expired to mitigate + // long fork attacks, this is unrecoverable. + error ConsensusClientExpired(); + // The IsmpHost has been frozen by the admin + error HostFrozen(); + // Challenge period has not yet elapsed + error ChallengePeriodNotElapsed(); + // The requested state commitment does not exist + error StateCommitmentNotFound(); + // The message destination is not intended for this host + error InvalidMessageDestination(); + // The provided message has now timed-out + error MessageTimedOut(); + // The provided message has not timed-out + error MessageNotTimedOut(); + // The message has been previously processed + error DuplicateMessage(); + // The provided message is unknown to the host + error UnknownMessage(); + // The provided proof is invalid + error InvalidProof(); + modifier notFrozen(IIsmpHost host) { - require(!host.frozen(), "IHandler: frozen"); + if (host.frozen()) revert HostFrozen(); _; } @@ -63,7 +85,7 @@ contract HandlerV1 is IHandler, Context { uint256 delay = block.timestamp - host.consensusUpdateTime(); if (delay >= host.unStakingPeriod()) { - revert("IHandler: consensus client is now expired"); + revert ConsensusClientExpired(); } (bytes memory verifiedState, IntermediateState memory intermediate) = @@ -89,26 +111,26 @@ contract HandlerV1 is IHandler, Context { uint256 delay = timestamp - host.stateMachineCommitmentUpdateTime(request.proof.height); uint256 challengePeriod = host.challengePeriod(); if (challengePeriod != 0 && challengePeriod > delay) { - revert("IHandler: still in challenge period"); + revert ChallengePeriodNotElapsed(); } uint256 requestsLen = request.requests.length; MmrLeaf[] memory leaves = new MmrLeaf[](requestsLen); - for (uint256 i = 0; i < requestsLen; i++) { + for (uint256 i = 0; i < requestsLen; ++i) { PostRequestLeaf memory leaf = request.requests[i]; // check destination if (!leaf.request.dest.equals(host.host())) { - revert("IHandler: Invalid request destination"); + revert InvalidMessageDestination(); } // check time-out if (timestamp > leaf.request.timeout()) { - revert("IHandler: Request timed out"); + revert MessageTimedOut(); } // duplicate request? bytes32 commitment = leaf.request.hash(); if (host.requestReceipts(commitment) != address(0)) { - revert("IHandler: Duplicate request"); + revert DuplicateMessage(); } leaves[i] = MmrLeaf(leaf.kIndex, leaf.index, commitment); @@ -116,13 +138,13 @@ contract HandlerV1 is IHandler, Context { bytes32 root = host.stateMachineCommitment(request.proof.height).overlayRoot; if (root == bytes32(0)) { - revert("IHandler: Proof height not found!"); + revert StateCommitmentNotFound(); } if (!MerkleMountainRange.VerifyProof(root, request.proof.multiproof, leaves, request.proof.leafCount)) { - revert("IHandler: Invalid request proofs"); + revert InvalidProof(); } - for (uint256 i = 0; i < requestsLen; i++) { + for (uint256 i = 0; i < requestsLen; ++i) { PostRequestLeaf memory leaf = request.requests[i]; host.dispatchIncoming(leaf.request, _msgSender()); } @@ -139,41 +161,41 @@ contract HandlerV1 is IHandler, Context { uint256 challengePeriod = host.challengePeriod(); if (challengePeriod != 0 && challengePeriod > delay) { - revert("IHandler: still in challenge period"); + revert ChallengePeriodNotElapsed(); } uint256 responsesLength = response.responses.length; MmrLeaf[] memory leaves = new MmrLeaf[](responsesLength); - for (uint256 i = 0; i < responsesLength; i++) { + for (uint256 i = 0; i < responsesLength; ++i) { PostResponseLeaf memory leaf = response.responses[i]; // check time-out if (timestamp > leaf.response.timeout()) { - revert("IHandler: Response timed out"); + revert MessageTimedOut(); } // known request? also serves as a source check bytes32 requestCommitment = leaf.response.request.hash(); FeeMetadata memory meta = host.requestCommitments(requestCommitment); if (meta.sender == address(0)) { - revert("IHandler: Unknown request"); + revert InvalidProof(); } // duplicate response? if (host.responseReceipts(leaf.response.hash()).relayer != address(0)) { - revert("IHandler: Duplicate Post response"); + revert DuplicateMessage(); } leaves[i] = MmrLeaf(leaf.kIndex, leaf.index, leaf.response.hash()); } bytes32 root = host.stateMachineCommitment(response.proof.height).overlayRoot; if (root == bytes32(0)) { - revert("IHandler: Proof height not found!"); + revert StateCommitmentNotFound(); } if (!MerkleMountainRange.VerifyProof(root, response.proof.multiproof, leaves, response.proof.leafCount)) { - revert("IHandler: Invalid response proofs"); + revert InvalidProof(); } - for (uint256 i = 0; i < responsesLength; i++) { + for (uint256 i = 0; i < responsesLength; ++i) { PostResponseLeaf memory leaf = response.responses[i]; host.dispatchIncoming(leaf.response, _msgSender()); } @@ -191,27 +213,27 @@ contract HandlerV1 is IHandler, Context { uint256 delay = block.timestamp - host.stateMachineCommitmentUpdateTime(message.height); uint256 challengePeriod = host.challengePeriod(); if (challengePeriod != 0 && challengePeriod > delay) { - revert("IHandler: still in challenge period"); + revert ChallengePeriodNotElapsed(); } // fetch the state commitment StateCommitment memory state = host.stateMachineCommitment(message.height); if (state.stateRoot == bytes32(0)) { - revert("IHandler: State Commitment doesn't exist"); + revert StateCommitmentNotFound(); } uint256 timeoutsLength = message.timeouts.length; - for (uint256 i = 0; i < timeoutsLength; i++) { + for (uint256 i = 0; i < timeoutsLength; ++i) { PostRequest memory request = message.timeouts[i]; // timed-out? if (request.timeout() > state.timestamp) { - revert("Request not timed out"); + revert MessageNotTimedOut(); } // known request? also serves as source check bytes32 requestCommitment = request.hash(); FeeMetadata memory meta = host.requestCommitments(requestCommitment); - require(meta.sender != address(0), "IHandler: Unknown request"); + if (meta.sender == address(0)) revert UnknownMessage(); bytes[] memory keys = new bytes[](1); keys[i] = bytes.concat(REQUEST_RECEIPTS_STORAGE_PREFIX, bytes.concat(requestCommitment)); @@ -219,7 +241,7 @@ contract HandlerV1 is IHandler, Context { // verify state trie non-membership proofs StorageValue memory entry = MerklePatricia.VerifySubstrateProof(state.stateRoot, message.proof, keys)[0]; if (entry.value.length != 0) { - revert("IHandler: Invalid non-membership proof"); + revert InvalidProof(); } host.dispatchIncoming(request, meta, requestCommitment); @@ -238,28 +260,28 @@ contract HandlerV1 is IHandler, Context { uint256 delay = block.timestamp - host.stateMachineCommitmentUpdateTime(message.height); uint256 challengePeriod = host.challengePeriod(); if (challengePeriod != 0 && challengePeriod > delay) { - revert("IHandler: still in challenge period"); + revert ChallengePeriodNotElapsed(); } // fetch the state commitment StateCommitment memory state = host.stateMachineCommitment(message.height); if (state.stateRoot == bytes32(0)) { - revert("IHandler: State Commitment doesn't exist"); + revert StateCommitmentNotFound(); } uint256 timeoutsLength = message.timeouts.length; - for (uint256 i = 0; i < timeoutsLength; i++) { + for (uint256 i = 0; i < timeoutsLength; ++i) { PostResponse memory response = message.timeouts[i]; // timed-out? if (response.timeout() > state.timestamp) { - revert("IHandler: Response not timed out"); + revert MessageNotTimedOut(); } // known response? also serves as source check bytes32 responseCommitment = response.hash(); FeeMetadata memory meta = host.responseCommitments(responseCommitment); if (meta.sender == address(0)) { - revert("IHandler: Unknown response"); + revert UnknownMessage(); } bytes[] memory keys = new bytes[](1); @@ -268,7 +290,7 @@ contract HandlerV1 is IHandler, Context { // verify state trie non-membership proofs StorageValue memory entry = MerklePatricia.VerifySubstrateProof(state.stateRoot, message.proof, keys)[0]; if (entry.value.length != 0) { - revert("IHandler: Invalid non-membership proof"); + revert InvalidProof(); } host.dispatchIncoming(response, meta, responseCommitment); @@ -285,34 +307,34 @@ contract HandlerV1 is IHandler, Context { uint256 delay = timestamp - host.stateMachineCommitmentUpdateTime(message.height); uint256 challengePeriod = host.challengePeriod(); if (challengePeriod != 0 && challengePeriod > delay) { - revert("IHandler: still in challenge period"); + revert ChallengePeriodNotElapsed(); } bytes32 root = host.stateMachineCommitment(message.height).stateRoot; if (root == bytes32(0)) { - revert("IHandler: Proof height not found!"); + revert StateCommitmentNotFound(); } uint256 responsesLength = message.requests.length; bytes[] memory proof = message.proof; - for (uint256 i = 0; i < responsesLength; i++) { + for (uint256 i = 0; i < responsesLength; ++i) { GetRequest memory request = message.requests[i]; // timed-out? if (timestamp > request.timeout()) { - revert("IHandler: GET request timed out"); + revert MessageTimedOut(); } // known request? also serves as source check bytes32 requestCommitment = request.hash(); FeeMetadata memory meta = host.requestCommitments(requestCommitment); if (meta.sender == address(0)) { - revert("IHandler: Unknown GET request"); + revert UnknownMessage(); } // duplicate response? if (host.responseReceipts(requestCommitment).relayer != address(0)) { - revert("IHandler: Duplicate GET response"); + revert DuplicateMessage(); } StorageValue[] memory values = MerklePatricia.ReadChildProofCheck(root, proof, request.keys, bytes.concat(requestCommitment)); @@ -331,16 +353,16 @@ contract HandlerV1 is IHandler, Context { uint256 timeoutsLength = message.timeouts.length; uint256 timestamp = block.timestamp; - for (uint256 i = 0; i < timeoutsLength; i++) { + for (uint256 i = 0; i < timeoutsLength; ++i) { GetRequest memory request = message.timeouts[i]; bytes32 requestCommitment = request.hash(); FeeMetadata memory meta = host.requestCommitments(requestCommitment); if (meta.sender == address(0)) { - revert("IHandler: Unknown request"); + revert InvalidProof(); } if (request.timeout() > timestamp) { - revert("IHandler: GET request not timed out"); + revert MessageNotTimedOut(); } host.dispatchIncoming(request, meta, requestCommitment); } diff --git a/evm/src/modules/TokenFaucet.sol b/evm/src/modules/TokenFaucet.sol index 116faf31a..b21ef4867 100644 --- a/evm/src/modules/TokenFaucet.sol +++ b/evm/src/modules/TokenFaucet.sol @@ -35,6 +35,6 @@ contract TokenFaucet { } consumers[msg.sender] = block.timestamp; - IERC6160Ext20(token).mint(msg.sender, 1000 * 1e18, ""); + IERC6160Ext20(token).mint(msg.sender, 1000 * 1e18); } } diff --git a/evm/src/modules/TokenGateway.sol b/evm/src/modules/TokenGateway.sol index f368d90f7..3ce7cb09f 100644 --- a/evm/src/modules/TokenGateway.sol +++ b/evm/src/modules/TokenGateway.sol @@ -101,9 +101,8 @@ struct AssetFees { uint256 protocolFeePercentage; } -enum OnAcceptActions -// Incoming asset from a chain -{ +enum OnAcceptActions { + // Incoming asset from a chain IncomingAsset, // Governance action to update protocol parameters GovernanceAction @@ -197,9 +196,15 @@ contract TokenGateway is BaseIsmpModule { } function teleport(TeleportParams memory teleportParams) public { - require(teleportParams.to != bytes32(0), "Burn your funds some other way"); - require(teleportParams.amount > 100_000, "Amount too low"); - require(teleportParams.feeToken != address(0), "Fee token not selected"); + if (teleportParams.to == bytes32(0)) { + revert("Cannot send tokens to the zero address"); + } + if (teleportParams.amount == 0) { + revert("Cannot teleport zero funds"); + } + if (teleportParams.feeToken == address(0)) { + revert("Fee token must be selected"); + } address from = msg.sender; bytes32 fromBytes32 = addressToBytes32(msg.sender); @@ -230,11 +235,11 @@ contract TokenGateway is BaseIsmpModule { data = bytes.concat(hex"00", data); // add enum variant for body if (_erc20 != address(0) && !teleportParams.redeem) { - require( - IERC20(_erc20).transferFrom(from, address(this), teleportParams.amount), "Insufficient user balance" - ); + if (!IERC20(_erc20).transferFrom(from, address(this), teleportParams.amount)) { + revert("Insufficient user balance"); + } } else if (_erc6160 != address(0)) { - IERC6160Ext20(_erc6160).burn(from, teleportParams.amount, ""); + IERC6160Ext20(_erc6160).burn(from, teleportParams.amount); } else { revert("Unknown Token Identifier"); } @@ -246,22 +251,25 @@ contract TokenGateway is BaseIsmpModule { path[0] = teleportParams.feeToken; path[1] = feeToken; - require( - IERC20(teleportParams.feeToken).transferFrom(from, address(this), teleportParams.amountInMax), - "insufficient funds for intended fee token" - ); - require( - IERC20(teleportParams.feeToken).approve(_params.uniswapV2, teleportParams.amountInMax), "approve failed" - ); + if (!IERC20(teleportParams.feeToken).transferFrom(from, address(this), teleportParams.amountInMax)) { + revert("insufficient funds for intended fee token"); + } + if (!IERC20(teleportParams.feeToken).approve(_params.uniswapV2, teleportParams.amountInMax)) { + revert("approve failed"); + } IUniswapV2Router(_params.uniswapV2).swapTokensForExactTokens( fee, teleportParams.amountInMax, path, address(this), block.timestamp ); } else { - require(IERC20(feeToken).transferFrom(from, address(this), fee), "user has insufficient funds"); + if (!IERC20(feeToken).transferFrom(from, address(this), fee)) { + revert("user has insufficient funds"); + } } // approve the host with the exact amount - require(IERC20(feeToken).approve(_params.host, fee), "approve failed"); + if (!IERC20(feeToken).approve(_params.host, fee)) { + revert("Token Approval failed"); + } DispatchPost memory request = DispatchPost({ dest: teleportParams.dest, to: abi.encodePacked(address(this)), @@ -282,6 +290,8 @@ contract TokenGateway is BaseIsmpModule { }); } + function registerMultiChainNativeAsset() public {} + function onAccept(IncomingPostRequest calldata incoming) external override onlyIsmpHost { OnAcceptActions action = OnAcceptActions(uint8(incoming.request.body[0])); @@ -298,8 +308,9 @@ contract TokenGateway is BaseIsmpModule { } } + // Triggered when a previously sent out request has confirmed to be timed-out by the IsmpHost. + // This means the funds could not be sent, we simply refund the user's assets here. function onPostRequestTimeout(PostRequest calldata request) external override onlyIsmpHost { - // The funds could not be sent, this would allow users to get their funds back. Body memory body; if (request.body.length > BODY_BYTES_SIZE) { BodyWithCall memory bodyWithCall = abi.decode(request.body[1:], (BodyWithCall)); @@ -319,9 +330,11 @@ contract TokenGateway is BaseIsmpModule { address from = bytes32ToAddress(body.from); if (_erc20 != address(0) && !body.redeem) { - require(IERC20(_erc20).transfer(from, body.amount), "Gateway: Insufficient Balance"); + if (!IERC20(_erc20).transfer(from, body.amount)) { + revert("Gateway: Insufficient Balance"); + } } else if (_erc6160 != address(0)) { - IERC6160Ext20(_erc6160).mint(from, body.amount, ""); + IERC6160Ext20(_erc6160).mint(from, body.amount); } else { revert("Gateway: Inconsistent State"); } @@ -338,7 +351,9 @@ contract TokenGateway is BaseIsmpModule { function handleIncomingAssetWithoutCall(IncomingPostRequest calldata incoming) private { PostRequest calldata request = incoming.request; // TokenGateway only accepts incoming assets from it's instances on other chains. - require(request.from.equals(abi.encodePacked(address(this))), "Unauthorized request"); + if (!request.from.equals(abi.encodePacked(address(this)))) { + revert("Unauthorized request"); + } Body memory body = abi.decode(request.body[1:], (Body)); address to = bytes32ToAddress(body.to); handleIncomingAsset(body.assetId, body.redeem, body.amount, to, incoming.relayer); @@ -354,8 +369,10 @@ contract TokenGateway is BaseIsmpModule { function handleIncomingAssetWithCall(IncomingPostRequest calldata incoming) private { PostRequest calldata request = incoming.request; - /// TokenGateway only accepts incoming assets from it's instances on other chains. - require(request.from.equals(abi.encodePacked(address(this))), "Unauthorized request"); + // TokenGateway only accepts incoming assets from it's instances on other chains. + if (!request.from.equals(abi.encodePacked(address(this)))) { + revert("Unauthorized request"); + } BodyWithCall memory body = abi.decode(request.body[1:], (BodyWithCall)); address to = bytes32ToAddress(body.to); handleIncomingAsset(body.assetId, body.redeem, body.amount, to, incoming.relayer); @@ -380,19 +397,21 @@ contract TokenGateway is BaseIsmpModule { if (_erc20 != address(0) && redeem) { // a relayer/user is redeeming the native asset uint256 transferredAmount = amount - protocolFee(assetId, amount); - require(IERC20(_erc20).transfer(to, transferredAmount), "Gateway: Insufficient Balance"); + if (!IERC20(_erc20).transfer(to, transferredAmount)) { + revert("Gateway: Insufficient Balance"); + } } else if (_erc20 != address(0) && _erc6160 != address(0) && !redeem) { // user is swapping, relayers should double as liquidity providers. uint256 transferredAmount = amount - relayerLiquidityFee(assetId, amount); - require( - IERC20(_erc20).transferFrom(relayer, to, transferredAmount), "Gateway: Insufficient relayer balance" - ); + if (!IERC20(_erc20).transferFrom(relayer, to, transferredAmount)) { + revert("Gateway: Insufficient relayer balance"); + } // hand the relayer the erc6160, so they can redeem on the source chain - IERC6160Ext20(_erc6160).mint(relayer, amount, ""); + IERC6160Ext20(_erc6160).mint(relayer, amount); emit LiquidityProvided({relayer: relayer, amount: transferredAmount, assetId: assetId}); } else if (_erc6160 != address(0)) { - IERC6160Ext20(_erc6160).mint(to, amount, ""); + IERC6160Ext20(_erc6160).mint(to, amount); } else { revert("Gateway: Unknown Token Identifier"); } @@ -400,7 +419,9 @@ contract TokenGateway is BaseIsmpModule { function handleGovernance(PostRequest calldata request) private { // only hyperbridge can do this - require(request.source.equals(IIsmpHost(_params.host).hyperbridge()), "Unauthorized request"); + if (!request.source.equals(IIsmpHost(_params.host).hyperbridge())) { + revert("Unauthorized request"); + } TokenGatewayParamsExt memory teleportParams = abi.decode(request.body[1:], (TokenGatewayParamsExt)); _params = teleportParams.params; diff --git a/evm/test/EvmHostTest.sol b/evm/test/EvmHostTest.sol index 2dddc29f3..e00f9130d 100644 --- a/evm/test/EvmHostTest.sol +++ b/evm/test/EvmHostTest.sol @@ -74,7 +74,7 @@ contract EvmHostTest is BaseTest { // can't set on mainnet vm.chainId(host.chainId()); vm.prank(host.hostParams().admin); - vm.expectRevert("Cannot set params on mainnet"); + vm.expectRevert(EvmHost.UnauthorizedAction.selector); host.setHostParamsAdmin(params); } @@ -99,12 +99,12 @@ contract EvmHostTest is BaseTest { assert(host.requestCommitments(commitment).fee == 10 * 1e18); // can't fund unknown requests - vm.expectRevert("Unknown request"); + vm.expectRevert(EvmHost.UnknownRequest.selector); vm.prank(tx.origin); host.fundRequest(keccak256(hex"dead"), 10 * 1e18); // another person can fund your request - feeToken.mint(address(this), 10 * 1e18, ""); + feeToken.mint(address(this), 10 * 1e18); host.fundRequest(commitment, 10 * 1e18); } @@ -126,7 +126,7 @@ contract EvmHostTest is BaseTest { assert(host.stateMachineCommitment(height).timestamp == 200); // can't veto if not in fishermen set - vm.expectRevert("EvmHost: Account is not in the fishermen set"); + vm.expectRevert(EvmHost.UnauthorizedAccount.selector); host.vetoStateCommitment(height); // veto with fisherman @@ -206,13 +206,13 @@ contract EvmHostTest is BaseTest { assert(host.stateMachineCommitment(height).timestamp == 200); // cannot veto - vm.expectRevert("EvmHost: Account is not in the fishermen set"); + vm.expectRevert(EvmHost.UnauthorizedAccount.selector); host.vetoStateCommitment(height); assert(host.stateMachineCommitment(height).timestamp == 200); // cannot veto vm.prank(tx.origin); - vm.expectRevert("EvmHost: Account is not in the fishermen set"); + vm.expectRevert(EvmHost.UnauthorizedAccount.selector); host.vetoStateCommitment(height); assert(host.stateMachineCommitment(height).timestamp == 200); } diff --git a/evm/test/HostManagerTest.sol b/evm/test/HostManagerTest.sol index c88904a87..b9ae19bbf 100644 --- a/evm/test/HostManagerTest.sol +++ b/evm/test/HostManagerTest.sol @@ -20,12 +20,12 @@ import {BaseTest} from "./BaseTest.sol"; import {PostRequest} from "ismp/Message.sol"; import {IncomingPostRequest} from "ismp/IIsmpModule.sol"; import {HostManagerParams, HostManager} from "../src/modules/HostManager.sol"; -import {HostParams} from "../src/hosts/EvmHost.sol"; +import {HostParams, EvmHost} from "../src/hosts/EvmHost.sol"; contract HostManagerTest is BaseTest { function HostManagerWithdraw(PostRequest memory request) public { // add balance to the host - feeToken.mint(address(host), 1000e18, ""); + feeToken.mint(address(host), 1000e18); require(feeToken.balanceOf(address(host)) == 1000e18, "Failed to mint user tokens"); @@ -45,6 +45,20 @@ contract HostManagerTest is BaseTest { require(host.hostParams().challengePeriod == params.challengePeriod, "Failed to process request"); } + function testCannotSetInvalidHostManagerAddress() public { + HostParams memory params = host.hostParams(); + address manager = params.hostManager; + params.hostManager = address(0); + + vm.startPrank(manager); + vm.expectRevert(EvmHost.InvalidHostManagerAddress.selector); + host.updateHostParams(params); + + params.hostManager = msg.sender; + vm.expectRevert(EvmHost.InvalidHostManagerAddress.selector); + host.updateHostParams(params); + } + function HostManagerOnAccept(PostRequest calldata request) public { vm.startPrank(address(host)); diff --git a/evm/test/TokenGatewayTest.sol b/evm/test/TokenGatewayTest.sol index 117ff7980..cabda17c2 100644 --- a/evm/test/TokenGatewayTest.sol +++ b/evm/test/TokenGatewayTest.sol @@ -36,7 +36,7 @@ contract TokenGatewayTest is BaseTest { // relayer fee + per-byte fee uint256 messagingFee = (9 * 1e17) + (BODY_BYTES_SIZE * host.perByteFee()); uint256 totalFee = 1_000 * 1e18 + messagingFee; - feeToken.mint(address(this), totalFee, ""); + feeToken.mint(address(this), totalFee); assert(feeToken.balanceOf(address(this)) == 1_000 * 1e18 + messagingFee); assert(feeToken.balanceOf(address(host)) == 0); @@ -64,7 +64,7 @@ contract TokenGatewayTest is BaseTest { // relayer fee + per-byte fee uint256 messagingFee = (9 * 1e17) + (321 * host.perByteFee()); uint256 totalFee = 1_000 * 1e18 + messagingFee; - feeToken.mint(address(this), totalFee, ""); + feeToken.mint(address(this), totalFee); assert(feeToken.balanceOf(address(this)) == 1_000 * 1e18 + messagingFee); assert(feeToken.balanceOf(address(host)) == 0); @@ -486,7 +486,7 @@ contract TokenGatewayTest is BaseTest { bytes memory hyperbridge = StateMachine.kusama(2000); TokenGatewayParamsExt memory params = TokenGatewayParamsExt({params: gateway.params(), assets: assets}); - feeToken.mint(address(this), 1_000 * 1e18, ""); + feeToken.mint(address(this), 1_000 * 1e18); mockUSDC.mint(address(this), 1_000_000 * 1e18); vm.prank(address(host)); @@ -563,7 +563,7 @@ contract TokenGatewayTest is BaseTest { // relayer fee + per-byte fee uint256 messagingFee = (9 * 1e17) + (BODY_BYTES_SIZE * host.perByteFee()); - feeToken.mint(address(this), 1_000 * 1e18 + messagingFee, ""); + feeToken.mint(address(this), 1_000 * 1e18 + messagingFee); vm.prank(address(host)); gateway.onAccept( diff --git a/parachain/node/src/command.rs b/parachain/node/src/command.rs index be874f043..93d0ed04c 100644 --- a/parachain/node/src/command.rs +++ b/parachain/node/src/command.rs @@ -97,7 +97,7 @@ impl SubstrateCli for Cli { } fn support_url() -> String { - "https://github.com/paritytech/cumulus/issues/new".into() + "https://github.com/polytope-labs/hyperbridge/issues/new".into() } fn copyright_start_year() -> i32 { @@ -133,7 +133,7 @@ impl SubstrateCli for RelayChainCli { } fn support_url() -> String { - "https://github.com/paritytech/cumulus/issues/new".into() + "https://github.com/paritytech/polkadot-sdk/issues/new".into() } fn copyright_start_year() -> i32 {