@@ -545,3 +545,113 @@ fn test_subaccount_transfers() {
545545 ) ;
546546 assert_eq ! ( to_balance, <u64 as Into <Nat >>:: into( 1_000_000u64 ) ) ;
547547}
548+
549+ #[ test]
550+ fn test_zero_amount_transfer ( ) {
551+ let ctx = TestContext :: new ( ) ;
552+ let from = create_test_account ( 13 ) ;
553+ let to = create_test_account ( 14 ) ;
554+
555+ // Mint tokens
556+ ctx. mint_tokens_for_test ( & from, 1_000_000 ) ;
557+
558+ // Get current timestamp and fee
559+ let ts = ctx. get_timestamp_ns ( ) ;
560+ let fee = ctx. get_transfer_fee ( ) ;
561+
562+ // Try to transfer zero amount
563+ let transfer_arg = TransferArg {
564+ from_subaccount : None ,
565+ to,
566+ amount : 0u64 . into ( ) ,
567+ fee : Some ( fee) ,
568+ created_at_time : Some ( ts) ,
569+ memo : None ,
570+ } ;
571+
572+ let result = update_check_and_decode ! (
573+ ctx. pic,
574+ ctx. canister_id,
575+ from. owner,
576+ "icrc1_transfer" ,
577+ candid:: encode_one( transfer_arg) . unwrap( ) ,
578+ Result <Nat , TransferError >
579+ ) ;
580+ assert ! ( result. is_ok( ) ) ;
581+ }
582+
583+ #[ test]
584+ #[ should_panic(
585+ expected = "Error from Canister lxzze-o7777-77777-aaaaa-cai: Canister called `ic0.trap` with message: the memo field is too large."
586+ ) ]
587+ fn test_max_memo_size ( ) {
588+ let ctx = TestContext :: new ( ) ;
589+ let from = create_test_account ( 15 ) ;
590+ let to = create_test_account ( 16 ) ;
591+
592+ // Mint tokens
593+ ctx. mint_tokens_for_test ( & from, 1_000_000 ) ;
594+
595+ // Get current timestamp and fee
596+ let ts = ctx. get_timestamp_ns ( ) ;
597+ let fee = ctx. get_transfer_fee ( ) ;
598+
599+ // Create memo that exceeds maximum size
600+ let large_memo = vec ! [ 0u8 ; 33 ] ; // MEMO_BYTES_MAX is typically 32
601+
602+ let transfer_arg = TransferArg {
603+ from_subaccount : None ,
604+ to,
605+ amount : 100_000u64 . into ( ) ,
606+ fee : Some ( fee) ,
607+ created_at_time : Some ( ts) ,
608+ memo : Some ( Memo ( large_memo. into ( ) ) ) ,
609+ } ;
610+
611+ let result = update_check_and_decode ! (
612+ ctx. pic,
613+ ctx. canister_id,
614+ from. owner,
615+ "icrc1_transfer" ,
616+ candid:: encode_one( transfer_arg) . unwrap( ) ,
617+ Result <Nat , TransferError >
618+ ) ;
619+ assert ! ( result. is_err( ) ) ;
620+ }
621+
622+ #[ test]
623+ fn test_self_transfer ( ) {
624+ let ctx = TestContext :: new ( ) ;
625+ let account = create_test_account ( 17 ) ;
626+ let fee = ctx. get_transfer_fee ( ) . 0 . to_u64_digits ( ) [ 0 ] ;
627+
628+ // Mint tokens
629+ ctx. mint_tokens_for_test ( & account, 1_000_000u64 + fee) ;
630+
631+ // Get current timestamp and fee
632+ let ts = ctx. get_timestamp_ns ( ) ;
633+
634+ // Transfer to self
635+ let transfer_arg = TransferArg {
636+ from_subaccount : None ,
637+ to : account,
638+ amount : 100_000u64 . into ( ) ,
639+ fee : None ,
640+ created_at_time : Some ( ts) ,
641+ memo : None ,
642+ } ;
643+
644+ let result = update_check_and_decode ! (
645+ ctx. pic,
646+ ctx. canister_id,
647+ account. owner,
648+ "icrc1_transfer" ,
649+ candid:: encode_one( transfer_arg) . unwrap( ) ,
650+ Result <Nat , TransferError >
651+ ) ;
652+ assert ! ( result. is_ok( ) ) ;
653+
654+ // Verify balance (should only be reduced by fee)
655+ let balance = ctx. get_account_balance ( & account) ;
656+ assert_eq ! ( balance, Nat :: from( 1_000_000u64 ) ) ;
657+ }
0 commit comments