Skip to content

Commit

Permalink
Clean up ibc-apps errors (#1318)
Browse files Browse the repository at this point in the history
* Clean up ics20-transfer error

* Clean up NftTransfer error

* Incorporate PR feedback

* Remove redundant TODO comment

* Simplify NftTransferError variant

* Add TODO reminder
  • Loading branch information
seanchen1991 authored Aug 22, 2024
1 parent 60ff9bd commit 0d98ebf
Show file tree
Hide file tree
Showing 18 changed files with 171 additions and 252 deletions.
4 changes: 2 additions & 2 deletions ibc-apps/ics20-transfer/src/handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub fn refund_packet_token_execute(
.sender
.clone()
.try_into()
.map_err(|_| TokenTransferError::ParseAccountFailure)?;
.map_err(|_| TokenTransferError::FailedToParseAccount)?;

if is_sender_chain_source(
packet.port_id_on_a.clone(),
Expand Down Expand Up @@ -49,7 +49,7 @@ pub fn refund_packet_token_validate(
.sender
.clone()
.try_into()
.map_err(|_| TokenTransferError::ParseAccountFailure)?;
.map_err(|_| TokenTransferError::FailedToParseAccount)?;

if is_sender_chain_source(
packet.port_id_on_a.clone(),
Expand Down
2 changes: 1 addition & 1 deletion ibc-apps/ics20-transfer/src/handler/on_recv_packet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pub fn process_recv_packet_execute<Ctx: TokenTransferExecutionContext>(
let receiver_account = data.receiver.clone().try_into().map_err(|_| {
(
ModuleExtras::empty(),
TokenTransferError::ParseAccountFailure,
TokenTransferError::FailedToParseAccount,
)
})?;

Expand Down
8 changes: 4 additions & 4 deletions ibc-apps/ics20-transfer/src/handler/send_transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ where
let chan_id_on_b = chan_end_on_a
.counterparty()
.channel_id()
.ok_or_else(|| TokenTransferError::DestinationChannelNotFound {
.ok_or_else(|| TokenTransferError::MissingDestinationChannel {
port_id: msg.port_id_on_a.clone(),
channel_id: msg.chan_id_on_a.clone(),
})?
Expand All @@ -61,7 +61,7 @@ where
.sender
.clone()
.try_into()
.map_err(|_| TokenTransferError::ParseAccountFailure)?;
.map_err(|_| TokenTransferError::FailedToParseAccount)?;

if is_sender_chain_source(
msg.port_id_on_a.clone(),
Expand Down Expand Up @@ -117,7 +117,7 @@ where
let chan_on_b = chan_end_on_a
.counterparty()
.channel_id()
.ok_or_else(|| TokenTransferError::DestinationChannelNotFound {
.ok_or_else(|| TokenTransferError::MissingDestinationChannel {
port_id: msg.port_id_on_a.clone(),
channel_id: msg.chan_id_on_a.clone(),
})?
Expand All @@ -134,7 +134,7 @@ where
.sender
.clone()
.try_into()
.map_err(|_| TokenTransferError::ParseAccountFailure)?;
.map_err(|_| TokenTransferError::FailedToParseAccount)?;

if is_sender_chain_source(
msg.port_id_on_a.clone(),
Expand Down
42 changes: 21 additions & 21 deletions ibc-apps/ics20-transfer/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ pub fn on_chan_open_init_validate(
version: &Version,
) -> Result<(), TokenTransferError> {
if order != Order::Unordered {
return Err(TokenTransferError::ChannelNotUnordered {
expect_order: Order::Unordered,
got_order: order,
return Err(TokenTransferError::MismatchedChannelOrders {
expected: Order::Unordered,
actual: order,
});
}
let bound_port = ctx.get_port()?;
if port_id != &bound_port {
return Err(TokenTransferError::InvalidPort {
port_id: port_id.clone(),
exp_port_id: bound_port,
return Err(TokenTransferError::MismatchedPortIds {
actual: port_id.clone(),
expected: bound_port,
});
}

Expand Down Expand Up @@ -71,9 +71,9 @@ pub fn on_chan_open_try_validate(
counterparty_version: &Version,
) -> Result<(), TokenTransferError> {
if order != Order::Unordered {
return Err(TokenTransferError::ChannelNotUnordered {
expect_order: Order::Unordered,
got_order: order,
return Err(TokenTransferError::MismatchedChannelOrders {
expected: Order::Unordered,
actual: order,
});
}

Expand Down Expand Up @@ -139,15 +139,15 @@ pub fn on_chan_close_init_validate(
_port_id: &PortId,
_channel_id: &ChannelId,
) -> Result<(), TokenTransferError> {
Err(TokenTransferError::CantCloseChannel)
Err(TokenTransferError::UnsupportedClosedChannel)
}

pub fn on_chan_close_init_execute(
_ctx: &mut impl TokenTransferExecutionContext,
_port_id: &PortId,
_channel_id: &ChannelId,
) -> Result<ModuleExtras, TokenTransferError> {
Err(TokenTransferError::CantCloseChannel)
Err(TokenTransferError::UnsupportedClosedChannel)
}

pub fn on_chan_close_confirm_validate(
Expand All @@ -172,7 +172,7 @@ pub fn on_recv_packet_execute(
) -> (ModuleExtras, Acknowledgement) {
let Ok(data) = serde_json::from_slice::<PacketData>(&packet.data) else {
let ack =
AcknowledgementStatus::error(TokenTransferError::PacketDataDeserialization.into());
AcknowledgementStatus::error(TokenTransferError::FailedToDeserializePacketData.into());
return (ModuleExtras::empty(), ack.into());
};

Expand Down Expand Up @@ -204,10 +204,10 @@ where
Ctx: TokenTransferValidationContext,
{
let data = serde_json::from_slice::<PacketData>(&packet.data)
.map_err(|_| TokenTransferError::PacketDataDeserialization)?;
.map_err(|_| TokenTransferError::FailedToDeserializePacketData)?;

let acknowledgement = serde_json::from_slice::<AcknowledgementStatus>(acknowledgement.as_ref())
.map_err(|_| TokenTransferError::AckDeserialization)?;
.map_err(|_| TokenTransferError::FailedToDeserializeAck)?;

if !acknowledgement.is_successful() {
refund_packet_token_validate(ctx, packet, &data)?;
Expand All @@ -225,7 +225,7 @@ pub fn on_acknowledgement_packet_execute(
let Ok(data) = serde_json::from_slice::<PacketData>(&packet.data) else {
return (
ModuleExtras::empty(),
Err(TokenTransferError::PacketDataDeserialization),
Err(TokenTransferError::FailedToDeserializePacketData),
);
};

Expand All @@ -234,7 +234,7 @@ pub fn on_acknowledgement_packet_execute(
else {
return (
ModuleExtras::empty(),
Err(TokenTransferError::AckDeserialization),
Err(TokenTransferError::FailedToDeserializeAck),
);
};

Expand Down Expand Up @@ -270,7 +270,7 @@ where
Ctx: TokenTransferValidationContext,
{
let data = serde_json::from_slice::<PacketData>(&packet.data)
.map_err(|_| TokenTransferError::PacketDataDeserialization)?;
.map_err(|_| TokenTransferError::FailedToDeserializePacketData)?;

refund_packet_token_validate(ctx, packet, &data)?;

Expand All @@ -285,7 +285,7 @@ pub fn on_timeout_packet_execute(
let Ok(data) = serde_json::from_slice::<PacketData>(&packet.data) else {
return (
ModuleExtras::empty(),
Err(TokenTransferError::PacketDataDeserialization),
Err(TokenTransferError::FailedToDeserializePacketData),
);
};

Expand Down Expand Up @@ -324,7 +324,7 @@ mod test {
r#"{"result":"AQ=="}"#,
);
ser_json_assert_eq(
AcknowledgementStatus::error(TokenTransferError::PacketDataDeserialization.into()),
AcknowledgementStatus::error(TokenTransferError::FailedToDeserializePacketData.into()),
r#"{"error":"failed to deserialize packet data"}"#,
);
}
Expand All @@ -342,7 +342,7 @@ mod test {
#[test]
fn test_ack_error_to_vec() {
let ack_error: Vec<u8> =
AcknowledgementStatus::error(TokenTransferError::PacketDataDeserialization.into())
AcknowledgementStatus::error(TokenTransferError::FailedToDeserializePacketData.into())
.into();

// Check that it's the same output as ibc-go
Expand All @@ -367,7 +367,7 @@ mod test {
);
de_json_assert_eq(
r#"{"error":"failed to deserialize packet data"}"#,
AcknowledgementStatus::error(TokenTransferError::PacketDataDeserialization.into()),
AcknowledgementStatus::error(TokenTransferError::FailedToDeserializePacketData.into()),
);

assert!(serde_json::from_str::<AcknowledgementStatus>(r#"{"success":"AQ=="}"#).is_err());
Expand Down
4 changes: 1 addition & 3 deletions ibc-apps/ics20-transfer/types/src/coin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ where
.chars()
.all(|x| x.is_alphanumeric() || VALID_DENOM_CHARACTERS.contains(x))
})
.ok_or_else(|| TokenTransferError::InvalidCoin {
coin: coin_str.to_string(),
})?;
.ok_or_else(|| TokenTransferError::InvalidCoin(coin_str.to_string()))?;

Ok(Coin {
amount: amount.parse()?,
Expand Down
2 changes: 1 addition & 1 deletion ibc-apps/ics20-transfer/types/src/denom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ impl FromStr for TracePath {
remaining_parts
.is_none()
.then_some(trace_path)
.ok_or_else(|| TokenTransferError::MalformedTrace(s.to_string()))
.ok_or_else(|| TokenTransferError::InvalidTrace(s.to_string()))
}
}

Expand Down
97 changes: 29 additions & 68 deletions ibc-apps/ics20-transfer/types/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Defines the token transfer error type
use core::convert::Infallible;
use core::str::Utf8Error;

use displaydoc::Display;
use ibc_core::channel::types::acknowledgement::StatusValue;
Expand All @@ -17,86 +16,48 @@ pub enum TokenTransferError {
ContextError(ContextError),
/// invalid identifier: `{0}`
InvalidIdentifier(IdentifierError),
/// insufficient funds: tried to send `{send_attempt}`, sender only has `{available_funds}`
InsufficientFunds {
send_attempt: String,
available_funds: String,
},
/// destination channel not found in the counterparty of port_id `{port_id}` and channel_id `{channel_id}`
DestinationChannelNotFound {
port_id: PortId,
channel_id: ChannelId,
},
/// base denomination is empty
EmptyBaseDenom,
/// invalid prot id n trace at position: `{pos}`, validation error: `{validation_error}`
InvalidTracePortId {
pos: u64,
validation_error: IdentifierError,
},
/// invalid channel id in trace at position: `{pos}`, validation error: `{validation_error}`
InvalidTraceChannelId {
pos: u64,
validation_error: IdentifierError,
},
/// malformed trace: `{0}`
MalformedTrace(String),
/// trace length must be even but got: `{len}`
InvalidTraceLength { len: u64 },
/// invalid trace: `{0}`
InvalidTrace(String),
/// invalid amount: `{0}`
InvalidAmount(FromDecStrErr),
/// invalid token
InvalidToken,
/// expected `{expect_order}` channel, got `{got_order}`
ChannelNotUnordered {
expect_order: Order,
got_order: Order,
/// invalid coin: `{0}`
InvalidCoin(String),
/// missing token
MissingToken,
/// missing destination channel `{channel_id}` on port `{port_id}`
MissingDestinationChannel {
port_id: PortId,
channel_id: ChannelId,
},
/// channel cannot be closed
CantCloseChannel,
/// mismatched channel orders: expected `{expected}`, actual `{actual}`
MismatchedChannelOrders { expected: Order, actual: Order },
/// mismatched port IDs: expected `{expected}`, actual `{actual}`
MismatchedPortIds { expected: PortId, actual: PortId },
/// failed to deserialize packet data
PacketDataDeserialization,
FailedToDeserializePacketData,
/// failed to deserialize acknowledgement
AckDeserialization,
/// receive is not enabled
ReceiveDisabled { reason: String },
/// send is not enabled
SendDisabled { reason: String },
/// failed to parse as AccountId
ParseAccountFailure,
/// invalid port: `{port_id}`, expected `{exp_port_id}`
InvalidPort {
port_id: PortId,
exp_port_id: PortId,
},
/// decoding raw msg error: `{reason}`
DecodeRawMsg { reason: String },
/// unknown msg type: `{msg_type}`
UnknownMsgType { msg_type: String },
/// invalid coin string: `{coin}`
InvalidCoin { coin: String },
/// decoding raw bytes as UTF-8 string error: `{0}`
Utf8Decode(Utf8Error),
/// other error: `{0}`
Other(String),
FailedToDeserializeAck,
// TODO(seanchen1991): Used in basecoin; this variant should be moved
// to a host-relevant error
/// failed to parse account ID
FailedToParseAccount,
/// failed to decode raw msg: `{description}`
FailedToDecodeRawMsg { description: String },
/// channel cannot be closed
UnsupportedClosedChannel,
/// empty base denomination
EmptyBaseDenom,
/// unknown msg type: `{0}`
UnknownMsgType(String),
}

#[cfg(feature = "std")]
impl std::error::Error for TokenTransferError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match &self {
Self::ContextError(e) => Some(e),
Self::InvalidIdentifier(e)
| Self::InvalidTracePortId {
validation_error: e,
..
}
| Self::InvalidTraceChannelId {
validation_error: e,
..
} => Some(e),
Self::InvalidIdentifier(e) => Some(e),
Self::InvalidAmount(e) => Some(e),
Self::Utf8Decode(e) => Some(e),
_ => None,
}
}
Expand Down
16 changes: 7 additions & 9 deletions ibc-apps/ics20-transfer/types/src/msgs/transfer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ impl TryFrom<RawMsgTransfer> for MsgTransfer {
packet_data: PacketData {
token: raw_msg
.token
.ok_or(TokenTransferError::InvalidToken)?
.ok_or(TokenTransferError::MissingToken)?
.try_into()
.map_err(|_| TokenTransferError::InvalidToken)?,
.map_err(|_| TokenTransferError::MissingToken)?,
sender: raw_msg.sender.into(),
receiver: raw_msg.receiver.into(),
memo: raw_msg.memo.into(),
Expand Down Expand Up @@ -104,14 +104,12 @@ impl TryFrom<Any> for MsgTransfer {

fn try_from(raw: Any) -> Result<Self, Self::Error> {
match raw.type_url.as_str() {
TYPE_URL => {
MsgTransfer::decode_vec(&raw.value).map_err(|e| TokenTransferError::DecodeRawMsg {
reason: e.to_string(),
})
}
_ => Err(TokenTransferError::UnknownMsgType {
msg_type: raw.type_url,
TYPE_URL => MsgTransfer::decode_vec(&raw.value).map_err(|e| {
TokenTransferError::FailedToDecodeRawMsg {
description: e.to_string(),
}
}),
_ => Err(TokenTransferError::UnknownMsgType(raw.type_url)),
}
}
}
4 changes: 2 additions & 2 deletions ibc-apps/ics721-nft-transfer/src/handler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub fn refund_packet_nft_execute(
.sender
.clone()
.try_into()
.map_err(|_| NftTransferError::ParseAccountFailure)?;
.map_err(|_| NftTransferError::FailedToParseAccount)?;

if is_sender_chain_source(
packet.port_id_on_a.clone(),
Expand Down Expand Up @@ -58,7 +58,7 @@ pub fn refund_packet_nft_validate(
.sender
.clone()
.try_into()
.map_err(|_| NftTransferError::ParseAccountFailure)?;
.map_err(|_| NftTransferError::FailedToParseAccount)?;

if is_sender_chain_source(
packet.port_id_on_a.clone(),
Expand Down
Loading

0 comments on commit 0d98ebf

Please sign in to comment.