Skip to content

Commit f56ba17

Browse files
committed
wip2
there is still a bug. when refunding a packet, we're charging unshielding fees, for some reason :\
1 parent d12d23c commit f56ba17

File tree

3 files changed

+101
-82
lines changed

3 files changed

+101
-82
lines changed

crates/ibc/src/context/middlewares.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,8 @@ pub fn send_transfer_execute<SendPacketCtx, TokenCtx>(
8888
) -> Result<(), TokenTransferError>
8989
where
9090
SendPacketCtx: SendPacketExecutionContext,
91-
TokenCtx: TokenTransferExecutionContext
92-
+ MaspUnshieldingFeesExecutionContext<MsgTransfer>,
91+
TokenCtx:
92+
TokenTransferExecutionContext + MaspUnshieldingFeesExecutionContext,
9393
{
9494
macro_rules! assemble_middlewares {
9595
($base:expr) => { $base };
@@ -106,11 +106,11 @@ where
106106
}
107107

108108
/// Context that handles ICS-20 MASP unshielding fees.
109-
pub trait MaspUnshieldingFeesExecutionContext<Msg> {
109+
pub trait MaspUnshieldingFeesExecutionContext {
110110
/// Apply a MASP unshielding fee over the given ICS-20 packet.
111111
fn apply_masp_unshielding_fee(
112112
&self,
113-
msg: &mut Msg,
113+
msg: &mut MsgTransfer,
114114
) -> Result<(), TokenTransferError>;
115115
}
116116

@@ -128,8 +128,8 @@ where
128128
MsgTransfer,
129129
) -> Result<(), TokenTransferError>,
130130
SendPacketCtx: SendPacketExecutionContext,
131-
TokenCtx: TokenTransferExecutionContext
132-
+ MaspUnshieldingFeesExecutionContext<MsgTransfer>,
131+
TokenCtx:
132+
TokenTransferExecutionContext + MaspUnshieldingFeesExecutionContext,
133133
{
134134
|send_packet_ctx_a, token_ctx_a, mut msg| {
135135
token_ctx_a.apply_masp_unshielding_fee(&mut msg)?;

crates/ibc/src/context/token_transfer.rs

Lines changed: 16 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -776,60 +776,7 @@ where
776776
)?))
777777
}
778778

