From 7de2fdbf48c90ee6c61e654c3e63f7d2703f0097 Mon Sep 17 00:00:00 2001 From: CJ Cobb Date: Tue, 5 Nov 2024 15:55:06 -0500 Subject: [PATCH 1/6] feat(minor-interchain-token-service): refactor chain registration * combine SetChainConfig and RegisterItsContract into single message * add UpdateChain message --- .../interchain-token-service/src/contract.rs | 50 +++---- .../src/contract/execute.rs | 52 +++---- contracts/interchain-token-service/src/msg.rs | 26 ++-- .../interchain-token-service/src/state.rs | 74 +++++---- .../interchain-token-service/tests/execute.rs | 141 +++++++++++++----- .../tests/instantiate.rs | 14 -- .../interchain-token-service/tests/query.rs | 30 +++- ...cimals_when_max_uints_are_different.golden | 54 +++---- ...ecimals_when_max_uints_are_the_same.golden | 54 +++---- ..._when_source_decimals_are_different.golden | 56 +++---- .../instantiate_with_args_succeeds.golden | 29 +--- .../tests/utils/execute.rs | 112 ++++++-------- .../tests/utils/instantiate.rs | 1 - 13 files changed, 359 insertions(+), 334 deletions(-) diff --git a/contracts/interchain-token-service/src/contract.rs b/contracts/interchain-token-service/src/contract.rs index e7d3aaf7a0..ddf3d3277f 100644 --- a/contracts/interchain-token-service/src/contract.rs +++ b/contracts/interchain-token-service/src/contract.rs @@ -9,7 +9,6 @@ use cosmwasm_std::{Addr, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Respons use error_stack::{Report, ResultExt}; use execute::{freeze_chain, unfreeze_chain}; -use crate::events::Event; use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; use crate::state; use crate::state::Config; @@ -26,10 +25,10 @@ const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub enum Error { #[error("failed to execute a cross-chain message")] Execute, - #[error("failed to register an its edge contract")] - RegisterItsContract, - #[error("failed to deregsiter an its edge contract")] - DeregisterItsContract, + #[error("failed to register chain")] + RegisterChain, + #[error("failed to update chain")] + UpdateChain, #[error("failed to freeze chain")] FreezeChain, #[error("failed to unfreeze chain")] @@ -79,17 +78,9 @@ pub fn instantiate( state::save_config(deps.storage, &Config { axelarnet_gateway })?; - for (chain, address) in msg.its_contracts.iter() { - state::save_its_contract(deps.storage, chain, address)?; - } - killswitch::init(deps.storage, killswitch::State::Disengaged)?; - Ok(Response::new().add_events( - msg.its_contracts - .into_iter() - .map(|(chain, address)| Event::ItsContractRegistered { chain, address }.into()), - )) + Ok(Response::new()) } #[cfg_attr(not(feature = "library"), entry_point)] @@ -106,13 +97,24 @@ pub fn execute( payload, }) => execute::execute_message(deps, cc_id, source_address, payload) .change_context(Error::Execute), - ExecuteMsg::RegisterItsContract { chain, address } => { - execute::register_its_contract(deps, chain, address) - .change_context(Error::RegisterItsContract) - } - ExecuteMsg::DeregisterItsContract { chain } => { - execute::deregister_its_contract(deps, chain) - .change_context(Error::DeregisterItsContract) + ExecuteMsg::RegisterChain { + chain, + its_edge_contract, + max_uint, + max_target_decimals, + } => execute::register_chain( + deps, + chain, + its_edge_contract, + max_uint, + max_target_decimals, + ) + .change_context(Error::RegisterChain), + ExecuteMsg::UpdateChain { + chain, + its_edge_contract, + } => { + execute::update_chain(deps, chain, its_edge_contract).change_context(Error::UpdateChain) } ExecuteMsg::FreezeChain { chain } => { freeze_chain(deps, chain).change_context(Error::FreezeChain) @@ -126,12 +128,6 @@ pub fn execute( ExecuteMsg::EnableExecution => { execute::enable_execution(deps).change_context(Error::EnableExecution) } - ExecuteMsg::SetChainConfig { - chain, - max_uint, - max_target_decimals, - } => execute::set_chain_config(deps, chain, max_uint, max_target_decimals) - .change_context(Error::SetChainConfig), }? .then(Ok) } diff --git a/contracts/interchain-token-service/src/contract/execute.rs b/contracts/interchain-token-service/src/contract/execute.rs index 4346f4298a..ad8491cc1e 100644 --- a/contracts/interchain-token-service/src/contract/execute.rs +++ b/contracts/interchain-token-service/src/contract/execute.rs @@ -205,24 +205,6 @@ fn send_to_destination( Ok(Response::new().add_message(call_contract_msg)) } -pub fn register_its_contract( - deps: DepsMut, - chain: ChainNameRaw, - address: Address, -) -> Result { - state::save_its_contract(deps.storage, &chain, &address) - .change_context_lazy(|| Error::FailedItsContractRegistration(chain.clone()))?; - - Ok(Response::new().add_event(Event::ItsContractRegistered { chain, address }.into())) -} - -pub fn deregister_its_contract(deps: DepsMut, chain: ChainNameRaw) -> Result { - state::remove_its_contract(deps.storage, &chain) - .change_context_lazy(|| Error::FailedItsContractDeregistration(chain.clone()))?; - - Ok(Response::new().add_event(Event::ItsContractDeregistered { chain }.into())) -} - pub fn freeze_chain(deps: DepsMut, chain: ChainNameRaw) -> Result { state::freeze_chain(deps.storage, &chain).change_context(Error::State)?; @@ -243,20 +225,36 @@ pub fn enable_execution(deps: DepsMut) -> Result { killswitch::disengage(deps.storage, Event::ExecutionEnabled).change_context(Error::State) } -pub fn set_chain_config( +pub fn register_chain( deps: DepsMut, chain: ChainNameRaw, + its_address: Address, max_uint: nonempty::Uint256, max_target_decimals: u8, ) -> Result { match state::may_load_chain_config(deps.storage, &chain).change_context(Error::State)? { Some(_) => bail!(Error::ChainConfigAlreadySet(chain)), - None => state::save_chain_config(deps.storage, &chain, max_uint, max_target_decimals) - .change_context(Error::State)? - .then(|_| Ok(Response::new())), + None => state::save_chain_config( + deps.storage, + &chain, + its_address, + max_uint, + max_target_decimals, + ) + .change_context(Error::State)? + .then(|_| Ok(Response::new())), } } +pub fn update_chain( + deps: DepsMut, + chain: ChainNameRaw, + its_address: Address, +) -> Result { + state::update_its_contract(deps.storage, &chain, its_address).change_context(Error::State)?; + Ok(Response::new()) +} + /// Calculates the destination on token transfer amount. /// /// The amount is calculated based on the token decimals on the source and destination chains. @@ -612,8 +610,8 @@ mod tests { use router_api::{ChainNameRaw, CrossChainId}; use crate::contract::execute::{ - disable_execution, enable_execution, execute_message, freeze_chain, register_its_contract, - set_chain_config, unfreeze_chain, Error, + disable_execution, enable_execution, execute_message, freeze_chain, register_chain, + unfreeze_chain, Error, }; use crate::state::{self, Config}; use crate::{DeployInterchainToken, HubMessage, InterchainTransfer}; @@ -867,14 +865,10 @@ mod tests { for chain_name in [SOLANA, ETHEREUM, XRPL] { let chain = ChainNameRaw::try_from(chain_name).unwrap(); - assert_ok!(register_its_contract( + assert_ok!(register_chain( deps.as_mut(), chain.clone(), ITS_ADDRESS.to_string().try_into().unwrap(), - )); - assert_ok!(set_chain_config( - deps.as_mut(), - chain, Uint256::one().try_into().unwrap(), 16u8 )); diff --git a/contracts/interchain-token-service/src/msg.rs b/contracts/interchain-token-service/src/msg.rs index b38732379b..0e7debbbab 100644 --- a/contracts/interchain-token-service/src/msg.rs +++ b/contracts/interchain-token-service/src/msg.rs @@ -15,8 +15,6 @@ pub struct InstantiateMsg { pub admin_address: String, /// The address of the axelarnet-gateway contract on Amplifier pub axelarnet_gateway_address: String, - /// Addresses of the ITS edge contracts on connected chains - pub its_contracts: HashMap, } #[cw_serde] @@ -25,18 +23,23 @@ pub enum ExecuteMsg { /// Execute a cross-chain message received by the axelarnet-gateway from another chain #[permission(Specific(gateway))] Execute(AxelarExecutableMsg), + /// Register the ITS contract address of another chain. Each chain's ITS contract has to be whitelisted before /// ITS Hub can send cross-chain messages to it, or receive messages from it. /// If an ITS contract is already set for the chain, an error is returned. #[permission(Governance)] - RegisterItsContract { + RegisterChain { chain: ChainNameRaw, - address: Address, + its_edge_contract: Address, + max_uint: nonempty::Uint256, // The maximum uint value that is supported by the chain's token standard + max_target_decimals: u8, // The maximum number of decimals that is preserved when deploying a token to another chain where smaller uint values are used + }, + + #[permission(Governance)] + UpdateChain { + chain: ChainNameRaw, + its_edge_contract: Address, }, - /// Deregister the ITS contract address for the given chain. - /// The admin is allowed to remove the ITS address of a chain for emergencies. - #[permission(Elevated)] - DeregisterItsContract { chain: ChainNameRaw }, /// Freeze execution of ITS messages for a particular chain #[permission(Elevated)] @@ -51,13 +54,6 @@ pub enum ExecuteMsg { #[permission(Elevated)] EnableExecution, - /// Set the chain configuration for a chain. - #[permission(Governance)] - SetChainConfig { - chain: ChainNameRaw, - max_uint: nonempty::Uint256, // The maximum uint value that is supported by the chain's token standard - max_target_decimals: u8, // The maximum number of decimals that is preserved when deploying a token to another chain where smaller uint values are used - }, } #[cw_serde] diff --git a/contracts/interchain-token-service/src/state.rs b/contracts/interchain-token-service/src/state.rs index 0ded455cf3..385c783c08 100644 --- a/contracts/interchain-token-service/src/state.rs +++ b/contracts/interchain-token-service/src/state.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use axelar_wasm_std::{nonempty, FnExt, IntoContractError}; use cosmwasm_schema::cw_serde; -use cosmwasm_std::{ensure, Addr, OverflowError, StdError, Storage, Uint256}; +use cosmwasm_std::{Addr, OverflowError, StdError, Storage, Uint256}; use cw_storage_plus::{Item, Map}; use error_stack::{report, Result, ResultExt}; use router_api::{Address, ChainNameRaw}; @@ -36,6 +36,7 @@ pub struct Config { pub struct ChainConfig { pub max_uint: nonempty::Uint256, pub max_target_decimals: u8, + pub its_address: Address, frozen: bool, } @@ -108,7 +109,6 @@ pub struct TokenConfig { } const CONFIG: Item = Item::new("config"); -const ITS_CONTRACTS: Map<&ChainNameRaw, Address> = Map::new("its_contracts"); const CHAIN_CONFIGS: Map<&ChainNameRaw, ChainConfig> = Map::new("chain_configs"); const TOKEN_INSTANCE: Map<&(ChainNameRaw, TokenId), TokenInstance> = Map::new("token_instance"); const TOKEN_CONFIGS: Map<&TokenId, TokenConfig> = Map::new("token_configs"); @@ -144,6 +144,7 @@ pub fn load_chain_config( pub fn save_chain_config( storage: &mut dyn Storage, chain: &ChainNameRaw, + its_contract: Address, max_uint: nonempty::Uint256, max_target_decimals: u8, ) -> Result<(), Error> { @@ -154,18 +155,36 @@ pub fn save_chain_config( &ChainConfig { max_uint, max_target_decimals, + its_address: its_contract, frozen: false, }, ) .change_context(Error::Storage) } +pub fn update_its_contract( + storage: &mut dyn Storage, + chain: &ChainNameRaw, + its_address: Address, +) -> Result { + CHAIN_CONFIGS + .update(storage, chain, |config| match config { + Some(config) => Ok(ChainConfig { + its_address, + ..config + }), + None => Err(StdError::not_found("config not found")), + }) + .change_context(Error::ChainNotFound(chain.to_owned())) +} + pub fn may_load_its_contract( storage: &dyn Storage, chain: &ChainNameRaw, ) -> Result, Error> { - ITS_CONTRACTS + CHAIN_CONFIGS .may_load(storage, chain) + .map(|res| res.map(|config| config.its_address)) .change_context(Error::Storage) } @@ -175,38 +194,15 @@ pub fn load_its_contract(storage: &dyn Storage, chain: &ChainNameRaw) -> Result< .ok_or_else(|| report!(Error::ItsContractNotFound(chain.clone()))) } -pub fn save_its_contract( - storage: &mut dyn Storage, - chain: &ChainNameRaw, - address: &Address, -) -> Result<(), Error> { - ensure!( - may_load_its_contract(storage, chain)?.is_none(), - Error::ItsContractAlreadyRegistered(chain.clone()) - ); - - ITS_CONTRACTS - .save(storage, chain, address) - .change_context(Error::Storage) -} - -pub fn remove_its_contract(storage: &mut dyn Storage, chain: &ChainNameRaw) -> Result<(), Error> { - ensure!( - may_load_its_contract(storage, chain)?.is_some(), - Error::ItsContractNotFound(chain.clone()) - ); - - ITS_CONTRACTS.remove(storage, chain); - - Ok(()) -} - pub fn load_all_its_contracts( storage: &dyn Storage, ) -> Result, Error> { - ITS_CONTRACTS + CHAIN_CONFIGS .range(storage, None, None, cosmwasm_std::Order::Ascending) - .map(|res| res.change_context(Error::Storage)) + .map(|res| { + res.map(|(chain, config)| (chain, config.its_address)) + .change_context(Error::Storage) + }) .collect::, _>>() } @@ -324,8 +320,20 @@ mod tests { HashMap::new() ); - assert_ok!(save_its_contract(deps.as_mut().storage, &chain1, &address1)); - assert_ok!(save_its_contract(deps.as_mut().storage, &chain2, &address2)); + assert_ok!(save_chain_config( + deps.as_mut().storage, + &chain1, + address1.clone(), + Uint256::MAX.try_into().unwrap(), + 16u8 + )); + assert_ok!(save_chain_config( + deps.as_mut().storage, + &chain2, + address2.clone(), + Uint256::MAX.try_into().unwrap(), + 16u8 + )); assert_eq!( assert_ok!(load_its_contract(deps.as_ref().storage, &chain1)), address1 diff --git a/contracts/interchain-token-service/tests/execute.rs b/contracts/interchain-token-service/tests/execute.rs index 2c8b012a4b..67dd2f7b64 100644 --- a/contracts/interchain-token-service/tests/execute.rs +++ b/contracts/interchain-token-service/tests/execute.rs @@ -18,8 +18,10 @@ use utils::{params, TestMessage}; mod utils; +use crate::contract::Error; + #[test] -fn register_deregister_its_contract_succeeds() { +fn register_update_its_contract_succeeds() { let mut deps = mock_dependencies(); utils::instantiate_contract(deps.as_mut()).unwrap(); @@ -28,20 +30,28 @@ fn register_deregister_its_contract_succeeds() { .parse() .unwrap(); - let register_response = assert_ok!(utils::register_its_contract( + let register_response = assert_ok!(utils::register_chain( deps.as_mut(), chain.clone(), - address.clone() + address.clone(), + Uint256::MAX.try_into().unwrap(), + u8::MAX )); let res = assert_ok!(utils::query_its_contract(deps.as_ref(), chain.clone())); assert_eq!(res, Some(address)); - let deregister_response = - assert_ok!(utils::deregister_its_contract(deps.as_mut(), chain.clone())); + let new_address: Address = "0x9999999990123456789012345678901234567890" + .parse() + .unwrap(); + let update_response = assert_ok!(utils::update_chain( + deps.as_mut(), + chain.clone(), + new_address.clone() + )); let res = assert_ok!(utils::query_its_contract(deps.as_ref(), chain.clone())); - assert_eq!(res, None); + assert_eq!(res, Some(new_address)); - goldie::assert_json!([register_response, deregister_response]); + goldie::assert_json!([register_response, update_response]); } #[test] @@ -54,16 +64,24 @@ fn reregistering_its_contract_fails() { .parse() .unwrap(); - assert_ok!(utils::register_its_contract( + assert_ok!(utils::register_chain( deps.as_mut(), chain.clone(), - address.clone() + address.clone(), + Uint256::MAX.try_into().unwrap(), + u8::MAX )); assert_err_contains!( - utils::register_its_contract(deps.as_mut(), chain, address), - ExecuteError, - ExecuteError::FailedItsContractRegistration(..) + utils::register_chain( + deps.as_mut(), + chain.clone(), + address.clone(), + Uint256::MAX.try_into().unwrap(), + u8::MAX + ), + Error, + Error::RegisterChain ); } @@ -75,9 +93,15 @@ fn deregistering_unknown_chain_fails() { let chain: ChainNameRaw = "ethereum".parse().unwrap(); assert_err_contains!( - utils::deregister_its_contract(deps.as_mut(), chain), - ExecuteError, - ExecuteError::FailedItsContractDeregistration(..) + utils::update_chain( + deps.as_mut(), + chain, + "0x1234567890123456789012345678901234567890" + .parse() + .unwrap() + ), + Error, + Error::UpdateChain ); } @@ -387,7 +411,14 @@ fn execute_message_when_unknown_source_address_fails() { .. } = TestMessage::dummy(); - utils::register_its_contract(deps.as_mut(), source_its_chain, source_its_contract).unwrap(); + utils::register_chain( + deps.as_mut(), + source_its_chain, + source_its_contract, + Uint256::MAX.try_into().unwrap(), + u8::MAX, + ) + .unwrap(); let unknown_address: Address = "unknown-address".parse().unwrap(); let result = utils::execute( @@ -415,8 +446,14 @@ fn execute_message_when_invalid_payload_fails() { .. } = TestMessage::dummy(); - utils::register_its_contract(deps.as_mut(), source_its_chain, source_its_contract.clone()) - .unwrap(); + utils::register_chain( + deps.as_mut(), + source_its_chain, + source_its_contract.clone(), + Uint256::MAX.try_into().unwrap(), + u8::MAX, + ) + .unwrap(); let invalid_payload = HexBinary::from_hex("1234").unwrap(); let result = utils::execute( @@ -450,8 +487,14 @@ fn execute_message_when_unknown_chain_fails() { ); assert_err_contains!(result, ExecuteError, ExecuteError::UnknownChain(chain) if chain == &source_its_chain); - utils::register_its_contract(deps.as_mut(), source_its_chain, source_its_contract.clone()) - .unwrap(); + utils::register_chain( + deps.as_mut(), + source_its_chain, + source_its_contract.clone(), + Uint256::MAX.try_into().unwrap(), + u8::MAX, + ) + .unwrap(); let result = utils::execute( deps.as_mut(), @@ -475,10 +518,12 @@ fn execute_message_when_invalid_message_type_fails() { .. } = TestMessage::dummy(); - utils::register_its_contract( + utils::register_chain( deps.as_mut(), source_its_chain.clone(), source_its_contract.clone(), + Uint256::MAX.try_into().unwrap(), + u8::MAX, ) .unwrap(); @@ -547,9 +592,14 @@ fn admin_or_governance_can_freeze_chain() { .unwrap(); let decimals = 18; - assert_ok!(utils::set_chain_config( + let address: Address = "0x1234567890123456789012345678901234567890" + .parse() + .unwrap(); + + assert_ok!(utils::register_chain( deps.as_mut(), chain, + address, max_uint, decimals )); @@ -585,9 +635,14 @@ fn admin_or_governance_can_unfreeze_chain() { .unwrap(); let decimals = 18; - assert_ok!(utils::set_chain_config( + let address: Address = "0x1234567890123456789012345678901234567890" + .parse() + .unwrap(); + + assert_ok!(utils::register_chain( deps.as_mut(), chain, + address, max_uint, decimals )); @@ -696,12 +751,17 @@ fn set_chain_config_should_succeed() { .unwrap(); let decimals = 18; + let address: Address = "0x1234567890123456789012345678901234567890" + .parse() + .unwrap(); + let mut deps = mock_dependencies(); utils::instantiate_contract(deps.as_mut()).unwrap(); - assert_ok!(utils::set_chain_config( + assert_ok!(utils::register_chain( deps.as_mut(), chain, + address, max_uint, decimals )); @@ -716,17 +776,22 @@ fn set_chain_config_should_fail_if_chain_config_is_already_set() { .unwrap(); let decimals = 18; + let address: Address = "0x1234567890123456789012345678901234567890" + .parse() + .unwrap(); + let mut deps = mock_dependencies(); utils::instantiate_contract(deps.as_mut()).unwrap(); - assert_ok!(utils::set_chain_config( + assert_ok!(utils::register_chain( deps.as_mut(), chain.clone(), + address.clone(), max_uint, decimals )); assert_err_contains!( - utils::set_chain_config(deps.as_mut(), chain, max_uint, decimals), + utils::register_chain(deps.as_mut(), chain, address, max_uint, decimals), ExecuteError, ExecuteError::ChainConfigAlreadySet(_) ) @@ -1085,17 +1150,21 @@ fn deploy_interchain_token_from_non_origin_chain_fails() { // Deploy the same token from a different origin chain to a different destination chain now let another_source_chain: ChainNameRaw = "another-source-chain".parse().unwrap(); - utils::register_chain( - &mut deps, + assert_ok!(utils::register_chain( + deps.as_mut(), another_source_chain.clone(), source_its_contract.clone(), - ); + Uint256::MAX.try_into().unwrap(), + u8::MAX, + )); let another_destination_chain: ChainNameRaw = "another-dest-chain".parse().unwrap(); - utils::register_chain( - &mut deps, + assert_ok!(utils::register_chain( + deps.as_mut(), another_destination_chain.clone(), source_its_contract.clone(), - ); + Uint256::MAX.try_into().unwrap(), + u8::MAX, + )); let new_destination_msg = HubMessage::SendToHub { destination_chain: another_source_chain.clone(), @@ -1134,11 +1203,13 @@ fn deploy_interchain_token_to_multiple_destination_succeeds() { )); let another_chain: ChainNameRaw = "another-chain".parse().unwrap(); - utils::register_chain( - &mut deps, + assert_ok!(utils::register_chain( + deps.as_mut(), another_chain.clone(), source_its_contract.clone(), - ); + Uint256::MAX.try_into().unwrap(), + u8::MAX, + )); let msg = HubMessage::SendToHub { destination_chain: another_chain, diff --git a/contracts/interchain-token-service/tests/instantiate.rs b/contracts/interchain-token-service/tests/instantiate.rs index a29bd37ee0..556ffaf9fc 100644 --- a/contracts/interchain-token-service/tests/instantiate.rs +++ b/contracts/interchain-token-service/tests/instantiate.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use assert_ok::assert_ok; use axelar_wasm_std::permission_control::Permission; use axelar_wasm_std::{assert_err_contains, permission_control}; @@ -22,13 +20,6 @@ fn instantiate_succeeds() { fn instantiate_with_args_succeeds() { let mut deps = mock_dependencies(); - let its_contracts = vec![ - ("ethereum".parse().unwrap(), "eth-address".parse().unwrap()), - ("optimism".parse().unwrap(), "op-address".parse().unwrap()), - ] - .into_iter() - .collect::>(); - let mut response = assert_ok!(contract::instantiate( deps.as_mut(), mock_env(), @@ -37,7 +28,6 @@ fn instantiate_with_args_succeeds() { governance_address: params::GOVERNANCE.to_string(), admin_address: params::ADMIN.to_string(), axelarnet_gateway_address: params::GATEWAY.to_string(), - its_contracts: its_contracts.clone(), }, )); @@ -67,9 +57,6 @@ fn instantiate_with_args_succeeds() { )), Permission::Governance.into() ); - - let stored_its_contracts = assert_ok!(utils::query_all_its_contracts(deps.as_ref())); - assert_eq!(stored_its_contracts, its_contracts); } #[test] @@ -79,7 +66,6 @@ fn invalid_gateway_address() { governance_address: utils::params::GOVERNANCE.to_string(), admin_address: utils::params::ADMIN.to_string(), axelarnet_gateway_address: "".to_string(), - its_contracts: Default::default(), }; assert_err_contains!( contract::instantiate(deps.as_mut(), mock_env(), mock_info("sender", &[]), msg), diff --git a/contracts/interchain-token-service/tests/query.rs b/contracts/interchain-token-service/tests/query.rs index c50c996f0e..40be3d1292 100644 --- a/contracts/interchain-token-service/tests/query.rs +++ b/contracts/interchain-token-service/tests/query.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use assert_ok::assert_ok; use cosmwasm_std::testing::mock_dependencies; +use cosmwasm_std::Uint256; use interchain_token_service::TokenId; use router_api::{Address, ChainNameRaw}; @@ -17,7 +18,14 @@ fn query_its_contract() { .parse() .unwrap(); - utils::register_its_contract(deps.as_mut(), chain.clone(), address.clone()).unwrap(); + utils::register_chain( + deps.as_mut(), + chain.clone(), + address.clone(), + Uint256::MAX.try_into().unwrap(), + u8::MAX, + ) + .unwrap(); let queried_address = assert_ok!(utils::query_its_contract(deps.as_ref(), chain.clone())); assert_eq!(queried_address, Some(address)); @@ -29,10 +37,17 @@ fn query_its_contract() { )); assert_eq!(queried_address, None); - assert_ok!(utils::deregister_its_contract(deps.as_mut(), chain.clone())); + let new_address: Address = "0x9999999990123456789012345678901234567890" + .parse() + .unwrap(); + assert_ok!(utils::update_chain( + deps.as_mut(), + chain.clone(), + new_address.clone() + )); let queried_address = assert_ok!(utils::query_its_contract(deps.as_ref(), chain.clone())); - assert_eq!(queried_address, None); + assert_eq!(queried_address, Some(new_address)); let non_existent_chain: ChainNameRaw = "non-existent-chain".parse().unwrap(); let queried_address = assert_ok!(utils::query_its_contract(deps.as_ref(), non_existent_chain)); @@ -62,7 +77,14 @@ fn query_all_its_contracts() { .collect::>(); for (chain, address) in its_contracts.iter() { - utils::register_its_contract(deps.as_mut(), chain.clone(), address.clone()).unwrap(); + utils::register_chain( + deps.as_mut(), + chain.clone(), + address.clone(), + Uint256::MAX.try_into().unwrap(), + u8::MAX, + ) + .unwrap(); } let queried_addresses = assert_ok!(utils::query_all_its_contracts(deps.as_ref())); diff --git a/contracts/interchain-token-service/tests/testdata/execute_message_deploy_interchain_token_should_translate_decimals_when_max_uints_are_different.golden b/contracts/interchain-token-service/tests/testdata/execute_message_deploy_interchain_token_should_translate_decimals_when_max_uints_are_different.golden index 61a3e9a265..869d0f1e5e 100644 --- a/contracts/interchain-token-service/tests/testdata/execute_message_deploy_interchain_token_should_translate_decimals_when_max_uints_are_different.golden +++ b/contracts/interchain-token-service/tests/testdata/execute_message_deploy_interchain_token_should_translate_decimals_when_max_uints_are_different.golden @@ -1,25 +1,15 @@ { + "destination_token_instance": { + "decimals": 6, + "supply": { + "tracked": "0" + } + }, "response": { - "messages": [ - { - "id": 0, - "msg": { - "wasm": { - "execute": { - "contract_addr": "gateway", - "msg": "eyJjYWxsX2NvbnRyYWN0Ijp7ImRlc3RpbmF0aW9uX2NoYWluIjoiZGVzdC1pdHMtY2hhaW4iLCJkZXN0aW5hdGlvbl9hZGRyZXNzIjoiZGVzdC1pdHMtY29udHJhY3QiLCJwYXlsb2FkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDczNmY3NTcyNjM2NTJkNjk3NDczMmQ2MzY4NjE2OTZlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNDU0NjU3Mzc0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzNTQ1MzU0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAifX0=", - "funds": [] - } - } - }, - "gas_limit": null, - "reply_on": "never" - } - ], "attributes": [], + "data": null, "events": [ { - "type": "message_received", "attributes": [ { "key": "cc_id", @@ -49,19 +39,29 @@ "key": "decimals", "value": "6" } - ] + ], + "type": "message_received" } ], - "data": null + "messages": [ + { + "gas_limit": null, + "id": 0, + "msg": { + "wasm": { + "execute": { + "contract_addr": "gateway", + "funds": [], + "msg": "eyJjYWxsX2NvbnRyYWN0Ijp7ImRlc3RpbmF0aW9uX2NoYWluIjoiZGVzdC1pdHMtY2hhaW4iLCJkZXN0aW5hdGlvbl9hZGRyZXNzIjoiZGVzdC1pdHMtY29udHJhY3QiLCJwYXlsb2FkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDczNmY3NTcyNjM2NTJkNjk3NDczMmQ2MzY4NjE2OTZlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNDU0NjU3Mzc0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzNTQ1MzU0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAifX0=" + } + } + }, + "reply_on": "never" + } + ] }, "source_token_instance": { - "supply": "untracked", - "decimals": 18 - }, - "destination_token_instance": { - "supply": { - "tracked": "0" - }, - "decimals": 6 + "decimals": 18, + "supply": "untracked" } } \ No newline at end of file diff --git a/contracts/interchain-token-service/tests/testdata/execute_message_deploy_interchain_token_should_translate_decimals_when_max_uints_are_the_same.golden b/contracts/interchain-token-service/tests/testdata/execute_message_deploy_interchain_token_should_translate_decimals_when_max_uints_are_the_same.golden index 864041d280..a1e3f18c9b 100644 --- a/contracts/interchain-token-service/tests/testdata/execute_message_deploy_interchain_token_should_translate_decimals_when_max_uints_are_the_same.golden +++ b/contracts/interchain-token-service/tests/testdata/execute_message_deploy_interchain_token_should_translate_decimals_when_max_uints_are_the_same.golden @@ -1,25 +1,15 @@ { + "destination_token_instance": { + "decimals": 18, + "supply": { + "tracked": "0" + } + }, "response": { - "messages": [ - { - "id": 0, - "msg": { - "wasm": { - "execute": { - "contract_addr": "gateway", - "msg": "eyJjYWxsX2NvbnRyYWN0Ijp7ImRlc3RpbmF0aW9uX2NoYWluIjoiZGVzdC1pdHMtY2hhaW4iLCJkZXN0aW5hdGlvbl9hZGRyZXNzIjoiZGVzdC1pdHMtY29udHJhY3QiLCJwYXlsb2FkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDczNmY3NTcyNjM2NTJkNjk3NDczMmQ2MzY4NjE2OTZlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNDU0NjU3Mzc0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzNTQ1MzU0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAifX0=", - "funds": [] - } - } - }, - "gas_limit": null, - "reply_on": "never" - } - ], "attributes": [], + "data": null, "events": [ { - "type": "message_received", "attributes": [ { "key": "cc_id", @@ -49,19 +39,29 @@ "key": "decimals", "value": "18" } - ] + ], + "type": "message_received" } ], - "data": null + "messages": [ + { + "gas_limit": null, + "id": 0, + "msg": { + "wasm": { + "execute": { + "contract_addr": "gateway", + "funds": [], + "msg": "eyJjYWxsX2NvbnRyYWN0Ijp7ImRlc3RpbmF0aW9uX2NoYWluIjoiZGVzdC1pdHMtY2hhaW4iLCJkZXN0aW5hdGlvbl9hZGRyZXNzIjoiZGVzdC1pdHMtY29udHJhY3QiLCJwYXlsb2FkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDczNmY3NTcyNjM2NTJkNjk3NDczMmQ2MzY4NjE2OTZlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTIwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNDU0NjU3Mzc0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzNTQ1MzU0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAifX0=" + } + } + }, + "reply_on": "never" + } + ] }, "source_token_instance": { - "supply": "untracked", - "decimals": 18 - }, - "destination_token_instance": { - "supply": { - "tracked": "0" - }, - "decimals": 18 + "decimals": 18, + "supply": "untracked" } } \ No newline at end of file diff --git a/contracts/interchain-token-service/tests/testdata/execute_message_interchain_transfer_should_scale_the_amount_when_source_decimals_are_different.golden b/contracts/interchain-token-service/tests/testdata/execute_message_interchain_transfer_should_scale_the_amount_when_source_decimals_are_different.golden index c9e1f61447..2705330dbe 100644 --- a/contracts/interchain-token-service/tests/testdata/execute_message_interchain_transfer_should_scale_the_amount_when_source_decimals_are_different.golden +++ b/contracts/interchain-token-service/tests/testdata/execute_message_interchain_transfer_should_scale_the_amount_when_source_decimals_are_different.golden @@ -1,25 +1,9 @@ { "response_to_destination": { - "messages": [ - { - "id": 0, - "msg": { - "wasm": { - "execute": { - "contract_addr": "gateway", - "msg": "eyJjYWxsX2NvbnRyYWN0Ijp7ImRlc3RpbmF0aW9uX2NoYWluIjoiZGVzdC1pdHMtY2hhaW4iLCJkZXN0aW5hdGlvbl9hZGRyZXNzIjoiZGVzdC1pdHMtY29udHJhY3QiLCJwYXlsb2FkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDczNmY3NTcyNjM2NTJkNjk3NDczMmQ2MzY4NjE2OTZlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwZjQyNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAyMDAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDIwMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAifX0=", - "funds": [] - } - } - }, - "gas_limit": null, - "reply_on": "never" - } - ], "attributes": [], + "data": null, "events": [ { - "type": "message_received", "attributes": [ { "key": "cc_id", @@ -49,32 +33,32 @@ "key": "amount", "value": "1000000" } - ] + ], + "type": "message_received" } ], - "data": null - }, - "response_to_source": { "messages": [ { + "gas_limit": null, "id": 0, "msg": { "wasm": { "execute": { "contract_addr": "gateway", - "msg": "eyJjYWxsX2NvbnRyYWN0Ijp7ImRlc3RpbmF0aW9uX2NoYWluIjoic291cmNlLWl0cy1jaGFpbiIsImRlc3RpbmF0aW9uX2FkZHJlc3MiOiJzb3VyY2UtaXRzLWNvbnRyYWN0IiwicGF5bG9hZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBhMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGU2NDY1NzM3NDJkNjk3NDczMmQ2MzY4NjE2OTZlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDE2MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBjMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwZGUwYjZiM2E3NjQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDE0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMjAwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAyMDAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIn19", - "funds": [] + "funds": [], + "msg": "eyJjYWxsX2NvbnRyYWN0Ijp7ImRlc3RpbmF0aW9uX2NoYWluIjoiZGVzdC1pdHMtY2hhaW4iLCJkZXN0aW5hdGlvbl9hZGRyZXNzIjoiZGVzdC1pdHMtY29udHJhY3QiLCJwYXlsb2FkIjoiMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDczNmY3NTcyNjM2NTJkNjk3NDczMmQ2MzY4NjE2OTZlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwZjQyNDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAyMDAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDIwMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAifX0=" } } }, - "gas_limit": null, "reply_on": "never" } - ], + ] + }, + "response_to_source": { "attributes": [], + "data": null, "events": [ { - "type": "message_received", "attributes": [ { "key": "cc_id", @@ -104,9 +88,25 @@ "key": "amount", "value": "1000000000000000000" } - ] + ], + "type": "message_received" } ], - "data": null + "messages": [ + { + "gas_limit": null, + "id": 0, + "msg": { + "wasm": { + "execute": { + "contract_addr": "gateway", + "funds": [], + "msg": "eyJjYWxsX2NvbnRyYWN0Ijp7ImRlc3RpbmF0aW9uX2NoYWluIjoic291cmNlLWl0cy1jaGFpbiIsImRlc3RpbmF0aW9uX2FkZHJlc3MiOiJzb3VyY2UtaXRzLWNvbnRyYWN0IiwicGF5bG9hZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDMwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDYwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBhMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMGU2NDY1NzM3NDJkNjk3NDczMmQ2MzY4NjE2OTZlMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDE2MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBjMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwZGUwYjZiM2E3NjQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDE0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMjAwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDIwMjAyMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAyMDAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMTAxMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIn19" + } + } + }, + "reply_on": "never" + } + ] } } \ No newline at end of file diff --git a/contracts/interchain-token-service/tests/testdata/instantiate_with_args_succeeds.golden b/contracts/interchain-token-service/tests/testdata/instantiate_with_args_succeeds.golden index 50b1e20565..c9a213425c 100644 --- a/contracts/interchain-token-service/tests/testdata/instantiate_with_args_succeeds.golden +++ b/contracts/interchain-token-service/tests/testdata/instantiate_with_args_succeeds.golden @@ -1,33 +1,6 @@ { "messages": [], "attributes": [], - "events": [ - { - "type": "its_contract_registered", - "attributes": [ - { - "key": "chain", - "value": "ethereum" - }, - { - "key": "address", - "value": "eth-address" - } - ] - }, - { - "type": "its_contract_registered", - "attributes": [ - { - "key": "chain", - "value": "optimism" - }, - { - "key": "address", - "value": "op-address" - } - ] - } - ], + "events": [], "data": null } \ No newline at end of file diff --git a/contracts/interchain-token-service/tests/utils/execute.rs b/contracts/interchain-token-service/tests/utils/execute.rs index e6e15a9793..771f5a4f9c 100644 --- a/contracts/interchain-token-service/tests/utils/execute.rs +++ b/contracts/interchain-token-service/tests/utils/execute.rs @@ -1,4 +1,5 @@ use std::marker::PhantomData; +use std::u8; use axelar_core_std::nexus; use axelar_core_std::nexus::query::IsChainRegisteredResponse; @@ -44,49 +45,6 @@ pub fn execute_hub_message( execute(deps, cc_id, source_address, message.abi_encode()) } -pub fn register_its_contract( - deps: DepsMut, - chain: ChainNameRaw, - address: Address, -) -> Result { - contract::execute( - deps, - mock_env(), - mock_info(params::GOVERNANCE, &[]), - ExecuteMsg::RegisterItsContract { chain, address }, - ) -} - -pub fn deregister_its_contract( - deps: DepsMut, - chain: ChainNameRaw, -) -> Result { - contract::execute( - deps, - mock_env(), - mock_info(params::ADMIN, &[]), - ExecuteMsg::DeregisterItsContract { chain }, - ) -} - -pub fn set_chain_config( - deps: DepsMut, - chain: ChainNameRaw, - max_uint: nonempty::Uint256, - max_target_decimals: u8, -) -> Result { - contract::execute( - deps, - mock_env(), - mock_info(params::GOVERNANCE, &[]), - ExecuteMsg::SetChainConfig { - chain, - max_uint, - max_target_decimals, - }, - ) -} - pub fn make_deps() -> OwnedDeps> { let addr = Addr::unchecked(params::GATEWAY); let mut deps = OwnedDeps { @@ -127,18 +85,39 @@ pub fn make_deps() -> OwnedDeps>, + deps: DepsMut, chain: ChainNameRaw, - its_contract: Address, -) { - register_its_contract(deps.as_mut(), chain.clone(), its_contract).unwrap(); - set_chain_config( - deps.as_mut(), - chain, - Uint256::MAX.try_into().unwrap(), - u8::MAX, + its_edge_contract: Address, + max_uint: nonempty::Uint256, + max_target_decimals: u8, +) -> Result { + contract::execute( + deps, + mock_env(), + mock_info(params::GOVERNANCE, &[]), + ExecuteMsg::RegisterChain { + chain, + its_edge_contract, + max_uint, + max_target_decimals, + }, + ) +} + +pub fn update_chain( + deps: DepsMut, + chain: ChainNameRaw, + its_edge_contract: Address, +) -> Result { + contract::execute( + deps, + mock_env(), + mock_info(params::GOVERNANCE, &[]), + ExecuteMsg::UpdateChain { + chain, + its_edge_contract, + }, ) - .unwrap(); } pub fn setup_with_chain_configs( @@ -161,24 +140,19 @@ pub fn setup_with_chain_configs( .. } = TestMessage::dummy(); - register_its_contract(deps.as_mut(), source_its_chain.clone(), source_its_contract).unwrap(); - set_chain_config( + register_chain( deps.as_mut(), source_its_chain, + source_its_contract, source_max_uint, source_max_target_decimals, ) .unwrap(); - register_its_contract( - deps.as_mut(), - destination_its_chain.clone(), - destination_its_contract, - ) - .unwrap(); - set_chain_config( + register_chain( deps.as_mut(), destination_its_chain, + destination_its_contract, destination_max_uint, destination_max_target_decimals, ) @@ -203,15 +177,21 @@ pub fn setup() -> ( } = TestMessage::dummy(); register_chain( - &mut deps, + deps.as_mut(), source_its_chain.clone(), source_its_contract.clone(), - ); + Uint256::MAX.try_into().unwrap(), + u8::MAX, + ) + .unwrap(); register_chain( - &mut deps, + deps.as_mut(), destination_its_chain.clone(), destination_its_contract.clone(), - ); + Uint256::MAX.try_into().unwrap(), + u8::MAX, + ) + .unwrap(); (deps, TestMessage::dummy()) } diff --git a/contracts/interchain-token-service/tests/utils/instantiate.rs b/contracts/interchain-token-service/tests/utils/instantiate.rs index e409dc675f..28c8116045 100644 --- a/contracts/interchain-token-service/tests/utils/instantiate.rs +++ b/contracts/interchain-token-service/tests/utils/instantiate.rs @@ -15,7 +15,6 @@ pub fn instantiate_contract(deps: DepsMut) -> Result { governance_address: params::GOVERNANCE.to_string(), admin_address: params::ADMIN.to_string(), axelarnet_gateway_address: params::GATEWAY.to_string(), - its_contracts: Default::default(), }, ) } From fa0e3f68b6a4127e0bcb6b9e055a2020477124c2 Mon Sep 17 00:00:00 2001 From: CJ Cobb Date: Wed, 6 Nov 2024 16:08:42 -0500 Subject: [PATCH 2/6] add batching --- .../interchain-token-service/src/contract.rs | 20 +-- .../src/contract/execute.rs | 119 ++++++++++++++---- contracts/interchain-token-service/src/msg.rs | 15 ++- .../interchain-token-service/tests/execute.rs | 59 +++++++-- .../tests/utils/execute.rs | 23 ++-- 5 files changed, 178 insertions(+), 58 deletions(-) diff --git a/contracts/interchain-token-service/src/contract.rs b/contracts/interchain-token-service/src/contract.rs index ddf3d3277f..bb4751358c 100644 --- a/contracts/interchain-token-service/src/contract.rs +++ b/contracts/interchain-token-service/src/contract.rs @@ -25,8 +25,8 @@ const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); pub enum Error { #[error("failed to execute a cross-chain message")] Execute, - #[error("failed to register chain")] - RegisterChain, + #[error("failed to register chains")] + RegisterChains, #[error("failed to update chain")] UpdateChain, #[error("failed to freeze chain")] @@ -97,19 +97,9 @@ pub fn execute( payload, }) => execute::execute_message(deps, cc_id, source_address, payload) .change_context(Error::Execute), - ExecuteMsg::RegisterChain { - chain, - its_edge_contract, - max_uint, - max_target_decimals, - } => execute::register_chain( - deps, - chain, - its_edge_contract, - max_uint, - max_target_decimals, - ) - .change_context(Error::RegisterChain), + ExecuteMsg::RegisterChains { chains } => { + execute::register_chains(deps, chains).change_context(Error::RegisterChains) + } ExecuteMsg::UpdateChain { chain, its_edge_contract, diff --git a/contracts/interchain-token-service/src/contract/execute.rs b/contracts/interchain-token-service/src/contract/execute.rs index ad8491cc1e..1b20dc6bbc 100644 --- a/contracts/interchain-token-service/src/contract/execute.rs +++ b/contracts/interchain-token-service/src/contract/execute.rs @@ -1,19 +1,20 @@ use axelar_wasm_std::{killswitch, nonempty, FnExt, IntoContractError}; use cosmwasm_std::{DepsMut, HexBinary, QuerierWrapper, Response, Storage, Uint256}; use error_stack::{bail, ensure, report, Result, ResultExt}; +use itertools::Itertools; use router_api::{Address, ChainNameRaw, CrossChainId}; use crate::events::Event; use crate::primitives::HubMessage; use crate::state::{self, is_chain_frozen, load_config, load_its_contract, TokenDeploymentType}; use crate::{ - DeployInterchainToken, InterchainTransfer, Message, TokenConfig, TokenId, TokenInstance, + msg, DeployInterchainToken, InterchainTransfer, Message, TokenConfig, TokenId, TokenInstance, }; #[derive(thiserror::Error, Debug, IntoContractError)] pub enum Error { - #[error("unknown chain {0}")] - UnknownChain(ChainNameRaw), + #[error("chain not found {0}")] + ChainNotFound(ChainNameRaw), #[error("unknown its address {0}")] UnknownItsContract(Address), #[error("failed to decode payload")] @@ -40,8 +41,8 @@ pub enum Error { }, #[error("state error")] State, - #[error("chain config for {0} already set")] - ChainConfigAlreadySet(ChainNameRaw), + #[error("chain {0} already registered")] + ChainAlreadyRegistered(ChainNameRaw), #[error("token {token_id} not deployed on chain {chain}")] TokenNotDeployed { token_id: TokenId, @@ -107,7 +108,7 @@ fn execute_message_on_hub( message: Message, ) -> Result { let destination_address = load_its_contract(deps.storage, &destination_chain) - .change_context_lazy(|| Error::UnknownChain(destination_chain.clone()))?; + .change_context_lazy(|| Error::ChainNotFound(destination_chain.clone()))?; let message = apply_to_hub( deps.storage, @@ -177,7 +178,7 @@ fn ensure_is_its_source_address( source_address: &Address, ) -> Result<(), Error> { let source_its_contract = load_its_contract(storage, source_chain) - .change_context_lazy(|| Error::UnknownChain(source_chain.clone()))?; + .change_context_lazy(|| Error::ChainNotFound(source_chain.clone()))?; ensure!( source_address == &source_its_contract, @@ -225,24 +226,36 @@ pub fn enable_execution(deps: DepsMut) -> Result { killswitch::disengage(deps.storage, Event::ExecutionEnabled).change_context(Error::State) } +pub fn register_chains(deps: DepsMut, chains: Vec) -> Result { + chains + .into_iter() + .map(|chain_config| { + register_chain( + deps.storage, + chain_config.chain, + chain_config.its_edge_contract, + chain_config.max_uint, + chain_config.max_target_decimals, + ) + }) + .try_collect::<_, Vec, _>()? + .then(|_| Ok(Response::new())) +} + pub fn register_chain( - deps: DepsMut, + storage: &mut dyn Storage, chain: ChainNameRaw, its_address: Address, max_uint: nonempty::Uint256, max_target_decimals: u8, ) -> Result { - match state::may_load_chain_config(deps.storage, &chain).change_context(Error::State)? { - Some(_) => bail!(Error::ChainConfigAlreadySet(chain)), - None => state::save_chain_config( - deps.storage, - &chain, - its_address, - max_uint, - max_target_decimals, - ) - .change_context(Error::State)? - .then(|_| Ok(Response::new())), + match state::may_load_chain_config(storage, &chain).change_context(Error::State)? { + Some(_) => bail!(Error::ChainAlreadyRegistered(chain)), + None => { + state::save_chain_config(storage, &chain, its_address, max_uint, max_target_decimals) + .change_context(Error::State)? + .then(|_| Ok(Response::new())) + } } } @@ -611,10 +624,10 @@ mod tests { use crate::contract::execute::{ disable_execution, enable_execution, execute_message, freeze_chain, register_chain, - unfreeze_chain, Error, + register_chains, unfreeze_chain, update_chain, Error, }; use crate::state::{self, Config}; - use crate::{DeployInterchainToken, HubMessage, InterchainTransfer}; + use crate::{msg, DeployInterchainToken, HubMessage, InterchainTransfer}; const SOLANA: &str = "solana"; const ETHEREUM: &str = "ethereum"; @@ -841,6 +854,68 @@ mod tests { )); } + #[test] + fn register_chain_fails_if_already_registered() { + let mut deps = mock_dependencies(); + assert_ok!(register_chain( + deps.as_mut().storage, + SOLANA.parse().unwrap(), + ITS_ADDRESS.to_string().try_into().unwrap(), + Uint256::one().try_into().unwrap(), + 16u8 + )); + assert_err_contains!( + register_chain( + deps.as_mut().storage, + SOLANA.parse().unwrap(), + ITS_ADDRESS.to_string().try_into().unwrap(), + Uint256::one().try_into().unwrap(), + 16u8 + ), + Error, + Error::ChainAlreadyRegistered(..) + ); + } + + #[test] + fn register_chains_fails_if_any_already_registered() { + let mut deps = mock_dependencies(); + let chains = vec![ + msg::ChainConfig { + chain: SOLANA.parse().unwrap(), + its_edge_contract: ITS_ADDRESS.to_string().try_into().unwrap(), + max_uint: Uint256::MAX.try_into().unwrap(), + max_target_decimals: 16u8, + }, + msg::ChainConfig { + chain: XRPL.parse().unwrap(), + its_edge_contract: ITS_ADDRESS.to_string().try_into().unwrap(), + max_uint: Uint256::MAX.try_into().unwrap(), + max_target_decimals: 16u8, + }, + ]; + assert_ok!(register_chains(deps.as_mut(), chains[0..1].to_vec())); + assert_err_contains!( + register_chains(deps.as_mut(), chains,), + Error, + Error::ChainAlreadyRegistered(..) + ); + } + + #[test] + fn update_chain_fails_if_not_registered() { + let mut deps = mock_dependencies(); + assert_err_contains!( + update_chain( + deps.as_mut(), + SOLANA.parse().unwrap(), + ITS_ADDRESS.parse().unwrap() + ), + Error, + Error::State + ); + } + fn init(deps: &mut OwnedDeps) { assert_ok!(permission_control::set_admin( deps.as_mut().storage, @@ -866,7 +941,7 @@ mod tests { for chain_name in [SOLANA, ETHEREUM, XRPL] { let chain = ChainNameRaw::try_from(chain_name).unwrap(); assert_ok!(register_chain( - deps.as_mut(), + deps.as_mut().storage, chain.clone(), ITS_ADDRESS.to_string().try_into().unwrap(), Uint256::one().try_into().unwrap(), diff --git a/contracts/interchain-token-service/src/msg.rs b/contracts/interchain-token-service/src/msg.rs index 0e7debbbab..cefba6a12e 100644 --- a/contracts/interchain-token-service/src/msg.rs +++ b/contracts/interchain-token-service/src/msg.rs @@ -28,12 +28,7 @@ pub enum ExecuteMsg { /// ITS Hub can send cross-chain messages to it, or receive messages from it. /// If an ITS contract is already set for the chain, an error is returned. #[permission(Governance)] - RegisterChain { - chain: ChainNameRaw, - its_edge_contract: Address, - max_uint: nonempty::Uint256, // The maximum uint value that is supported by the chain's token standard - max_target_decimals: u8, // The maximum number of decimals that is preserved when deploying a token to another chain where smaller uint values are used - }, + RegisterChains { chains: Vec }, #[permission(Governance)] UpdateChain { @@ -56,6 +51,14 @@ pub enum ExecuteMsg { EnableExecution, } +#[cw_serde] +pub struct ChainConfig { + pub chain: ChainNameRaw, + pub its_edge_contract: Address, + pub max_uint: nonempty::Uint256, // The maximum uint value that is supported by the chain's token standard + pub max_target_decimals: u8, // The maximum number of decimals that is preserved when deploying a token to another chain where smaller uint values are used +} + #[cw_serde] #[derive(QueryResponses)] pub enum QueryMsg { diff --git a/contracts/interchain-token-service/tests/execute.rs b/contracts/interchain-token-service/tests/execute.rs index 67dd2f7b64..52f26a91f2 100644 --- a/contracts/interchain-token-service/tests/execute.rs +++ b/contracts/interchain-token-service/tests/execute.rs @@ -8,13 +8,13 @@ use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; use cosmwasm_std::{HexBinary, Uint256}; use interchain_token_service::contract::{self, ExecuteError}; use interchain_token_service::events::Event; -use interchain_token_service::msg::ExecuteMsg; +use interchain_token_service::msg::{self, ExecuteMsg}; use interchain_token_service::{ DeployInterchainToken, HubMessage, InterchainTransfer, TokenId, TokenSupply, }; use router_api::{Address, ChainName, ChainNameRaw, CrossChainId}; use serde_json::json; -use utils::{params, TestMessage}; +use utils::{params, register_chains, TestMessage}; mod utils; @@ -55,7 +55,7 @@ fn register_update_its_contract_succeeds() { } #[test] -fn reregistering_its_contract_fails() { +fn reregistering_same_chain_fails() { let mut deps = mock_dependencies(); utils::instantiate_contract(deps.as_mut()).unwrap(); @@ -81,12 +81,12 @@ fn reregistering_its_contract_fails() { u8::MAX ), Error, - Error::RegisterChain + Error::RegisterChains ); } #[test] -fn deregistering_unknown_chain_fails() { +fn update_unknown_chain_fails() { let mut deps = mock_dependencies(); utils::instantiate_contract(deps.as_mut()).unwrap(); @@ -105,6 +105,49 @@ fn deregistering_unknown_chain_fails() { ); } +#[test] +fn register_multiple_chains_succeeds() { + let mut deps = mock_dependencies(); + utils::instantiate_contract(deps.as_mut()).unwrap(); + let chains: Vec = (0..10) + .map(|i| msg::ChainConfig { + chain: i.to_string().parse().unwrap(), + its_edge_contract: i.to_string().parse().unwrap(), + max_target_decimals: 18u8, + max_uint: Uint256::MAX.try_into().unwrap(), + }) + .collect(); + assert_ok!(register_chains(deps.as_mut(), chains.clone())); + + for chain in chains { + let res = assert_ok!(utils::query_its_contract( + deps.as_ref(), + chain.chain.clone() + )); + assert_eq!(res, Some(chain.its_edge_contract)); + } +} + +#[test] +fn register_multiple_chains_fails_if_one_invalid() { + let mut deps = mock_dependencies(); + utils::instantiate_contract(deps.as_mut()).unwrap(); + let chains: Vec = (0..10) + .map(|i| msg::ChainConfig { + chain: i.to_string().parse().unwrap(), + its_edge_contract: i.to_string().parse().unwrap(), + max_target_decimals: 18u8, + max_uint: Uint256::MAX.try_into().unwrap(), + }) + .collect(); + assert_ok!(register_chains(deps.as_mut(), chains[0..1].to_vec())); + assert_err_contains!( + register_chains(deps.as_mut(), chains.clone()), + Error, + Error::RegisterChains + ); +} + #[test] fn execute_hub_message_succeeds() { let ( @@ -485,7 +528,7 @@ fn execute_message_when_unknown_chain_fails() { source_its_contract.clone(), hub_message.clone().abi_encode(), ); - assert_err_contains!(result, ExecuteError, ExecuteError::UnknownChain(chain) if chain == &source_its_chain); + assert_err_contains!(result, ExecuteError, ExecuteError::ChainNotFound(chain) if chain == &source_its_chain); utils::register_chain( deps.as_mut(), @@ -502,7 +545,7 @@ fn execute_message_when_unknown_chain_fails() { source_its_contract, hub_message.abi_encode(), ); - assert_err_contains!(result, ExecuteError, ExecuteError::UnknownChain(chain) if chain == &destination_its_chain); + assert_err_contains!(result, ExecuteError, ExecuteError::ChainNotFound(chain) if chain == &destination_its_chain); } #[test] @@ -793,7 +836,7 @@ fn set_chain_config_should_fail_if_chain_config_is_already_set() { assert_err_contains!( utils::register_chain(deps.as_mut(), chain, address, max_uint, decimals), ExecuteError, - ExecuteError::ChainConfigAlreadySet(_) + ExecuteError::ChainAlreadyRegistered(_) ) } diff --git a/contracts/interchain-token-service/tests/utils/execute.rs b/contracts/interchain-token-service/tests/utils/execute.rs index 771f5a4f9c..0c7c4ac971 100644 --- a/contracts/interchain-token-service/tests/utils/execute.rs +++ b/contracts/interchain-token-service/tests/utils/execute.rs @@ -1,5 +1,4 @@ use std::marker::PhantomData; -use std::u8; use axelar_core_std::nexus; use axelar_core_std::nexus::query::IsChainRegisteredResponse; @@ -11,7 +10,7 @@ use cosmwasm_std::{ from_json, to_json_binary, Addr, DepsMut, HexBinary, MemoryStorage, OwnedDeps, Response, Uint256, WasmQuery, }; -use interchain_token_service::msg::ExecuteMsg; +use interchain_token_service::msg::{self, ExecuteMsg}; use interchain_token_service::{contract, HubMessage}; use router_api::{Address, ChainName, ChainNameRaw, CrossChainId}; @@ -91,16 +90,26 @@ pub fn register_chain( max_uint: nonempty::Uint256, max_target_decimals: u8, ) -> Result { - contract::execute( + register_chains( deps, - mock_env(), - mock_info(params::GOVERNANCE, &[]), - ExecuteMsg::RegisterChain { + vec![msg::ChainConfig { chain, its_edge_contract, max_uint, max_target_decimals, - }, + }], + ) +} + +pub fn register_chains( + deps: DepsMut, + chains: Vec, +) -> Result { + contract::execute( + deps, + mock_env(), + mock_info(params::GOVERNANCE, &[]), + ExecuteMsg::RegisterChains { chains }, ) } From a6505eaf6303ef9f1355701801c6690c97b13c8e Mon Sep 17 00:00:00 2001 From: CJ Cobb Date: Wed, 6 Nov 2024 16:15:26 -0500 Subject: [PATCH 3/6] remove goldie --- contracts/interchain-token-service/tests/execute.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/contracts/interchain-token-service/tests/execute.rs b/contracts/interchain-token-service/tests/execute.rs index 52f26a91f2..f1b9677d13 100644 --- a/contracts/interchain-token-service/tests/execute.rs +++ b/contracts/interchain-token-service/tests/execute.rs @@ -30,7 +30,7 @@ fn register_update_its_contract_succeeds() { .parse() .unwrap(); - let register_response = assert_ok!(utils::register_chain( + assert_ok!(utils::register_chain( deps.as_mut(), chain.clone(), address.clone(), @@ -43,15 +43,13 @@ fn register_update_its_contract_succeeds() { let new_address: Address = "0x9999999990123456789012345678901234567890" .parse() .unwrap(); - let update_response = assert_ok!(utils::update_chain( + assert_ok!(utils::update_chain( deps.as_mut(), chain.clone(), new_address.clone() )); let res = assert_ok!(utils::query_its_contract(deps.as_ref(), chain.clone())); assert_eq!(res, Some(new_address)); - - goldie::assert_json!([register_response, update_response]); } #[test] From ef5ef51f611eb5217dd18baa77c47ddbcc47abf5 Mon Sep 17 00:00:00 2001 From: CJ Cobb Date: Wed, 6 Nov 2024 16:25:49 -0500 Subject: [PATCH 4/6] add comments --- contracts/interchain-token-service/src/msg.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/interchain-token-service/src/msg.rs b/contracts/interchain-token-service/src/msg.rs index cefba6a12e..a52e550299 100644 --- a/contracts/interchain-token-service/src/msg.rs +++ b/contracts/interchain-token-service/src/msg.rs @@ -24,12 +24,14 @@ pub enum ExecuteMsg { #[permission(Specific(gateway))] Execute(AxelarExecutableMsg), - /// Register the ITS contract address of another chain. Each chain's ITS contract has to be whitelisted before + /// For each chain, register the ITS contract and set config parameters. + /// Each chain's ITS contract has to be whitelisted before /// ITS Hub can send cross-chain messages to it, or receive messages from it. /// If an ITS contract is already set for the chain, an error is returned. #[permission(Governance)] RegisterChains { chains: Vec }, + /// Update the address of the ITS contract registered to the specified chain #[permission(Governance)] UpdateChain { chain: ChainNameRaw, From dfc0a7f0448be2f93f4b6e3895f2b121a380ed38 Mon Sep 17 00:00:00 2001 From: CJ Cobb Date: Thu, 7 Nov 2024 12:02:05 -0500 Subject: [PATCH 5/6] review --- .../src/contract/execute.rs | 62 ++++++++----------- .../interchain-token-service/src/state.rs | 50 ++++++++------- 2 files changed, 55 insertions(+), 57 deletions(-) diff --git a/contracts/interchain-token-service/src/contract/execute.rs b/contracts/interchain-token-service/src/contract/execute.rs index 1b20dc6bbc..f2d6df469b 100644 --- a/contracts/interchain-token-service/src/contract/execute.rs +++ b/contracts/interchain-token-service/src/contract/execute.rs @@ -229,33 +229,17 @@ pub fn enable_execution(deps: DepsMut) -> Result { pub fn register_chains(deps: DepsMut, chains: Vec) -> Result { chains .into_iter() - .map(|chain_config| { - register_chain( - deps.storage, - chain_config.chain, - chain_config.its_edge_contract, - chain_config.max_uint, - chain_config.max_target_decimals, - ) - }) + .map(|chain_config| register_chain(deps.storage, chain_config)) .try_collect::<_, Vec, _>()? .then(|_| Ok(Response::new())) } -pub fn register_chain( - storage: &mut dyn Storage, - chain: ChainNameRaw, - its_address: Address, - max_uint: nonempty::Uint256, - max_target_decimals: u8, -) -> Result { - match state::may_load_chain_config(storage, &chain).change_context(Error::State)? { - Some(_) => bail!(Error::ChainAlreadyRegistered(chain)), - None => { - state::save_chain_config(storage, &chain, its_address, max_uint, max_target_decimals) - .change_context(Error::State)? - .then(|_| Ok(Response::new())) - } +fn register_chain(storage: &mut dyn Storage, config: msg::ChainConfig) -> Result { + match state::may_load_chain_config(storage, &config.chain).change_context(Error::State)? { + Some(_) => bail!(Error::ChainAlreadyRegistered(config.chain)), + None => state::save_chain_config(storage, &config.chain.clone(), config) + .change_context(Error::State)? + .then(|_| Ok(Response::new())), } } @@ -859,18 +843,24 @@ mod tests { let mut deps = mock_dependencies(); assert_ok!(register_chain( deps.as_mut().storage, - SOLANA.parse().unwrap(), - ITS_ADDRESS.to_string().try_into().unwrap(), - Uint256::one().try_into().unwrap(), - 16u8 + msg::ChainConfig { + chain: SOLANA.parse().unwrap(), + + its_edge_contract: ITS_ADDRESS.to_string().try_into().unwrap(), + max_uint: Uint256::one().try_into().unwrap(), + max_target_decimals: 16u8 + } )); assert_err_contains!( register_chain( deps.as_mut().storage, - SOLANA.parse().unwrap(), - ITS_ADDRESS.to_string().try_into().unwrap(), - Uint256::one().try_into().unwrap(), - 16u8 + msg::ChainConfig { + chain: SOLANA.parse().unwrap(), + + its_edge_contract: ITS_ADDRESS.to_string().try_into().unwrap(), + max_uint: Uint256::one().try_into().unwrap(), + max_target_decimals: 16u8 + } ), Error, Error::ChainAlreadyRegistered(..) @@ -942,10 +932,12 @@ mod tests { let chain = ChainNameRaw::try_from(chain_name).unwrap(); assert_ok!(register_chain( deps.as_mut().storage, - chain.clone(), - ITS_ADDRESS.to_string().try_into().unwrap(), - Uint256::one().try_into().unwrap(), - 16u8 + msg::ChainConfig { + chain: chain.clone(), + its_edge_contract: ITS_ADDRESS.to_string().try_into().unwrap(), + max_uint: Uint256::one().try_into().unwrap(), + max_target_decimals: 16u8 + } )); } } diff --git a/contracts/interchain-token-service/src/state.rs b/contracts/interchain-token-service/src/state.rs index 385c783c08..f48e973b4d 100644 --- a/contracts/interchain-token-service/src/state.rs +++ b/contracts/interchain-token-service/src/state.rs @@ -7,7 +7,7 @@ use cw_storage_plus::{Item, Map}; use error_stack::{report, Result, ResultExt}; use router_api::{Address, ChainNameRaw}; -use crate::TokenId; +use crate::{msg, TokenId}; #[derive(thiserror::Error, Debug, IntoContractError)] pub enum Error { @@ -40,6 +40,17 @@ pub struct ChainConfig { frozen: bool, } +impl From for ChainConfig { + fn from(value: msg::ChainConfig) -> Self { + Self { + max_uint: value.max_uint, + max_target_decimals: value.max_target_decimals, + its_address: value.its_edge_contract, + frozen: false, + } + } +} + #[cw_serde] pub enum TokenSupply { /// The total token supply bridged to this chain. @@ -144,21 +155,10 @@ pub fn load_chain_config( pub fn save_chain_config( storage: &mut dyn Storage, chain: &ChainNameRaw, - its_contract: Address, - max_uint: nonempty::Uint256, - max_target_decimals: u8, + config: impl Into, ) -> Result<(), Error> { CHAIN_CONFIGS - .save( - storage, - chain, - &ChainConfig { - max_uint, - max_target_decimals, - its_address: its_contract, - frozen: false, - }, - ) + .save(storage, chain, &config.into()) .change_context(Error::Storage) } @@ -322,17 +322,23 @@ mod tests { assert_ok!(save_chain_config( deps.as_mut().storage, - &chain1, - address1.clone(), - Uint256::MAX.try_into().unwrap(), - 16u8 + &chain1.clone(), + msg::ChainConfig { + chain: chain1.clone(), + its_edge_contract: address1.clone(), + max_uint: Uint256::MAX.try_into().unwrap(), + max_target_decimals: 16u8 + } )); assert_ok!(save_chain_config( deps.as_mut().storage, - &chain2, - address2.clone(), - Uint256::MAX.try_into().unwrap(), - 16u8 + &chain2.clone(), + msg::ChainConfig { + chain: chain2.clone(), + its_edge_contract: address2.clone(), + max_uint: Uint256::MAX.try_into().unwrap(), + max_target_decimals: 16u8 + } )); assert_eq!( assert_ok!(load_its_contract(deps.as_ref().storage, &chain1)), From 79ccf5605c830fc5b517aaa0888a2e9fd90119ad Mon Sep 17 00:00:00 2001 From: CJ Cobb Date: Thu, 7 Nov 2024 12:03:11 -0500 Subject: [PATCH 6/6] cleanup --- contracts/interchain-token-service/src/contract/execute.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/contracts/interchain-token-service/src/contract/execute.rs b/contracts/interchain-token-service/src/contract/execute.rs index f2d6df469b..1ab5ee7468 100644 --- a/contracts/interchain-token-service/src/contract/execute.rs +++ b/contracts/interchain-token-service/src/contract/execute.rs @@ -845,7 +845,6 @@ mod tests { deps.as_mut().storage, msg::ChainConfig { chain: SOLANA.parse().unwrap(), - its_edge_contract: ITS_ADDRESS.to_string().try_into().unwrap(), max_uint: Uint256::one().try_into().unwrap(), max_target_decimals: 16u8 @@ -856,7 +855,6 @@ mod tests { deps.as_mut().storage, msg::ChainConfig { chain: SOLANA.parse().unwrap(), - its_edge_contract: ITS_ADDRESS.to_string().try_into().unwrap(), max_uint: Uint256::one().try_into().unwrap(), max_target_decimals: 16u8