diff --git a/crates/core/src/masp.rs b/crates/core/src/masp.rs index d5a2522610..5b3c234945 100644 --- a/crates/core/src/masp.rs +++ b/crates/core/src/masp.rs @@ -399,6 +399,14 @@ impl TransferSource { _ => None, } } + + /// Get the contained MaybeIbcAddress, if any + pub fn maybe_ibc_address(&self) -> Option { + match self { + Self::Address(x) => Some(MaybeIbcAddress::Address(x.clone())), + _ => None, + } + } } impl Display for TransferSource { @@ -410,6 +418,43 @@ impl Display for TransferSource { } } +/// Represents either a Namada address or some IBC address +#[derive(Debug, Clone, BorshDeserialize, BorshSerialize, BorshDeserializer)] +pub enum MaybeIbcAddress { + /// A transparent address + Address(Address), + /// An IBC address + Ibc(String), +} + +impl MaybeIbcAddress { + /// Get the transparent address that this target would effectively go to + pub fn effective_address(&self) -> Address { + match self { + Self::Address(x) => x.clone(), + // An IBC signer address effectively means that assets are + // associated with the IBC internal address + Self::Ibc(_) => IBC, + } + } + + /// Get the contained IBC receiver, if any + pub fn payment_address(&self) -> Option { + match self { + Self::Ibc(address) => Some(address.clone()), + _ => None, + } + } + + /// Get the contained Address, if any + pub fn address(&self) -> Option
{ + match self { + Self::Address(x) => Some(x.clone()), + _ => None, + } + } +} + /// Represents a target for the funds of a transfer #[derive(Debug, Clone, BorshDeserialize, BorshSerialize, BorshDeserializer)] pub enum TransferTarget { @@ -450,6 +495,15 @@ impl TransferTarget { _ => None, } } + + /// Get the contained MaybeIbcAddress, if any + pub fn maybe_ibc_address(&self) -> Option { + match self { + Self::Address(x) => Some(MaybeIbcAddress::Address(x.clone())), + Self::Ibc(x) => Some(MaybeIbcAddress::Ibc(x.clone())), + _ => None, + } + } } impl Display for TransferTarget { diff --git a/crates/core/src/token.rs b/crates/core/src/token.rs index 616ec87221..7a713a1355 100644 --- a/crates/core/src/token.rs +++ b/crates/core/src/token.rs @@ -946,7 +946,7 @@ impl From for IbcAmount { impl From for IbcAmount { fn from(amount: DenominatedAmount) -> Self { - amount.canonical().amount.into() + amount.amount.into() } } diff --git a/crates/events/src/extend.rs b/crates/events/src/extend.rs index fdd098b401..b4111fc4a5 100644 --- a/crates/events/src/extend.rs +++ b/crates/events/src/extend.rs @@ -483,6 +483,21 @@ impl EventAttributeEntry<'static> for Info { } } +/// Extend an [`Event`] with `packet_ack` data, indicating the success or +/// failure of processing a received packet. +pub struct PacketAck(pub Vec); + +impl EventAttributeEntry<'static> for PacketAck { + type Value = Vec; + type ValueOwned = Self::Value; + + const KEY: &'static str = "packet_ack"; + + fn into_value(self) -> Self::Value { + self.0 + } +} + /// Extend an [`Event`] with `masp_tx_block_index` data, indicating that the tx /// at the specified index in the block contains a valid masp transaction. pub struct MaspTxBlockIndex(pub TxIndex); diff --git a/crates/ibc/src/actions.rs b/crates/ibc/src/actions.rs index 24a13a35bf..44726014c0 100644 --- a/crates/ibc/src/actions.rs +++ b/crates/ibc/src/actions.rs @@ -200,18 +200,9 @@ where D: DB + for<'iter> DBIter<'iter> + 'static, H: StorageHasher + 'static, { - let denom = token::read_denom(state, token)?.ok_or_else(|| { - StorageError::new_alloc(format!("No denomination for {token}")) - })?; - let amount = DenominatedAmount::new(target.amount, denom).canonical(); - if amount.denom().0 != 0 { - return Err(StorageError::new_alloc(format!( - "The amount for the IBC transfer should be an integer: {amount}" - ))); - } let token = PrefixedCoin { denom: token.to_string().parse().expect("invalid token"), - amount: amount.amount().into(), + amount: target.amount.into(), }; let packet_data = PacketData { token, diff --git a/crates/ibc/src/context/token_transfer.rs b/crates/ibc/src/context/token_transfer.rs index 94410c5673..d511ee308a 100644 --- a/crates/ibc/src/context/token_transfer.rs +++ b/crates/ibc/src/context/token_transfer.rs @@ -61,11 +61,8 @@ where }; // Convert IBC amount to Namada amount for the token - let denom = read_denom(&*self.inner.borrow(), &token) - .map_err(ContextError::from)? - .unwrap_or(Denomination(0)); let uint_amount = Uint(primitive_types::U256::from(coin.amount).0); - let amount = Amount::from_uint(uint_amount, denom).map_err(|e| { + let amount = Amount::from_uint(uint_amount, 0).map_err(|e| { TokenTransferError::ContextError( ChannelError::Other { description: format!( diff --git a/crates/namada/src/ledger/native_vp/masp.rs b/crates/namada/src/ledger/native_vp/masp.rs index a1dd050f94..0e7891adf6 100644 --- a/crates/namada/src/ledger/native_vp/masp.rs +++ b/crates/namada/src/ledger/native_vp/masp.rs @@ -26,7 +26,7 @@ use namada_governance::storage::is_proposal_accepted; use namada_ibc::event as ibc_events; use namada_ibc::event::IbcEvent; use namada_proof_of_stake::Epoch; -use namada_sdk::masp::{verify_shielded_tx, TransferTarget}; +use namada_sdk::masp::{verify_shielded_tx, MaybeIbcAddress}; use namada_state::{ConversionState, OptionExt, ResultExt, StateRead}; use namada_token::read_denom; use namada_tx::BatchedTxRef; @@ -41,7 +41,7 @@ use token::storage_key::{ }; use token::Amount; -use crate::address::InternalAddress; +use crate::address::{IBC, InternalAddress}; use crate::ledger::ibc::storage::{ ibc_trace_key, ibc_trace_key_prefix, is_ibc_trace_key, }; @@ -52,6 +52,16 @@ use crate::token; use crate::token::MaspDigitPos; use crate::uint::{Uint, I320}; use crate::vm::WasmCacheAccess; +use crate::ledger::ibc::storage::ibc_token; +use crate::sdk::ibc::is_ibc_denom; +use crate::sdk::ibc::IbcTokenHash; +use crate::ledger::events::extend::PacketAck; +use crate::sdk::ibc::core::channel::types::acknowledgement::AcknowledgementStatus; + +/// Packet event types +const SEND_PACKET_EVENT: &str = "send_packet"; +const RECEIVE_PACKET_EVENT: &str = "recv_packet"; +const WRITE_ACK_EVENT: &str = "write_acknowledgement"; #[allow(missing_docs)] #[derive(Error, Debug)] @@ -78,10 +88,10 @@ where // the other balances maps the token address to the addresses of the // senders/receivers, their balance diff and whether this is positive or // negative diff -#[derive(Default)] +#[derive(Default, Debug, Clone)] struct ChangedBalances { tokens: BTreeMap, - decoder: BTreeMap, + decoder: BTreeMap, ibc_denoms: BTreeMap, pre: BTreeMap>, post: BTreeMap>, @@ -336,74 +346,67 @@ where let mut counterparts_balances = keys_changed.iter().filter_map(is_any_token_balance_key); - let mut changed_balances = counterparts_balances - .try_fold( - ChangedBalances::default(), - |mut result, [token, counterpart]| { - let denom = read_denom(&self.ctx.pre(), token)? - .ok_or_err_msg( - "No denomination found in storage for the given \ - token", - )?; - unepoched_tokens(token, denom, &mut result.tokens)?; - let counterpart_balance_key = - balance_key(token, counterpart); - let pre_balance: Amount = self - .ctx - .read_pre(&counterpart_balance_key)? - .unwrap_or_default(); - let post_balance: Amount = self - .ctx - .read_post(&counterpart_balance_key)? - .unwrap_or_default(); - // Make it possible to decode IBC tokens - result.ibc_denoms.insert( - self.query_ibc_denom( - token.to_string(), - Some(counterpart), - ) + let mut changed_balances = counterparts_balances.try_fold( + ChangedBalances::default(), + |mut result, [token, counterpart]| { + let denom = read_denom(&self.ctx.pre(), token)?.ok_or_err_msg( + "No denomination found in storage for the given token", + )?; + unepoched_tokens(token, denom, &mut result.tokens)?; + let counterpart_balance_key = balance_key(token, counterpart); + let pre_balance: Amount = self + .ctx + .read_pre(&counterpart_balance_key)? + .unwrap_or_default(); + let post_balance: Amount = self + .ctx + .read_post(&counterpart_balance_key)? + .unwrap_or_default(); + // Make it possible to decode IBC tokens + result.ibc_denoms.insert( + self.query_ibc_denom(token.to_string(), Some(counterpart)) .map_err(native_vp::Error::new)?, - token.clone(), - ); - // Public keys must be the hash of the sources/targets - let address_hash = TransparentAddress(<[u8; 20]>::from( - ripemd::Ripemd160::digest(sha2::Sha256::digest( - &TransferTarget::Address(counterpart.clone()).serialize_to_vec(), - )), - )); - // Enable the decoding of these counterpart addresses - result.decoder.insert( - address_hash, - TransferTarget::Address(counterpart.clone()), - ); - let pre_entry = result - .pre - .entry(address_hash) - .or_insert(ValueSum::zero()); - let post_entry = result - .post - .entry(address_hash) - .or_insert(ValueSum::zero()); - *pre_entry = checked!( - pre_entry - + &ValueSum::from_pair( - (*token).clone(), - pre_balance - ) - ) - .map_err(native_vp::Error::new)?; - *post_entry = checked!( - post_entry - + &ValueSum::from_pair( - (*token).clone(), - post_balance - ) - ) - .map_err(native_vp::Error::new)?; - Result::<_>::Ok(result) - }, - ) - .unwrap(); + token.clone(), + ); + // Public keys must be the hash of the sources/targets + let address_hash = TransparentAddress(<[u8; 20]>::from( + ripemd::Ripemd160::digest(sha2::Sha256::digest( + &MaybeIbcAddress::Address(counterpart.clone()) + .serialize_to_vec(), + )), + )); + // Enable the decoding of these counterpart addresses + result.decoder.insert( + address_hash, + MaybeIbcAddress::Address(counterpart.clone()), + ); + let pre_entry = + result.pre.entry(address_hash).or_insert(ValueSum::zero()); + let post_entry = + result.post.entry(address_hash).or_insert(ValueSum::zero()); + *pre_entry = checked!( + pre_entry + + &ValueSum::from_pair((*token).clone(), pre_balance) + ) + .map_err(native_vp::Error::new)?; + *post_entry = checked!( + post_entry + + &ValueSum::from_pair((*token).clone(), post_balance) + ) + .map_err(native_vp::Error::new)?; + Result::<_>::Ok(result) + }, + )?; + + let ibc_address = MaybeIbcAddress::Address(IBC); + // Public keys must be the hash of the sources/targets + let ibc_address_hash = TransparentAddress(<[u8; 20]>::from( + ripemd::Ripemd160::digest(sha2::Sha256::digest( + &ibc_address.serialize_to_vec(), + )), + )); + // Enable decoding the IBC address hash + changed_balances.decoder.insert(ibc_address_hash, ibc_address); // Extract the IBC events let ibc_events: BTreeSet<_> = self @@ -426,7 +429,7 @@ where serde_json::from_slice::(&msg.data) { let address = - TransferTarget::Ibc(packet_data.receiver.to_string()); + MaybeIbcAddress::Ibc(packet_data.receiver.to_string()); // Public keys must be the hash of the sources/targets let address_hash = TransparentAddress(<[u8; 20]>::from( ripemd::Ripemd160::digest(sha2::Sha256::digest( @@ -434,33 +437,115 @@ where )), )); changed_balances.decoder.insert(address_hash, address); - let pre_entry = changed_balances + changed_balances .pre .entry(address_hash) .or_insert(ValueSum::zero()); + changed_balances + .post + .entry(ibc_address_hash) + .or_insert(ValueSum::zero()); + // Also enable the tracking of received IBC + let pre_entry = changed_balances + .pre + .entry(ibc_address_hash) + .or_insert(ValueSum::zero()); let post_entry = changed_balances .post .entry(address_hash) .or_insert(ValueSum::zero()); - let token = changed_balances - .ibc_denoms - .get(&packet_data.token.denom.to_string()) - .ok_or_err_msg("Unable to decode IBC token")?; - let delta = ValueSum::from_pair( - token.clone(), - Amount::from_uint(Uint(*packet_data.token.amount), 0) - .unwrap(), - ); - if is_sender_chain_source( - msg.port_id_on_a.clone(), - msg.chan_id_on_a.clone(), - &packet_data.token.denom, - ) { - *post_entry = checked!(post_entry + &delta) - .map_err(native_vp::Error::new)?; - } else { - *pre_entry = checked!(pre_entry + &delta) - .map_err(native_vp::Error::new)?; + + match ibc_event.kind().sub_domain() { + // This event is emitted on the sender + SEND_PACKET_EVENT => { + // Since IBC denominations are derived from Addresses + // when sending, we have to do a reverse look-up of the + // relevant token Address + let token = changed_balances + .ibc_denoms + .get(&packet_data.token.denom.to_string()) + .cloned() + // If the reverse lookup failed, then guess the Address + // that might have yielded the IBC denom. However, + // guessing an IBC token address cannot possibly be + // correct due to the structure of query_ibc_denom + .or_else(|| Address::decode(&packet_data.token.denom.to_string()) + .ok() + .filter(|x| !matches!(x, Address::Internal(InternalAddress::IbcToken(_))))) + .ok_or_err_msg("Unable to decode IBC token")?; + let delta = ValueSum::from_pair( + token.clone(), + Amount::from_uint(Uint(*packet_data.token.amount), 0) + .unwrap(), + ); + // Enable funds to be received by the receiver in the + // IBC packet + *post_entry = checked!(post_entry + &delta) + .map_err(native_vp::Error::new)? + }, + // This event is emitted on the receiver + RECEIVE_PACKET_EVENT => { + // Mirror how the IBC token is derived in + // gen_ibc_shielded_transfer in the non-refund case + let ibc_denom = self.query_ibc_denom( + &packet_data.token.denom.to_string(), + Some(&Address::Internal(InternalAddress::Ibc)), + )?; + let token = namada_ibc::received_ibc_token( + ibc_denom, + &msg.port_id_on_a, + &msg.chan_id_on_a, + &msg.port_id_on_b, + &msg.chan_id_on_b, + ).into_storage_result() + .map_err(Error::NativeVpError)?; + let delta = ValueSum::from_pair( + token.clone(), + Amount::from_uint(Uint(*packet_data.token.amount), 0) + .unwrap(), + ); + // Enable funds to be taken from the IBC internal + // address and be deposited elsewhere + *pre_entry = checked!(pre_entry + &delta) + .map_err(native_vp::Error::new)? + }, + // This event is emitted on the sender + WRITE_ACK_EVENT => { + let acknowledgement = ibc_event + .raw_read_attribute::() + .ok_or_err_msg("packet_ack attribute missing from write_acknowledgement")?; + let acknowledgement: AcknowledgementStatus = + serde_json::from_slice(acknowledgement.as_ref()) + .wrap_err("Decoding acknowledment failed")?; + // If the transfer was a failure, then enable funds to + // be withdrawn from the IBC internal address + if !acknowledgement.is_successful() { + // Mirror how the IBC token is derived in + // gen_ibc_shielded_transfer in the refund case + let ibc_denom = self.query_ibc_denom( + &packet_data.token.denom.to_string(), + Some(&Address::Internal(InternalAddress::Ibc)), + )?; + let token = if ibc_denom.contains('/') { + ibc_token(ibc_denom) + } else { + // the token is a base token + Address::decode(&ibc_denom) + .wrap_err("Invalid token")? + }; + let delta = ValueSum::from_pair( + token.clone(), + Amount::from_uint(Uint(*packet_data.token.amount), 0) + .unwrap(), + ); + // Enable funds to be withdrawn from the IBC + // internal address + *pre_entry = checked!(pre_entry + &delta) + .map_err(native_vp::Error::new)? + } + }, + // Ignore all other IBC events + _ => {}, } } } @@ -490,14 +575,14 @@ where // The Sapling value balance adds to the transparent tx pool let mut transparent_tx_pool = shielded_tx.sapling_value_balance(); - // Check the validity of the keys and get the transfer data let mut changed_balances = self.validate_state_and_get_transfer_data(keys_changed)?; let masp_address_hash = TransparentAddress(<[u8; 20]>::from( ripemd::Ripemd160::digest(sha2::Sha256::digest( - &TransferTarget::Address(Address::Internal(Masp)).serialize_to_vec(), + &MaybeIbcAddress::Address(Address::Internal(Masp)) + .serialize_to_vec(), )), )); verify_sapling_balancing_value( @@ -551,7 +636,7 @@ where // Ensure that this transaction is authorized by all involved parties for signer in signers { - if let Some(TransferTarget::Ibc(_)) = + if let Some(MaybeIbcAddress::Address(Address::Internal(InternalAddress::Ibc))) = changed_balances.decoder.get(&signer) { // If the IBC address is a signatory, then it means that either @@ -568,20 +653,23 @@ where // Transaction(s). if let Some(transp_bundle) = shielded_tx.transparent_bundle() { for vout in transp_bundle.vout.iter() { - if let Some(TransferTarget::Ibc(_)) = + if let Some(MaybeIbcAddress::Ibc(_)) = changed_balances.decoder.get(&vout.address) { let error = native_vp::Error::new_const( "Simultaneous credit and debit of IBC account \ in a MASP transaction not allowed", ) - .into(); + .into(); tracing::debug!("{error}"); return Err(error); } } } - } else if let Some(TransferTarget::Address(signer)) = + } else if let Some(MaybeIbcAddress::Ibc(_)) = + changed_balances.decoder.get(&signer) + { + } else if let Some(MaybeIbcAddress::Address(signer)) = changed_balances.decoder.get(&signer) { // Otherwise the signer must be decodable so that we can diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs index d11278fedd..e9b543e763 100644 --- a/crates/sdk/src/lib.rs +++ b/crates/sdk/src/lib.rs @@ -810,6 +810,7 @@ pub mod testing { use namada_core::eth_bridge_pool::PendingTransfer; use namada_core::hash::testing::arb_hash; use namada_core::key::testing::arb_common_keypair; + use namada_core::masp::MaybeIbcAddress; use namada_core::token::testing::{arb_denominated_amount, arb_transfer}; use namada_core::token::Transfer; use namada_governance::storage::proposal::testing::{ @@ -1042,7 +1043,9 @@ pub mod testing { // Encode the given Address into TransparentAddress fn encode_address(source: &Address) -> TransparentAddress { let hash = ripemd::Ripemd160::digest(sha2::Sha256::digest( - TransferTarget::Address(source.clone()).serialize_to_vec().as_ref(), + MaybeIbcAddress::Address(source.clone()) + .serialize_to_vec() + .as_ref(), )); TransparentAddress(hash.into()) } diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 2bb7b64287..ec06d10dd5 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -55,7 +55,7 @@ use namada_core::collections::{HashMap, HashSet}; use namada_core::dec::Dec; pub use namada_core::masp::{ encode_asset_type, AssetData, BalanceOwner, ExtendedViewingKey, - PaymentAddress, TransferSource, TransferTarget, + MaybeIbcAddress, PaymentAddress, TransferSource, TransferTarget, }; use namada_core::storage::{BlockHeight, Epoch, TxIndex}; use namada_core::time::{DateTimeUtc, DurationSecs}; @@ -1719,13 +1719,13 @@ impl ShieldedContext { // We add a dummy UTXO to our transaction, but only the source of // the parent Transfer object is used to validate fund // availability - let source_enc = TransferTarget::Address(source - .address() + let source_enc = source + .maybe_ibc_address() .ok_or_else(|| { Error::Other( "source address should be transparent".to_string(), ) - })?) + })? .serialize_to_vec(); let hash = ripemd::Ripemd160::digest(sha2::Sha256::digest( @@ -1761,14 +1761,15 @@ impl ShieldedContext { // If we are sending to a transparent output, then we will need to embed // the transparent target address into the shielded transaction so that // it can be signed - let transparent_target_hash = if payment_address.is_none() { - let target_enc = target.serialize_to_vec(); - Some(ripemd::Ripemd160::digest(sha2::Sha256::digest( - target_enc.as_ref(), - ))) - } else { - None - }; + let transparent_target_hash = + if let Some(target) = target.maybe_ibc_address() { + let target_enc = target.serialize_to_vec(); + Some(ripemd::Ripemd160::digest(sha2::Sha256::digest( + target_enc.as_ref(), + ))) + } else { + None + }; // This indicates how many more assets need to be sent to the receiver // in order to satisfy the requested transfer amount. let mut rem_amount = amount.amount().raw_amount().0; diff --git a/crates/sdk/src/rpc.rs b/crates/sdk/src/rpc.rs index a03ec02ba9..b6610fa8c1 100644 --- a/crates/sdk/src/rpc.rs +++ b/crates/sdk/src/rpc.rs @@ -59,6 +59,7 @@ use crate::tendermint::block::Height; use crate::tendermint::merkle::proof::ProofOps; use crate::tendermint_rpc::query::Query; use crate::{display_line, edisplay_line, error, Namada, Tx}; +use crate::ibc::is_ibc_denom; /// Identical to [`query_tx_status`], but does not need a [`Namada`] /// context. @@ -1158,8 +1159,17 @@ pub async fn validate_amount( InputAmount::Unvalidated(amt) => amt.canonical(), InputAmount::Validated(amt) => return Ok(amt), }; + let token = if let Address::Internal(InternalAddress::IbcToken(ibc_token_hash)) = token { + extract_base_token(context, ibc_token_hash.clone(), None).await.ok_or( + Error::from(QueryError::General(format!( + "cannot extract base token for {token}" + ))) + )? + } else { + token.clone() + }; let denom = match convert_response::>( - RPC.vp().token().denomination(context.client(), token).await, + RPC.vp().token().denomination(context.client(), &token).await, )? { Some(denom) => Ok(denom), None => { @@ -1346,6 +1356,32 @@ pub async fn query_ibc_tokens( Ok(tokens) } +/// Obtain the base token of the given IBC token hash +pub async fn extract_base_token( + context: &N, + ibc_token_hash: IbcTokenHash, + owner: Option<&Address>, +) -> Option
{ + // First obtain the IBC denomination + let ibc_denom = query_ibc_denom( + context, + Address::Internal(InternalAddress::IbcToken(ibc_token_hash)).to_string(), + owner, + ).await; + // Then try to extract the base token + if let Some((_trace_path, base_token)) = is_ibc_denom(ibc_denom) { + match Address::decode(&base_token) { + // If the base token successfully decoded into an Address + Ok(base_token) => Some(base_token), + // Otherwise find the Address associated with the base token's alias + Err(_) => context.wallet().await.find_address(&base_token).map(|x| x.into_owned()), + } + } else { + // Otherwise the base token Address is unknown to this client + None + } +} + /// Look up the IBC denomination from a IbcToken. pub async fn query_ibc_denom( context: &N, diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs index a0e01dc021..3c81abe447 100644 --- a/crates/sdk/src/tx.rs +++ b/crates/sdk/src/tx.rs @@ -2473,12 +2473,6 @@ pub async fn build_ibc_transfer( validate_amount(context, args.amount, &args.token, args.tx.force) .await .expect("expected to validate amount"); - if validated_amount.canonical().denom().0 != 0 { - return Err(Error::Other(format!( - "The amount for the IBC transfer should be an integer: {}", - validated_amount - ))); - } // If source is transparent check the balance (MASP balance is checked when // constructing the shielded part) diff --git a/crates/tests/src/vm_host_env/ibc.rs b/crates/tests/src/vm_host_env/ibc.rs index 4bee157c12..184093f7c2 100644 --- a/crates/tests/src/vm_host_env/ibc.rs +++ b/crates/tests/src/vm_host_env/ibc.rs @@ -636,7 +636,6 @@ pub fn msg_transfer( denom: String, sender: &Address, ) -> MsgTransfer { - let amount = DenominatedAmount::native(Amount::native_whole(100)); let timestamp = (Timestamp::now() + Duration::from_secs(100)).unwrap(); let message = IbcMsgTransfer { port_id_on_a: port_id, @@ -644,7 +643,7 @@ pub fn msg_transfer( packet_data: PacketData { token: PrefixedCoin { denom: denom.parse().expect("invalid denom"), - amount: amount.into(), + amount: Amount::native_whole(100).into(), }, sender: sender.to_string().into(), receiver: address::testing::gen_established_address() @@ -693,12 +692,11 @@ pub fn received_packet( token: String, receiver: &Address, ) -> Packet { - let amount = DenominatedAmount::native(Amount::native_whole(100)); let counterparty = dummy_channel_counterparty(); let timestamp = (Timestamp::now() + Duration::from_secs(100)).unwrap(); let coin = PrefixedCoin { denom: token.parse().expect("invalid denom"), - amount: amount.into(), + amount: Amount::native_whole(100).into(), }; let sender = address::testing::gen_established_address(); let data = PacketData { diff --git a/wasm/checksums.json b/wasm/checksums.json index 09538165cb..c4c13d0d75 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -1,26 +1,26 @@ { - "tx_become_validator.wasm": "tx_become_validator.44147f819ea5512dcd6898f9984115fbc50444d9227025bf9d92a54ef678e719.wasm", - "tx_bond.wasm": "tx_bond.3b40c03fd37cba96eca01ebe931f9f1368c086158709b1f5560163982ee1fc4c.wasm", - "tx_bridge_pool.wasm": "tx_bridge_pool.4a0186bff0398d110006f51408d0bfcfe70d9bc569742f1c18cba38cae32ee5e.wasm", - "tx_change_consensus_key.wasm": "tx_change_consensus_key.2c3a97ce98ec1490f381b34209aef8a115b4259f2a8600366f0139f96d749171.wasm", - "tx_change_validator_commission.wasm": "tx_change_validator_commission.839878500e456d26734f35684df9d2dac5cd11db89a2661f03d5f1d3480c0e83.wasm", - "tx_change_validator_metadata.wasm": "tx_change_validator_metadata.5a29fc479f43a4d5d11b4094945807fd3be9c125d62ed502d3fc15675c1bdaf1.wasm", - "tx_claim_rewards.wasm": "tx_claim_rewards.3dff8f09496561a9aaba655aadc4a17fd3e748f70cb933de38bfc359c5440418.wasm", - "tx_deactivate_validator.wasm": "tx_deactivate_validator.aeb6a329a4848b8d91c3bba2f98fc253a758bd460407638cb2800618d6e765e5.wasm", - "tx_ibc.wasm": "tx_ibc.0b9ab2479de22e0022708f3616a0adc561051943bdec419b10e6be6cffde8161.wasm", - "tx_init_account.wasm": "tx_init_account.929e8be15b0c966ef6b896592d5a8452e8db4a11e40aec52ac1ca3606188291d.wasm", - "tx_init_proposal.wasm": "tx_init_proposal.b7b703c504cfe63db412938f68c5cc12c51f06c865d5be180feea381a04cd7fd.wasm", - "tx_reactivate_validator.wasm": "tx_reactivate_validator.8aed0bd2f609d658c595a7c0f0c1774d08964a237ac3883b60b84a46eb9a80ba.wasm", - "tx_redelegate.wasm": "tx_redelegate.b3880cfa4982cd9babc6777c2d0481c13b0074c613716536ddf57aaea3ef85d0.wasm", - "tx_resign_steward.wasm": "tx_resign_steward.d5c717719ee89d9def8b4a6b352ee6afaa7e7e89d073101e110c152f0a654833.wasm", - "tx_reveal_pk.wasm": "tx_reveal_pk.3c7dff6efd018a0d28db4ec6744bcec122ced0b47fe2907885e7f8e34bcbb4a4.wasm", - "tx_transfer.wasm": "tx_transfer.8719e986786ac8b0cd8e5692bf35234ae98b0674398257eb71eae839329114f6.wasm", - "tx_unbond.wasm": "tx_unbond.c8de749021c6a41bdb93444f9877b4f7ea62272634d2bbc9225005d346f62f7d.wasm", - "tx_unjail_validator.wasm": "tx_unjail_validator.91c3638110406510ef15867245f7ef016553b9c0815920c1eb611e3703e061f5.wasm", - "tx_update_account.wasm": "tx_update_account.e18b65753acd3ba4f2393d875c037cf056cf05c7dee29cdb15c9f93c9987c846.wasm", - "tx_update_steward_commission.wasm": "tx_update_steward_commission.72bd3ceda6f2ca319c228ce4fbf583849706b14a3a3f017952b933898c2d74ee.wasm", - "tx_vote_proposal.wasm": "tx_vote_proposal.ba502cb86890c869ea233d1fe3a20a14969d2b35107e68e5bd378f9a9ad664b9.wasm", - "tx_withdraw.wasm": "tx_withdraw.3aaa47f8fa71755aa645d84e49b69ec4bd54f95bbd14ba140049c98ce4a0e3b6.wasm", - "vp_implicit.wasm": "vp_implicit.04d0f961a87a373ddde65cdab69150c828c9f118cdf75a01b1b7b65aac866b00.wasm", - "vp_user.wasm": "vp_user.0a8c711b809e6217e963db5a13e80b08762479fb9b30c8b4ef10f636a074a19d.wasm" + "tx_become_validator.wasm": "tx_become_validator.e469768e9320dbefb6030fd74505ff7907010d45c6088db17c31c0fcd6284d64.wasm", + "tx_bond.wasm": "tx_bond.202c875f22180d112277488b9659430a288dcc4f4e4c057460ea6bb506755dac.wasm", + "tx_bridge_pool.wasm": "tx_bridge_pool.ac228e264479ea683c641a1eb9216c354cb46cb9d14be6fdbdbe190e7686a58c.wasm", + "tx_change_consensus_key.wasm": "tx_change_consensus_key.06e1998944d6b17b57e174f67065317b6551a81999025e5346de80f4d4e450fc.wasm", + "tx_change_validator_commission.wasm": "tx_change_validator_commission.283e9b69ee32eb565483a63810bca0fcf59ddfcc2861fc3658dbb2d1eba64a43.wasm", + "tx_change_validator_metadata.wasm": "tx_change_validator_metadata.47fe67380d405e03d8679e377597a896af1cd7c9ef300ae040dabbd81676aa8c.wasm", + "tx_claim_rewards.wasm": "tx_claim_rewards.35d701950d32f690360340e93bb2572770786f79d981d07c4f96d16bbbc94cfa.wasm", + "tx_deactivate_validator.wasm": "tx_deactivate_validator.d0efd18607dc18870590a504cc63d8c24c606894b932efda5ee0913f3666cec8.wasm", + "tx_ibc.wasm": "tx_ibc.2186350118f45fb09ce3c98cff777fc6864d8c32eb0ca86c25103597ba5d0b81.wasm", + "tx_init_account.wasm": "tx_init_account.36b2792c03d9a4ca35de5e61ca59a3cb9695e1dbffd5860ac90feddb07671e9a.wasm", + "tx_init_proposal.wasm": "tx_init_proposal.2de4c2cf0b3362e4171ffbf10617991b5a414eb901fe0adab9bec49b229d5b5c.wasm", + "tx_reactivate_validator.wasm": "tx_reactivate_validator.2d612d040562276a3117a7a697223be7ddea4523df5c7facbc04b9abb2100f20.wasm", + "tx_redelegate.wasm": "tx_redelegate.846d500717cb4a08165d23641b75ce30a4be10ac918c4d3db81371c69e3b2063.wasm", + "tx_resign_steward.wasm": "tx_resign_steward.1a8ec5b775088f32a7b68e8976b98dc88bd183170608b1bfe169f005d873dd9f.wasm", + "tx_reveal_pk.wasm": "tx_reveal_pk.d935ed0cd9e11a3d1e54b0a4ed7f6560588ee494a34e021637483bced6107e0e.wasm", + "tx_transfer.wasm": "tx_transfer.7e957ccff54cbeef7993e578151b52fa06ddd0b69cab3cb6e64923ba9c6e2b58.wasm", + "tx_unbond.wasm": "tx_unbond.2ead8660f57ba7010f5599a30eee2c7879df6fb491fe75ee22e4a7cb7dab8d3a.wasm", + "tx_unjail_validator.wasm": "tx_unjail_validator.a54af40b27b2fa8f5422411959b1664828b3efe8e72b05cb5c3eac055530c53c.wasm", + "tx_update_account.wasm": "tx_update_account.410b49c7c28dd003086b96e61469b5dd3485aa838334ed7f1b067f1aa0f6959e.wasm", + "tx_update_steward_commission.wasm": "tx_update_steward_commission.e5d73f1bdbead96fd7f1c8dc388bf6458931bf05317b1a556a2f6ffac7b2868f.wasm", + "tx_vote_proposal.wasm": "tx_vote_proposal.0f4caa64515acaaa218f909bc2f79c93369ee7fb51c3b8bd12680359dc4294e2.wasm", + "tx_withdraw.wasm": "tx_withdraw.c26f34fee02e29aef365fc1612e0d077072dc53f2faec409950f1c992d7c1dc6.wasm", + "vp_implicit.wasm": "vp_implicit.7ed6fb6bc160bdfdd4d837df505890adbb0134c34fd16b184215deb2fc57002c.wasm", + "vp_user.wasm": "vp_user.8aad829f98629a7185360bd86adca3b2f8f750675238e2d00da8e09457c2df11.wasm" } \ No newline at end of file diff --git a/wasm_for_tests/tx_fail.wasm b/wasm_for_tests/tx_fail.wasm index 55907e3b45..3bcad70e67 100755 Binary files a/wasm_for_tests/tx_fail.wasm and b/wasm_for_tests/tx_fail.wasm differ diff --git a/wasm_for_tests/tx_infinite_guest_gas.wasm b/wasm_for_tests/tx_infinite_guest_gas.wasm index b154f50d4a..51cefa0287 100755 Binary files a/wasm_for_tests/tx_infinite_guest_gas.wasm and b/wasm_for_tests/tx_infinite_guest_gas.wasm differ diff --git a/wasm_for_tests/tx_infinite_host_gas.wasm b/wasm_for_tests/tx_infinite_host_gas.wasm index 68592266d1..4bdd870571 100755 Binary files a/wasm_for_tests/tx_infinite_host_gas.wasm and b/wasm_for_tests/tx_infinite_host_gas.wasm differ diff --git a/wasm_for_tests/tx_invalid_data.wasm b/wasm_for_tests/tx_invalid_data.wasm index 5dd857ae73..df2353e0ce 100755 Binary files a/wasm_for_tests/tx_invalid_data.wasm and b/wasm_for_tests/tx_invalid_data.wasm differ diff --git a/wasm_for_tests/tx_memory_limit.wasm b/wasm_for_tests/tx_memory_limit.wasm index b8275aaa72..d94ec7c768 100755 Binary files a/wasm_for_tests/tx_memory_limit.wasm and b/wasm_for_tests/tx_memory_limit.wasm differ diff --git a/wasm_for_tests/tx_no_op.wasm b/wasm_for_tests/tx_no_op.wasm index a0e154abf2..c44428bad3 100755 Binary files a/wasm_for_tests/tx_no_op.wasm and b/wasm_for_tests/tx_no_op.wasm differ diff --git a/wasm_for_tests/tx_proposal_code.wasm b/wasm_for_tests/tx_proposal_code.wasm index abe21caa67..cf6fcb32f9 100755 Binary files a/wasm_for_tests/tx_proposal_code.wasm and b/wasm_for_tests/tx_proposal_code.wasm differ diff --git a/wasm_for_tests/tx_proposal_ibc_token_inflation.wasm b/wasm_for_tests/tx_proposal_ibc_token_inflation.wasm index ef853e4f30..c22dede573 100755 Binary files a/wasm_for_tests/tx_proposal_ibc_token_inflation.wasm and b/wasm_for_tests/tx_proposal_ibc_token_inflation.wasm differ diff --git a/wasm_for_tests/tx_proposal_masp_reward.wasm b/wasm_for_tests/tx_proposal_masp_reward.wasm index b26cbcc89e..56e9897505 100755 Binary files a/wasm_for_tests/tx_proposal_masp_reward.wasm and b/wasm_for_tests/tx_proposal_masp_reward.wasm differ diff --git a/wasm_for_tests/tx_read_storage_key.wasm b/wasm_for_tests/tx_read_storage_key.wasm index 724f2a45c1..f06fc18397 100755 Binary files a/wasm_for_tests/tx_read_storage_key.wasm and b/wasm_for_tests/tx_read_storage_key.wasm differ diff --git a/wasm_for_tests/tx_write.wasm b/wasm_for_tests/tx_write.wasm index e2ac390dbe..bae7cf9216 100755 Binary files a/wasm_for_tests/tx_write.wasm and b/wasm_for_tests/tx_write.wasm differ diff --git a/wasm_for_tests/vp_always_false.wasm b/wasm_for_tests/vp_always_false.wasm index 86dac8f462..31b3b0e3ed 100755 Binary files a/wasm_for_tests/vp_always_false.wasm and b/wasm_for_tests/vp_always_false.wasm differ diff --git a/wasm_for_tests/vp_always_true.wasm b/wasm_for_tests/vp_always_true.wasm index aafbad53c5..8fda29c456 100755 Binary files a/wasm_for_tests/vp_always_true.wasm and b/wasm_for_tests/vp_always_true.wasm differ diff --git a/wasm_for_tests/vp_eval.wasm b/wasm_for_tests/vp_eval.wasm index 3b7ea771d8..52b9d43bbe 100755 Binary files a/wasm_for_tests/vp_eval.wasm and b/wasm_for_tests/vp_eval.wasm differ diff --git a/wasm_for_tests/vp_infinite_guest_gas.wasm b/wasm_for_tests/vp_infinite_guest_gas.wasm index 3a7d8b8471..9a3d9c4921 100755 Binary files a/wasm_for_tests/vp_infinite_guest_gas.wasm and b/wasm_for_tests/vp_infinite_guest_gas.wasm differ diff --git a/wasm_for_tests/vp_infinite_host_gas.wasm b/wasm_for_tests/vp_infinite_host_gas.wasm index a22fb1e143..b0cf88ff20 100755 Binary files a/wasm_for_tests/vp_infinite_host_gas.wasm and b/wasm_for_tests/vp_infinite_host_gas.wasm differ diff --git a/wasm_for_tests/vp_memory_limit.wasm b/wasm_for_tests/vp_memory_limit.wasm index 5a66580cd6..d5ce074e53 100755 Binary files a/wasm_for_tests/vp_memory_limit.wasm and b/wasm_for_tests/vp_memory_limit.wasm differ diff --git a/wasm_for_tests/vp_read_storage_key.wasm b/wasm_for_tests/vp_read_storage_key.wasm index eecf7e4cd4..02b3f2e645 100755 Binary files a/wasm_for_tests/vp_read_storage_key.wasm and b/wasm_for_tests/vp_read_storage_key.wasm differ