@@ -545,3 +545,113 @@ fn test_subaccount_transfers() {
545
545
) ;
546
546
assert_eq ! ( to_balance, <u64 as Into <Nat >>:: into( 1_000_000u64 ) ) ;
547
547
}
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