diff --git a/cosmwasm/contracts/crosschain-registry/src/contract.rs b/cosmwasm/contracts/crosschain-registry/src/contract.rs index a448c651e23..3931b08a8ff 100644 --- a/cosmwasm/contracts/crosschain-registry/src/contract.rs +++ b/cosmwasm/contracts/crosschain-registry/src/contract.rs @@ -4,21 +4,15 @@ use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, use cw2::set_contract_version; use crate::error::ContractError; -use crate::msg::{ - ExecuteMsg, GetAddressFromAliasResponse, IBCLifecycleComplete, InstantiateMsg, QueryMsg, - SudoMsg, -}; -use crate::state::{ChainPFM, Config, CHAIN_PFM_MAP, CONFIG, CONTRACT_ALIAS_MAP}; -use crate::{execute, ibc_lifecycle, query}; +use crate::msg::{ExecuteMsg, GetAddressFromAliasResponse, InstantiateMsg, QueryMsg}; +use crate::state::{Config, CONFIG, CONTRACT_ALIAS_MAP}; +use crate::{execute, query}; use registry::Registry; // version info for migration const CONTRACT_NAME: &str = "crates.io:crosschain-registry"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); -// The name of the chain on which this contract is instantiated -pub const CONTRACT_CHAIN: &str = "osmosis"; - #[cfg_attr(not(feature = "imported"), entry_point)] pub fn instantiate( deps: DepsMut, @@ -33,15 +27,6 @@ pub fn instantiate( let state = Config { owner }; CONFIG.save(deps.storage, &state)?; - CHAIN_PFM_MAP.save( - deps.storage, - CONTRACT_CHAIN, - &ChainPFM { - acknowledged: true, - validated: true, - }, - )?; - Ok(Response::new().add_attribute("method", "instantiate")) } @@ -88,16 +73,12 @@ pub fn execute( env.block.time, with_memo, None, - false, )?; deps.api.debug(&format!("transfer_msg: {transfer_msg:?}")); Ok(Response::new() .add_message(transfer_msg) .add_attribute("method", "unwrap_coin")) } - - ExecuteMsg::ProposePFM { chain } => execute::propose_pfm((deps, env, info), chain), - ExecuteMsg::ValidatePFM { chain } => execute::validate_pfm((deps, env, info), chain), } } @@ -139,24 +120,6 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { QueryMsg::GetChainNameFromBech32Prefix { prefix } => { to_binary(&query::query_chain_name_from_bech32_prefix(deps, prefix)?) } - QueryMsg::HasPacketForwarding { chain } => { - to_binary(&query::query_chain_has_pfm(deps, chain)) - } - } -} - -#[cfg_attr(not(feature = "imported"), entry_point)] -pub fn sudo(deps: DepsMut, _env: Env, msg: SudoMsg) -> Result { - match msg { - SudoMsg::IBCLifecycleComplete(IBCLifecycleComplete::IBCAck { - channel, - sequence, - ack, - success, - }) => ibc_lifecycle::receive_ack(deps, channel, sequence, ack, success), - SudoMsg::IBCLifecycleComplete(IBCLifecycleComplete::IBCTimeout { channel, sequence }) => { - ibc_lifecycle::receive_timeout(deps, channel, sequence) - } } } @@ -248,7 +211,7 @@ mod test { deps.as_ref(), mock_env(), QueryMsg::GetChannelFromChainPair { - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "juno".to_string(), }, ) @@ -261,7 +224,7 @@ mod test { deps.as_ref(), mock_env(), QueryMsg::GetDestinationChainFromSourceChainViaChannel { - on_chain: CONTRACT_CHAIN.to_string(), + on_chain: "osmosis".to_string(), via_channel: "channel-42".to_string(), }, ) @@ -274,7 +237,7 @@ mod test { deps.as_ref(), mock_env(), QueryMsg::GetChannelFromChainPair { - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "stargaze".to_string(), }, ) @@ -287,7 +250,7 @@ mod test { deps.as_ref(), mock_env(), QueryMsg::GetDestinationChainFromSourceChainViaChannel { - on_chain: CONTRACT_CHAIN.to_string(), + on_chain: "osmosis".to_string(), via_channel: "channel-75".to_string(), }, ) @@ -301,7 +264,7 @@ mod test { mock_env(), QueryMsg::GetChannelFromChainPair { source_chain: "stargaze".to_string(), - destination_chain: CONTRACT_CHAIN.to_string(), + destination_chain: "osmosis".to_string(), }, ) .unwrap(); @@ -319,14 +282,14 @@ mod test { ) .unwrap(); let destination_chain: String = from_binary(&destination_chain).unwrap(); - assert_eq!(CONTRACT_CHAIN, destination_chain); + assert_eq!("osmosis", destination_chain); // Attempt to retrieve a link that doesn't exist and check that we get an error let channel_binary = query( deps.as_ref(), mock_env(), QueryMsg::GetChannelFromChainPair { - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "cerberus".to_string(), }, ); @@ -336,7 +299,7 @@ mod test { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: execute::FullOperation::Disable, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "OSMOSIS".to_string(), destination_chain: "JUNO".to_string(), channel_id: Some("CHANNEL-42".to_string()), new_source_chain: None, @@ -353,7 +316,7 @@ mod test { deps.as_ref(), mock_env(), QueryMsg::GetChannelFromChainPair { - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "juno".to_string(), }, ); @@ -363,7 +326,7 @@ mod test { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: execute::FullOperation::Enable, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "OSMOSIS".to_string(), destination_chain: "JUNO".to_string(), channel_id: Some("CHANNEL-42".to_string()), new_source_chain: None, @@ -379,7 +342,7 @@ mod test { deps.as_ref(), mock_env(), QueryMsg::GetChannelFromChainPair { - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "juno".to_string(), }, ) diff --git a/cosmwasm/contracts/crosschain-registry/src/error.rs b/cosmwasm/contracts/crosschain-registry/src/error.rs index e72f60f7dab..18ad07f9b56 100644 --- a/cosmwasm/contracts/crosschain-registry/src/error.rs +++ b/cosmwasm/contracts/crosschain-registry/src/error.rs @@ -13,34 +13,12 @@ pub enum ContractError { #[error("{0}")] Payment(#[from] cw_utils::PaymentError), - #[error("unauthorized")] + #[error("Unauthorized")] Unauthorized {}, - #[error("chain validation not started for {chain}")] - ValidationNotFound { chain: String }, - - #[error("coin from invalid chain. It belongs to {supplied_chain} and should be from {expected_chain}")] - CoinFromInvalidChain { - supplied_chain: String, - expected_chain: String, - }, - - #[error( - "only messages initialized by the address of this contract in another chain are allowed. Expected {expected_sender} but got {actual_sender}" - )] - InvalidSender { - expected_sender: String, - actual_sender: String, - }, - #[error("contract alias already exists: {alias:?}")] AliasAlreadyExists { alias: String }, - #[error( - "PFM validation already in progress for {chain:?}. Wait for the ibc lifecycle to complete" - )] - PFMValidationAlreadyInProgress { chain: String }, - #[error("authorized address already exists for source chain: {source_chain:?}")] ChainAuthorizedAddressAlreadyExists { source_chain: String }, diff --git a/cosmwasm/contracts/crosschain-registry/src/execute.rs b/cosmwasm/contracts/crosschain-registry/src/execute.rs index 7d713222e1b..4d2ff7964ce 100644 --- a/cosmwasm/contracts/crosschain-registry/src/execute.rs +++ b/cosmwasm/contracts/crosschain-registry/src/execute.rs @@ -1,15 +1,13 @@ -use crate::contract::CONTRACT_CHAIN; use crate::helpers::*; use crate::state::{ - ChainPFM, CHAIN_ADMIN_MAP, CHAIN_MAINTAINER_MAP, CHAIN_PFM_MAP, CHAIN_TO_BECH32_PREFIX_MAP, + CHAIN_ADMIN_MAP, CHAIN_MAINTAINER_MAP, CHAIN_TO_BECH32_PREFIX_MAP, CHAIN_TO_BECH32_PREFIX_REVERSE_MAP, CHAIN_TO_CHAIN_CHANNEL_MAP, CHANNEL_ON_CHAIN_CHAIN_MAP, CONTRACT_ALIAS_MAP, GLOBAL_ADMIN_MAP, }; use cosmwasm_schema::cw_serde; -use cosmwasm_std::{Addr, DepsMut, Env, MessageInfo, Response}; +use cosmwasm_std::{Addr, DepsMut, Response}; use cw_storage_plus::Map; -use registry::msg::Callback; -use registry::{Registry, RegistryError}; +use registry::RegistryError; use crate::ContractError; @@ -42,100 +40,6 @@ pub struct ContractAliasInput { pub new_alias: Option, } -pub fn propose_pfm( - ctx: (DepsMut, Env, MessageInfo), - chain: String, -) -> Result { - let (deps, env, info) = ctx; - - // enforce lowercase - let chain = chain.to_lowercase(); - - // validation - let registry = Registry::default(deps.as_ref()); - let coin = cw_utils::one_coin(&info)?; - let native_chain = registry.get_native_chain(&coin.denom)?; - - if native_chain.as_ref() != chain { - return Err(ContractError::CoinFromInvalidChain { - supplied_chain: native_chain.as_ref().to_string(), - expected_chain: chain, - }); - } - - // check if the chain is already registered or is in progress - if let Some(chain_pfm) = CHAIN_PFM_MAP.may_load(deps.storage, &chain)? { - if chain_pfm.is_validated() { - // Only authorized addresses can ask for a validated PFM to be re-checked - // If sender is the contract governor, then they are authorized to do do this to any chain - // Otherwise, they must be authorized to do manage the chain they are attempting to modify - let user_permission = - check_is_authorized(deps.as_ref(), info.sender, Some(chain.clone()))?; - check_action_permission(FullOperation::Change, user_permission)?; - } else { - return Err(ContractError::PFMValidationAlreadyInProgress { - chain: chain.clone(), - }); - } - }; - - // Store the chain to validate - CHAIN_PFM_MAP.save(deps.storage, &chain, &ChainPFM::default())?; - - let own_addr = env.contract.address; - - // redeclaring (shadowing) registry to avoid issues with the borrow checker - let registry = Registry::default(deps.as_ref()); - let ibc_transfer = registry.unwrap_coin_into( - coin, - own_addr.to_string(), - None, - own_addr.to_string(), - env.block.time, - format!(r#"{{"ibc_callback":"{}"}}"#, own_addr), - Some(Callback { - contract: own_addr, - msg: format!(r#"{{"validate_pfm": {{"chain": "{}"}} }}"#, chain).try_into()?, - }), - true, - )?; - - Ok(Response::default().add_message(ibc_transfer)) -} - -pub fn validate_pfm( - ctx: (DepsMut, Env, MessageInfo), - chain: String, -) -> Result { - let (deps, env, info) = ctx; - - let chain = chain.to_lowercase(); - - let registry = Registry::default(deps.as_ref()); - let channel = registry.get_channel(&chain, CONTRACT_CHAIN)?; - let own_addr = env.contract.address.as_str(); - let original_sender = registry.encode_addr_for_chain(own_addr, &chain)?; - let expected_sender = registry::derive_wasmhooks_sender(&channel, &original_sender, "osmo")?; - if expected_sender != info.sender { - return Err(ContractError::InvalidSender { - expected_sender, - actual_sender: info.sender.into_string(), - }); - } - - let mut chain_pfm = CHAIN_PFM_MAP.load(deps.storage, &chain).map_err(|_| { - ContractError::ValidationNotFound { - chain: chain.clone(), - } - })?; - - chain_pfm.validated = true; - - CHAIN_PFM_MAP.save(deps.storage, &chain, &chain_pfm)?; - - Ok(Response::default()) -} - // Set, change, or remove a contract alias to an address pub fn contract_alias_operations( deps: DepsMut, @@ -950,7 +854,7 @@ mod tests { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: FullOperation::Set, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "OSMOSIS".to_string(), destination_chain: "COSMOS".to_string(), channel_id: Some("CHANNEL-0".to_string()), new_source_chain: None, @@ -963,7 +867,7 @@ mod tests { assert_eq!( CHAIN_TO_CHAIN_CHANNEL_MAP - .load(&deps.storage, (CONTRACT_CHAIN, "cosmos")) + .load(&deps.storage, ("osmosis", "cosmos")) .unwrap(), ("channel-0", true).into() ); @@ -971,7 +875,7 @@ mod tests { // Verify that channel-0 on osmosis is linked to cosmos assert_eq!( CHANNEL_ON_CHAIN_CHAIN_MAP - .load(&deps.storage, ("channel-0", CONTRACT_CHAIN)) + .load(&deps.storage, ("channel-0", "osmosis")) .unwrap(), ("cosmos", true).into() ); @@ -981,7 +885,7 @@ mod tests { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: FullOperation::Set, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "cosmos".to_string(), channel_id: Some("channel-150".to_string()), new_source_chain: None, @@ -994,19 +898,19 @@ mod tests { assert!(result.is_err()); let expected_error = ContractError::ChainToChainChannelLinkAlreadyExists { - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "cosmos".to_string(), }; assert_eq!(result.unwrap_err(), expected_error); assert_eq!( CHAIN_TO_CHAIN_CHANNEL_MAP - .load(&deps.storage, (CONTRACT_CHAIN, "cosmos")) + .load(&deps.storage, ("osmosis", "cosmos")) .unwrap(), ("channel-0", true).into() ); assert_eq!( CHANNEL_ON_CHAIN_CHAIN_MAP - .load(&deps.storage, ("channel-0", CONTRACT_CHAIN)) + .load(&deps.storage, ("channel-0", "osmosis")) .unwrap(), ("cosmos", true).into() ); @@ -1016,7 +920,7 @@ mod tests { operations: vec![ConnectionInput { operation: FullOperation::Set, source_chain: "mars".to_string(), - destination_chain: CONTRACT_CHAIN.to_string(), + destination_chain: "osmosis".to_string(), channel_id: Some("channel-1".to_string()), new_source_chain: None, new_destination_chain: None, @@ -1029,14 +933,14 @@ mod tests { let expected_error = ContractError::Unauthorized {}; assert_eq!(result.unwrap_err(), expected_error); - assert!(!CHAIN_TO_CHAIN_CHANNEL_MAP.has(&deps.storage, ("mars", CONTRACT_CHAIN))); + assert!(!CHAIN_TO_CHAIN_CHANNEL_MAP.has(&deps.storage, ("mars", "osmosis"))); // Set the canonical channel link between mars and osmosis to channel-1 with a mars chain admin address let chain_admin_info = mock_info(CHAIN_ADMIN, &[]); contract::execute(deps.as_mut(), mock_env(), chain_admin_info.clone(), msg).unwrap(); assert_eq!( CHAIN_TO_CHAIN_CHANNEL_MAP - .load(&deps.storage, ("mars", CONTRACT_CHAIN)) + .load(&deps.storage, ("mars", "osmosis")) .unwrap(), ("channel-1", true).into() ); @@ -1044,7 +948,7 @@ mod tests { CHANNEL_ON_CHAIN_CHAIN_MAP .load(&deps.storage, ("channel-1", "mars")) .unwrap(), - (CONTRACT_CHAIN, true).into() + ("osmosis", true).into() ); // Set the canonical channel link between juno and mars to channel-2 with a juno chain maintainer address @@ -1136,7 +1040,7 @@ mod tests { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: FullOperation::Set, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "OSMOSIS".to_string(), destination_chain: "COSMOS".to_string(), channel_id: Some("CHANNEL-0".to_string()), new_source_chain: None, @@ -1152,7 +1056,7 @@ mod tests { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: FullOperation::Change, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "cosmos".to_string(), channel_id: None, new_source_chain: None, @@ -1166,7 +1070,7 @@ mod tests { // Verify that the channel between osmosis and cosmos has changed from channel-0 to channel-150 assert_eq!( CHAIN_TO_CHAIN_CHANNEL_MAP - .load(&deps.storage, (CONTRACT_CHAIN, "cosmos")) + .load(&deps.storage, ("osmosis", "cosmos")) .unwrap(), ("channel-150", true).into() ); @@ -1175,7 +1079,7 @@ mod tests { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: FullOperation::Change, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "regen".to_string(), channel_id: None, new_source_chain: None, @@ -1187,7 +1091,7 @@ mod tests { assert!(result.is_err()); let expected_error = ContractError::from(RegistryError::ChainChannelLinkDoesNotExist { - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "regen".to_string(), }); assert_eq!(result.unwrap_err(), expected_error); @@ -1196,7 +1100,7 @@ mod tests { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: FullOperation::Change, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "cosmos".to_string(), channel_id: None, new_source_chain: None, @@ -1210,7 +1114,7 @@ mod tests { // Verify that channel-150 on osmosis is linked to regen assert_eq!( CHANNEL_ON_CHAIN_CHAIN_MAP - .load(&deps.storage, ("channel-150", CONTRACT_CHAIN)) + .load(&deps.storage, ("channel-150", "osmosis")) .unwrap(), ("regen", true).into() ); @@ -1219,7 +1123,7 @@ mod tests { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: FullOperation::Change, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "regen".to_string(), channel_id: None, new_source_chain: None, @@ -1239,7 +1143,7 @@ mod tests { contract::execute(deps.as_mut(), mock_env(), info_chain_admin, msg).unwrap(); assert_eq!( CHAIN_TO_CHAIN_CHANNEL_MAP - .load(&deps.storage, (CONTRACT_CHAIN, "regen")) + .load(&deps.storage, ("osmosis", "regen")) .unwrap(), ("channel-2", true).into() ); @@ -1248,7 +1152,7 @@ mod tests { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: FullOperation::Change, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "cosmos".to_string(), channel_id: None, new_source_chain: None, @@ -1260,7 +1164,7 @@ mod tests { let result = contract::execute(deps.as_mut(), mock_env(), info, msg); let expected_error = ContractError::from(RegistryError::ChainChannelLinkDoesNotExist { - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "cosmos".to_string(), }); assert_eq!(result.unwrap_err(), expected_error); @@ -1271,7 +1175,7 @@ mod tests { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: FullOperation::Change, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "regen".to_string(), channel_id: None, new_source_chain: None, @@ -1296,7 +1200,7 @@ mod tests { operations: vec![ ConnectionInput { operation: FullOperation::Set, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "OSMOSIS".to_string(), destination_chain: "COSMOS".to_string(), channel_id: Some("CHANNEL-0".to_string()), new_source_chain: None, @@ -1305,7 +1209,7 @@ mod tests { }, ConnectionInput { operation: FullOperation::Set, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "OSMOSIS".to_string(), destination_chain: "REGEN".to_string(), channel_id: Some("CHANNEL-1".to_string()), new_source_chain: None, @@ -1321,7 +1225,7 @@ mod tests { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: FullOperation::Remove, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "cosmos".to_string(), channel_id: None, new_source_chain: None, @@ -1333,13 +1237,13 @@ mod tests { contract::execute(deps.as_mut(), mock_env(), info, msg.clone()).unwrap(); // Verify that the link no longer exists - assert!(!CHAIN_TO_CHAIN_CHANNEL_MAP.has(&deps.storage, (CONTRACT_CHAIN, "cosmos"))); + assert!(!CHAIN_TO_CHAIN_CHANNEL_MAP.has(&deps.storage, ("osmosis", "cosmos"))); let info = mock_info(CREATOR_ADDRESS, &[]); let result = contract::execute(deps.as_mut(), mock_env(), info, msg); let expected_error = ContractError::from(RegistryError::ChainChannelLinkDoesNotExist { - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "cosmos".to_string(), }); assert_eq!(result.unwrap_err(), expected_error); @@ -1350,7 +1254,7 @@ mod tests { let msg = ExecuteMsg::ModifyChainChannelLinks { operations: vec![ConnectionInput { operation: FullOperation::Remove, - source_chain: CONTRACT_CHAIN.to_string(), + source_chain: "osmosis".to_string(), destination_chain: "regen".to_string(), channel_id: None, new_source_chain: None, @@ -1374,7 +1278,7 @@ mod tests { let msg = ExecuteMsg::ModifyBech32Prefixes { operations: vec![ChainToBech32PrefixInput { operation: FullOperation::Set, - chain_name: CONTRACT_CHAIN.to_string(), + chain_name: "OSMOSIS".to_string(), prefix: "OSMO".to_string(), new_prefix: None, }], @@ -1384,7 +1288,7 @@ mod tests { assert_eq!( CHAIN_TO_BECH32_PREFIX_MAP - .load(&deps.storage, CONTRACT_CHAIN) + .load(&deps.storage, "osmosis") .unwrap(), ("osmo", true).into() ); @@ -1392,7 +1296,7 @@ mod tests { CHAIN_TO_BECH32_PREFIX_REVERSE_MAP .load(&deps.storage, "osmo") .unwrap(), - vec![CONTRACT_CHAIN] + vec!["osmosis"] ); // Set another chain with the same prefix @@ -1416,14 +1320,14 @@ mod tests { CHAIN_TO_BECH32_PREFIX_REVERSE_MAP .load(&deps.storage, "osmo") .unwrap(), - vec![CONTRACT_CHAIN, "ismisis"] + vec!["osmosis", "ismisis"] ); // Set another chain with the same prefix let msg = ExecuteMsg::ModifyBech32Prefixes { operations: vec![ChainToBech32PrefixInput { operation: FullOperation::Disable, - chain_name: CONTRACT_CHAIN.to_string(), + chain_name: "OSMOSIS".to_string(), prefix: "OSMO".to_string(), new_prefix: None, }], @@ -1431,7 +1335,7 @@ mod tests { contract::execute(deps.as_mut(), mock_env(), info.clone(), msg).unwrap(); assert_eq!( CHAIN_TO_BECH32_PREFIX_MAP - .load(&deps.storage, CONTRACT_CHAIN) + .load(&deps.storage, "osmosis") .unwrap(), ("osmo", false).into() ); @@ -1446,7 +1350,7 @@ mod tests { let msg = ExecuteMsg::ModifyBech32Prefixes { operations: vec![ChainToBech32PrefixInput { operation: FullOperation::Enable, - chain_name: CONTRACT_CHAIN.to_string(), + chain_name: "OSMOSIS".to_string(), prefix: "OSMO".to_string(), new_prefix: None, }], @@ -1454,7 +1358,7 @@ mod tests { contract::execute(deps.as_mut(), mock_env(), info.clone(), msg).unwrap(); assert_eq!( CHAIN_TO_BECH32_PREFIX_MAP - .load(&deps.storage, CONTRACT_CHAIN) + .load(&deps.storage, "osmosis") .unwrap(), ("osmo", true).into() ); @@ -1462,14 +1366,14 @@ mod tests { CHAIN_TO_BECH32_PREFIX_REVERSE_MAP .load(&deps.storage, "osmo") .unwrap(), - vec!["ismisis", CONTRACT_CHAIN] + vec!["ismisis", "osmosis"] ); // Set another chain with the same prefix let msg = ExecuteMsg::ModifyBech32Prefixes { operations: vec![ChainToBech32PrefixInput { operation: FullOperation::Remove, - chain_name: CONTRACT_CHAIN.to_string(), + chain_name: "OSMOSIS".to_string(), prefix: "OSMO".to_string(), new_prefix: None, }], @@ -1489,7 +1393,7 @@ mod tests { ); CHAIN_TO_BECH32_PREFIX_MAP - .load(&deps.storage, CONTRACT_CHAIN) + .load(&deps.storage, "osmosis") .unwrap_err(); } } diff --git a/cosmwasm/contracts/crosschain-registry/src/ibc_lifecycle.rs b/cosmwasm/contracts/crosschain-registry/src/ibc_lifecycle.rs deleted file mode 100644 index 23e4029e131..00000000000 --- a/cosmwasm/contracts/crosschain-registry/src/ibc_lifecycle.rs +++ /dev/null @@ -1,41 +0,0 @@ -use cosmwasm_std::{DepsMut, Response}; -use registry::Registry; - -use crate::{contract::CONTRACT_CHAIN, state::CHAIN_PFM_MAP, ContractError}; - -pub fn receive_ack( - deps: DepsMut, - source_channel: String, - _sequence: u64, - _ack: String, - success: bool, -) -> Result { - let registry = Registry::default(deps.as_ref()); - let chain = registry.get_connected_chain(CONTRACT_CHAIN, source_channel.as_str())?; - let mut chain_pfm = CHAIN_PFM_MAP.load(deps.storage, &chain).map_err(|_| { - ContractError::ValidationNotFound { - chain: chain.clone(), - } - })?; - - if success { - chain_pfm.acknowledged = true; - CHAIN_PFM_MAP.save(deps.storage, &chain, &chain_pfm)?; - } else { - CHAIN_PFM_MAP.remove(deps.storage, &chain); - } - - Ok(Response::default()) -} - -pub fn receive_timeout( - deps: DepsMut, - source_channel: String, - _sequence: u64, -) -> Result { - let registry = Registry::default(deps.as_ref()); - let chain = registry.get_connected_chain(CONTRACT_CHAIN, source_channel.as_str())?; - CHAIN_PFM_MAP.remove(deps.storage, &chain); - - Ok(Response::default()) -} diff --git a/cosmwasm/contracts/crosschain-registry/src/lib.rs b/cosmwasm/contracts/crosschain-registry/src/lib.rs index c00aae18bb8..ac94946c4d1 100644 --- a/cosmwasm/contracts/crosschain-registry/src/lib.rs +++ b/cosmwasm/contracts/crosschain-registry/src/lib.rs @@ -3,7 +3,6 @@ mod error; pub mod execute; mod exports; pub mod helpers; -mod ibc_lifecycle; pub mod msg; pub mod query; pub mod state; diff --git a/cosmwasm/contracts/crosschain-registry/src/msg.rs b/cosmwasm/contracts/crosschain-registry/src/msg.rs index 2bf534b5803..c7de423f2ee 100644 --- a/cosmwasm/contracts/crosschain-registry/src/msg.rs +++ b/cosmwasm/contracts/crosschain-registry/src/msg.rs @@ -29,12 +29,6 @@ pub enum ExecuteMsg { operations: Vec, }, - // Add PFM to the registry - #[serde(rename = "propose_pfm")] - ProposePFM { chain: String }, - #[serde(rename = "validate_pfm")] - ValidatePFM { chain: String }, - UnwrapCoin { receiver: String, into_chain: Option, @@ -50,32 +44,3 @@ pub use registry::msg::{ GetDestinationChainFromSourceChainViaChannelResponse, QueryGetBech32PrefixFromChainNameResponse, }; - -#[cw_serde] -pub enum IBCLifecycleComplete { - #[serde(rename = "ibc_ack")] - IBCAck { - /// The source channel (osmosis side) of the IBC packet - channel: String, - /// The sequence number that the packet was sent with - sequence: u64, - /// String encoded version of the ack as seen by OnAcknowledgementPacket(..) - ack: String, - /// Whether an ack is a success of failure according to the transfer spec - success: bool, - }, - #[serde(rename = "ibc_timeout")] - IBCTimeout { - /// The source channel (osmosis side) of the IBC packet - channel: String, - /// The sequence number that the packet was sent with - sequence: u64, - }, -} - -/// Message type for `sudo` entry_point -#[cw_serde] -pub enum SudoMsg { - #[serde(rename = "ibc_lifecycle_complete")] - IBCLifecycleComplete(IBCLifecycleComplete), -} diff --git a/cosmwasm/contracts/crosschain-registry/src/query.rs b/cosmwasm/contracts/crosschain-registry/src/query.rs index aff0b77fbbf..d507d62837c 100644 --- a/cosmwasm/contracts/crosschain-registry/src/query.rs +++ b/cosmwasm/contracts/crosschain-registry/src/query.rs @@ -1,6 +1,6 @@ use crate::state::{ - CHAIN_PFM_MAP, CHAIN_TO_BECH32_PREFIX_MAP, CHAIN_TO_BECH32_PREFIX_REVERSE_MAP, - CHAIN_TO_CHAIN_CHANNEL_MAP, CHANNEL_ON_CHAIN_CHAIN_MAP, + CHAIN_TO_BECH32_PREFIX_MAP, CHAIN_TO_BECH32_PREFIX_REVERSE_MAP, CHAIN_TO_CHAIN_CHANNEL_MAP, + CHANNEL_ON_CHAIN_CHAIN_MAP, }; use cosmwasm_std::{Deps, StdError}; @@ -89,13 +89,3 @@ pub fn query_chain_from_channel_chain_pair( Ok(chain.value) } - -pub fn query_chain_has_pfm(deps: Deps, chain: String) -> bool { - let chain = chain.to_lowercase(); - if let Ok(chain_pfm) = CHAIN_PFM_MAP.load(deps.storage, &chain) { - deps.api.debug(&format!("{chain_pfm:?}")); - chain_pfm.is_validated() - } else { - false - } -} diff --git a/cosmwasm/contracts/crosschain-registry/src/state.rs b/cosmwasm/contracts/crosschain-registry/src/state.rs index 0c6d0da7635..1fafa24192c 100644 --- a/cosmwasm/contracts/crosschain-registry/src/state.rs +++ b/cosmwasm/contracts/crosschain-registry/src/state.rs @@ -13,7 +13,6 @@ enum StorageKey { GlobalAdminMap, ChainAdminMap, ChainMaintainerMap, - HasPacketForwardMiddleware, } // Implement the `StorageKey` enum to a string conversion. @@ -29,7 +28,6 @@ impl StorageKey { StorageKey::GlobalAdminMap => "gam", StorageKey::ChainAdminMap => "cam", StorageKey::ChainMaintainerMap => "cmm", - StorageKey::HasPacketForwardMiddleware => "hpfm", } } } @@ -49,27 +47,6 @@ impl> From<(T, bool)> for RegistryValue { } } -/// ChainPFM stores the state of the packet forward middleware for a chain. Anyone can request -/// to enable the packet forward middleware for a chain, but the contract will verify that -/// packets can properly be forwarded by the chain -#[cw_serde] -#[derive(Default)] -pub struct ChainPFM { - /// The verification packet has been received by the chain, forwarded, and the ack has been received - pub acknowledged: bool, - /// The contract has validated that the received packet is as expected - pub validated: bool, -} - -impl ChainPFM { - /// Both acknowledged and validated must be true for the pfm to be enabled. This is to avoid - /// situations in which the chain calls the contract to set validated to true but that call is - /// not from the same packet that was forwarded by this contract. - pub fn is_validated(&self) -> bool { - self.acknowledged && self.validated - } -} - // CONTRACT_ALIAS_MAP is a map from a contract alias to a contract address pub const CONTRACT_ALIAS_MAP: Map<&str, String> = Map::new(StorageKey::ContractAliasMap.to_string()); @@ -111,10 +88,6 @@ pub const CHAIN_ADMIN_MAP: Map<&str, Addr> = Map::new(StorageKey::ChainAdminMap. pub const CHAIN_MAINTAINER_MAP: Map<&str, Addr> = Map::new(StorageKey::ChainMaintainerMap.to_string()); -// CHAIN_PFM_MAP stores whether a chain supports the Packet Forward Middleware interface for forwarding IBC packets -pub const CHAIN_PFM_MAP: Map<&str, ChainPFM> = - Map::new(StorageKey::HasPacketForwardMiddleware.to_string()); - #[cw_serde] pub struct Config { pub owner: Addr, diff --git a/cosmwasm/contracts/crosschain-swaps/src/execute.rs b/cosmwasm/contracts/crosschain-swaps/src/execute.rs index eec1762095c..8cd393d5ca2 100644 --- a/cosmwasm/contracts/crosschain-swaps/src/execute.rs +++ b/cosmwasm/contracts/crosschain-swaps/src/execute.rs @@ -69,7 +69,6 @@ pub fn unwrap_or_swap_and_forward( })? .into(), }), - false, )?; return Ok(Response::new().add_message(ibc_transfer)); } @@ -128,7 +127,6 @@ pub fn swap_and_forward( env.block.time, memo, None, - false, )?; // Message to swap tokens in the underlying swaprouter contract @@ -202,7 +200,6 @@ pub fn handle_swap_reply( env.block.time, memo, None, - false, )?; deps.api.debug(&format!("IBC transfer: {ibc_transfer:?}")); diff --git a/cosmwasm/packages/registry/src/error.rs b/cosmwasm/packages/registry/src/error.rs index 9c38d910a1d..e926975766b 100644 --- a/cosmwasm/packages/registry/src/error.rs +++ b/cosmwasm/packages/registry/src/error.rs @@ -15,9 +15,6 @@ pub enum RegistryError { #[error("{0}")] ValueSerialization(ValueSerError), - #[error("{0}")] - Bech32ErrorRaw(#[from] bech32::Error), - // Validation errors #[error("Invalid channel id: {0}")] InvalidChannelId(String), @@ -33,9 +30,6 @@ pub enum RegistryError { #[error("serialization error: {error}")] SerialiaztionError { error: String }, - #[error("registry improperly configured")] - ImproperlyConfigured {}, - #[error("denom {denom:?} is not an IBC denom")] InvalidIBCDenom { denom: String }, @@ -98,9 +92,6 @@ pub enum RegistryError { #[error("bech32 prefix does not exist for chain: {chain}")] Bech32PrefixDoesNotExist { chain: String }, - - #[error("Chain {chain} does not support forwarding")] - ForwardingUnsopported { chain: String }, } impl From for StdError { diff --git a/cosmwasm/packages/registry/src/lib.rs b/cosmwasm/packages/registry/src/lib.rs index 0568bb6d0e7..35d6aba584c 100644 --- a/cosmwasm/packages/registry/src/lib.rs +++ b/cosmwasm/packages/registry/src/lib.rs @@ -1,9 +1,7 @@ mod error; mod registry; -pub use crate::registry::derive_wasmhooks_sender; pub use crate::registry::Registry; - pub use error::RegistryError; pub mod msg; diff --git a/cosmwasm/packages/registry/src/msg.rs b/cosmwasm/packages/registry/src/msg.rs index c831d4d1fba..5d71a48d58b 100644 --- a/cosmwasm/packages/registry/src/msg.rs +++ b/cosmwasm/packages/registry/src/msg.rs @@ -1,7 +1,6 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::Addr; use schemars::JsonSchema; -use serde_json_wasm::from_str; use crate::RegistryError; @@ -31,9 +30,6 @@ pub enum QueryMsg { #[returns(crate::proto::QueryDenomTraceResponse)] GetDenomTrace { ibc_denom: String }, - - #[returns(bool)] - HasPacketForwarding { chain: String }, } // Response for GetAddressFromAlias query @@ -100,14 +96,6 @@ impl From for SerializableJson { } } -impl TryFrom for SerializableJson { - type Error = RegistryError; - - fn try_from(value: String) -> Result { - Ok(Self(from_str(&value)?)) - } -} - /// Information about which contract to call when the crosschain swap finishes #[cw_serde] pub struct Callback { diff --git a/cosmwasm/packages/registry/src/registry.rs b/cosmwasm/packages/registry/src/registry.rs index f0b6d35be3a..6ac40eae331 100644 --- a/cosmwasm/packages/registry/src/registry.rs +++ b/cosmwasm/packages/registry/src/registry.rs @@ -19,44 +19,6 @@ pub fn hash_denom_trace(unwrapped: &str) -> String { format!("ibc/{}", hash.to_uppercase()) } -// When a contract is called using ibc callbacks, the addres is a combination of -// the channel and the original sender. This function lets us compute that. -pub fn derive_wasmhooks_sender( - channel: &str, - original_sender: &str, - bech32_prefix: &str, -) -> Result { - let sender = format!("{}/{}", channel, original_sender); - - let mut hasher0 = Sha256::new(); - hasher0.update("ibc-wasm-hook-intermediary".as_bytes()); - let th = hasher0.finalize(); - - let mut hasher = Sha256::new(); - hasher.reset(); - hasher.update(th.as_slice()); - hasher.update(sender.as_bytes()); - - let result = hasher.finalize(); - - // The bech32 crate requires a Vec as input, so we need to convert the bytes. - let result_u5 = bech32::convert_bits(result.as_slice(), 8, 5, true)?; - // result_u5 contains the bytes as a u5 but in an u8 type, so we need to explicitly - // do the type conversion - let result_u5: Vec = result_u5 - .iter() - .filter_map(|&x| bech32::u5::try_from_u8(x).ok()) - .collect(); - - bech32::encode(bech32_prefix, result_u5, bech32::Variant::Bech32).map_err(|e| { - RegistryError::Bech32Error { - action: "encoding".into(), - addr: original_sender.into(), - source: e, - } - }) -} - // IBC transfer port const TRANSFER_PORT: &str = "transfer"; // IBC timeout @@ -139,9 +101,6 @@ pub struct MultiHopDenom { pub via: Option, // This is optional because native tokens have no channel } -// The name of the chain on which the contract using this lib is instantiated -pub const CONTRACT_CHAIN: &str = "osmosis"; - pub struct Registry<'a> { pub deps: Deps<'a>, pub registry_contract: String, @@ -156,6 +115,7 @@ impl<'a> Registry<'a> { }) } + #[allow(dead_code)] pub fn default(deps: Deps<'a>) -> Self { Self { deps, @@ -228,20 +188,6 @@ impl<'a> Registry<'a> { }) } - /// Returns a boolean specifying if a chain supports forwarding - /// Example: supports_forwarding("gaia") -> true - pub fn supports_forwarding(&self, chain: &str) -> Result { - self.deps - .querier - .query_wasm_smart( - &self.registry_contract, - &QueryMsg::HasPacketForwarding { - chain: chain.to_string(), - }, - ) - .map_err(|_e| RegistryError::ImproperlyConfigured {}) - } - /// Re-encodes the bech32 address for the receiving chain /// Example: encode_addr_for_chain("osmo1...", "juno") -> "juno1..." pub fn encode_addr_for_chain(&self, addr: &str, chain: &str) -> Result { @@ -316,7 +262,7 @@ impl<'a> Registry<'a> { pub fn unwrap_denom_path(&self, denom: &str) -> Result, RegistryError> { self.debug(format!("Unwrapping denom {denom}")); - let mut current_chain = CONTRACT_CHAIN.to_string(); // The initial chain is always the contract chain + let mut current_chain = "osmosis".to_string(); // The initial chain is always osmosis // Check that the denom is an IBC denom if !denom.starts_with("ibc/") { @@ -343,7 +289,9 @@ impl<'a> Registry<'a> { }), }?; - self.debug(format!("procesing denom trace {path}")); + self.deps + .api + .debug(&format!("procesing denom trace {path}")); // Let's iterate over the parts of the denom trace and extract the // chain/channels into a more useful structure: MultiHopDenom let mut hops: Vec = vec![]; @@ -383,21 +331,6 @@ impl<'a> Registry<'a> { Ok(hops) } - pub fn get_native_chain(&self, denom: &str) -> Result { - let hops = self.unwrap_denom_path(denom)?; - self.debug(format!("hops: {:?}", hops)); - // verify that the last hop is native - let last_hop = hops.last().ok_or(RegistryError::NoDenomTrace { - denom: denom.into(), - })?; - if last_hop.via.is_some() { - return Err(RegistryError::InvalidDenomTrace { - error: format!("Path {hops:?} is not properly formatted"), - }); - } - Ok(hops.last().unwrap().on.clone()) - } - /// Returns an IBC MsgTransfer that with a packet forward middleware memo /// that will send the coin back to its original chain and then to the /// receiver in `into_chain`. @@ -421,7 +354,6 @@ impl<'a> Registry<'a> { block_time: Timestamp, first_transfer_memo: String, receiver_callback: Option, - skip_forwarding_check: bool, ) -> Result { // Calculate the path that this coin took to get to the current chain. // Each element in the path is an IBC hop. @@ -538,17 +470,6 @@ impl<'a> Registry<'a> { None => ChannelId(self.get_channel(prev_chain, hop.on.as_ref())?), }; - self.debug(format!( - "checking that: {:?} supports pfm (into {:?})", - hop.on.as_ref(), - prev_chain - )); - if !skip_forwarding_check && !self.supports_forwarding(hop.on.as_ref())? { - return Err(RegistryError::ForwardingUnsopported { - chain: hop.on.as_ref().into(), - }); - } - // The next memo wraps the previous one next = Some(Box::new(Memo { forward: Some(ForwardingMemo { @@ -656,39 +577,4 @@ mod test { r#"{"forward":{"receiver":"receiver","port":"port","channel":"channel-0","next":{"forward":{"receiver":"receiver2","port":"port2","channel":"channel-1"}}}}"# ) } - - #[test] - fn test_derive_wasmhooks_sender() { - let test_cases = vec![ - ( - "channel-0", - "cosmos1tfejvgp5yzd8ypvn9t0e2uv2kcjf2laa8upya8", - "osmo", - "osmo1sguz3gtyl2tjsdulwxmtprd68xtd43yyep6g5c554utz642sr8rqcgw0q6", - ), - ( - "channel-1", - "cosmos1tfejvgp5yzd8ypvn9t0e2uv2kcjf2laa8upya8", - "osmo", - "osmo1svnare87kluww5hnltv24m4dg72hst0qqwm5xslsvnwd22gftcussaz5l7", - ), - ( - "channel-0", - "osmo12smx2wdlyttvyzvzg54y2vnqwq2qjateuf7thj", - "osmo", - "osmo1vz8evs4ek3vnz4f8wy86nw9ayzn67y28vtxzjgxv6achc4pa8gesqldfz0", - ), - ( - "channel-0", - "osmo12smx2wdlyttvyzvzg54y2vnqwq2qjateuf7thj", - "cosmos", - "cosmos1vz8evs4ek3vnz4f8wy86nw9ayzn67y28vtxzjgxv6achc4pa8ges4z434f", - ), - ]; - - for tc in test_cases { - assert!(derive_wasmhooks_sender(tc.0, tc.1, tc.2).is_ok()); - assert_eq!(derive_wasmhooks_sender(tc.0, tc.1, tc.2).unwrap(), tc.3); - } - } } diff --git a/tests/ibc-hooks/bytecode/crosschain_registry.wasm b/tests/ibc-hooks/bytecode/crosschain_registry.wasm index f6e8b703266..4248452bd5a 100644 Binary files a/tests/ibc-hooks/bytecode/crosschain_registry.wasm and b/tests/ibc-hooks/bytecode/crosschain_registry.wasm differ diff --git a/tests/ibc-hooks/bytecode/crosschain_swaps.wasm b/tests/ibc-hooks/bytecode/crosschain_swaps.wasm index 1a87f6548c4..910814081e3 100644 Binary files a/tests/ibc-hooks/bytecode/crosschain_swaps.wasm and b/tests/ibc-hooks/bytecode/crosschain_swaps.wasm differ diff --git a/tests/ibc-hooks/bytecode/outpost.wasm b/tests/ibc-hooks/bytecode/outpost.wasm index 25a95ad62f9..0b1f86d5cb3 100644 Binary files a/tests/ibc-hooks/bytecode/outpost.wasm and b/tests/ibc-hooks/bytecode/outpost.wasm differ diff --git a/tests/ibc-hooks/ibc_middleware_test.go b/tests/ibc-hooks/ibc_middleware_test.go index d1990be95f1..630b7f49bf3 100644 --- a/tests/ibc-hooks/ibc_middleware_test.go +++ b/tests/ibc-hooks/ibc_middleware_test.go @@ -70,7 +70,6 @@ func (suite *HooksTestSuite) SetupTest() { suite.SkipIfWSL() // TODO: This needs to get removed. Waiting on https://github.com/cosmos/ibc-go/issues/3123 txfeetypes.ConsensusMinFee = sdk.ZeroDec() - suite.Setup() ibctesting.DefaultTestingAppInit = osmosisibctesting.SetupTestingApp suite.coordinator = ibctesting.NewCoordinator(suite.T(), 3) @@ -203,50 +202,6 @@ func (suite *HooksTestSuite) GetReceiverChannel(chainA, chainB Chain) string { return receiver.ChannelID } -func (suite *HooksTestSuite) TestDeriveIntermediateSender() { - - testCases := []struct { - channel string - originalSender string - bech32Prefix string - expectedAddress string - }{ - { - channel: "channel-0", - originalSender: "cosmos1tfejvgp5yzd8ypvn9t0e2uv2kcjf2laa8upya8", - bech32Prefix: "osmo", - expectedAddress: "osmo1sguz3gtyl2tjsdulwxmtprd68xtd43yyep6g5c554utz642sr8rqcgw0q6", - }, - { - channel: "channel-1", - originalSender: "cosmos1tfejvgp5yzd8ypvn9t0e2uv2kcjf2laa8upya8", - bech32Prefix: "osmo", - expectedAddress: "osmo1svnare87kluww5hnltv24m4dg72hst0qqwm5xslsvnwd22gftcussaz5l7", - }, - { - channel: "channel-0", - originalSender: "osmo12smx2wdlyttvyzvzg54y2vnqwq2qjateuf7thj", - bech32Prefix: "osmo", - expectedAddress: "osmo1vz8evs4ek3vnz4f8wy86nw9ayzn67y28vtxzjgxv6achc4pa8gesqldfz0", - }, - { - channel: "channel-0", - originalSender: "osmo12smx2wdlyttvyzvzg54y2vnqwq2qjateuf7thj", - bech32Prefix: "cosmos", - expectedAddress: "cosmos1vz8evs4ek3vnz4f8wy86nw9ayzn67y28vtxzjgxv6achc4pa8ges4z434f", - }, - } - - for _, tc := range testCases { - suite.Run(fmt.Sprintf("Test failed for case (channel=%s, originalSender=%s, bech32Prefix=%s).", - tc.channel, tc.originalSender, tc.bech32Prefix), func() { - actualAddress, err := ibchookskeeper.DeriveIntermediateSender(tc.channel, tc.originalSender, tc.bech32Prefix) - suite.Require().NoError(err) - suite.Require().Equal(tc.expectedAddress, actualAddress) - }) - } -} - func (suite *HooksTestSuite) TestOnRecvPacketHooks() { var ( trace transfertypes.DenomTrace @@ -742,16 +697,13 @@ func (suite *HooksTestSuite) SetupPools(chainName Chain, multipliers []sdk.Dec) return pools } -func (suite *HooksTestSuite) SetupCrosschainSwaps(chainName Chain, setupForwarding bool) (sdk.AccAddress, sdk.AccAddress) { +func (suite *HooksTestSuite) SetupCrosschainSwaps(chainName Chain) (sdk.AccAddress, sdk.AccAddress) { chain := suite.GetChain(chainName) owner := chain.SenderAccount.GetAddress() registryAddr, _, _, _ := suite.SetupCrosschainRegistry(chainName) suite.setChainChannelLinks(registryAddr, chainName) - suite.setAllPrefixesToOsmo(registryAddr, chainName) - if setupForwarding { - suite.setForwardingOnAllChains(registryAddr) - } + fmt.Println("registryAddr", registryAddr) // Fund the account with some uosmo and some stake bankKeeper := chain.GetOsmosisApp().BankKeeper @@ -779,7 +731,23 @@ func (suite *HooksTestSuite) SetupCrosschainSwaps(chainName Chain, setupForwardi contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(osmosisApp.WasmKeeper) ctx := chain.GetContext() - msg := `{"set_route":{"input_denom":"token0","output_denom":"token1","pool_route":[{"pool_id":"1","token_out_denom":"stake"},{"pool_id":"2","token_out_denom":"token1"}]}}` + // Configuring two prefixes for the same channel here. This is so that we can test bad acks when the receiver can't handle the receiving addr + msg := `{ + "modify_bech32_prefixes": { + "operations": [ + {"operation": "set", "chain_name": "osmosis", "prefix": "osmo"}, + {"operation": "set", "chain_name": "chainB", "prefix": "osmo"}, + {"operation": "set", "chain_name": "chainB-cw20", "prefix": "osmo"}, + {"operation": "set", "chain_name": "chainC", "prefix": "osmo"} + ] + } + } + ` + _, err = contractKeeper.Execute(ctx, registryAddr, owner, []byte(msg), sdk.NewCoins()) + suite.Require().NoError(err) + + // ctx sdk.Context, contractAddress sdk.AccAddress, caller sdk.AccAddress, msg []byte, coins sdk.Coins + msg = fmt.Sprintf(`{"set_route":{"input_denom":"token0","output_denom":"token1","pool_route":[{"pool_id":"1","token_out_denom":"%s"},{"pool_id":"2","token_out_denom":"token1"}]}}`, sdk.DefaultBondDenom) _, err = contractKeeper.Execute(ctx, swaprouterAddr, owner, []byte(msg), sdk.NewCoins()) suite.Require().NoError(err) @@ -888,35 +856,6 @@ func (suite *HooksTestSuite) setChainChannelLinks(registryAddr sdk.AccAddress, c ` _, err := contractKeeper.Execute(ctx, registryAddr, owner, []byte(msg), sdk.NewCoins()) suite.Require().NoError(err) - -} - -func (suite *HooksTestSuite) setAllPrefixesToOsmo(registryAddr sdk.AccAddress, chainName Chain) { - chain := suite.GetChain(chainName) - ctx := chain.GetContext() - owner := chain.SenderAccount.GetAddress() - osmosisApp := chain.GetOsmosisApp() - contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(osmosisApp.WasmKeeper) - - // Add all chain channel links in a single message - msg := fmt.Sprintf(`{ - "modify_bech32_prefixes": { - "operations": [ - {"operation": "set", "chain_name": "osmosis", "prefix": "osmo"}, - {"operation": "set", "chain_name": "chainB", "prefix": "osmo"}, - {"operation": "set", "chain_name": "chainB-cw20", "prefix": "osmo"}, - {"operation": "set", "chain_name": "chainC", "prefix": "osmo"} - ] - } - } - `) - _, err := contractKeeper.Execute(ctx, registryAddr, owner, []byte(msg), sdk.NewCoins()) - suite.Require().NoError(err) -} - -func (suite *HooksTestSuite) setForwardingOnAllChains(registryAddr sdk.AccAddress) { - suite.SetupAndTestPFM(ChainB, "chainB", registryAddr) - suite.SetupAndTestPFM(ChainC, "chainC", registryAddr) } // modifyChainChannelLinks modifies the chain channel links in the crosschain registry utilizing set, remove, and change operations @@ -1010,14 +949,29 @@ func (suite *HooksTestSuite) TestUnwrapToken() { // Instantiate contract and set up three chains with funds sent between each registryAddr, _, token0CBA, _ := suite.SetupCrosschainRegistry(ChainA) suite.setChainChannelLinks(registryAddr, ChainA) - suite.setAllPrefixesToOsmo(registryAddr, ChainA) - suite.setForwardingOnAllChains(registryAddr) chain := suite.GetChain(ChainA) + ctx := chain.GetContext() owner := chain.SenderAccount.GetAddress() receiver := chain.SenderAccounts[1].SenderAccount.GetAddress() osmosisApp := chain.GetOsmosisApp() + contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(osmosisApp.WasmKeeper) + + msg := `{ + "modify_bech32_prefixes": { + "operations": [ + {"operation": "set", "chain_name": "osmosis", "prefix": "osmo"}, + {"operation": "set", "chain_name": "chainA", "prefix": "osmo"}, + {"operation": "set", "chain_name": "chainB", "prefix": "osmo"}, + {"operation": "set", "chain_name": "chainC", "prefix": "osmo"} + ] + } + } + ` + _, err := contractKeeper.Execute(ctx, registryAddr, owner, []byte(msg), sdk.NewCoins()) + suite.Require().NoError(err) + // Check that the balances are correct: token0CB should be >100, token0CBA should be 0 denomTrace0CA := transfertypes.ParseDenomTrace(transfertypes.GetPrefixedDenom("transfer", suite.pathAC.EndpointA.ChannelID, "token0")) token0CA := denomTrace0CA.IBCDenom() @@ -1050,7 +1004,7 @@ func (suite *HooksTestSuite) TestUnwrapToken() { initialReceiverBalance := receiverApp.BankKeeper.GetBalance(receiverChain.GetContext(), receiver, tc.receivedToken) suite.Require().Equal(sdk.NewInt(0), initialReceiverBalance.Amount) - msg := fmt.Sprintf(`{ + msg = fmt.Sprintf(`{ "unwrap_coin": { "receiver": "%s", "into_chain": "%s" @@ -1082,7 +1036,7 @@ func (suite *HooksTestSuite) TestUnwrapToken() { func (suite *HooksTestSuite) TestCrosschainSwaps() { owner := suite.chainA.SenderAccount.GetAddress() - _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, true) + _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA) osmosisApp := suite.chainA.GetOsmosisApp() contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(osmosisApp.WasmKeeper) @@ -1116,7 +1070,7 @@ func (suite *HooksTestSuite) TestCrosschainSwaps() { packetSequence, ok := responseJson["packet_sequence"].(float64) suite.Require().True(ok) - suite.Require().Equal(packetSequence, 2.0) + suite.Require().Equal(packetSequence, 1.0) balanceSender2 := osmosisApp.BankKeeper.GetBalance(suite.chainA.GetContext(), owner, "token0") suite.Require().Equal(int64(1000), balanceSender.Amount.Sub(balanceSender2.Amount).Int64()) @@ -1124,7 +1078,7 @@ func (suite *HooksTestSuite) TestCrosschainSwaps() { func (suite *HooksTestSuite) TestCrosschainSwapsViaIBCTest() { initializer := suite.chainB.SenderAccount.GetAddress() - _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, true) + _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA) // Send some token0 tokens to B so that there are ibc tokens to send to A and crosschain-swap transferMsg := NewMsgTransfer(sdk.NewCoin("token0", sdk.NewInt(2000)), suite.chainA.SenderAccount.GetAddress().String(), initializer.String(), "channel-0", "") _, _, _, err := suite.FullSend(transferMsg, AtoB) @@ -1175,7 +1129,7 @@ func (suite *HooksTestSuite) TestCrosschainSwapsViaIBCTest() { // exist on chain B func (suite *HooksTestSuite) TestCrosschainSwapsViaIBCBadAck() { initializer := suite.chainB.SenderAccount.GetAddress() - _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, true) + _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA) // Send some token0 tokens to B so that there are ibc tokens to send to A and crosschain-swap transferMsg := NewMsgTransfer(sdk.NewCoin("token0", sdk.NewInt(2000)), suite.chainA.SenderAccount.GetAddress().String(), initializer.String(), "channel-0", "") _, _, _, err := suite.FullSend(transferMsg, AtoB) @@ -1251,7 +1205,7 @@ func (suite *HooksTestSuite) TestCrosschainSwapsViaIBCBadAck() { &suite.Suite, crosschainAddr, []byte(fmt.Sprintf(`{"recoverable": {"addr": "%s"}}`, recoverAddr))) suite.Require().Contains(state, "token1") - suite.Require().Contains(state, `"sequence":3`) + suite.Require().Contains(state, `"sequence":2`) // Recover the stuck amount recoverMsg := `{"recover": {}}` @@ -1271,7 +1225,7 @@ func (suite *HooksTestSuite) TestCrosschainSwapsViaIBCBadAck() { // This is very similar to the two tests above, but the swap is done incorrectly func (suite *HooksTestSuite) TestCrosschainSwapsViaIBCBadSwap() { initializer := suite.chainB.SenderAccount.GetAddress() - _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, true) + _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA) // Send some token0 tokens to B so that there are ibc tokens to send to A and crosschain-swap transferMsg := NewMsgTransfer(sdk.NewCoin("token0", sdk.NewInt(2000)), suite.chainA.SenderAccount.GetAddress().String(), initializer.String(), "channel-0", "") _, _, _, err := suite.FullSend(transferMsg, AtoB) @@ -1314,7 +1268,7 @@ func (suite *HooksTestSuite) TestCrosschainSwapsViaIBCBadSwap() { func (suite *HooksTestSuite) TestBadCrosschainSwapsNextMemoMessages() { initializer := suite.chainB.SenderAccount.GetAddress() - _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, true) + _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA) // Send some token0 tokens to B so that there are ibc tokens to send to A and crosschain-swap transferMsg := NewMsgTransfer(sdk.NewCoin("token0", sdk.NewInt(20000)), suite.chainA.SenderAccount.GetAddress().String(), initializer.String(), "channel-0", "") _, _, _, err := suite.FullSend(transferMsg, AtoB) @@ -1463,8 +1417,8 @@ func (suite *HooksTestSuite) TestCrosschainForwardWithMemo() { initializer := suite.chainB.SenderAccount.GetAddress() receiver := suite.chainA.SenderAccounts[5].SenderAccount.GetAddress() - _, crosschainAddrA := suite.SetupCrosschainSwaps(ChainA, true) - swaprouterAddrB, crosschainAddrB := suite.SetupCrosschainSwaps(ChainB, false) + _, crosschainAddrA := suite.SetupCrosschainSwaps(ChainA) + swaprouterAddrB, crosschainAddrB := suite.SetupCrosschainSwaps(ChainB) // Send some token0 and token1 tokens to B so that there are ibc token0 to send to A and crosschain-swap, and token1 to create the pool transferMsg := NewMsgTransfer(sdk.NewCoin("token0", sdk.NewInt(500000)), suite.chainA.SenderAccount.GetAddress().String(), initializer.String(), "channel-0", "") _, _, _, err := suite.FullSend(transferMsg, AtoB) @@ -1535,7 +1489,7 @@ func (suite *HooksTestSuite) TestCrosschainSwapsViaIBCMultiHop() { accountB := suite.chainB.SenderAccount.GetAddress() accountC := suite.chainC.SenderAccount.GetAddress() - _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, true) + _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA) // Send A's token0 all the way to B (A->C->B) transferMsg := NewMsgTransfer( @@ -1660,7 +1614,7 @@ type ChainActorDefinition struct { func (suite *HooksTestSuite) TestMultiHopXCS() { accountB := suite.chainB.SenderAccount.GetAddress() - swapRouterAddr, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, true) + swapRouterAddr, crosschainAddr := suite.SetupCrosschainSwaps(ChainA) sendAmount := sdk.NewInt(100) @@ -1861,7 +1815,7 @@ func (suite *HooksTestSuite) TestMultiHopXCS() { func (suite *HooksTestSuite) ExecuteOutpostSwap(initializer, receiverAddr sdk.AccAddress, receiver string) { // Setup - _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, true) + _, crosschainAddr := suite.SetupCrosschainSwaps(ChainA) // Store and instantiate the outpost on chainB suite.chainB.StoreContractCode(&suite.Suite, "./bytecode/outpost.wasm") outpostAddr := suite.chainB.InstantiateContract(&suite.Suite, diff --git a/tests/ibc-hooks/path_validation_test.go b/tests/ibc-hooks/path_validation_test.go deleted file mode 100644 index 5c96f8fa2b7..00000000000 --- a/tests/ibc-hooks/path_validation_test.go +++ /dev/null @@ -1,101 +0,0 @@ -package ibc_hooks_test - -import ( - "fmt" - wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" - sdk "github.com/cosmos/cosmos-sdk/types" - ibctesting "github.com/cosmos/ibc-go/v4/testing" -) - -// This sets up PFM on chainB and tests that it works as expected. We assume ChainA is osmosis -func (suite *HooksTestSuite) SetupAndTestPFM(chainBId Chain, chainBName string, registryAddr sdk.AccAddress) { - targetChain := suite.GetChain(chainBId) - sendFrom := targetChain.SenderAccount.GetAddress() - direction := suite.GetDirection(ChainA, chainBId) - reverseDirection := suite.GetDirection(chainBId, ChainA) - sender, receiver := suite.GetEndpoints(suite.GetDirection(ChainA, chainBId)) - - osmosisApp := suite.chainA.GetOsmosisApp() - contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(osmosisApp.WasmKeeper) - - pfm_msg := fmt.Sprintf(`{"has_packet_forwarding": {"chain": "%s"}}`, chainBName) - forwarding := suite.chainA.QueryContractJson(&suite.Suite, registryAddr, []byte(pfm_msg)) - suite.Require().False(forwarding.Bool()) - - transferMsg := NewMsgTransfer(sdk.NewCoin("token0", sdk.NewInt(2000)), targetChain.SenderAccount.GetAddress().String(), sendFrom.String(), suite.GetSenderChannel(chainBId, ChainA), "") - suite.FullSend(transferMsg, reverseDirection) - tokenBA := suite.GetIBCDenom(chainBId, ChainA, "token0") - - ctx := suite.chainA.GetContext() - - msg := fmt.Sprintf(`{"propose_pfm":{"chain": "%s"}}`, chainBName) - _, err := contractKeeper.Execute(ctx, registryAddr, sendFrom, []byte(msg), sdk.NewCoins(sdk.NewCoin(tokenBA, sdk.NewInt(1)))) - suite.Require().NoError(err) - - forwarding = suite.chainA.QueryContractJson(&suite.Suite, registryAddr, []byte(pfm_msg)) - suite.Require().False(forwarding.Bool()) - - // Move forward one block - suite.chainA.NextBlock() - suite.chainA.Coordinator.IncrementTime() - - // Update both clients - err = receiver.UpdateClient() - suite.Require().NoError(err) - err = sender.UpdateClient() - suite.Require().NoError(err) - - events := ctx.EventManager().Events() - packet0, err := ibctesting.ParsePacketFromEvents(events) - suite.Require().NoError(err) - result := suite.RelayPacketNoAck(packet0, direction) // No ack because it's a forward - - forwarding = suite.chainA.QueryContractJson(&suite.Suite, registryAddr, []byte(pfm_msg)) - suite.Require().False(forwarding.Bool()) - - packet1, err := ibctesting.ParsePacketFromEvents(result.GetEvents()) - suite.Require().NoError(err) - receiveResult, _ := suite.RelayPacket(packet1, reverseDirection) - - forwarding = suite.chainA.QueryContractJson(&suite.Suite, registryAddr, []byte(pfm_msg)) - suite.Require().False(forwarding.Bool()) - - err = sender.UpdateClient() - suite.Require().NoError(err) - err = receiver.UpdateClient() - suite.Require().NoError(err) - - ack, err := ibctesting.ParseAckFromEvents(receiveResult.GetEvents()) - suite.Require().NoError(err) - - err = sender.AcknowledgePacket(packet0, ack) - suite.Require().NoError(err) - - // After the ack fully travels back to the initial chain, we consider PFM to be properly set - forwarding = suite.chainA.QueryContractJson(&suite.Suite, registryAddr, []byte(pfm_msg)) - suite.Require().True(forwarding.Bool()) -} - -func (suite *HooksTestSuite) TestPathValidation() { - owner := suite.chainA.SenderAccount.GetAddress() - registryAddr, _, _, _ := suite.SetupCrosschainRegistry(ChainA) - suite.setChainChannelLinks(registryAddr, ChainA) - - osmosisApp := suite.chainA.GetOsmosisApp() - contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(osmosisApp.WasmKeeper) - - msg := fmt.Sprintf(`{ - "modify_bech32_prefixes": { - "operations": [ - {"operation": "set", "chain_name": "osmosis", "prefix": "osmo"}, - {"operation": "set", "chain_name": "chainA", "prefix": "osmo"}, - {"operation": "set", "chain_name": "chainB", "prefix": "osmo"}, - {"operation": "set", "chain_name": "chainC", "prefix": "osmo"} - ] - } - } - `) - _, err := contractKeeper.Execute(suite.chainA.GetContext(), registryAddr, owner, []byte(msg), sdk.NewCoins()) - suite.Require().NoError(err) - suite.SetupAndTestPFM(ChainB, "chainB", registryAddr) -} diff --git a/tests/ibc-hooks/xcs_cw20_test.go b/tests/ibc-hooks/xcs_cw20_test.go index 62da7cdd1d5..38d85c66dcc 100644 --- a/tests/ibc-hooks/xcs_cw20_test.go +++ b/tests/ibc-hooks/xcs_cw20_test.go @@ -104,7 +104,7 @@ func (suite *HooksTestSuite) TestCW20ICS20() { cw20IbcDenom := "ibc/134A49086C1164C78313D57E69E5A8656D8AE8CF6BB45B52F2DBFEFAE6EE30B8" cw20Addr, cw20ics20Addr := suite.SetupCW20(ChainB) - swaprouterAddr, crosschainAddr := suite.SetupCrosschainSwaps(ChainA, true) + swaprouterAddr, crosschainAddr := suite.SetupCrosschainSwaps(ChainA) chainA := suite.GetChain(ChainA) chainB := suite.GetChain(ChainB)