From 519d86e3eed149ac9166823e939ebc20ba81ff4f Mon Sep 17 00:00:00 2001 From: Simeon Nakov Date: Fri, 17 Jan 2025 16:44:45 +0200 Subject: [PATCH] feat: added test coverage of CancelAirdrop.sol Signed-off-by: Simeon Nakov --- .../CancelAirdrop.sol/CancelAirdrop.json | 6 +- .../CancelAirdrop.sol/CancelAirdrop.json | 2 +- .../examples/hrc-904/CancelAirdrop.sol | 2 +- test/constants.js | 10 + .../hrc-904/CancelAirdropContract.js | 381 ++++++++++++++++++ .../hedera-token-service/utils.js | 171 ++------ 6 files changed, 432 insertions(+), 140 deletions(-) create mode 100644 test/system-contracts/hedera-token-service/hrc-904/CancelAirdropContract.js diff --git a/artifacts/contracts/system-contracts/hedera-token-service/examples/hrc-904/CancelAirdrop.sol/CancelAirdrop.json b/artifacts/contracts/system-contracts/hedera-token-service/examples/hrc-904/CancelAirdrop.sol/CancelAirdrop.json index 5812f5f5d..892eb8ba8 100644 --- a/artifacts/contracts/system-contracts/hedera-token-service/examples/hrc-904/CancelAirdrop.sol/CancelAirdrop.json +++ b/artifacts/contracts/system-contracts/hedera-token-service/examples/hrc-904/CancelAirdrop.sol/CancelAirdrop.json @@ -74,7 +74,7 @@ "type": "int64[]" } ], - "name": "cancelAirdrops", + "name": "cancelMultipleAirdrops", "outputs": [ { "internalType": "int64", @@ -217,8 +217,8 @@ "type": "function" } ], - "bytecode": "0x608060405234801561000f575f80fd5b50610c4d8061001d5f395ff3fe608060405234801561000f575f80fd5b506004361061006f575f3560e01c8063660297ab1161004d578063660297ab146100d25780638f68e13c146100e55780639b23d3d9146100f8575f80fd5b806304e74b561461007357806315dacbea1461009e578063618dc65e146100b1575b5f80fd5b610086610081366004610742565b61010b565b60405160079190910b81526020015b60405180910390f35b6100866100ac366004610782565b6101ca565b6100c46100bf36600461080f565b6102b9565b6040516100959291906108fc565b6100866100e03660046109c3565b6103d0565b6100866100f3366004610ac1565b610567565b610086610106366004610782565b61060f565b6040805160018082528183019092525f91829190816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610124575050604080516080810182525f606082018190526001600160a01b03898116835288811660208401528716928201929092528251929350918291849161019b5761019b610b12565b60200260200101819052506101af82610653565b9250600783900b6016146101c1575f80fd5b50509392505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516102489190610b26565b5f604051808303815f865af19150503d805f8114610281576040519150601f19603f3d011682016040523d82523d5f602084013e610286565b606091505b5091509150816102975760156102ab565b808060200190518101906102ab9190610b41565b60030b979650505050505050565b5f60605f806101676001600160a01b031663618dc65e60e01b87876040516024016102e5929190610b68565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516103239190610b26565b5f604051808303815f865af19150503d805f811461035c576040519150601f19603f3d011682016040523d82523d5f602084013e610361565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc8282604051610397929190610b89565b60405180910390a1816103ba57601560405180602001604052805f8152506103be565b6016815b60039190910b97909650945050505050565b83515f90818167ffffffffffffffff8111156103ee576103ee6107ca565b60405190808252806020026020018201604052801561043e57816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161040c5790505b5090505f5b8281101561054157604080516080810182525f80825260208201819052918101829052606081019190915288828151811061048057610480610b12565b60209081029190910101516001600160a01b0316815287518890839081106104aa576104aa610b12565b6020908102919091018101516001600160a01b03169082015286518790839081106104d7576104d7610b12565b60209081029190910101516001600160a01b03166040820152855186908390811061050457610504610b12565b602090810291909101015160070b60608201528251819084908490811061052d5761052d610b12565b602090810291909101015250600101610443565b5061054b81610653565b9250600783900b60161461055d575f80fd5b5050949350505050565b6040805160018082528183019092525f91829190816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610580575050604080516080810182526001600160a01b0389811682528881166020830152871691810191909152600785900b6060820152815191925090819083905f906105fb576105fb610b12565b602002602001018190525061054b82610653565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a40161020a565b5f805f6101676001600160a01b031663012ebcaf60e01b8560405160240161067b9190610ba3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516106b99190610b26565b5f604051808303815f865af19150503d805f81146106f2576040519150601f19603f3d011682016040523d82523d5f602084013e6106f7565b606091505b50915091508161070857601561071c565b8080602001905181019061071c9190610b41565b60030b949350505050565b80356001600160a01b038116811461073d575f80fd5b919050565b5f805f60608486031215610754575f80fd5b61075d84610727565b925061076b60208501610727565b915061077960408501610727565b90509250925092565b5f805f8060808587031215610795575f80fd5b61079e85610727565b93506107ac60208601610727565b92506107ba60408601610727565b9396929550929360600135925050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610807576108076107ca565b604052919050565b5f8060408385031215610820575f80fd5b61082983610727565b915060208084013567ffffffffffffffff80821115610846575f80fd5b818601915086601f830112610859575f80fd5b81358181111561086b5761086b6107ca565b61087d601f8201601f191685016107de565b91508082528784828501011115610892575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f5b838110156108c95781810151838201526020016108b1565b50505f910152565b5f81518084526108e88160208601602086016108af565b601f01601f19169290920160200192915050565b828152604060208201525f61091460408301846108d1565b949350505050565b5f67ffffffffffffffff821115610935576109356107ca565b5060051b60200190565b5f82601f83011261094e575f80fd5b8135602061096361095e8361091c565b6107de565b8083825260208201915060208460051b870101935086841115610984575f80fd5b602086015b848110156109a75761099a81610727565b8352918301918301610989565b509695505050505050565b8035600781900b811461073d575f80fd5b5f805f80608085870312156109d6575f80fd5b843567ffffffffffffffff808211156109ed575f80fd5b6109f98883890161093f565b9550602091508187013581811115610a0f575f80fd5b610a1b89828a0161093f565b955050604087013581811115610a2f575f80fd5b610a3b89828a0161093f565b945050606087013581811115610a4f575f80fd5b87019050601f81018813610a61575f80fd5b8035610a6f61095e8261091c565b81815260059190911b8201830190838101908a831115610a8d575f80fd5b928401925b82841015610ab257610aa3846109b2565b82529284019290840190610a92565b979a9699509497505050505050565b5f805f8060808587031215610ad4575f80fd5b610add85610727565b9350610aeb60208601610727565b9250610af960408601610727565b9150610b07606086016109b2565b905092959194509250565b634e487b7160e01b5f52603260045260245ffd5b5f8251610b378184602087016108af565b9190910192915050565b5f60208284031215610b51575f80fd5b81518060030b8114610b61575f80fd5b9392505050565b6001600160a01b0383168152604060208201525f61091460408301846108d1565b8215158152604060208201525f61091460408301846108d1565b602080825282518282018190525f919060409081850190868401855b82811015610c0a57815180516001600160a01b0390811686528782015181168887015286820151168686015260609081015160070b9085015260809093019290850190600101610bbf565b509197965050505050505056fea26469706673582212208ee1de80164e305680d6ab87ca9e98500d69d15dfd487324dd17ffe81fe3c9b964736f6c63430008180033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061006f575f3560e01c8063660297ab1161004d578063660297ab146100d25780638f68e13c146100e55780639b23d3d9146100f8575f80fd5b806304e74b561461007357806315dacbea1461009e578063618dc65e146100b1575b5f80fd5b610086610081366004610742565b61010b565b60405160079190910b81526020015b60405180910390f35b6100866100ac366004610782565b6101ca565b6100c46100bf36600461080f565b6102b9565b6040516100959291906108fc565b6100866100e03660046109c3565b6103d0565b6100866100f3366004610ac1565b610567565b610086610106366004610782565b61060f565b6040805160018082528183019092525f91829190816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610124575050604080516080810182525f606082018190526001600160a01b03898116835288811660208401528716928201929092528251929350918291849161019b5761019b610b12565b60200260200101819052506101af82610653565b9250600783900b6016146101c1575f80fd5b50509392505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516102489190610b26565b5f604051808303815f865af19150503d805f8114610281576040519150601f19603f3d011682016040523d82523d5f602084013e610286565b606091505b5091509150816102975760156102ab565b808060200190518101906102ab9190610b41565b60030b979650505050505050565b5f60605f806101676001600160a01b031663618dc65e60e01b87876040516024016102e5929190610b68565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516103239190610b26565b5f604051808303815f865af19150503d805f811461035c576040519150601f19603f3d011682016040523d82523d5f602084013e610361565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc8282604051610397929190610b89565b60405180910390a1816103ba57601560405180602001604052805f8152506103be565b6016815b60039190910b97909650945050505050565b83515f90818167ffffffffffffffff8111156103ee576103ee6107ca565b60405190808252806020026020018201604052801561043e57816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161040c5790505b5090505f5b8281101561054157604080516080810182525f80825260208201819052918101829052606081019190915288828151811061048057610480610b12565b60209081029190910101516001600160a01b0316815287518890839081106104aa576104aa610b12565b6020908102919091018101516001600160a01b03169082015286518790839081106104d7576104d7610b12565b60209081029190910101516001600160a01b03166040820152855186908390811061050457610504610b12565b602090810291909101015160070b60608201528251819084908490811061052d5761052d610b12565b602090810291909101015250600101610443565b5061054b81610653565b9250600783900b60161461055d575f80fd5b5050949350505050565b6040805160018082528183019092525f91829190816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610580575050604080516080810182526001600160a01b0389811682528881166020830152871691810191909152600785900b6060820152815191925090819083905f906105fb576105fb610b12565b602002602001018190525061054b82610653565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a40161020a565b5f805f6101676001600160a01b031663012ebcaf60e01b8560405160240161067b9190610ba3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516106b99190610b26565b5f604051808303815f865af19150503d805f81146106f2576040519150601f19603f3d011682016040523d82523d5f602084013e6106f7565b606091505b50915091508161070857601561071c565b8080602001905181019061071c9190610b41565b60030b949350505050565b80356001600160a01b038116811461073d575f80fd5b919050565b5f805f60608486031215610754575f80fd5b61075d84610727565b925061076b60208501610727565b915061077960408501610727565b90509250925092565b5f805f8060808587031215610795575f80fd5b61079e85610727565b93506107ac60208601610727565b92506107ba60408601610727565b9396929550929360600135925050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610807576108076107ca565b604052919050565b5f8060408385031215610820575f80fd5b61082983610727565b915060208084013567ffffffffffffffff80821115610846575f80fd5b818601915086601f830112610859575f80fd5b81358181111561086b5761086b6107ca565b61087d601f8201601f191685016107de565b91508082528784828501011115610892575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f5b838110156108c95781810151838201526020016108b1565b50505f910152565b5f81518084526108e88160208601602086016108af565b601f01601f19169290920160200192915050565b828152604060208201525f61091460408301846108d1565b949350505050565b5f67ffffffffffffffff821115610935576109356107ca565b5060051b60200190565b5f82601f83011261094e575f80fd5b8135602061096361095e8361091c565b6107de565b8083825260208201915060208460051b870101935086841115610984575f80fd5b602086015b848110156109a75761099a81610727565b8352918301918301610989565b509695505050505050565b8035600781900b811461073d575f80fd5b5f805f80608085870312156109d6575f80fd5b843567ffffffffffffffff808211156109ed575f80fd5b6109f98883890161093f565b9550602091508187013581811115610a0f575f80fd5b610a1b89828a0161093f565b955050604087013581811115610a2f575f80fd5b610a3b89828a0161093f565b945050606087013581811115610a4f575f80fd5b87019050601f81018813610a61575f80fd5b8035610a6f61095e8261091c565b81815260059190911b8201830190838101908a831115610a8d575f80fd5b928401925b82841015610ab257610aa3846109b2565b82529284019290840190610a92565b979a9699509497505050505050565b5f805f8060808587031215610ad4575f80fd5b610add85610727565b9350610aeb60208601610727565b9250610af960408601610727565b9150610b07606086016109b2565b905092959194509250565b634e487b7160e01b5f52603260045260245ffd5b5f8251610b378184602087016108af565b9190910192915050565b5f60208284031215610b51575f80fd5b81518060030b8114610b61575f80fd5b9392505050565b6001600160a01b0383168152604060208201525f61091460408301846108d1565b8215158152604060208201525f61091460408301846108d1565b602080825282518282018190525f919060409081850190868401855b82811015610c0a57815180516001600160a01b0390811686528782015181168887015286820151168686015260609081015160070b9085015260809093019290850190600101610bbf565b509197965050505050505056fea26469706673582212208ee1de80164e305680d6ab87ca9e98500d69d15dfd487324dd17ffe81fe3c9b964736f6c63430008180033", + "bytecode": "0x608060405234801561000f575f80fd5b50610c4d8061001d5f395ff3fe608060405234801561000f575f80fd5b506004361061006f575f3560e01c80637e5fb7dc1161004d5780637e5fb7dc146100d25780638f68e13c146100e55780639b23d3d9146100f8575f80fd5b806304e74b561461007357806315dacbea1461009e578063618dc65e146100b1575b5f80fd5b610086610081366004610742565b61010b565b60405160079190910b81526020015b60405180910390f35b6100866100ac366004610782565b6101ca565b6100c46100bf36600461080f565b6102b9565b6040516100959291906108fc565b6100866100e03660046109c3565b6103d0565b6100866100f3366004610ac1565b610567565b610086610106366004610782565b61060f565b6040805160018082528183019092525f91829190816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610124575050604080516080810182525f606082018190526001600160a01b03898116835288811660208401528716928201929092528251929350918291849161019b5761019b610b12565b60200260200101819052506101af82610653565b9250600783900b6016146101c1575f80fd5b50509392505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516102489190610b26565b5f604051808303815f865af19150503d805f8114610281576040519150601f19603f3d011682016040523d82523d5f602084013e610286565b606091505b5091509150816102975760156102ab565b808060200190518101906102ab9190610b41565b60030b979650505050505050565b5f60605f806101676001600160a01b031663618dc65e60e01b87876040516024016102e5929190610b68565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516103239190610b26565b5f604051808303815f865af19150503d805f811461035c576040519150601f19603f3d011682016040523d82523d5f602084013e610361565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc8282604051610397929190610b89565b60405180910390a1816103ba57601560405180602001604052805f8152506103be565b6016815b60039190910b97909650945050505050565b83515f90818167ffffffffffffffff8111156103ee576103ee6107ca565b60405190808252806020026020018201604052801561043e57816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161040c5790505b5090505f5b8281101561054157604080516080810182525f80825260208201819052918101829052606081019190915288828151811061048057610480610b12565b60209081029190910101516001600160a01b0316815287518890839081106104aa576104aa610b12565b6020908102919091018101516001600160a01b03169082015286518790839081106104d7576104d7610b12565b60209081029190910101516001600160a01b03166040820152855186908390811061050457610504610b12565b602090810291909101015160070b60608201528251819084908490811061052d5761052d610b12565b602090810291909101015250600101610443565b5061054b81610653565b9250600783900b60161461055d575f80fd5b5050949350505050565b6040805160018082528183019092525f91829190816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610580575050604080516080810182526001600160a01b0389811682528881166020830152871691810191909152600785900b6060820152815191925090819083905f906105fb576105fb610b12565b602002602001018190525061054b82610653565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a40161020a565b5f805f6101676001600160a01b031663012ebcaf60e01b8560405160240161067b9190610ba3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516106b99190610b26565b5f604051808303815f865af19150503d805f81146106f2576040519150601f19603f3d011682016040523d82523d5f602084013e6106f7565b606091505b50915091508161070857601561071c565b8080602001905181019061071c9190610b41565b60030b949350505050565b80356001600160a01b038116811461073d575f80fd5b919050565b5f805f60608486031215610754575f80fd5b61075d84610727565b925061076b60208501610727565b915061077960408501610727565b90509250925092565b5f805f8060808587031215610795575f80fd5b61079e85610727565b93506107ac60208601610727565b92506107ba60408601610727565b9396929550929360600135925050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610807576108076107ca565b604052919050565b5f8060408385031215610820575f80fd5b61082983610727565b915060208084013567ffffffffffffffff80821115610846575f80fd5b818601915086601f830112610859575f80fd5b81358181111561086b5761086b6107ca565b61087d601f8201601f191685016107de565b91508082528784828501011115610892575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f5b838110156108c95781810151838201526020016108b1565b50505f910152565b5f81518084526108e88160208601602086016108af565b601f01601f19169290920160200192915050565b828152604060208201525f61091460408301846108d1565b949350505050565b5f67ffffffffffffffff821115610935576109356107ca565b5060051b60200190565b5f82601f83011261094e575f80fd5b8135602061096361095e8361091c565b6107de565b8083825260208201915060208460051b870101935086841115610984575f80fd5b602086015b848110156109a75761099a81610727565b8352918301918301610989565b509695505050505050565b8035600781900b811461073d575f80fd5b5f805f80608085870312156109d6575f80fd5b843567ffffffffffffffff808211156109ed575f80fd5b6109f98883890161093f565b9550602091508187013581811115610a0f575f80fd5b610a1b89828a0161093f565b955050604087013581811115610a2f575f80fd5b610a3b89828a0161093f565b945050606087013581811115610a4f575f80fd5b87019050601f81018813610a61575f80fd5b8035610a6f61095e8261091c565b81815260059190911b8201830190838101908a831115610a8d575f80fd5b928401925b82841015610ab257610aa3846109b2565b82529284019290840190610a92565b979a9699509497505050505050565b5f805f8060808587031215610ad4575f80fd5b610add85610727565b9350610aeb60208601610727565b9250610af960408601610727565b9150610b07606086016109b2565b905092959194509250565b634e487b7160e01b5f52603260045260245ffd5b5f8251610b378184602087016108af565b9190910192915050565b5f60208284031215610b51575f80fd5b81518060030b8114610b61575f80fd5b9392505050565b6001600160a01b0383168152604060208201525f61091460408301846108d1565b8215158152604060208201525f61091460408301846108d1565b602080825282518282018190525f919060409081850190868401855b82811015610c0a57815180516001600160a01b0390811686528782015181168887015286820151168686015260609081015160070b9085015260809093019290850190600101610bbf565b509197965050505050505056fea2646970667358221220f1a1f12b097858c4cc8e88d72e780efebeaca5729e9bf087780b4700756d2a9764736f6c63430008180033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061006f575f3560e01c80637e5fb7dc1161004d5780637e5fb7dc146100d25780638f68e13c146100e55780639b23d3d9146100f8575f80fd5b806304e74b561461007357806315dacbea1461009e578063618dc65e146100b1575b5f80fd5b610086610081366004610742565b61010b565b60405160079190910b81526020015b60405180910390f35b6100866100ac366004610782565b6101ca565b6100c46100bf36600461080f565b6102b9565b6040516100959291906108fc565b6100866100e03660046109c3565b6103d0565b6100866100f3366004610ac1565b610567565b610086610106366004610782565b61060f565b6040805160018082528183019092525f91829190816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610124575050604080516080810182525f606082018190526001600160a01b03898116835288811660208401528716928201929092528251929350918291849161019b5761019b610b12565b60200260200101819052506101af82610653565b9250600783900b6016146101c1575f80fd5b50509392505050565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790630aed65f560e11b9060a4015b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516102489190610b26565b5f604051808303815f865af19150503d805f8114610281576040519150601f19603f3d011682016040523d82523d5f602084013e610286565b606091505b5091509150816102975760156102ab565b808060200190518101906102ab9190610b41565b60030b979650505050505050565b5f60605f806101676001600160a01b031663618dc65e60e01b87876040516024016102e5929190610b68565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516103239190610b26565b5f604051808303815f865af19150503d805f811461035c576040519150601f19603f3d011682016040523d82523d5f602084013e610361565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc8282604051610397929190610b89565b60405180910390a1816103ba57601560405180602001604052805f8152506103be565b6016815b60039190910b97909650945050505050565b83515f90818167ffffffffffffffff8111156103ee576103ee6107ca565b60405190808252806020026020018201604052801561043e57816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f1990920191018161040c5790505b5090505f5b8281101561054157604080516080810182525f80825260208201819052918101829052606081019190915288828151811061048057610480610b12565b60209081029190910101516001600160a01b0316815287518890839081106104aa576104aa610b12565b6020908102919091018101516001600160a01b03169082015286518790839081106104d7576104d7610b12565b60209081029190910101516001600160a01b03166040820152855186908390811061050457610504610b12565b602090810291909101015160070b60608201528251819084908490811061052d5761052d610b12565b602090810291909101015250600101610443565b5061054b81610653565b9250600783900b60161461055d575f80fd5b5050949350505050565b6040805160018082528183019092525f91829190816020015b604080516080810182525f8082526020808301829052928201819052606082015282525f19909201910181610580575050604080516080810182526001600160a01b0389811682528881166020830152871691810191909152600785900b6060820152815191925090819083905f906105fb576105fb610b12565b602002602001018190525061054b82610653565b6040516001600160a01b038581166024830152848116604483015283166064820152608481018290525f908190819061016790639b23d3d960e01b9060a40161020a565b5f805f6101676001600160a01b031663012ebcaf60e01b8560405160240161067b9190610ba3565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516106b99190610b26565b5f604051808303815f865af19150503d805f81146106f2576040519150601f19603f3d011682016040523d82523d5f602084013e6106f7565b606091505b50915091508161070857601561071c565b8080602001905181019061071c9190610b41565b60030b949350505050565b80356001600160a01b038116811461073d575f80fd5b919050565b5f805f60608486031215610754575f80fd5b61075d84610727565b925061076b60208501610727565b915061077960408501610727565b90509250925092565b5f805f8060808587031215610795575f80fd5b61079e85610727565b93506107ac60208601610727565b92506107ba60408601610727565b9396929550929360600135925050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610807576108076107ca565b604052919050565b5f8060408385031215610820575f80fd5b61082983610727565b915060208084013567ffffffffffffffff80821115610846575f80fd5b818601915086601f830112610859575f80fd5b81358181111561086b5761086b6107ca565b61087d601f8201601f191685016107de565b91508082528784828501011115610892575f80fd5b80848401858401375f848284010152508093505050509250929050565b5f5b838110156108c95781810151838201526020016108b1565b50505f910152565b5f81518084526108e88160208601602086016108af565b601f01601f19169290920160200192915050565b828152604060208201525f61091460408301846108d1565b949350505050565b5f67ffffffffffffffff821115610935576109356107ca565b5060051b60200190565b5f82601f83011261094e575f80fd5b8135602061096361095e8361091c565b6107de565b8083825260208201915060208460051b870101935086841115610984575f80fd5b602086015b848110156109a75761099a81610727565b8352918301918301610989565b509695505050505050565b8035600781900b811461073d575f80fd5b5f805f80608085870312156109d6575f80fd5b843567ffffffffffffffff808211156109ed575f80fd5b6109f98883890161093f565b9550602091508187013581811115610a0f575f80fd5b610a1b89828a0161093f565b955050604087013581811115610a2f575f80fd5b610a3b89828a0161093f565b945050606087013581811115610a4f575f80fd5b87019050601f81018813610a61575f80fd5b8035610a6f61095e8261091c565b81815260059190911b8201830190838101908a831115610a8d575f80fd5b928401925b82841015610ab257610aa3846109b2565b82529284019290840190610a92565b979a9699509497505050505050565b5f805f8060808587031215610ad4575f80fd5b610add85610727565b9350610aeb60208601610727565b9250610af960408601610727565b9150610b07606086016109b2565b905092959194509250565b634e487b7160e01b5f52603260045260245ffd5b5f8251610b378184602087016108af565b9190910192915050565b5f60208284031215610b51575f80fd5b81518060030b8114610b61575f80fd5b9392505050565b6001600160a01b0383168152604060208201525f61091460408301846108d1565b8215158152604060208201525f61091460408301846108d1565b602080825282518282018190525f919060409081850190868401855b82811015610c0a57815180516001600160a01b0390811686528782015181168887015286820151168686015260609081015160070b9085015260809093019290850190600101610bbf565b509197965050505050505056fea2646970667358221220f1a1f12b097858c4cc8e88d72e780efebeaca5729e9bf087780b4700756d2a9764736f6c63430008180033", "linkReferences": {}, "deployedLinkReferences": {} } diff --git a/contracts-abi/contracts/system-contracts/hedera-token-service/examples/hrc-904/CancelAirdrop.sol/CancelAirdrop.json b/contracts-abi/contracts/system-contracts/hedera-token-service/examples/hrc-904/CancelAirdrop.sol/CancelAirdrop.json index 93492afc3..350cbbb35 100644 --- a/contracts-abi/contracts/system-contracts/hedera-token-service/examples/hrc-904/CancelAirdrop.sol/CancelAirdrop.json +++ b/contracts-abi/contracts/system-contracts/hedera-token-service/examples/hrc-904/CancelAirdrop.sol/CancelAirdrop.json @@ -70,7 +70,7 @@ "type": "int64[]" } ], - "name": "cancelAirdrops", + "name": "cancelMultipleAirdrops", "outputs": [ { "internalType": "int64", diff --git a/contracts/system-contracts/hedera-token-service/examples/hrc-904/CancelAirdrop.sol b/contracts/system-contracts/hedera-token-service/examples/hrc-904/CancelAirdrop.sol index f7866d63c..473f9559a 100644 --- a/contracts/system-contracts/hedera-token-service/examples/hrc-904/CancelAirdrop.sol +++ b/contracts/system-contracts/hedera-token-service/examples/hrc-904/CancelAirdrop.sol @@ -71,7 +71,7 @@ contract CancelAirdrop is HederaTokenService { // @param tokens Array of token addresses for the pending airdrops // @param serials Array of serial numbers for NFT airdrops (use 0 for fungible tokens) // @return responseCode The response code from the batch cancel operation (22 = success) - function cancelAirdrops(address[] memory senders, address[] memory receivers, address[] memory tokens, int64[] memory serials) public returns (int64 responseCode) { + function cancelMultipleAirdrops(address[] memory senders, address[] memory receivers, address[] memory tokens, int64[] memory serials) public returns (int64 responseCode) { uint length = senders.length; IHederaTokenService.PendingAirdrop[] memory pendingAirdrops = new IHederaTokenService.PendingAirdrop[](length); for (uint i = 0; i < length; i++) { diff --git a/test/constants.js b/test/constants.js index 1e07319ec..0e95bd36d 100644 --- a/test/constants.js +++ b/test/constants.js @@ -204,11 +204,15 @@ const Contract = { CancunOpcodes: 'CancunOpcodes', KZGPointEvaluation: 'KZGPointEvaluation', StateRegistry: 'StateRegistry', + Airdrop: 'Airdrop', + CancelAirdrop: 'CancelAirdrop', }; const CALL_EXCEPTION = 'CALL_EXCEPTION'; const CONTRACT_REVERT_EXECUTED_CODE = 3; const GAS_LIMIT_1_000_000 = { gasLimit: 1_000_000 }; +const GAS_LIMIT_2_000_000 = { gasLimit: 2_000_000 }; +const GAS_LIMIT_5_000_000 = { gasLimit: 5_000_000 }; const GAS_LIMIT_10_000_000 = { gasLimit: 10_000_000 }; const GAS_LIMIT_800000 = { gasLimit: 800000 }; const GAS_LIMIT_8000000 = { gasLimit: 8000000 }; @@ -222,6 +226,8 @@ const HOUR = 60 * MINUTE; const DAY = 24 * HOUR; const WEEK = 7 * DAY; const GWEI = 1e9; +const HTS_SYSTEM_CONTRACT_ADDRESS = '0.0.359'; +const HAS_SYSTEM_CONTRACT_ADDRESS = '0.0.362'; module.exports = { Events, @@ -230,6 +236,8 @@ module.exports = { CALL_EXCEPTION, CONTRACT_REVERT_EXECUTED_CODE, GAS_LIMIT_1_000_000, + GAS_LIMIT_2_000_000, + GAS_LIMIT_5_000_000, GAS_LIMIT_10_000_000, GAS_LIMIT_800000, GAS_LIMIT_8000000, @@ -244,4 +252,6 @@ module.exports = { WEEK, WEI, GWEI, + HTS_SYSTEM_CONTRACT_ADDRESS, + HAS_SYSTEM_CONTRACT_ADDRESS, }; diff --git a/test/system-contracts/hedera-token-service/hrc-904/CancelAirdropContract.js b/test/system-contracts/hedera-token-service/hrc-904/CancelAirdropContract.js new file mode 100644 index 000000000..8233c3778 --- /dev/null +++ b/test/system-contracts/hedera-token-service/hrc-904/CancelAirdropContract.js @@ -0,0 +1,381 @@ +const { expect } = require('chai'); +const { ethers } = require('hardhat'); +const utils = require('../utils'); +const Constants = require('../../../constants'); + +describe('HRC-904 CancelAirdropContract Test Suite', function () { + let airdropContract; + let cancelAirdropContract; + let tokenCreateContract; + let erc20Contract; + let erc721Contract; + let signers; + let owner; + let accounts; + let receiver; + let walletIHRC904AccountFacade; + + async function setupToken() { + const tokenAddress = + await utils.createFungibleTokenWithSECP256K1AdminKeyWithoutKYC( + tokenCreateContract, + owner, + utils.getSignerCompressedPublicKey() + ); + + await utils.updateTokenKeysViaHapi( + tokenAddress, + [ + await airdropContract.getAddress(), + await tokenCreateContract.getAddress(), + ], + true, + true, + false, + true, + true, + true, + false + ); + + await utils.associateToken( + tokenCreateContract, + tokenAddress, + Constants.Contract.TokenCreateContract + ); + + return tokenAddress; + } + + async function setupNft() { + const nftTokenAddress = + await utils.createNonFungibleTokenWithSECP256K1AdminKeyWithoutKYC( + tokenCreateContract, + owner, + utils.getSignerCompressedPublicKey() + ); + + await utils.updateTokenKeysViaHapi( + nftTokenAddress, + [ + await airdropContract.getAddress(), + await tokenCreateContract.getAddress(), + ], + true, + true, + false, + true, + true, + true, + false + ); + + await utils.associateToken( + tokenCreateContract, + nftTokenAddress, + Constants.Contract.TokenCreateContract + ); + + return nftTokenAddress; + } + + async function createPendingAirdrops(count) { + const senders = []; + const receivers = []; + const tokens = []; + const serials = []; + const amounts = []; + + for (let i = 0; i < count; i++) { + const tokenAddress = await setupToken(); + const ftAmount = BigInt(i + 1); // Different amount for each airdrop + + const airdropTx = await airdropContract.tokenAirdrop( + tokenAddress, + owner, + receiver, + ftAmount, + { + value: BigInt('850000000000000000'), + gasLimit: 2_000_000, + } + ); + await airdropTx.wait(); + + senders.push(owner); + receivers.push(receiver); + tokens.push(tokenAddress); + serials.push(0); // 0 for fungible tokens + amounts.push(ftAmount); + } + + return { senders, receivers, tokens, serials, amounts }; + } + + before(async function () { + signers = await ethers.getSigners(); + airdropContract = await utils.deployContract(Constants.Contract.Airdrop); + cancelAirdropContract = await utils.deployContract( + Constants.Contract.CancelAirdrop + ); + + receiver = new ethers.Wallet( + ethers.hexlify(ethers.randomBytes(32)) + ).connect(ethers.provider); + + // Send some HBAR to activate the account + await signers[0].sendTransaction({ + to: receiver.address, + value: ethers.parseEther('100'), + }); + tokenCreateContract = await utils.deployContract( + Constants.Contract.TokenCreateContract + ); + erc20Contract = await utils.deployContract( + Constants.Contract.ERC20Contract + ); + erc721Contract = await utils.deployContract( + Constants.Contract.ERC721Contract + ); + owner = signers[0].address; + accounts = signers.slice(1, 3).map((s) => s.address); + + await utils.updateAccountKeysViaHapi([ + await airdropContract.getAddress(), + await tokenCreateContract.getAddress(), + await cancelAirdropContract.getAddress(), + ]); + + tokenAddress = await setupToken(); + + const IHRC904AccountFacade = new ethers.Interface( + (await hre.artifacts.readArtifact('IHRC904AccountFacade')).abi + ); + + walletIHRC904AccountFacade = new ethers.Contract( + receiver.address, + IHRC904AccountFacade, + receiver + ); + + // Disabling automatic associations for receiver so all airdrops will be pending + const disableAutoAssociations = + await walletIHRC904AccountFacade.setUnlimitedAutomaticAssociations( + false, + { + gasLimit: 2_000_000, + } + ); + await disableAutoAssociations.wait(); + }); + + it('should cancel a single pending fungible token airdrop', async function () { + const ftAmount = BigInt(1); + const sender = signers[0].address; + const tokenAddress = await setupToken(); + + const initialBalance = await erc20Contract.balanceOf( + tokenAddress, + receiver.address + ); + + const airdropTx = await airdropContract.tokenAirdrop( + tokenAddress, + sender, + receiver.address, + ftAmount, + { + value: BigInt('850000000000000000'), + gasLimit: 2_000_000, + } + ); + await airdropTx.wait(); + + const cancelTx = await cancelAirdropContract.cancelAirdrop( + sender, + receiver.address, + tokenAddress, + Constants.GAS_LIMIT_2_000_000 + ); + await cancelTx.wait(); + + const updatedBalance = await erc20Contract.balanceOf( + tokenAddress, + receiver.address + ); + expect(updatedBalance).to.equal(initialBalance); + }); + + it('should cancel a single pending NFT airdrop', async function () { + const sender = signers[0].address; + const nftTokenAddress = await setupNft(); + + const serialNumber = await utils.mintNFTToAddress( + tokenCreateContract, + nftTokenAddress + ); + + const airdropTx = await airdropContract.nftAirdrop( + nftTokenAddress, + sender, + receiver.address, + serialNumber, + { + value: BigInt('850000000000000000'), + gasLimit: 2_000_000, + } + ); + await airdropTx.wait(); + + const cancelTx = await cancelAirdropContract.cancelNFTAirdrop( + sender, + receiver.address, + nftTokenAddress, + serialNumber, + Constants.GAS_LIMIT_2_000_000 + ); + await cancelTx.wait(); + + const nftOwner = await erc721Contract.ownerOf( + nftTokenAddress, + serialNumber + ); + expect(nftOwner).to.equal(sender); + }); + + it('should cancel multiple pending fungible token airdrops', async function () { + const numAirdrops = 10; + const { senders, receivers, tokens, serials, amounts } = + await createPendingAirdrops(numAirdrops); + + const initialBalances = await Promise.all( + tokens.map(async (token) => erc20Contract.balanceOf(token, receiver)) + ); + + const cancelTx = await cancelAirdropContract.cancelMultipleAirdrops( + senders, + receivers, + tokens, + serials, + Constants.GAS_LIMIT_2_000_000 + ); + await cancelTx.wait(); + + for (let i = 0; i < tokens.length; i++) { + const updatedBalance = await erc20Contract.balanceOf(tokens[i], receiver); + expect(updatedBalance).to.equal(initialBalances[i]); + } + }); + + it('should fail when sender has no pending airdrops', async function () { + const sender = signers[1].address; + const tokenAddress = await setupToken(); + + const tx = await cancelAirdropContract.cancelAirdrop( + sender, + receiver, + tokenAddress, + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('367'); // NO_PENDING_REWARD code + }); + + it('should fail when sender account is invalid', async function () { + const invalidSender = ethers.Wallet.createRandom().address; + const tokenAddress = await setupToken(); + + const tx = await cancelAirdropContract.cancelAirdrop( + invalidSender, + receiver, + tokenAddress, + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('15'); // INVALID_ACCOUNT_ID code + }); + + it('should fail when receiver account is invalid', async function () { + const invalidReceiver = ethers.Wallet.createRandom().address; + const tokenAddress = await setupToken(); + + const tx = await cancelAirdropContract.cancelAirdrop( + owner, + invalidReceiver, + tokenAddress, + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('367'); // INVALID_PENDING_AIRDROP_ID code + }); + + it('should fail when token does not exist', async function () { + const invalidToken = ethers.Wallet.createRandom().address; + + try { + const tx = await cancelAirdropContract.cancelAirdrop( + owner, + receiver, + invalidToken, + Constants.GAS_LIMIT_2_000_000 + ); + await tx.wait(); + expect.fail('Should revert'); + } catch (error) { + expect(error.shortMessage).to.eq('transaction execution reverted'); + } + }); + + it('should fail when NFT does not exist', async function () { + const invalidNftToken = ethers.Wallet.createRandom().address; + const serialNumber = 1; + + try { + const tx = await cancelAirdropContract.cancelNFTAirdrop( + owner, + receiver, + invalidNftToken, + serialNumber, + Constants.GAS_LIMIT_2_000_000 + ); + await tx.wait(); + expect.fail('Should revert'); + } catch (error) { + expect(error.shortMessage).to.eq('transaction execution reverted'); + } + }); + + it('should fail when more than 10 pending airdrops provided', async function () { + try { + const { senders, receivers, tokens, serials } = + await createPendingAirdrops(11); + + const tx = await cancelAirdropContract.cancelMultipleAirdrops( + senders, + receivers, + tokens, + serials, + Constants.GAS_LIMIT_2_000_000 + ); + await tx.wait(); + expect.fail('Should revert'); + } catch (error) { + expect(error.shortMessage).to.eq('transaction execution reverted'); + } + }); + + it('should fail when NFT serial number does not exist', async function () { + const nftTokenAddress = await setupNft(); + const invalidSerialNumber = 999; + + const tx = await cancelAirdropContract.cancelNFTAirdrop( + owner, + receiver, + nftTokenAddress, + invalidSerialNumber, + Constants.GAS_LIMIT_2_000_000 + ); + const responseCode = await utils.getHTSResponseCode(tx.hash); + expect(responseCode).to.eq('367'); // INVALID_PENDING_AIRDROP_ID code + }); +}); diff --git a/test/system-contracts/hedera-token-service/utils.js b/test/system-contracts/hedera-token-service/utils.js index e20b11a6b..7b90fb9e8 100644 --- a/test/system-contracts/hedera-token-service/utils.js +++ b/test/system-contracts/hedera-token-service/utils.js @@ -36,6 +36,10 @@ const { ContractInfoQuery, } = require('@hashgraph/sdk'); const Constants = require('../../constants'); +const axios = require('axios'); +const { + getMirrorNodeUrl, +} = require('../native/evm-compatibility-ecrecover/utils'); class Utils { //createTokenCost is cost for creating the token, which is passed to the system-contracts. This is equivalent of 40 and 60hbars, any excess hbars are refunded. @@ -65,143 +69,16 @@ class Utils { DELEGETABLE_CONTRACT_ID: 4, }; - static async deployERC20Mock() { - const erc20MockFactory = await ethers.getContractFactory( - Constants.Path.HIP583_ERC20Mock - ); - const erc20Mock = await erc20MockFactory.deploy( - Constants.GAS_LIMIT_1_000_000 - ); - - return await ethers.getContractAt( - Constants.Path.HIP583_ERC20Mock, - await erc20Mock.getAddress() - ); - } - - static async deployERC721Mock() { - const erc721MockFactory = await ethers.getContractFactory( - Constants.Path.HIP583_ERC721Mock - ); - const erc721Mock = await erc721MockFactory.deploy( - Constants.GAS_LIMIT_1_000_000 - ); - - return await ethers.getContractAt( - Constants.Path.HIP583_ERC721Mock, - await erc721Mock.getAddress() - ); - } - - static async deployTokenCreateContract() { - const tokenCreateFactory = await ethers.getContractFactory( - Constants.Contract.TokenCreateContract - ); - const tokenCreate = await tokenCreateFactory.deploy( - Constants.GAS_LIMIT_1_000_000 - ); - - return await ethers.getContractAt( - Constants.Contract.TokenCreateContract, - await tokenCreate.getAddress() - ); - } - - static async deployTokenCreateCustomContract() { - const tokenCreateCustomFactory = await ethers.getContractFactory( - Constants.Contract.TokenCreateCustomContract - ); - const tokenCreateCustom = await tokenCreateCustomFactory.deploy( - Constants.GAS_LIMIT_1_000_000 - ); - - return await ethers.getContractAt( - Constants.Contract.TokenCreateCustomContract, - await tokenCreateCustom.getAddress() - ); - } - - static async deployTokenManagementContract() { - const tokenManagementFactory = await ethers.getContractFactory( - Constants.Contract.TokenManagementContract - ); - const tokenManagement = await tokenManagementFactory.deploy( - Constants.GAS_LIMIT_1_000_000 - ); - - return await ethers.getContractAt( - Constants.Contract.TokenManagementContract, - await tokenManagement.getAddress() - ); - } - - static async deployTokenQueryContract() { - const tokenQueryFactory = await ethers.getContractFactory( - Constants.Contract.TokenQueryContract - ); - const tokenQuery = await tokenQueryFactory.deploy( - Constants.GAS_LIMIT_1_000_000 - ); - - return await ethers.getContractAt( - Constants.Contract.TokenQueryContract, - await tokenQuery.getAddress() - ); - } - - static async deployTokenTransferContract() { - const tokenTransferFactory = await ethers.getContractFactory( - Constants.Contract.TokenTransferContract - ); - const tokenTransfer = await tokenTransferFactory.deploy( - Constants.GAS_LIMIT_1_000_000 - ); - - return await ethers.getContractAt( - Constants.Contract.TokenTransferContract, - await tokenTransfer.getAddress() - ); - } - - static async deployHRC719Contract() { - const hrcContractFactory = await ethers.getContractFactory( - Constants.Contract.HRC719Contract - ); - const hrcContract = await hrcContractFactory.deploy( - Constants.GAS_LIMIT_1_000_000 - ); - - return await ethers.getContractAt( - Constants.Contract.HRC719Contract, - await hrcContract.getAddress() - ); - } - - static async deployERC20Contract() { - const erc20ContractFactory = await ethers.getContractFactory( - Constants.Contract.ERC20Contract - ); - const erc20Contract = await erc20ContractFactory.deploy( - Constants.GAS_LIMIT_1_000_000 - ); - - return await ethers.getContractAt( - Constants.Contract.ERC20Contract, - await erc20Contract.getAddress() - ); - } - - static async deployERC721Contract() { - const erc721ContractFactory = await ethers.getContractFactory( - Constants.Contract.ERC721Contract - ); - const erc721Contract = await erc721ContractFactory.deploy( - Constants.GAS_LIMIT_1_000_000 - ); + static async deployContract( + contractPath, + gasLimit = Constants.GAS_LIMIT_1_000_000 + ) { + const factory = await ethers.getContractFactory(contractPath); + const contract = await factory.deploy(gasLimit); return await ethers.getContractAt( - Constants.Contract.ERC721Contract, - await erc721Contract.getAddress() + contractPath, + await contract.getAddress() ); } @@ -942,6 +819,30 @@ class Utils { return; } } + + static async getHTSResponseCode(txHash) { + const network = hre.network.name; + const mirrorNodeUrl = getMirrorNodeUrl(network); + const res = await axios.get( + `${mirrorNodeUrl}/contracts/results/${txHash}/actions` + ); + const precompileAction = res.data.actions.find( + (x) => x.recipient === Constants.HTS_SYSTEM_CONTRACT_ADDRESS + ); + return BigInt(precompileAction.result_data).toString(); + } + + static async getHASResponseCode(txHash) { + const network = hre.network.name; + const mirrorNodeUrl = getMirrorNodeUrl(network); + const res = await axios.get( + `${mirrorNodeUrl}/contracts/results/${txHash}/actions` + ); + const precompileAction = res.data.actions.find( + (x) => x.recipient === Constants.HAS_SYSTEM_CONTRACT_ADDRESS + ); + return BigInt(precompileAction.result_data).toString(); + } } module.exports = Utils;