@@ -476,7 +476,9 @@ mod tests {
476476 use std:: str:: FromStr ;
477477
478478 use assert_matches:: assert_matches;
479+ use ibc:: apps:: transfer:: types:: error:: TokenTransferError ;
479480 use ibc:: core:: channel:: types:: timeout:: TimeoutTimestamp ;
481+ use ibc:: core:: host:: types:: error:: HostError ;
480482 use ibc:: primitives:: IntoTimestamp ;
481483 use ibc_testkit:: testapp:: ibc:: clients:: mock:: client_state:: {
482484 MOCK_CLIENT_TYPE , MockClientState , client_type,
@@ -485,7 +487,7 @@ mod tests {
485487 use ibc_testkit:: testapp:: ibc:: clients:: mock:: header:: MockHeader ;
486488 use namada_core:: address:: InternalAddress ;
487489 use namada_core:: address:: testing:: {
488- established_address_1, established_address_2, nam,
490+ apfel , established_address_1, established_address_2, nam,
489491 } ;
490492 use namada_core:: borsh:: { BorshDeserialize , BorshSerializeExt } ;
491493 use namada_core:: chain:: testing:: get_dummy_header;
@@ -3507,4 +3509,177 @@ mod tests {
35073509 Ok ( _)
35083510 ) ;
35093511 }
3512+
3513+ #[ test]
3514+ fn test_send_invalid_base_denom ( ) {
3515+ let mut keys_changed = BTreeSet :: new ( ) ;
3516+ let mut state = init_storage ( ) ;
3517+ insert_init_client ( & mut state) ;
3518+
3519+ // insert an open connection
3520+ let conn_key = connection_key ( & get_connection_id ( ) ) ;
3521+ let conn = get_connection ( ConnState :: Open ) ;
3522+ let bytes = conn. encode_vec ( ) ;
3523+ let _ = state
3524+ . write_log_mut ( )
3525+ . write ( & conn_key, bytes)
3526+ . expect ( "write failed" ) ;
3527+ // insert an Open channel
3528+ let channel_key = channel_key ( & get_port_id ( ) , & get_channel_id ( ) ) ;
3529+ let channel = get_channel ( ChanState :: Open , Order :: Unordered ) ;
3530+ let bytes = channel. encode_vec ( ) ;
3531+ let _ = state
3532+ . write_log_mut ( )
3533+ . write ( & channel_key, bytes)
3534+ . expect ( "write failed" ) ;
3535+ // init balance
3536+ let sender = established_address_1 ( ) ;
3537+ let ibc_token = ibc_token ( format ! (
3538+ "{}/{}/{}" ,
3539+ get_port_id( ) ,
3540+ get_channel_id( ) ,
3541+ apfel( )
3542+ ) ) ;
3543+ let balance_key = balance_key ( & ibc_token, & sender) ;
3544+ let amount = Amount :: from_u64 ( 100 ) ;
3545+ let _ = state
3546+ . write_log_mut ( )
3547+ . write ( & balance_key, amount. serialize_to_vec ( ) )
3548+ . expect ( "write failed" ) ;
3549+ state. write_log_mut ( ) . commit_batch_and_current_tx ( ) ;
3550+ state. commit_block ( ) . expect ( "commit failed" ) ;
3551+ // for next block
3552+ state
3553+ . in_mem_mut ( )
3554+ . set_header ( get_dummy_header ( ) )
3555+ . expect ( "Setting a dummy header shouldn't fail" ) ;
3556+ state. in_mem_mut ( ) . begin_block ( BlockHeight ( 2 ) ) . unwrap ( ) ;
3557+
3558+ // prepare data with an invalid message
3559+ let msg = IbcMsgTransfer {
3560+ port_id_on_a : get_port_id ( ) ,
3561+ chan_id_on_a : get_channel_id ( ) ,
3562+ packet_data : PacketData {
3563+ token : PrefixedCoin {
3564+ // Invalid denom with IbcToken address
3565+ denom : ibc_token. to_string ( ) . parse ( ) . unwrap ( ) ,
3566+ amount : amount. into ( ) ,
3567+ } ,
3568+ sender : sender. to_string ( ) . into ( ) ,
3569+ receiver : "receiver" . to_string ( ) . into ( ) ,
3570+ memo : "memo" . to_string ( ) . into ( ) ,
3571+ } ,
3572+ timeout_height_on_b : TimeoutHeight :: At ( Height :: new ( 0 , 10 ) . unwrap ( ) ) ,
3573+ timeout_timestamp_on_b : TimeoutTimestamp :: Never ,
3574+ } ;
3575+
3576+ // the sequence send
3577+ let seq_key = next_sequence_send_key ( & get_port_id ( ) , & get_channel_id ( ) ) ;
3578+ let sequence = get_next_seq ( & state, & seq_key) ;
3579+ let _ = state
3580+ . write_log_mut ( )
3581+ . write ( & seq_key, ( u64:: from ( sequence) + 1 ) . to_be_bytes ( ) . to_vec ( ) )
3582+ . expect ( "write failed" ) ;
3583+ keys_changed. insert ( seq_key) ;
3584+ // packet commitment
3585+ let packet =
3586+ packet_from_message ( & msg, sequence, & get_channel_counterparty ( ) ) ;
3587+ let commitment_key =
3588+ commitment_key ( & msg. port_id_on_a , & msg. chan_id_on_a , sequence) ;
3589+ let commitment = commitment ( & packet) ;
3590+ let bytes = commitment. into_vec ( ) ;
3591+ let _ = state
3592+ . write_log_mut ( )
3593+ . write ( & commitment_key, bytes)
3594+ . expect ( "write failed" ) ;
3595+ keys_changed. insert ( commitment_key) ;
3596+ // withdraw
3597+ let withdraw_key = withdraw_key ( & ibc_token) ;
3598+ let bytes = amount. serialize_to_vec ( ) ;
3599+ let _ = state
3600+ . write_log_mut ( )
3601+ . write ( & withdraw_key, bytes)
3602+ . expect ( "write failed" ) ;
3603+ keys_changed. insert ( withdraw_key) ;
3604+ // event
3605+ let transfer_event = TransferEvent {
3606+ sender : msg. packet_data . sender . clone ( ) ,
3607+ receiver : msg. packet_data . receiver . clone ( ) ,
3608+ amount : msg. packet_data . token . amount ,
3609+ denom : msg. packet_data . token . denom . clone ( ) ,
3610+ memo : msg. packet_data . memo . clone ( ) ,
3611+ } ;
3612+ let event = RawIbcEvent :: Module ( ModuleEvent :: from ( transfer_event) ) ;
3613+ state
3614+ . write_log_mut ( )
3615+ . emit_event :: < IbcEvent > ( event. try_into ( ) . unwrap ( ) ) ;
3616+ let event = RawIbcEvent :: SendPacket ( SendPacket :: new (
3617+ packet,
3618+ Order :: Unordered ,
3619+ get_connection_id ( ) ,
3620+ ) ) ;
3621+ let message_event = RawIbcEvent :: Message ( MessageEvent :: Channel ) ;
3622+ state
3623+ . write_log_mut ( )
3624+ . emit_event :: < IbcEvent > ( message_event. try_into ( ) . unwrap ( ) ) ;
3625+ state
3626+ . write_log_mut ( )
3627+ . emit_event :: < IbcEvent > ( event. try_into ( ) . unwrap ( ) ) ;
3628+ let message_event =
3629+ RawIbcEvent :: Message ( MessageEvent :: Module ( "transfer" . to_owned ( ) ) ) ;
3630+ state
3631+ . write_log_mut ( )
3632+ . emit_event :: < IbcEvent > ( message_event. try_into ( ) . unwrap ( ) ) ;
3633+
3634+ let tx_index = TxIndex :: default ( ) ;
3635+ let tx_code = vec ! [ ] ;
3636+ let tx_data = MsgTransfer :: < Transfer > {
3637+ message : msg,
3638+ transfer : None ,
3639+ }
3640+ . serialize_to_vec ( ) ;
3641+
3642+ let mut tx = Tx :: new ( state. in_mem ( ) . chain_id . clone ( ) , None ) ;
3643+ tx. add_code ( tx_code, None )
3644+ . add_serialized_data ( tx_data)
3645+ . sign_wrapper ( keypair_1 ( ) ) ;
3646+
3647+ let gas_meter = RefCell :: new ( VpGasMeter :: new_from_tx_meter (
3648+ & TxGasMeter :: new ( TX_GAS_LIMIT , GAS_SCALE ) ,
3649+ ) ) ;
3650+ let ( vp_wasm_cache, _vp_cache_dir) =
3651+ wasm:: compilation_cache:: common:: testing:: vp_cache ( ) ;
3652+
3653+ let verifiers = BTreeSet :: new ( ) ;
3654+ let batched_tx = tx. batch_ref_first_tx ( ) . unwrap ( ) ;
3655+ let ctx = Ctx :: new (
3656+ & ADDRESS ,
3657+ & state,
3658+ batched_tx. tx ,
3659+ batched_tx. cmt ,
3660+ & tx_index,
3661+ & gas_meter,
3662+ & keys_changed,
3663+ & verifiers,
3664+ vp_wasm_cache,
3665+ GasMeterKind :: MutGlobal ,
3666+ ) ;
3667+ let ibc = Ibc :: new ( ctx) ;
3668+ // this should fail because of the invalid message
3669+ let result = ibc
3670+ . validate_tx ( & batched_tx, & keys_changed, & verifiers)
3671+ . unwrap_err ( ) ;
3672+ println ! ( "DEBUG: {result:?}" ) ;
3673+ let error = result. downcast_ref :: < ActionError > ( ) . unwrap ( ) ;
3674+
3675+ // check the error is related to "base denom"
3676+ match error {
3677+ ActionError :: TokenTransfer ( TokenTransferError :: Host (
3678+ HostError :: Other { description : e } ,
3679+ ) ) => {
3680+ assert ! ( e. contains( "base denom" ) ) ;
3681+ }
3682+ _ => panic ! ( "Unexpected error: {error}" ) ,
3683+ }
3684+ }
35103685}
0 commit comments