Skip to content

Commit 4b5004c

Browse files
imp: refactor send-coins-*() and add memo field to escrow-* and burn-* methods (#836)
* split send_coins_*() functions and introduce extra data * arg name change * add error variant * add error * add `Other` variant to `TokenTransferError` * fmt * fix: restore `no_std` support for `serde` feature (#790) * fix: restore no_std support for serde feature * deps: bump ibc-proto-rs to v0.34.0 * fix: reflect changes b/c of ibc-proto-rs * imp: comply naming + use better domain type for host_consensus_state * fix: apply host_cons_state_proof changes for conn_open_ack * fix: use domain TmEvent instead of proto for upgrade client proposal handler * misc: add a unclog for ibc-proto-rs upgrade * bump ibc-proto to v0.34.1 and borsh to v0.10 (#844) * bump ibc-proto and borsh * changelog * add borsh derive for `MsgTransfer` * derive JsonSchema for MsgTransfer * fix JsonSchema derive for MsgTransfer Fix is in implementing it properly for our `Timestamp` * execute() methods must have &mut self * nit: spell checker * imp: simplify escrow/unescrow abstraction + using memo instead * chore: dress up with unclogs * nit: adjust unlogs * nit: remove confusing InternalTransferFailed error variant * imp: add memo field to burn-coins-* * docs: adjust & add missing docstrings --------- Co-authored-by: Farhad Shabani <[email protected]>
1 parent cf485ad commit 4b5004c

File tree

14 files changed

+140
-61
lines changed

14 files changed

+140
-61
lines changed

.changelog/unreleased/993-bump-ibc-proto-rs.md

Lines changed: 0 additions & 2 deletions
This file was deleted.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
- `[ibc-app-transfer]` Refactor `send-coins-*()` methods by breaking them down
2+
into distinct escrow and unescrow methods, enhancing both clarity and
3+
specificity in functionality.
4+
([\#837](https://github.com/cosmos/ibc-rs/issues/837))
5+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
- `[ibc-app-transfer]` Add `memo` field to `escrow-coins-*()` and
2+
`burn-coins-*()` methods, allowing implementors to pass in arbitrary data
3+
necessary for their use case.
4+
([\#839](https://github.com/cosmos/ibc-rs/issues/837))
5+
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
- Optimize `IdentifierError` variants and make them mutually exclusive.
2-
([\#978](https://github.com/cosmos/ibc-rs/issues/978))
1+
- `[ibc-core-host-type]` Optimize `IdentifierError` variants and make them
2+
mutually exclusive. ([\#978](https://github.com/cosmos/ibc-rs/issues/978))
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- `[ibc-data-types]` Bump ibc-proto-rs dependency to v0.39.1.
2+
([\#993](https://github.com/cosmos/ibc-rs/issues/993))

.changelog/unreleased/breaking-changes/997-minimize-prost-dependency.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- [`ibc`] Minimize `prost` dependency by introducing `ToVec` trait
1+
- `[ibc]` Minimize `prost` dependency by introducing `ToVec` trait
22
- Now `prost` is only imported in `ibc-primitives` crate
33
- Remove error variants originating from `prost` (Breaking change)
44
- Eliminate the need for the `bytes` dependency
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
- [`cw-check`] More rigorous CosmWasm check by upgrading dependencies and
1+
- `[cw-check]` More rigorous CosmWasm check by upgrading dependencies and
22
including `std` and `schema` features for `ibc-core`.
33
([\#992](https://github.com/cosmos/ibc-rs/pull/992))
Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Defines the main context traits and IBC module callbacks
22
33
use ibc_app_transfer_types::error::TokenTransferError;
4-
use ibc_app_transfer_types::{PrefixedCoin, PrefixedDenom};
4+
use ibc_app_transfer_types::{Memo, PrefixedCoin, PrefixedDenom};
55
use ibc_core::host::types::identifiers::{ChannelId, PortId};
66
use ibc_core::primitives::prelude::*;
77
use ibc_core::primitives::Signer;
@@ -13,24 +13,31 @@ pub trait TokenTransferValidationContext {
1313
/// get_port returns the portID for the transfer module.
1414
fn get_port(&self) -> Result<PortId, TokenTransferError>;
1515

16-
/// Returns the escrow account id for a port and channel combination
17-
fn get_escrow_account(
18-
&self,
19-
port_id: &PortId,
20-
channel_id: &ChannelId,
21-
) -> Result<Self::AccountId, TokenTransferError>;
22-
2316
/// Returns Ok() if the host chain supports sending coins.
2417
fn can_send_coins(&self) -> Result<(), TokenTransferError>;
2518

2619
/// Returns Ok() if the host chain supports receiving coins.
2720
fn can_receive_coins(&self) -> Result<(), TokenTransferError>;
2821

29-
/// Validates the sender and receiver accounts and the coin inputs
30-
fn send_coins_validate(
22+
/// Validates that the tokens can be escrowed successfully.
23+
///
24+
/// `memo` field allows to incorporate additional contextual details in the
25+
/// escrow validation.
26+
fn escrow_coins_validate(
3127
&self,
3228
from_account: &Self::AccountId,
29+
port_id: &PortId,
30+
channel_id: &ChannelId,
31+
coin: &PrefixedCoin,
32+
memo: &Memo,
33+
) -> Result<(), TokenTransferError>;
34+
35+
/// Validates that the tokens can be unescrowed successfully.
36+
fn unescrow_coins_validate(
37+
&self,
3338
to_account: &Self::AccountId,
39+
port_id: &PortId,
40+
channel_id: &ChannelId,
3441
coin: &PrefixedCoin,
3542
) -> Result<(), TokenTransferError>;
3643

@@ -41,11 +48,15 @@ pub trait TokenTransferValidationContext {
4148
coin: &PrefixedCoin,
4249
) -> Result<(), TokenTransferError>;
4350

44-
/// Validates the sender account and the coin input
51+
/// Validates the sender account and the coin input before burning.
52+
///
53+
/// `memo` field allows to incorporate additional contextual details in the
54+
/// burn validation.
4555
fn burn_coins_validate(
4656
&self,
4757
account: &Self::AccountId,
4858
coin: &PrefixedCoin,
59+
memo: &Memo,
4960
) -> Result<(), TokenTransferError>;
5061

5162
/// Returns a hash of the prefixed denom.
@@ -55,27 +66,45 @@ pub trait TokenTransferValidationContext {
5566
}
5667
}
5768

58-
/// Methods required in token transfer execution, to be implemented by the host
69+
/// Methods required in token transfer execution, to be implemented by the host.
5970
pub trait TokenTransferExecutionContext: TokenTransferValidationContext {
60-
/// This function should enable sending ibc fungible tokens from one account to another
61-
fn send_coins_execute(
71+
/// Executes the escrow of the tokens in a user account.
72+
///
73+
/// `memo` field allows to incorporate additional contextual details in the
74+
/// escrow execution.
75+
fn escrow_coins_execute(
6276
&mut self,
6377
from_account: &Self::AccountId,
78+
port_id: &PortId,
79+
channel_id: &ChannelId,
80+
coin: &PrefixedCoin,
81+
memo: &Memo,
82+
) -> Result<(), TokenTransferError>;
83+
84+
/// Executes the unescrow of the tokens in a user account.
85+
fn unescrow_coins_execute(
86+
&mut self,
6487
to_account: &Self::AccountId,
88+
port_id: &PortId,
89+
channel_id: &ChannelId,
6590
coin: &PrefixedCoin,
6691
) -> Result<(), TokenTransferError>;
6792

68-
/// This function to enable minting ibc tokens to a user account
93+
/// Executes minting of the tokens in a user account.
6994
fn mint_coins_execute(
7095
&mut self,
7196
account: &Self::AccountId,
7297
coin: &PrefixedCoin,
7398
) -> Result<(), TokenTransferError>;
7499

75-
/// This function should enable burning of minted tokens in a user account
100+
/// Executes burning of the tokens in a user account.
101+
///
102+
/// `memo` field allows to incorporate additional contextual details in the
103+
/// burn execution.
76104
fn burn_coins_execute(
77105
&mut self,
78106
account: &Self::AccountId,
79107
coin: &PrefixedCoin,
108+
memo: &Memo,
80109
) -> Result<(), TokenTransferError>;
81110
}

ibc-apps/ics20-transfer/src/handler/mod.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,12 @@ pub fn refund_packet_token_execute(
2727
packet.chan_id_on_a.clone(),
2828
&data.token.denom,
2929
) {
30-
// unescrow tokens back to sender
31-
let escrow_address =
32-
ctx_a.get_escrow_account(&packet.port_id_on_a, &packet.chan_id_on_a)?;
33-
34-
ctx_a.send_coins_execute(&escrow_address, &sender, &data.token)
30+
ctx_a.unescrow_coins_execute(
31+
&sender,
32+
&packet.port_id_on_a,
33+
&packet.chan_id_on_a,
34+
&data.token,
35+
)
3536
}
3637
// mint vouchers back to sender
3738
else {
@@ -55,10 +56,12 @@ pub fn refund_packet_token_validate(
5556
packet.chan_id_on_a.clone(),
5657
&data.token.denom,
5758
) {
58-
let escrow_address =
59-
ctx_a.get_escrow_account(&packet.port_id_on_a, &packet.chan_id_on_a)?;
60-
61-
ctx_a.send_coins_validate(&escrow_address, &sender, &data.token)
59+
ctx_a.unescrow_coins_validate(
60+
&sender,
61+
&packet.port_id_on_a,
62+
&packet.chan_id_on_a,
63+
&data.token,
64+
)
6265
} else {
6366
ctx_a.mint_coins_validate(&sender, &data.token)
6467
}

ibc-apps/ics20-transfer/src/handler/on_recv_packet.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,6 @@ pub fn process_recv_packet_execute<Ctx: TokenTransferExecutionContext>(
4343
c
4444
};
4545

46-
let escrow_address = ctx_b
47-
.get_escrow_account(&packet.port_id_on_b, &packet.chan_id_on_b)
48-
.map_err(|token_err| (ModuleExtras::empty(), token_err))?;
49-
5046
// Note: it is correct to do the validation here because `recv_packet()`
5147
// works slightly differently. We do not have a
5248
// `on_recv_packet_validate()` callback because regardless of whether or
@@ -58,11 +54,20 @@ pub fn process_recv_packet_execute<Ctx: TokenTransferExecutionContext>(
5854
// gets relayed back to the sender so that the escrowed tokens
5955
// can be refunded.
6056
ctx_b
61-
.send_coins_validate(&escrow_address, &receiver_account, &coin)
57+
.unescrow_coins_validate(
58+
&receiver_account,
59+
&packet.port_id_on_b,
60+
&packet.chan_id_on_b,
61+
&coin,
62+
)
6263
.map_err(|token_err| (ModuleExtras::empty(), token_err))?;
63-
6464
ctx_b
65-
.send_coins_execute(&escrow_address, &receiver_account, &coin)
65+
.unescrow_coins_execute(
66+
&receiver_account,
67+
&packet.port_id_on_b,
68+
&packet.chan_id_on_b,
69+
&coin,
70+
)
6671
.map_err(|token_err| (ModuleExtras::empty(), token_err))?;
6772

6873
ModuleExtras::empty()

ibc-apps/ics20-transfer/src/handler/send_transfer.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,15 @@ where
6868
msg.chan_id_on_a.clone(),
6969
&token.denom,
7070
) {
71-
let escrow_address =
72-
token_ctx_a.get_escrow_account(&msg.port_id_on_a, &msg.chan_id_on_a)?;
73-
token_ctx_a.send_coins_validate(&sender, &escrow_address, token)?;
71+
token_ctx_a.escrow_coins_validate(
72+
&sender,
73+
&msg.port_id_on_a,
74+
&msg.chan_id_on_a,
75+
token,
76+
&msg.packet_data.memo,
77+
)?;
7478
} else {
75-
token_ctx_a.burn_coins_validate(&sender, token)?;
79+
token_ctx_a.burn_coins_validate(&sender, token, &msg.packet_data.memo)?;
7680
}
7781

7882
let packet = {
@@ -137,11 +141,15 @@ where
137141
msg.chan_id_on_a.clone(),
138142
&token.denom,
139143
) {
140-
let escrow_address =
141-
token_ctx_a.get_escrow_account(&msg.port_id_on_a, &msg.chan_id_on_a)?;
142-
token_ctx_a.send_coins_execute(&sender, &escrow_address, token)?;
144+
token_ctx_a.escrow_coins_execute(
145+
&sender,
146+
&msg.port_id_on_a,
147+
&msg.chan_id_on_a,
148+
token,
149+
&msg.packet_data.memo,
150+
)?;
143151
} else {
144-
token_ctx_a.burn_coins_execute(&sender, token)?;
152+
token_ctx_a.burn_coins_execute(&sender, token, &msg.packet_data.memo)?;
145153
}
146154

147155
let packet = {

ibc-apps/ics20-transfer/types/src/error.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,19 @@ use ibc_core::host::types::identifiers::{ChannelId, PortId};
1111
use ibc_core::primitives::prelude::*;
1212
use uint::FromDecStrErr;
1313

14+
use crate::Amount;
15+
1416
#[derive(Display, Debug)]
1517
pub enum TokenTransferError {
1618
/// context error: `{0}`
1719
ContextError(ContextError),
1820
/// invalid identifier: `{0}`
1921
InvalidIdentifier(IdentifierError),
22+
/// insufficient funds: tried to send `{send_attempt}`, sender only has `{available_funds}`
23+
InsufficientFunds {
24+
send_attempt: Amount,
25+
available_funds: Amount,
26+
},
2027
/// destination channel not found in the counterparty of port_id `{port_id}` and channel_id `{channel_id}`
2128
DestinationChannelNotFound {
2229
port_id: PortId,
@@ -70,6 +77,8 @@ pub enum TokenTransferError {
7077
InvalidCoin { coin: String },
7178
/// decoding raw bytes as UTF8 string error: `{0}`
7279
Utf8Decode(Utf8Error),
80+
/// other error: `{0}`
81+
Other(String),
7382
}
7483

7584
#[cfg(feature = "std")]

ibc-apps/ics20-transfer/types/src/msgs/transfer.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub(crate) const TYPE_URL: &str = "/ibc.applications.transfer.v1.MsgTransfer";
3232
feature = "borsh",
3333
derive(borsh::BorshSerialize, borsh::BorshDeserialize)
3434
)]
35+
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
3536
pub struct MsgTransfer {
3637
/// the port on which the packet will be sent
3738
pub port_id_on_a: PortId,

ibc-testkit/src/testapp/ibc/applications/transfer/context.rs

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
use ibc::apps::transfer::context::{TokenTransferExecutionContext, TokenTransferValidationContext};
22
use ibc::apps::transfer::types::error::TokenTransferError;
3-
use ibc::apps::transfer::types::PrefixedCoin;
3+
use ibc::apps::transfer::types::{Memo, PrefixedCoin};
44
use ibc::core::host::types::identifiers::{ChannelId, PortId};
55
use ibc::core::primitives::Signer;
6-
use ibc::cosmos_host::utils::cosmos_adr028_escrow_address;
7-
use subtle_encoding::bech32;
86

97
use super::types::DummyTransferModule;
108

@@ -15,27 +13,29 @@ impl TokenTransferValidationContext for DummyTransferModule {
1513
Ok(PortId::transfer())
1614
}
1715

18-
fn get_escrow_account(
19-
&self,
20-
port_id: &PortId,
21-
channel_id: &ChannelId,
22-
) -> Result<Self::AccountId, TokenTransferError> {
23-
let addr = cosmos_adr028_escrow_address(port_id, channel_id);
24-
Ok(bech32::encode("cosmos", addr).into())
25-
}
26-
2716
fn can_send_coins(&self) -> Result<(), TokenTransferError> {
2817
Ok(())
2918
}
3019

3120
fn can_receive_coins(&self) -> Result<(), TokenTransferError> {
3221
Ok(())
3322
}
34-
35-
fn send_coins_validate(
23+
fn escrow_coins_validate(
3624
&self,
3725
_from_account: &Self::AccountId,
26+
_port_id: &PortId,
27+
_channel_id: &ChannelId,
28+
_coin: &PrefixedCoin,
29+
_memo: &Memo,
30+
) -> Result<(), TokenTransferError> {
31+
Ok(())
32+
}
33+
34+
fn unescrow_coins_validate(
35+
&self,
3836
_to_account: &Self::AccountId,
37+
_port_id: &PortId,
38+
_channel_id: &ChannelId,
3939
_coin: &PrefixedCoin,
4040
) -> Result<(), TokenTransferError> {
4141
Ok(())
@@ -53,16 +53,29 @@ impl TokenTransferValidationContext for DummyTransferModule {
5353
&self,
5454
_account: &Self::AccountId,
5555
_coin: &PrefixedCoin,
56+
_memo: &Memo,
5657
) -> Result<(), TokenTransferError> {
5758
Ok(())
5859
}
5960
}
6061

6162
impl TokenTransferExecutionContext for DummyTransferModule {
62-
fn send_coins_execute(
63+
fn escrow_coins_execute(
6364
&mut self,
6465
_from_account: &Self::AccountId,
66+
_port_id: &PortId,
67+
_channel_id: &ChannelId,
68+
_coin: &PrefixedCoin,
69+
_memo: &Memo,
70+
) -> Result<(), TokenTransferError> {
71+
Ok(())
72+
}
73+
74+
fn unescrow_coins_execute(
75+
&mut self,
6576
_to_account: &Self::AccountId,
77+
_port_id: &PortId,
78+
_channel_id: &ChannelId,
6679
_coin: &PrefixedCoin,
6780
) -> Result<(), TokenTransferError> {
6881
Ok(())
@@ -80,6 +93,7 @@ impl TokenTransferExecutionContext for DummyTransferModule {
8093
&mut self,
8194
_account: &Self::AccountId,
8295
_coin: &PrefixedCoin,
96+
_memo: &Memo,
8397
) -> Result<(), TokenTransferError> {
8498
Ok(())
8599
}

0 commit comments

Comments
 (0)