@@ -6,18 +6,19 @@ use crate::common::{
66use candid:: { Decode , Encode , Nat , Principal } ;
77use ic_agent:: identity:: Identity ;
88use ic_base_types:: { CanisterId , PrincipalId } ;
9+ use ic_icrc1:: blocks:: generic_block_to_encoded_block;
10+ use ic_icrc1:: { Block , Operation } ;
911use ic_icrc1_index_ng:: {
1012 DEFAULT_MAX_BLOCKS_PER_RESPONSE , FeeCollectorRanges , GetAccountTransactionsArgs ,
1113 GetAccountTransactionsResponse , GetAccountTransactionsResult , GetBlocksResponse , IndexArg ,
1214 InitArg as IndexInitArg , ListSubaccountsArgs , TransactionWithId ,
1315} ;
14- use ic_icrc1_ledger:: {
15- ChangeFeeCollector , LedgerArgument , Tokens , UpgradeArgs as LedgerUpgradeArgs ,
16- } ;
16+ use ic_icrc1_ledger:: { ChangeFeeCollector , LedgerArgument , UpgradeArgs as LedgerUpgradeArgs } ;
1717use ic_icrc1_test_utils:: {
1818 ArgWithCaller , LedgerEndpointArg , icrc3:: BlockBuilder , minter_identity,
1919 valid_transactions_strategy,
2020} ;
21+ use ic_ledger_core:: block:: BlockType ;
2122use ic_ledger_suite_state_machine_helpers:: {
2223 add_block, archive_blocks, get_logs, set_icrc3_enabled,
2324} ;
@@ -26,6 +27,7 @@ use ic_state_machine_tests::StateMachine;
2627use icrc_ledger_types:: icrc:: generic_value:: ICRC3Value ;
2728use icrc_ledger_types:: icrc1:: account:: { Account , Subaccount } ;
2829use icrc_ledger_types:: icrc1:: transfer:: { BlockIndex , TransferArg , TransferError } ;
30+ use icrc_ledger_types:: icrc2:: allowance:: { Allowance , AllowanceArgs } ;
2931use icrc_ledger_types:: icrc2:: approve:: { ApproveArgs , ApproveError } ;
3032use icrc_ledger_types:: icrc2:: transfer_from:: { TransferFromArgs , TransferFromError } ;
3133use icrc_ledger_types:: icrc3:: blocks:: GetBlocksRequest ;
@@ -40,6 +42,12 @@ use std::time::{Duration, SystemTime};
4042
4143mod common;
4244
45+ #[ cfg( not( feature = "u256-tokens" ) ) ]
46+ type Tokens = ic_icrc1_tokens_u64:: U64 ;
47+
48+ #[ cfg( feature = "u256-tokens" ) ]
49+ type Tokens = ic_icrc1_tokens_u256:: U256 ;
50+
4351fn index_wasm ( ) -> Vec < u8 > {
4452 ic_test_utilities_load_wasm:: load_wasm (
4553 std:: env:: var ( "CARGO_MANIFEST_DIR" ) . unwrap ( ) ,
@@ -1536,6 +1544,92 @@ fn test_principal_subaccounts() {
15361544 assert ! ( subaccounts. contains( & account( 2 , 1 ) . subaccount. unwrap( ) ) ) ;
15371545}
15381546
1547+ #[ test]
1548+ fn test_large_transfers_and_approvals ( ) {
1549+ let env = & StateMachine :: new ( ) ;
1550+ let minter = minter_identity ( ) . sender ( ) . unwrap ( ) ;
1551+ let ledger_id = install_ledger ( env, vec ! [ ] , default_archive_options ( ) , None , minter) ;
1552+ let index_id = install_index_ng ( env, index_init_arg_without_interval ( ledger_id) ) ;
1553+ let account1 = account ( 1 , 0 ) ;
1554+ let account2 = account ( 2 , 0 ) ;
1555+ let max_amount = Nat :: from ( Tokens :: MAX ) ;
1556+
1557+ // Make sure we are using the correct token type.
1558+ #[ cfg( not( feature = "u256-tokens" ) ) ]
1559+ assert_eq ! ( max_amount, Nat :: from( u64 :: MAX ) ) ;
1560+ #[ cfg( feature = "u256-tokens" ) ]
1561+ assert_ne ! ( max_amount, Nat :: from( u64 :: MAX ) ) ;
1562+
1563+ // Mint a huge amount
1564+ let req = TransferArg {
1565+ from_subaccount : None ,
1566+ to : account1,
1567+ amount : max_amount. clone ( ) ,
1568+ created_at_time : None ,
1569+ fee : None ,
1570+ memo : None ,
1571+ } ;
1572+ let mint_index = icrc1_transfer ( env, ledger_id, minter. into ( ) , req) ;
1573+ assert_eq ! ( mint_index, Nat :: from( 0u64 ) ) ;
1574+
1575+ // Test initial mint block.
1576+ wait_until_sync_is_completed ( env, index_id, ledger_id) ;
1577+ assert_ledger_index_parity ( env, ledger_id, index_id) ;
1578+ let balance = Decode ! (
1579+ & env. execute_ingress( index_id, "icrc1_balance_of" , Encode !( & account1) . unwrap( ) )
1580+ . expect( "Failed to send icrc1_balance_of" )
1581+ . bytes( ) ,
1582+ Nat
1583+ )
1584+ . expect ( "Failed to decode icrc1_balance_of response" ) ;
1585+ assert_eq ! ( balance, max_amount) ;
1586+
1587+ // Approve a huge amount
1588+ let req = ApproveArgs {
1589+ from_subaccount : None ,
1590+ spender : account2,
1591+ amount : max_amount. clone ( ) ,
1592+ expected_allowance : None ,
1593+ expires_at : None ,
1594+ fee : None ,
1595+ memo : None ,
1596+ created_at_time : None ,
1597+ } ;
1598+ let approve_index = icrc2_approve ( env, ledger_id, PrincipalId ( account1. owner ) , req) ;
1599+ assert_eq ! ( approve_index, Nat :: from( 1u64 ) ) ;
1600+
1601+ wait_until_sync_is_completed ( env, index_id, ledger_id) ;
1602+ assert_ledger_index_parity ( env, ledger_id, index_id) ;
1603+
1604+ let arg = AllowanceArgs {
1605+ account : account1,
1606+ spender : account2,
1607+ } ;
1608+ let allowance = Decode ! (
1609+ & env. query( ledger_id, "icrc2_allowance" , Encode !( & arg) . unwrap( ) )
1610+ . expect( "failed to guery the allowance" )
1611+ . bytes( ) ,
1612+ Allowance
1613+ )
1614+ . expect ( "failed to decode allowance response" ) ;
1615+ assert_eq ! ( allowance. allowance, max_amount) ;
1616+
1617+ let res = index_get_blocks ( env, index_id, 1 , 1 ) ;
1618+ let index_approval_block = res. blocks . first ( ) . expect ( "expected at least one block" ) ;
1619+ let encoded_block = generic_block_to_encoded_block ( index_approval_block. clone ( ) )
1620+ . expect ( "should convert generic block to encoded block" ) ;
1621+ let block: Block < Tokens > = Block :: decode ( encoded_block) . expect ( "should decode encoded block" ) ;
1622+ match block. transaction . operation {
1623+ Operation :: Approve { amount, .. } => {
1624+ assert_eq ! (
1625+ amount,
1626+ Tokens :: try_from( max_amount) . expect( "should convert max amount to Tokens" )
1627+ ) ;
1628+ }
1629+ _ => panic ! ( "expected Approve operation" ) ,
1630+ }
1631+ }
1632+
15391633#[ test]
15401634fn test_index_http_request_decoding_quota ( ) {
15411635 let env = & StateMachine :: new ( ) ;
0 commit comments