@@ -596,3 +596,115 @@ func TestUnlimitedMaxAutoAssociationsFailsWithInvalid(t *testing.T) {
596596 _ , err = tx .SetValidateStatus (true ).GetReceipt (env .Client )
597597 require .ErrorContains (t , err , "INVALID_MAX_AUTO_ASSOCIATIONS" )
598598}
599+
600+ // HIP-904 contract tests
601+
602+ func TestUnlimitedMaxAutoAssociationsContractAllowsToTransferFungibleTokens (t * testing.T ) {
603+ testContractByteCode := []byte (`608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101cb806100606000396000f3fe608060405260043610610046576000357c01000000000000000000000000000000000000000000000000000000009004806341c0e1b51461004b578063cfae321714610062575b600080fd5b34801561005757600080fd5b506100606100f2565b005b34801561006e57600080fd5b50610077610162565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100b757808201518184015260208101905061009c565b50505050905090810190601f1680156100e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610160573373ffffffffffffffffffffffffffffffffffffffff16ff5b565b60606040805190810160405280600d81526020017f48656c6c6f2c20776f726c64210000000000000000000000000000000000000081525090509056fea165627a7a72305820ae96fb3af7cde9c0abfe365272441894ab717f816f07f41f07b1cbede54e256e0029` )
604+
605+ t .Parallel ()
606+ env := NewIntegrationTestEnv (t )
607+ defer CloseIntegrationTestEnv (env , nil )
608+
609+ // deploy the bytecode
610+ fileCreate , err := NewFileCreateTransaction ().
611+ SetKeys (env .Client .GetOperatorPublicKey ()).
612+ SetContents (testContractByteCode ).
613+ Execute (env .Client )
614+ require .NoError (t , err )
615+
616+ fileReceipt , err := fileCreate .SetValidateStatus (true ).GetReceipt (env .Client )
617+ require .NoError (t , err )
618+ fileID := * fileReceipt .FileID
619+
620+ // create a contract with unlimited max auto associations
621+ contractCreate , err := NewContractCreateTransaction ().
622+ SetAdminKey (env .Client .GetOperatorPublicKey ()).
623+ SetGas (contractDeployGas ).
624+ SetBytecodeFileID (fileID ).
625+ SetMaxAutomaticTokenAssociations (- 1 ).
626+ Execute (env .Client )
627+ require .NoError (t , err )
628+
629+ contractReceipt , err := contractCreate .SetValidateStatus (true ).GetReceipt (env .Client )
630+ require .NoError (t , err )
631+ require .NotNil (t , contractReceipt .ContractID )
632+ contractID := * contractReceipt .ContractID
633+
634+ // the contract's own account is addressed by the same shard.realm.num
635+ contractAccountID := AccountID {Shard : contractID .Shard , Realm : contractID .Realm , Account : contractID .Contract }
636+
637+ // create token1
638+ tokenID1 , err := createFungibleToken (& env )
639+ require .NoError (t , err )
640+
641+ // create token2
642+ tokenID2 , err := createFungibleToken (& env )
643+ require .NoError (t , err )
644+
645+ // transfer both tokens to the contract with no explicit association
646+ tokenTransferTransaction , err := NewTransferTransaction ().
647+ AddTokenTransfer (tokenID1 , env .Client .GetOperatorAccountID (), - 1000 ).
648+ AddTokenTransfer (tokenID1 , contractAccountID , 1000 ).
649+ AddTokenTransfer (tokenID2 , env .Client .GetOperatorAccountID (), - 1000 ).
650+ AddTokenTransfer (tokenID2 , contractAccountID , 1000 ).
651+ Execute (env .Client )
652+ require .NoError (t , err )
653+
654+ _ , err = tokenTransferTransaction .SetValidateStatus (true ).GetReceipt (env .Client )
655+ require .NoError (t , err )
656+
657+ // verify both balances arrived on the contract
658+ contractBalance , err := NewAccountBalanceQuery ().SetContractID (contractID ).Execute (env .Client )
659+ require .NoError (t , err )
660+ assert .Equal (t , uint64 (1000 ), contractBalance .Tokens .Get (tokenID1 ))
661+ assert .Equal (t , uint64 (1000 ), contractBalance .Tokens .Get (tokenID2 ))
662+ }
663+
664+ func TestUnlimitedMaxAutoAssociationsContractUpdate (t * testing.T ) {
665+ testContractByteCode := []byte (`608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101cb806100606000396000f3fe608060405260043610610046576000357c01000000000000000000000000000000000000000000000000000000009004806341c0e1b51461004b578063cfae321714610062575b600080fd5b34801561005757600080fd5b506100606100f2565b005b34801561006e57600080fd5b50610077610162565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100b757808201518184015260208101905061009c565b50505050905090810190601f1680156100e45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610160573373ffffffffffffffffffffffffffffffffffffffff16ff5b565b60606040805190810160405280600d81526020017f48656c6c6f2c20776f726c64210000000000000000000000000000000000000081525090509056fea165627a7a72305820ae96fb3af7cde9c0abfe365272441894ab717f816f07f41f07b1cbede54e256e0029` )
666+
667+ t .Parallel ()
668+ env := NewIntegrationTestEnv (t )
669+ defer CloseIntegrationTestEnv (env , nil )
670+
671+ // deploy the bytecode
672+ fileCreate , err := NewFileCreateTransaction ().
673+ SetKeys (env .Client .GetOperatorPublicKey ()).
674+ SetContents (testContractByteCode ).
675+ Execute (env .Client )
676+ require .NoError (t , err )
677+
678+ fileReceipt , err := fileCreate .SetValidateStatus (true ).GetReceipt (env .Client )
679+ require .NoError (t , err )
680+ fileID := * fileReceipt .FileID
681+
682+ // create a contract with a limited number of max auto associations
683+ contractCreate , err := NewContractCreateTransaction ().
684+ SetAdminKey (env .Client .GetOperatorPublicKey ()).
685+ SetGas (contractDeployGas ).
686+ SetBytecodeFileID (fileID ).
687+ SetMaxAutomaticTokenAssociations (1 ).
688+ Execute (env .Client )
689+ require .NoError (t , err )
690+
691+ contractReceipt , err := contractCreate .SetValidateStatus (true ).GetReceipt (env .Client )
692+ require .NoError (t , err )
693+ require .NotNil (t , contractReceipt .ContractID )
694+ contractID := * contractReceipt .ContractID
695+
696+ // update the contract to unlimited max auto associations
697+ contractUpdate , err := NewContractUpdateTransaction ().
698+ SetContractID (contractID ).
699+ SetMaxAutomaticTokenAssociations (- 1 ).
700+ Execute (env .Client )
701+ require .NoError (t , err )
702+
703+ _ , err = contractUpdate .SetValidateStatus (true ).GetReceipt (env .Client )
704+ require .NoError (t , err )
705+
706+ // verify the contract now reports unlimited (-1) max auto associations
707+ info , err := NewContractInfoQuery ().SetContractID (contractID ).Execute (env .Client )
708+ require .NoError (t , err )
709+ assert .Equal (t , int32 (- 1 ), info .MaxAutomaticTokenAssociations )
710+ }
0 commit comments