779-
#[allow(missing_docs)]
780-
pub struct ParamsStorageAdapter<S, Params>(S, PhantomData<Params>);
781-
782-
impl<S, Params> ParamsStorageAdapter<S, Params> {
783-
#[allow(missing_docs)]
784-
pub const fn adapt(storage: S) -> Self {
785-
Self(storage, PhantomData)
786-
}
787-
}
788-
789-
impl<S, Params> MaspUnshieldingFeesExecutionContext<crate::IbcTransferInfo>
790-
for ParamsStorageAdapter<S, Params>
791-
where
792-
Params: namada_systems::parameters::Read<S>,
793-
{
794-
fn apply_masp_unshielding_fee(
795-
&self,
796-
msg: &mut crate::IbcTransferInfo,
797-
) -> Result<(), TokenTransferError> {
798-
for trace in msg.ibc_traces.iter() {
799-
let ibc_token =
800-
crate::trace::convert_to_address(trace).map_err(|err| {
801-
HostError::Other {
802-
description: format!(
803-
"Failed to convert {trace:?} to address: {err}"
804-
),
805-
}
806-
})?;
807-
808-
if let Some(fee) = get_masp_unshielding_fee::<_, Params>(
809-
&self.0,
810-
&ibc_token,
811-
&msg.amount,
812-
)
813-
.map_err(TokenTransferError::Host)?
814-
.filter(|fee| !fee.is_zero())
815-
{
816-
msg.amount =
817-
// NOTE: we're adding the fee, because we want to recreate the
818-
// original packet
819-
msg.amount.checked_add(fee).ok_or_else(|| HostError::Other {
820-
description: "Unshielding fee greater than withdrawn \
821-
amount"
822-
.to_string(),
823-
})?;
824-
}
825-
}
826-
827-
Ok(())
828-
}
829-
}
830-
831-
impl<C, Params, Token, ShieldedToken>
832-
MaspUnshieldingFeesExecutionContext<MsgTransfer>
779+
impl<C, Params, Token, ShieldedToken> MaspUnshieldingFeesExecutionContext
833780
for TokenTransferContext<C, Params, Token, ShieldedToken>
834781
where
835782
C: IbcCommonContext,
@@ -839,31 +786,34 @@ where
839786
&self,
840787
msg: &mut MsgTransfer,
841788
) -> Result<(), TokenTransferError> {
789+
tracing::warn!(?msg, "called apply_masp_unshielding_fee");
790+
842791
// no fee is taken if this is not a masp unshielding op
843792
let has_masp_tx = self
844793
.config
845794
.contains(TokenTransferContextConfig::HAS_MASP_TX);
846795
if !has_masp_tx {
796+
tracing::warn!("apply_masp_unshielding_fee has no masp tx");
847797
return Ok(());
848798
}
849799

850-
let (ibc_token, mut amount) = get_token_amount(&msg.packet_data.token)
800+
let (ibc_token, amount) = get_token_amount(&msg.packet_data.token)
851801
.map_err(TokenTransferError::Host)?;
852802

853803
if let Some(fee) = self
854804
.get_masp_unshielding_fee(&ibc_token, &amount)
855805
.map_err(TokenTransferError::Host)?
856806
.filter(|fee| !fee.is_zero())
857807
{
858-
amount =
808+
let new_amount =
859809
amount.checked_sub(fee).ok_or_else(|| HostError::Other {
860810
description: "Unshielding fee greater than withdrawn \
861811
amount"
862812
.to_string(),
863813
})?;
864814

865815
// commit the updated amount to the packet
866-
msg.packet_data.token.amount = amount.into();
816+
msg.packet_data.token.amount = new_amount.into();
867817

868818
// transfer the fee to PGF, and trigger its vp
869819
self.insert_verifier(&PGF);
@@ -872,6 +822,15 @@ where
872822
.transfer_token(&MASP, &PGF, &ibc_token, fee)
873823
.map_err(HostError::from)
874824
.map_err(TokenTransferError::Host)?;
825+
826+
tracing::warn!(
827+
%ibc_token,
828+
%fee,
829+
original_amount = %amount,
830+
%new_amount,
831+
new_msg = ?msg,
832+
"apply_masp_unshielding_fee fees applied"
833+
);
875834
}
876835

877836
Ok(())

crates/ibc/src/lib.rs

Lines changed: 79 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,7 @@ use trace::{
113113
is_sender_chain_source,
114114
};
115115

116-
use crate::context::middlewares::{
117-
MaspUnshieldingFeesExecutionContext, send_transfer_execute,
118-
};
119-
use crate::context::token_transfer::ParamsStorageAdapter;
116+
use crate::context::middlewares::send_transfer_execute;
120117
use crate::storage::{
121118
channel_counter_key, client_counter_key, connection_counter_key,
122119
deposit_prefix, nft_class_key, nft_metadata_key, withdraw_prefix,
@@ -164,6 +161,7 @@ impl From<Error> for StorageError {
164161
}
165162
}
166163

164+
#[derive(Debug)]
167165
struct IbcTransferInfo {
168166
src_port_id: PortId,
169167
src_channel_id: ChannelId,
@@ -183,6 +181,11 @@ impl TryFrom<IbcMsgTransfer> for IbcTransferInfo {
183181
) -> std::result::Result<Self, Self::Error> {
184182
let packet_data = serde_json::to_vec(&message.packet_data)
185183
.map_err(StorageError::new)?;
184+
tracing::warn!(
185+
?message,
186+
?packet_data,
187+
"parsing IbcTransferInfo from IbcMsgTransfer"
188+
);
186189
let ibc_traces = vec![message.packet_data.token.denom.to_string()];
187190
let amount: Amount = message.packet_data.token.amount.into();
188191
let receiver = message.packet_data.receiver.to_string();
@@ -328,6 +331,7 @@ where
328331
Some(IbcMessage::Transfer(msg)) => {
329332
// Get the packet commitment from post-storage that corresponds
330333
// to this event
334+
tracing::warn!(msg = ?msg.message, "calling apply_transfer_msg");
331335
let ibc_transfer = IbcTransferInfo::try_from(msg.message)?;
332336
let receiver = ibc_transfer.receiver.clone();
333337
let addr = TAddrData::Ibc(receiver.clone());
@@ -337,14 +341,60 @@ where
337341
accum,
338342
ibc_transfer,
339343
keys_changed,
340-
|ibc_transfer| {
341-
// Recreate the original packet, by applying middlewares
342-
let adapter = ParamsStorageAdapter::<_, Params>::adapt(
343-
storage_pre,
344-
);
345-
adapter
346-
.apply_masp_unshielding_fee(ibc_transfer)
347-
.into_storage_result()
344+
|packet_data_vec| {
345+
let mut packet_data =
346+
serde_json::from_slice::<PacketData>(
347+
packet_data_vec,
348+
)
349+
.map_err(StorageError::new)?;
350+
351+
let token = trace::convert_to_address(
352+
packet_data.token.denom.to_string(),
353+
)
354+
.map_err(|e| {
355+
Error::Trace(format!(
356+
"Failed to convert IBC trace to Namada \
357+
address: {e}"
358+
))
359+
})
360+
.into_storage_result()?;
361+
362+
let Some(fee_percentage) =
363+
Params::ibc_unshielding_fee_percentage(
364+
&storage_pre,
365+
&token,
366+
)?
367+
else {
368+
return Ok(());
369+
};
370+
371+
let old_amount: Amount =
372+
packet_data.token.amount.into();
373+
let fee = old_amount
374+
.checked_mul_dec(fee_percentage)
375+
.ok_or(StorageError::new_const(
376+
"IBC unshielding fee overflow",
377+
))?;
378+
379+
if fee.is_zero() {
380+
return Ok(());
381+
}
382+
383+
packet_data.token.amount = old_amount
384+
.checked_sub(fee)
385+
.ok_or_else(|| {
386+
StorageError::new_const(
387+
"Unshielding fee greater than withdrawn \
388+
amount",
389+
)
390+
})?
391+
.into();
392+
393+
packet_data_vec.clear();
394+
serde_json::to_writer(packet_data_vec, &packet_data)
395+
.map_err(StorageError::new)?;
396+
397+
Ok(())
348398
},
349399
)?;
350400
}
@@ -525,14 +575,17 @@ impl fmt::Display for IbcAccountId {
525575
}
526576
}
527577

528-
fn check_ibc_transfer<S>(
578+
fn check_ibc_transfer<S, F>(
529579
storage: &S,
530580
ibc_transfer: &IbcTransferInfo,
531581
keys_changed: &BTreeSet<Key>,
582+
alter_packet_data: F,
532583
) -> StorageResult<()>
533584
where
534585
S: StorageRead,
586+
F: FnOnce(&mut Vec<u8>) -> StorageResult<()>,
535587
{
588+
tracing::warn!(?ibc_transfer, "calling check_ibc_transfer");
536589
let IbcTransferInfo {
537590
src_port_id,
538591
src_channel_id,
@@ -553,6 +606,9 @@ where
553606
)));
554607
}
555608

609+
let mut packet_data = packet_data.clone();
610+
alter_packet_data(&mut packet_data)?;
611+
556612
// The commitment is also validated in IBC VP. Make sure that for when
557613
// IBC VP isn't triggered.
558614
let actual: PacketCommitment = storage
@@ -563,7 +619,7 @@ where
563619
)))?
564620
.into();
565621
let expected = compute_packet_commitment(
566-
packet_data,
622+
&packet_data,
567623
timeout_height,
568624
timeout_timestamp,
569625
);
@@ -601,16 +657,20 @@ fn check_packet_receiving(
601657
fn apply_transfer_msg<S, F>(
602658
storage: &S,
603659
mut accum: ChangedBalances,
604-
mut ibc_transfer: IbcTransferInfo,
660+
ibc_transfer: IbcTransferInfo,
605661
keys_changed: &BTreeSet<Key>,
606-
alter_ibc_transfer: F,
662+
alter_packet_data: F,
607663
) -> StorageResult<ChangedBalances>
608664
where
609665
S: StorageRead,
610-
F: FnOnce(&mut IbcTransferInfo) -> StorageResult<()>,
666+
F: FnOnce(&mut Vec<u8>) -> StorageResult<()>,
611667
{
612-
check_ibc_transfer(storage, &ibc_transfer, keys_changed)?;
613-
alter_ibc_transfer(&mut ibc_transfer)?;
668+
check_ibc_transfer(
669+
storage,
670+
&ibc_transfer,
671+
keys_changed,
672+
alter_packet_data,
673+
)?;
614674

615675
let IbcTransferInfo {
616676
ref ibc_traces,

0 commit comments

Comments
 (0)