From 9060c474da522475c77d327817c190c007e754b9 Mon Sep 17 00:00:00 2001 From: snissn Date: Tue, 31 Jan 2023 19:13:13 -1000 Subject: [PATCH] test: fevm: add in tests for deploying, destroying contracts, recursive calls, sending value (#10082) adds the following tests to itests/fevm_test.go: - recursive tests - delegate call tests - delegate call recursive tests - revert tests - destruct tests - contract deploy address tests - send value to contracts - gas limit on value transfer tests - sending value to destroyed contracts adds the test to itests/fevm_address_test.go: - deploy contract and confirm address is different second deploy --- itests/contracts/AutoSelfDestruct.hex | 1 + itests/contracts/AutoSelfDestruct.sol | 11 + itests/contracts/Constructor.hex | 1 + itests/contracts/Constructor.sol | 29 ++ itests/contracts/DelegatecallStorage.hex | 2 +- itests/contracts/DelegatecallStorage.sol | 22 +- itests/contracts/GasLimitSend.hex | 1 + itests/contracts/GasLimitSend.sol | 34 ++ itests/contracts/GasSendTest.hex | 1 + itests/contracts/GasSendTest.sol | 9 + itests/contracts/NotPayable.hex | 1 + itests/contracts/NotPayable.sol | 7 + itests/contracts/Recursive.hex | 1 + itests/contracts/Recursive.sol | 26 ++ itests/contracts/RecursiveDelegeatecall.hex | 1 + itests/contracts/RecursiveDelegeatecall.sol | 21 + itests/contracts/SelfDestruct.hex | 1 + itests/contracts/SelfDestruct.sol | 8 + itests/contracts/TestApp.hex | 1 + itests/contracts/TestApp.sol | 211 ++++++++++ itests/contracts/ValueSender.hex | 1 + itests/contracts/ValueSender.sol | 54 +++ itests/contracts/compile.sh | 17 +- itests/eth_filter_test.go | 3 +- itests/fevm_address_test.go | 140 ++++--- itests/fevm_events_test.go | 9 +- itests/fevm_test.go | 442 ++++++++++++++++++-- itests/kit/evm.go | 77 +++- 28 files changed, 1036 insertions(+), 96 deletions(-) create mode 100644 itests/contracts/AutoSelfDestruct.hex create mode 100644 itests/contracts/AutoSelfDestruct.sol create mode 100644 itests/contracts/Constructor.hex create mode 100644 itests/contracts/Constructor.sol create mode 100644 itests/contracts/GasLimitSend.hex create mode 100644 itests/contracts/GasLimitSend.sol create mode 100644 itests/contracts/GasSendTest.hex create mode 100644 itests/contracts/GasSendTest.sol create mode 100644 itests/contracts/NotPayable.hex create mode 100644 itests/contracts/NotPayable.sol create mode 100644 itests/contracts/Recursive.hex create mode 100644 itests/contracts/Recursive.sol create mode 100644 itests/contracts/RecursiveDelegeatecall.hex create mode 100644 itests/contracts/RecursiveDelegeatecall.sol create mode 100644 itests/contracts/SelfDestruct.hex create mode 100644 itests/contracts/SelfDestruct.sol create mode 100644 itests/contracts/TestApp.hex create mode 100644 itests/contracts/TestApp.sol create mode 100644 itests/contracts/ValueSender.hex create mode 100644 itests/contracts/ValueSender.sol diff --git a/itests/contracts/AutoSelfDestruct.hex b/itests/contracts/AutoSelfDestruct.hex new file mode 100644 index 000000000..f5128bf30 --- /dev/null +++ b/itests/contracts/AutoSelfDestruct.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5061001f61002460201b60201c565b61003d565b3373ffffffffffffffffffffffffffffffffffffffff16ff5b60848061004b6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806383197ef014602d575b600080fd5b60336035565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea26469706673582212208d48a69a112633756d84552847610df29b02ac89dd39e4e295066e99a45e809664736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/AutoSelfDestruct.sol b/itests/contracts/AutoSelfDestruct.sol new file mode 100644 index 000000000..bdb165f5d --- /dev/null +++ b/itests/contracts/AutoSelfDestruct.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract AutoSelfDestruct { + constructor() { + destroy(); + } + function destroy() public { + selfdestruct(payable(msg.sender)); + } +} diff --git a/itests/contracts/Constructor.hex b/itests/contracts/Constructor.hex new file mode 100644 index 000000000..e46d5bcd1 --- /dev/null +++ b/itests/contracts/Constructor.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506103ca806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806358f5ebb614610030575b600080fd5b61004a60048036038101906100459190610123565b610060565b6040516100579190610191565b60405180910390f35b60008082604051610070906100db565b61007a91906101bb565b604051809103906000f080158015610096573d6000803e3d6000fd5b5090507f3a5c468996b00310e3e82919e3af9cce21d49c40c39a2627a9f946e1a54d886232846040516100ca9291906101d6565b60405180910390a180915050919050565b6101958061020083390190565b600080fd5b6000819050919050565b610100816100ed565b811461010b57600080fd5b50565b60008135905061011d816100f7565b92915050565b600060208284031215610139576101386100e8565b5b60006101478482850161010e565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061017b82610150565b9050919050565b61018b81610170565b82525050565b60006020820190506101a66000830184610182565b92915050565b6101b5816100ed565b82525050565b60006020820190506101d060008301846101ac565b92915050565b60006040820190506101eb6000830185610182565b6101f860208301846101ac565b939250505056fe608060405234801561001057600080fd5b506040516101953803806101958339818101604052810190610032919061007a565b80600081905550506100a7565b600080fd5b6000819050919050565b61005781610044565b811461006257600080fd5b50565b6000815190506100748161004e565b92915050565b6000602082840312156100905761008f61003f565b5b600061009e84828501610065565b91505092915050565b60e0806100b56000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80638381f58a146037578063eeb4e367146051575b600080fd5b603d606b565b604051604891906091565b60405180910390f35b60576071565b604051606291906091565b60405180910390f35b60005481565b60008054905090565b6000819050919050565b608b81607a565b82525050565b600060208201905060a460008301846084565b9291505056fea2646970667358221220451c388f24a935fc5f5eef536207cbd982254ac8521d49937bb10e5079e3924164736f6c63430008110033a264697066735822122027da159d84a9bdcd5aff5755c4602f7099db638f7a95d715c76454c99511146f64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/Constructor.sol b/itests/contracts/Constructor.sol new file mode 100644 index 000000000..a85d13269 --- /dev/null +++ b/itests/contracts/Constructor.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; + + +contract Test_contract { + uint256 public number; + + constructor(uint256 _number) { + number = _number; + } + + function get_number() public view returns (uint256) { + return number; + } +} + +contract App { + + event NewTest(address sender, uint256 number); + + function new_Test(uint256 number) + public + returns (address) + { + address mynew = address(new Test_contract({_number: number})); + emit NewTest(tx.origin, number); + return mynew; + } +} diff --git a/itests/contracts/DelegatecallStorage.hex b/itests/contracts/DelegatecallStorage.hex index 7ce9ef210..966e9e906 100644 --- a/itests/contracts/DelegatecallStorage.hex +++ b/itests/contracts/DelegatecallStorage.hex @@ -1 +1 @@ -608060405234801561001057600080fd5b50610477806100206000396000f3fe6080604052600436106100345760003560e01c806361bc221a146100395780638ada066e14610064578063d1e0f3081461008f575b600080fd5b34801561004557600080fd5b5061004e6100bf565b60405161005b919061022c565b60405180910390f35b34801561007057600080fd5b506100796100c5565b604051610086919061022c565b60405180910390f35b6100a960048036038101906100a491906102d6565b6100ce565b6040516100b6919061022c565b60405180910390f35b60005481565b60008054905090565b6000808373ffffffffffffffffffffffffffffffffffffffff16836040516024016100f9919061022c565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101839190610387565b600060405180830381855af49150503d80600081146101be576040519150601f19603f3d011682016040523d82523d6000602084013e6101c3565b606091505b5050905080610207576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101fe90610421565b60405180910390fd5b60005491505092915050565b6000819050919050565b61022681610213565b82525050565b6000602082019050610241600083018461021d565b92915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102778261024c565b9050919050565b6102878161026c565b811461029257600080fd5b50565b6000813590506102a48161027e565b92915050565b6102b381610213565b81146102be57600080fd5b50565b6000813590506102d0816102aa565b92915050565b600080604083850312156102ed576102ec610247565b5b60006102fb85828601610295565b925050602061030c858286016102c1565b9150509250929050565b600081519050919050565b600081905092915050565b60005b8381101561034a57808201518184015260208101905061032f565b60008484015250505050565b600061036182610316565b61036b8185610321565b935061037b81856020860161032c565b80840191505092915050565b60006103938284610356565b915081905092915050565b600082825260208201905092915050565b7f4572726f72206d6573736167653a2044656c656761746563616c6c206661696c60008201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b600061040b60228361039e565b9150610416826103af565b604082019050919050565b6000602082019050818103600083015261043a816103fe565b905091905056fea26469706673582212203663909b8221e9b87047be99420c00339af1430c085260df209b909ed8e0f05164736f6c63430008110033 \ No newline at end of file +608060405234801561001057600080fd5b5061087e806100206000396000f3fe6080604052600436106100555760003560e01c80630712ede21461005a57806361bc221a1461008a5780637da3c3ab146100b55780638ada066e146100cc578063bed56f47146100f7578063d1e0f30814610127575b600080fd5b610074600480360381019061006f919061060f565b610157565b604051610081919061065e565b60405180910390f35b34801561009657600080fd5b5061009f610298565b6040516100ac919061065e565b60405180910390f35b3480156100c157600080fd5b506100ca61029e565b005b3480156100d857600080fd5b506100e16102e1565b6040516100ee919061065e565b60405180910390f35b610111600480360381019061010c919061060f565b6102ea565b60405161011e919061065e565b60405180910390f35b610141600480360381019061013c919061060f565b610431565b60405161014e919061065e565b60405180910390f35b6000808373ffffffffffffffffffffffffffffffffffffffff1683604051602401610182919061065e565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161020c91906106ea565b600060405180830381855af49150503d8060008114610247576040519150601f19603f3d011682016040523d82523d6000602084013e61024c565b606091505b505090506000610291576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102889061075e565b60405180910390fd5b5092915050565b60005481565b60006102df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102d69061075e565b60405180910390fd5b565b60008054905090565b6000808373ffffffffffffffffffffffffffffffffffffffff16848460405160240161031792919061078d565b6040516020818303038152906040527fbed56f47000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516103a191906106ea565b600060405180830381855af49150503d80600081146103dc576040519150601f19603f3d011682016040523d82523d6000602084013e6103e1565b606091505b5050905080610425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161041c90610828565b60405180910390fd5b60005491505092915050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160240161045c919061065e565b6040516020818303038152906040527f6466414b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516104e691906106ea565b600060405180830381855af49150503d8060008114610521576040519150601f19603f3d011682016040523d82523d6000602084013e610526565b606091505b505090508061056a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161056190610828565b60405180910390fd5b60005491505092915050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006105a68261057b565b9050919050565b6105b68161059b565b81146105c157600080fd5b50565b6000813590506105d3816105ad565b92915050565b6000819050919050565b6105ec816105d9565b81146105f757600080fd5b50565b600081359050610609816105e3565b92915050565b6000806040838503121561062657610625610576565b5b6000610634858286016105c4565b9250506020610645858286016105fa565b9150509250929050565b610658816105d9565b82525050565b6000602082019050610673600083018461064f565b92915050565b600081519050919050565b600081905092915050565b60005b838110156106ad578082015181840152602081019050610692565b60008484015250505050565b60006106c482610679565b6106ce8185610684565b93506106de81856020860161068f565b80840191505092915050565b60006106f682846106b9565b915081905092915050565b600082825260208201905092915050565b7f696e74656e74696f6e616c6c79207468726f77696e67206572726f7200000000600082015250565b6000610748601c83610701565b915061075382610712565b602082019050919050565b600060208201905081810360008301526107778161073b565b9050919050565b6107878161059b565b82525050565b60006040820190506107a2600083018561077e565b6107af602083018461064f565b9392505050565b7f4572726f72206d6573736167653a2044656c656761746563616c6c206661696c60008201527f6564000000000000000000000000000000000000000000000000000000000000602082015250565b6000610812602283610701565b915061081d826107b6565b604082019050919050565b6000602082019050818103600083015261084181610805565b905091905056fea2646970667358221220b2a3ae7e2a9ffc78e3e2a7aadb2885435c5e51aa9d3f07372a0dffb6238aa1db64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/DelegatecallStorage.sol b/itests/contracts/DelegatecallStorage.sol index 434cd934e..15e672082 100644 --- a/itests/contracts/DelegatecallStorage.sol +++ b/itests/contracts/DelegatecallStorage.sol @@ -5,13 +5,29 @@ contract DelegatecallStorage { uint public counter; function getCounter() public view returns (uint){ - return counter; + return counter; } function setVars(address _contract, uint _counter) public payable returns (uint){ + (bool success, ) = _contract.delegatecall( + abi.encodeWithSignature("setVars(uint256)", _counter) + ); + require(success, 'Error message: Delegatecall failed'); + return counter; + } + function setVarsSelf(address _contract, uint _counter) public payable returns (uint){ + (bool success, ) = _contract.delegatecall( + abi.encodeWithSignature("setVarsSelf(address,uint256)", _contract, _counter) + ); + require(success, 'Error message: Delegatecall failed'); + return counter; + } + function setVarsRevert(address _contract, uint _counter) public payable returns (uint){ (bool success, ) = _contract.delegatecall( abi.encodeWithSignature("setVars(uint256)", _counter) ); - require(success, 'Error message: Delegatecall failed'); - return counter; + require(false,"intentionally throwing error"); + } + function revert() public{ + require(false,"intentionally throwing error"); } } diff --git a/itests/contracts/GasLimitSend.hex b/itests/contracts/GasLimitSend.hex new file mode 100644 index 000000000..ac4927d38 --- /dev/null +++ b/itests/contracts/GasLimitSend.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5061027c806100206000396000f3fe6080604052600436106100385760003560e01c80630bc07a88146100435780633da767881461005a578063f0ba84401461008557610039565b5b6100416100c2565b005b34801561004f57600080fd5b506100586100c2565b005b34801561006657600080fd5b5061006f61010d565b60405161007c9190610156565b60405180910390f35b34801561009157600080fd5b506100ac60048036038101906100a791906101a2565b610119565b6040516100b99190610156565b60405180910390f35b60005b606481101561010a5760008190806001815401808255809150506001900390600052602060002001600090919091909150558080610102906101fe565b9150506100c5565b50565b60008080549050905090565b6000818154811061012957600080fd5b906000526020600020016000915090505481565b6000819050919050565b6101508161013d565b82525050565b600060208201905061016b6000830184610147565b92915050565b600080fd5b61017f8161013d565b811461018a57600080fd5b50565b60008135905061019c81610176565b92915050565b6000602082840312156101b8576101b7610171565b5b60006101c68482850161018d565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006102098261013d565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361023b5761023a6101cf565b5b60018201905091905056fea2646970667358221220c56d78e0c60a01681eee1b76c95e7b214d16a512c944e31cfee71eb727c1e44064736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/GasLimitSend.sol b/itests/contracts/GasLimitSend.sol new file mode 100644 index 000000000..b5a91e14d --- /dev/null +++ b/itests/contracts/GasLimitSend.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract GasLimitTest { + address payable receiver; + constructor(){ + address mynew = address(new GasLimitTestReceiver()); + receiver = payable(mynew); + } + function send() public payable{ + receiver.transfer(msg.value); + } + function expensiveTest() public{ + GasLimitTestReceiver(receiver).expensive(); + } + function getDataLength() public returns (uint256) { + return GasLimitTestReceiver(receiver).getDataLength(); + } +} + +contract GasLimitTestReceiver { + uint256[] public data; + fallback() external payable { + expensive(); + } + function expensive() public{ + for (uint256 i = 0; i < 100; i++) { + data.push(i); + } + } + function getDataLength() public view returns (uint256) { + return data.length; + } +} diff --git a/itests/contracts/GasSendTest.hex b/itests/contracts/GasSendTest.hex new file mode 100644 index 000000000..b41be3463 --- /dev/null +++ b/itests/contracts/GasSendTest.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c80630c55699c14602d575b600080fd5b60336047565b604051603e91906067565b60405180910390f35b60006007905090565b6000819050919050565b6061816050565b82525050565b6000602082019050607a6000830184605a565b9291505056fea2646970667358221220c0f2da1b01178b54afba1ddf14f30307a03cdb66f61b4e1dc342079561db009064736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/GasSendTest.sol b/itests/contracts/GasSendTest.sol new file mode 100644 index 000000000..b422bda26 --- /dev/null +++ b/itests/contracts/GasSendTest.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract GasLimitTestReceiver { + function x() public returns (uint256){ + return 7; + } +} + diff --git a/itests/contracts/NotPayable.hex b/itests/contracts/NotPayable.hex new file mode 100644 index 000000000..c08070029 --- /dev/null +++ b/itests/contracts/NotPayable.hex @@ -0,0 +1 @@ +6080604052348015600f57600080fd5b50604780601d6000396000f3fe6080604052348015600f57600080fd5b00fea26469706673582212200cd38951eddebe3692dc8921afb65a04fbe64e10d5e261806330156459bf227264736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/NotPayable.sol b/itests/contracts/NotPayable.sol new file mode 100644 index 000000000..9b9a06e08 --- /dev/null +++ b/itests/contracts/NotPayable.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +//sending eth should fall because fallback is not payable +contract NotPayable { + fallback() external {} +} diff --git a/itests/contracts/Recursive.hex b/itests/contracts/Recursive.hex new file mode 100644 index 000000000..b211aafd9 --- /dev/null +++ b/itests/contracts/Recursive.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506102d9806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063032cec451461005c57806372536f3c1461007a57806399fdb86e14610098578063d2aac3ea146100b6578063ec49254c146100d4575b600080fd5b610064610104565b60405161007191906101c7565b60405180910390f35b610082610115565b60405161008f91906101c7565b60405180910390f35b6100a0610126565b6040516100ad91906101c7565b60405180910390f35b6100be610137565b6040516100cb91906101c7565b60405180910390f35b6100ee60048036038101906100e99190610213565b610148565b6040516100fb91906101c7565b60405180910390f35b60006101106001610148565b905090565b6000610121600a610148565b905090565b60006101326002610148565b905090565b60006101436000610148565b905090565b6000808211156101a5577f3110e0ccd510fcbb471c933ad12161c459e8735b5bde2eea61a659c2e2f0a3cc8260405161018191906101c7565b60405180910390a161019e600183610199919061026f565b610148565b90506101a9565b8190505b919050565b6000819050919050565b6101c1816101ae565b82525050565b60006020820190506101dc60008301846101b8565b92915050565b600080fd5b6101f0816101ae565b81146101fb57600080fd5b50565b60008135905061020d816101e7565b92915050565b600060208284031215610229576102286101e2565b5b6000610237848285016101fe565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061027a826101ae565b9150610285836101ae565b925082820390508181111561029d5761029c610240565b5b9291505056fea26469706673582212206178e15eb87e2f766b94ec09a6a860878c93d72a31de225e1684da1755f917c764736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/Recursive.sol b/itests/contracts/Recursive.sol new file mode 100644 index 000000000..aa8fe62b0 --- /dev/null +++ b/itests/contracts/Recursive.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract Recursive { + event RecursiveCallEvent(uint256 count); + + function recursive10() public returns (uint256){ + return recursiveCall(10); + } + function recursive2() public returns (uint256){ + return recursiveCall(2); + } + function recursive1() public returns (uint256){ + return recursiveCall(1); + } + function recursive0() public returns (uint256){ + return recursiveCall(0); + } + function recursiveCall(uint256 count) public returns (uint256) { + if (count > 0) { + emit RecursiveCallEvent(count); + return recursiveCall(count-1); + } + return count; + } +} diff --git a/itests/contracts/RecursiveDelegeatecall.hex b/itests/contracts/RecursiveDelegeatecall.hex new file mode 100644 index 000000000..d8337c258 --- /dev/null +++ b/itests/contracts/RecursiveDelegeatecall.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50610459806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80633af3f24f1461003b578063ec49254c14610059575b600080fd5b610043610089565b6040516100509190610221565b60405180910390f35b610073600480360381019061006e919061026d565b61008f565b6040516100809190610221565b60405180910390f35b60005481565b60007faab69767807d0ab32f0099452739da31b76ecd3e8694bb49898829c8bf9d063582306040516100c29291906102db565b60405180910390a160016000808282546100dc9190610333565b9250508190555060018211156101ff576001826100f99190610367565b91506000803073ffffffffffffffffffffffffffffffffffffffff16846040516024016101269190610221565b6040516020818303038152906040527fec49254c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101b0919061040c565b600060405180830381855af49150503d80600081146101eb576040519150601f19603f3d011682016040523d82523d6000602084013e6101f0565b606091505b50915091508392505050610203565b8190505b919050565b6000819050919050565b61021b81610208565b82525050565b60006020820190506102366000830184610212565b92915050565b600080fd5b61024a81610208565b811461025557600080fd5b50565b60008135905061026781610241565b92915050565b6000602082840312156102835761028261023c565b5b600061029184828501610258565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102c58261029a565b9050919050565b6102d5816102ba565b82525050565b60006040820190506102f06000830185610212565b6102fd60208301846102cc565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061033e82610208565b915061034983610208565b925082820190508082111561036157610360610304565b5b92915050565b600061037282610208565b915061037d83610208565b925082820390508181111561039557610394610304565b5b92915050565b600081519050919050565b600081905092915050565b60005b838110156103cf5780820151818401526020810190506103b4565b60008484015250505050565b60006103e68261039b565b6103f081856103a6565b93506104008185602086016103b1565b80840191505092915050565b600061041882846103db565b91508190509291505056fea2646970667358221220e70fbbfaccd3fbb084623d6d06895fba1abc5fefc181215b56ab1e43db79c7fb64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/RecursiveDelegeatecall.sol b/itests/contracts/RecursiveDelegeatecall.sol new file mode 100644 index 000000000..cd1b693c0 --- /dev/null +++ b/itests/contracts/RecursiveDelegeatecall.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract RecursiveDelegatecall { + event RecursiveCallEvent(uint256 count, address self); + uint256 public totalCalls; + + function recursiveCall(uint256 count) public returns (uint256) { + emit RecursiveCallEvent(count, address(this)); + totalCalls += 1; + if (count > 1) { + count -= 1; + (bool success, bytes memory returnedData) = address(this) + .delegatecall( + abi.encodeWithSignature("recursiveCall(uint256)", count) + ); + return count; + } + return count; + } +} diff --git a/itests/contracts/SelfDestruct.hex b/itests/contracts/SelfDestruct.hex new file mode 100644 index 000000000..c2f91b803 --- /dev/null +++ b/itests/contracts/SelfDestruct.hex @@ -0,0 +1 @@ +6080604052348015600f57600080fd5b5060848061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806383197ef014602d575b600080fd5b60336035565b005b3373ffffffffffffffffffffffffffffffffffffffff16fffea2646970667358221220d4aa109d42268586e7ce4f0fafb0ebbd04c412c6c7e8c387b009a08ecdff864264736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/SelfDestruct.sol b/itests/contracts/SelfDestruct.sol new file mode 100644 index 000000000..6c4ff9188 --- /dev/null +++ b/itests/contracts/SelfDestruct.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract SelfDestruct { + function destroy() public { + selfdestruct(payable(msg.sender)); + } +} diff --git a/itests/contracts/TestApp.hex b/itests/contracts/TestApp.hex new file mode 100644 index 000000000..bf1830071 --- /dev/null +++ b/itests/contracts/TestApp.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b50612e80806100206000396000f3fe60806040523480156200001157600080fd5b5060043610620000a05760003560e01c8063883a8410116200006f578063883a84101462000181578063c483289114620001bb578063d65c239c14620001dd578063dc33b0041462000213578063eae185c4146200024b57620000a0565b806308eaae9614620000a5578063120f83c414620000db5780632db0de8514620001115780637f823290146200014b575b600080fd5b620000c36004803603810190620000bd919062001a74565b62000281565b604051620000d2919062001b1f565b60405180910390f35b620000f96004803603810190620000f3919062001b6d565b620005b4565b60405162000108919062001bb0565b60405180910390f35b6200012f600480360381019062000129919062001bcd565b62000600565b6040516200014295949392919062001c88565b60405180910390f35b62000169600480360381019062000163919062001cec565b620006d3565b60405162000178919062001f0c565b60405180910390f35b6200019f600480360381019062000199919062001f30565b62000d53565b604051620001b295949392919062001c88565b60405180910390f35b620001c562000e68565b604051620001d4919062001bb0565b60405180910390f35b620001fb6004803603810190620001f5919062001f77565b62000e72565b6040516200020a919062001f0c565b60405180910390f35b6200023160048036038101906200022b919062001b6d565b6200127e565b604051620002429392919062001fdb565b60405180910390f35b62000269600480360381019062000263919062001f77565b620012d5565b60405162000278919062001f0c565b60405180910390f35b600080838360405162000294906200176c565b620002a192919062002018565b604051809103906000f080158015620002be573d6000803e3d6000fd5b509050600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000160149054906101000a900460ff16620003f4576200032181620016ba565b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff0219169083151502179055506040820151816001019080519060200190620003e59291906200177a565b50606082015181600201559050505b600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600260003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206002016000828254620004ec91906200207b565b925050819055506000819080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060018060008282546200056a91906200207b565b925050819055507f1e91349225b89f401c5f81de959b2a1cbc472147eeefbf4e367a6b7d2dfcd3bc32604051620005a2919062001b1f565b60405180910390a18091505092915050565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600201549050919050565b6000806000606060008086815481106200061f576200061e620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663909747956040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000695573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620006c0919062002191565b9450945094509450945091939590929450565b606060008367ffffffffffffffff811115620006f457620006f3620018f2565b5b6040519080825280602002602001820160405280156200073157816020015b6200071d62001809565b815260200190600190039081620007135790505b50905060008390505b8481101562000d4757600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010184826200079391906200207b565b81548110620007a757620007a6620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828583620007e1919062002238565b81518110620007f557620007f4620020b6565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010184826200088391906200207b565b81548110620008975762000896620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16632212dbc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200090d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000933919062002273565b82858362000942919062002238565b81518110620009565762000955620020b6565b5b60200260200101516020018181525050600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001018482620009b691906200207b565b81548110620009ca57620009c9620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a8d509ff6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000a40573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000a669190620022a5565b82858362000a75919062002238565b8151811062000a895762000a88620020b6565b5b60200260200101516040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101848262000b1791906200207b565b8154811062000b2b5762000b2a620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16630cb1851a6040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000ba1573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019062000bcc9190620022d7565b82858362000bdb919062002238565b8151811062000bef5762000bee620020b6565b5b602002602001015160600181905250600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101848262000c4e91906200207b565b8154811062000c625762000c61620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663eeb4e3676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000cd8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000cfe919062002273565b82858362000d0d919062002238565b8151811062000d215762000d20620020b6565b5b60200260200101516080018181525050808062000d3e9062002328565b9150506200073a565b50809150509392505050565b600080600060606000600260008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600101868154811062000db35762000db2620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663909747956040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000e29573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019062000e54919062002191565b945094509450945094509295509295909350565b6000600154905090565b606060008367ffffffffffffffff81111562000e935762000e92620018f2565b5b60405190808252806020026020018201604052801562000ed057816020015b62000ebc62001809565b81526020019060019003908162000eb25790505b50905060008390505b848110156200127357600080858362000ef391906200207b565b8154811062000f075762000f06620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508083868462000f44919062002238565b8151811062000f585762000f57620020b6565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16632212dbc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000fe2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001008919062002273565b83868462001017919062002238565b815181106200102b576200102a620020b6565b5b602002602001015160200181815250508073ffffffffffffffffffffffffffffffffffffffff1663a8d509ff6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001087573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620010ad9190620022a5565b838684620010bc919062002238565b81518110620010d057620010cf620020b6565b5b60200260200101516040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16630cb1851a6040518163ffffffff1660e01b8152600401600060405180830381865afa1580156200115a573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620011859190620022d7565b83868462001194919062002238565b81518110620011a857620011a7620020b6565b5b6020026020010151606001819052508073ffffffffffffffffffffffffffffffffffffffff1663eeb4e3676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001203573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001229919062002273565b83868462001238919062002238565b815181106200124c576200124b620020b6565b5b602002602001015160800181815250505080806200126a9062002328565b91505062000ed9565b508091505092915050565b60026020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900460ff16908060020154905083565b606060008367ffffffffffffffff811115620012f657620012f5620018f2565b5b6040519080825280602002602001820160405280156200133357816020015b6200131f62001809565b815260200190600190039081620013155790505b50905060005b84811015620016af576000806001868460015462001358919062002238565b62001364919062002238565b62001370919062002238565b81548110620013845762001383620020b6565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905080838381518110620013c857620013c7620020b6565b5b60200260200101516000019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16632212dbc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801562001452573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001478919062002273565b8383815181106200148e576200148d620020b6565b5b602002602001015160200181815250508073ffffffffffffffffffffffffffffffffffffffff1663a8d509ff6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620014ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620015109190620022a5565b838381518110620015265762001525620020b6565b5b60200260200101516040019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff16630cb1851a6040518163ffffffff1660e01b8152600401600060405180830381865afa158015620015b0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620015db9190620022d7565b838381518110620015f157620015f0620020b6565b5b6020026020010151606001819052508073ffffffffffffffffffffffffffffffffffffffff1663eeb4e3676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200164c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001672919062002273565b838381518110620016885762001687620020b6565b5b60200260200101516080018181525050508080620016a69062002328565b91505062001339565b508091505092915050565b620016c462001864565b60606003839080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060405180608001604052808473ffffffffffffffffffffffffffffffffffffffff1681526020016001151581526020018281526020016000815250915050919050565b610ad5806200237683390190565b828054828255906000526020600020908101928215620017f6579160200282015b82811115620017f55782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906200179b565b5b509050620018059190620018a4565b5090565b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001600081525090565b6040518060800160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160001515815260200160608152602001600081525090565b5b80821115620018bf576000816000905550600101620018a5565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200192c82620018e1565b810181811067ffffffffffffffff821117156200194e576200194d620018f2565b5b80604052505050565b600062001963620018c3565b905062001971828262001921565b919050565b600067ffffffffffffffff821115620019945762001993620018f2565b5b6200199f82620018e1565b9050602081019050919050565b82818337600083830152505050565b6000620019d2620019cc8462001976565b62001957565b905082815260208101848484011115620019f157620019f0620018dc565b5b620019fe848285620019ac565b509392505050565b600082601f83011262001a1e5762001a1d620018d7565b5b813562001a30848260208601620019bb565b91505092915050565b6000819050919050565b62001a4e8162001a39565b811462001a5a57600080fd5b50565b60008135905062001a6e8162001a43565b92915050565b6000806040838503121562001a8e5762001a8d620018cd565b5b600083013567ffffffffffffffff81111562001aaf5762001aae620018d2565b5b62001abd8582860162001a06565b925050602062001ad08582860162001a5d565b9150509250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062001b078262001ada565b9050919050565b62001b198162001afa565b82525050565b600060208201905062001b36600083018462001b0e565b92915050565b62001b478162001afa565b811462001b5357600080fd5b50565b60008135905062001b678162001b3c565b92915050565b60006020828403121562001b865762001b85620018cd565b5b600062001b968482850162001b56565b91505092915050565b62001baa8162001a39565b82525050565b600060208201905062001bc7600083018462001b9f565b92915050565b60006020828403121562001be65762001be5620018cd565b5b600062001bf68482850162001a5d565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101562001c3b57808201518184015260208101905062001c1e565b60008484015250505050565b600062001c548262001bff565b62001c60818562001c0a565b935062001c7281856020860162001c1b565b62001c7d81620018e1565b840191505092915050565b600060a08201905062001c9f600083018862001b0e565b62001cae602083018762001b9f565b62001cbd604083018662001b0e565b818103606083015262001cd1818562001c47565b905062001ce2608083018462001b9f565b9695505050505050565b60008060006060848603121562001d085762001d07620018cd565b5b600062001d188682870162001b56565b935050602062001d2b8682870162001a5d565b925050604062001d3e8682870162001a5d565b9150509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b62001d7f8162001afa565b82525050565b62001d908162001a39565b82525050565b600082825260208201905092915050565b600062001db48262001bff565b62001dc0818562001d96565b935062001dd281856020860162001c1b565b62001ddd81620018e1565b840191505092915050565b600060a08301600083015162001e02600086018262001d74565b50602083015162001e17602086018262001d85565b50604083015162001e2c604086018262001d74565b506060830151848203606086015262001e46828262001da7565b915050608083015162001e5d608086018262001d85565b508091505092915050565b600062001e76838362001de8565b905092915050565b6000602082019050919050565b600062001e988262001d48565b62001ea4818562001d53565b93508360208202850162001eb88562001d64565b8060005b8581101562001efa578484038952815162001ed8858262001e68565b945062001ee58362001e7e565b925060208a0199505060018101905062001ebc565b50829750879550505050505092915050565b6000602082019050818103600083015262001f28818462001e8b565b905092915050565b6000806040838503121562001f4a5762001f49620018cd565b5b600062001f5a8582860162001b56565b925050602062001f6d8582860162001a5d565b9150509250929050565b6000806040838503121562001f915762001f90620018cd565b5b600062001fa18582860162001a5d565b925050602062001fb48582860162001a5d565b9150509250929050565b60008115159050919050565b62001fd58162001fbe565b82525050565b600060608201905062001ff2600083018662001b0e565b62002001602083018562001fca565b62002010604083018462001b9f565b949350505050565b6000604082019050818103600083015262002034818562001c47565b905062002045602083018462001b9f565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000620020888262001a39565b9150620020958362001a39565b9250828201905080821115620020b057620020af6200204c565b5b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050620020f68162001b3c565b92915050565b6000815190506200210d8162001a43565b92915050565b60006200212a620021248462001976565b62001957565b905082815260208101848484011115620021495762002148620018dc565b5b6200215684828562001c1b565b509392505050565b600082601f830112620021765762002175620018d7565b5b81516200218884826020860162002113565b91505092915050565b600080600080600060a08688031215620021b057620021af620018cd565b5b6000620021c088828901620020e5565b9550506020620021d388828901620020fc565b9450506040620021e688828901620020e5565b935050606086015167ffffffffffffffff8111156200220a5762002209620018d2565b5b62002218888289016200215e565b92505060806200222b88828901620020fc565b9150509295509295909350565b6000620022458262001a39565b9150620022528362001a39565b92508282039050818111156200226d576200226c6200204c565b5b92915050565b6000602082840312156200228c576200228b620018cd565b5b60006200229c84828501620020fc565b91505092915050565b600060208284031215620022be57620022bd620018cd565b5b6000620022ce84828501620020e5565b91505092915050565b600060208284031215620022f057620022ef620018cd565b5b600082015167ffffffffffffffff811115620023115762002310620018d2565b5b6200231f848285016200215e565b91505092915050565b6000620023358262001a39565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036200236a57620023696200204c565b5b60018201905091905056fe60806040523480156200001157600080fd5b5060405162000ad538038062000ad583398181016040528101906200003791906200026e565b32600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555042600081905550816002908162000090919062000515565b50806003819055505050620005fc565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200010982620000be565b810181811067ffffffffffffffff821117156200012b576200012a620000cf565b5b80604052505050565b600062000140620000a0565b90506200014e8282620000fe565b919050565b600067ffffffffffffffff821115620001715762000170620000cf565b5b6200017c82620000be565b9050602081019050919050565b60005b83811015620001a95780820151818401526020810190506200018c565b60008484015250505050565b6000620001cc620001c68462000153565b62000134565b905082815260208101848484011115620001eb57620001ea620000b9565b5b620001f884828562000189565b509392505050565b600082601f830112620002185762000217620000b4565b5b81516200022a848260208601620001b5565b91505092915050565b6000819050919050565b620002488162000233565b81146200025457600080fd5b50565b60008151905062000268816200023d565b92915050565b60008060408385031215620002885762000287620000aa565b5b600083015167ffffffffffffffff811115620002a957620002a8620000af565b5b620002b78582860162000200565b9250506020620002ca8582860162000257565b9150509250929050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200032757607f821691505b6020821081036200033d576200033c620002df565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302620003a77fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8262000368565b620003b3868362000368565b95508019841693508086168417925050509392505050565b6000819050919050565b6000620003f6620003f0620003ea8462000233565b620003cb565b62000233565b9050919050565b6000819050919050565b6200041283620003d5565b6200042a6200042182620003fd565b84845462000375565b825550505050565b600090565b6200044162000432565b6200044e81848462000407565b505050565b5b8181101562000476576200046a60008262000437565b60018101905062000454565b5050565b601f821115620004c5576200048f8162000343565b6200049a8462000358565b81016020851015620004aa578190505b620004c2620004b98562000358565b83018262000453565b50505b505050565b600082821c905092915050565b6000620004ea60001984600802620004ca565b1980831691505092915050565b6000620005058383620004d7565b9150826002028217905092915050565b6200052082620002d4565b67ffffffffffffffff8111156200053c576200053b620000cf565b5b6200054882546200030e565b620005558282856200047a565b600060209050601f8311600181146200058d576000841562000578578287015190505b620005848582620004f7565b865550620005f4565b601f1984166200059d8662000343565b60005b82811015620005c757848901518255600182019150602085019450602081019050620005a0565b86831015620005e75784890151620005e3601f891682620004d7565b8355505b6001600288020188555050505b505050505050565b6104c9806200060c6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80630cb1851a1461005c5780632212dbc31461007a5780639097479514610098578063a8d509ff146100ba578063eeb4e367146100d8575b600080fd5b6100646100f6565b6040516100719190610327565b60405180910390f35b610082610188565b60405161008f9190610362565b60405180910390f35b6100a0610191565b6040516100b19594939291906103be565b60405180910390f35b6100c2610263565b6040516100cf9190610418565b60405180910390f35b6100e061028d565b6040516100ed9190610362565b60405180910390f35b60606002805461010590610462565b80601f016020809104026020016040519081016040528092919081815260200182805461013190610462565b801561017e5780601f106101535761010080835404028352916020019161017e565b820191906000526020600020905b81548152906001019060200180831161016157829003601f168201915b5050505050905090565b60008054905090565b60008060006060600030600054600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1660026003548180546101d290610462565b80601f01602080910402602001604051908101604052809291908181526020018280546101fe90610462565b801561024b5780601f106102205761010080835404028352916020019161024b565b820191906000526020600020905b81548152906001019060200180831161022e57829003601f168201915b50505050509150945094509450945094509091929394565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600354905090565b600081519050919050565b600082825260208201905092915050565b60005b838110156102d15780820151818401526020810190506102b6565b60008484015250505050565b6000601f19601f8301169050919050565b60006102f982610297565b61030381856102a2565b93506103138185602086016102b3565b61031c816102dd565b840191505092915050565b6000602082019050818103600083015261034181846102ee565b905092915050565b6000819050919050565b61035c81610349565b82525050565b60006020820190506103776000830184610353565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006103a88261037d565b9050919050565b6103b88161039d565b82525050565b600060a0820190506103d360008301886103af565b6103e06020830187610353565b6103ed60408301866103af565b81810360608301526103ff81856102ee565b905061040e6080830184610353565b9695505050505050565b600060208201905061042d60008301846103af565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061047a57607f821691505b60208210810361048d5761048c610433565b5b5091905056fea264697066735822122096ba86e2c854094a9f7774cf59534923c219cc0ab6e812963e86557d6743467c64736f6c63430008110033a2646970667358221220b58cd7b4415159e845caf380c6ffa231afa779fa9b6af3b83d7b80ca521527a464736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/TestApp.sol b/itests/contracts/TestApp.sol new file mode 100644 index 000000000..072eb7a61 --- /dev/null +++ b/itests/contracts/TestApp.sol @@ -0,0 +1,211 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; +pragma experimental ABIEncoderV2; + +contract Test_contract { + uint256 timestamp; + address sender; + string text; + uint256 number; + + constructor(string memory _text, uint256 _number) { + sender = tx.origin; + timestamp = block.timestamp; + text = _text; + number = _number; + } + + function getall() + public + view + returns ( + address, + uint256, + address, + string memory, + uint256 + ) + { + return (address(this), timestamp, sender, text, number); + } + + function get_timestamp() public view returns (uint256) { + return timestamp; + } + + function get_sender() public view returns (address) { + return sender; + } + + function get_text() public view returns (string memory) { + return text; + } + + function get_number() public view returns (uint256) { + return number; + } +} + +contract App { + address[] Test_list; + uint256 Test_list_length; + + function get_Test_list_length() public view returns (uint256) { + return Test_list_length; + } + + struct Test_getter { + address _address; + uint256 timestamp; + address sender; + string text; + uint256 number; + } + + function get_Test_N(uint256 index) + public + view + returns ( + address, + uint256, + address, + string memory, + uint256 + ) + { + return Test_contract(Test_list[index]).getall(); + } + + function get_first_Test_N(uint256 count, uint256 offset) + public + view + returns (Test_getter[] memory) + { + Test_getter[] memory getters = new Test_getter[](count); + for (uint256 i = offset; i < count; i++) { + Test_contract myTest = Test_contract(Test_list[i + offset]); + getters[i - offset]._address = address(myTest); + getters[i - offset].timestamp = myTest.get_timestamp(); + getters[i - offset].sender = myTest.get_sender(); + getters[i - offset].text = myTest.get_text(); + getters[i - offset].number = myTest.get_number(); + } + return getters; + } + + function get_last_Test_N(uint256 count, uint256 offset) + public + view + returns (Test_getter[] memory) + { + Test_getter[] memory getters = new Test_getter[](count); + for (uint256 i = 0; i < count; i++) { + Test_contract myTest = + Test_contract(Test_list[Test_list_length - i - offset - 1]); + getters[i]._address = address(myTest); + + getters[i].timestamp = myTest.get_timestamp(); + getters[i].sender = myTest.get_sender(); + getters[i].text = myTest.get_text(); + getters[i].number = myTest.get_number(); + } + return getters; + } + + function get_Test_user_length(address user) public view returns (uint256) { + return user_map[user].Test_list_length; + } + + function get_Test_user_N(address user, uint256 index) + public + view + returns ( + address, + uint256, + address, + string memory, + uint256 + ) + { + return Test_contract(user_map[user].Test_list[index]).getall(); + } + + function get_last_Test_user_N( + address user, + uint256 count, + uint256 offset + ) public view returns (Test_getter[] memory) { + Test_getter[] memory getters = new Test_getter[](count); + + for (uint256 i = offset; i < count; i++) { + getters[i - offset]._address = user_map[user].Test_list[i + offset]; + getters[i - offset].timestamp = Test_contract( + user_map[user].Test_list[i + offset] + ) + .get_timestamp(); + getters[i - offset].sender = Test_contract( + user_map[user].Test_list[i + offset] + ) + .get_sender(); + getters[i - offset].text = Test_contract( + user_map[user].Test_list[i + offset] + ) + .get_text(); + getters[i - offset].number = Test_contract( + user_map[user].Test_list[i + offset] + ) + .get_number(); + } + return getters; + } + + struct UserInfo { + address owner; + bool exists; + address[] Test_list; + uint256 Test_list_length; + } + mapping(address => UserInfo) public user_map; + address[] UserInfoList; + uint256 UserInfoListLength; + + event NewTest(address sender); + + function new_Test(string memory text, uint256 number) + public + returns (address) + { + address mynew = + address(new Test_contract({_text: text, _number: number})); + + if (!user_map[tx.origin].exists) { + user_map[tx.origin] = create_user_on_new_Test(mynew); + } + user_map[tx.origin].Test_list.push(mynew); + + user_map[tx.origin].Test_list_length += 1; + + Test_list.push(mynew); + Test_list_length += 1; + + emit NewTest(tx.origin); + + return mynew; + } + + function create_user_on_new_Test(address addr) + private + returns (UserInfo memory) + { + address[] memory Test_list_; + + UserInfoList.push(addr); + return + UserInfo({ + exists: true, + owner: addr, + Test_list: Test_list_, + Test_list_length: 0 + }); + } +} diff --git a/itests/contracts/ValueSender.hex b/itests/contracts/ValueSender.hex new file mode 100644 index 000000000..ed69dacdb --- /dev/null +++ b/itests/contracts/ValueSender.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b506106dc806100206000396000f3fe60806040526004361061002d5760003560e01c8063dbdc275d14610072578063fd75295a1461009d5761006d565b3661006d577f34fb9cb8f63eaccc6c0beefc202db703e529c3bf9ce83f485b398af7fd679308333460405161006392919061020f565b60405180910390a1005b600080fd5b34801561007e57600080fd5b506100876100b9565b6040516100949190610238565b60405180910390f35b6100b760048036038101906100b29190610296565b610125565b005b6000806040516100c8906101a8565b604051809103906000f0801580156100e4573d6000803e3d6000fd5b5090507f8db3b20eed31d927a4f613b5c11765212e129cf726d025649650665569ea683b816040516101169190610238565b60405180910390a18091505090565b7f34fb9cb8f63eaccc6c0beefc202db703e529c3bf9ce83f485b398af7fd6793088134604051610156929190610322565b60405180910390a18073ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501580156101a4573d6000803e3d6000fd5b5050565b61035b8061034c83390190565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101e0826101b5565b9050919050565b6101f0816101d5565b82525050565b6000819050919050565b610209816101f6565b82525050565b600060408201905061022460008301856101e7565b6102316020830184610200565b9392505050565b600060208201905061024d60008301846101e7565b92915050565b600080fd5b6000610263826101b5565b9050919050565b61027381610258565b811461027e57600080fd5b50565b6000813590506102908161026a565b92915050565b6000602082840312156102ac576102ab610253565b5b60006102ba84828501610281565b91505092915050565b6000819050919050565b60006102e86102e36102de846101b5565b6102c3565b6101b5565b9050919050565b60006102fa826102cd565b9050919050565b600061030c826102ef565b9050919050565b61031c81610301565b82525050565b60006040820190506103376000830185610313565b6103446020830184610200565b939250505056fe608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506102fb806100606000396000f3fe60806040526004361061002d5760003560e01c806337cb6570146100725780639cb8a26a1461007c5761006d565b3661006d577fe1494f56a1ccfd8c7361f2ca5b8fd2b1a2fe11773821ac29534f09f4a0637d603334604051610063929190610214565b60405180910390a1005b600080fd5b61007a610093565b005b34801561008857600080fd5b50610091610155565b005b7f76cff203b0794a9e9013657ecb172f2d6e8de5941fd11a6bfbc0fb6014a5f07960008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16476040516100e492919061029c565b60405180910390a160008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f19350505050158015610152573d6000803e3d6000fd5b50565b7f1cbd47e7b0f55dc1a45ba8ebada53eaa1712b3e3e86f49a12c008ff22334569060405160405180910390a160008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006101e5826101ba565b9050919050565b6101f5816101da565b82525050565b6000819050919050565b61020e816101fb565b82525050565b600060408201905061022960008301856101ec565b6102366020830184610205565b9392505050565b6000819050919050565b600061026261025d610258846101ba565b61023d565b6101ba565b9050919050565b600061027482610247565b9050919050565b600061028682610269565b9050919050565b6102968161027b565b82525050565b60006040820190506102b1600083018561028d565b6102be6020830184610205565b939250505056fea2646970667358221220bdf21908b1c91973a8440fe81130e0077cf83c8f8e9a053d8a0c3063391aa40764736f6c63430008110033a26469706673582212202e514fe078dfcf4f1142a088c57cfa71ada74d72ee0cc4a46b7e1141cdbaeeed64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/ValueSender.sol b/itests/contracts/ValueSender.sol new file mode 100644 index 000000000..1be682b25 --- /dev/null +++ b/itests/contracts/ValueSender.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract A { + event LogCreateB(address _bAddress); + event LogSendEthA(address _bAddress, uint _value); + event LogReceiveEthA(address _bAddress, uint _value); + + // Function to create a new instance of contract B and return its address + function createB() public returns (address) { + address bAddress = address(new B()); + emit LogCreateB(bAddress); + return bAddress; + } + + // Payable method to accept eth and an address for B and send the eth to B + function sendEthToB(address payable _bAddress) public payable { + emit LogSendEthA(_bAddress, msg.value); + _bAddress.transfer(msg.value); + } + + // Payable function to accept the eth + receive() external payable { + emit LogSendEthA(msg.sender, msg.value); + } +} + +contract B { + event LogSelfDestruct(); + event LogSendEthToA(address _to, uint _value); + event LogReceiveEth(address from, uint value); + address payable creator; + + constructor(){ + creator = payable(msg.sender); + } + + // Payable function to accept the eth + receive() external payable { + emit LogReceiveEth(msg.sender, msg.value); + } + + // Method to send ether to contract A + function sendEthToA() public payable { + emit LogSendEthToA(creator,address(this).balance); + creator.transfer(address(this).balance); + } + + // Self destruct method to send eth to its creator + function selfDestruct() public { + emit LogSelfDestruct(); + selfdestruct(creator); + } +} diff --git a/itests/contracts/compile.sh b/itests/contracts/compile.sh index 1163ad9a6..4395fdb53 100755 --- a/itests/contracts/compile.sh +++ b/itests/contracts/compile.sh @@ -1,6 +1,19 @@ +set -eu +set -o pipefail + #use the solc compiler https://docs.soliditylang.org/en/v0.8.17/installing-solidity.html # to compile all of the .sol files to their corresponding evm binary files stored as .hex # solc outputs to stdout a format that we just want to grab the last line of and then remove the trailing newline on that line -find -type f -name \*.sol -print0 | - xargs -0 -I{} bash -c 'solc --bin {} |tail -n1 | tr -d "\n" > $(echo {} | sed -e s/.sol$/.hex/)' +find . -name \*.sol -print0 | + xargs -0 -I{} bash -euc -o pipefail 'solc --bin {} |tail -n1 | tr -d "\n" > $(echo {} | sed -e s/.sol$/.hex/)' + + + +#for these contracts we have 2 contracts in the same solidity file +#this command grabs the correct bytecode for us +for filename in Constructor TestApp ValueSender ; do + echo $filename + solc --bin $filename.sol | tail -n5|head -n1 | tr -d "\n" > $filename.hex +done + diff --git a/itests/eth_filter_test.go b/itests/eth_filter_test.go index 22fb17757..c66a56154 100644 --- a/itests/eth_filter_test.go +++ b/itests/eth_filter_test.go @@ -1099,7 +1099,8 @@ func invokeAndWaitUntilAllOnChain(t *testing.T, client *kit.TestFullNode, invoca } } } - ret := client.EVM().InvokeSolidity(ctx, inv.Sender, inv.Target, inv.Selector, inv.Data) + ret, err := client.EVM().InvokeSolidity(ctx, inv.Sender, inv.Target, inv.Selector, inv.Data) + require.NoError(err) require.True(ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") invocationMap[ret.Message] = inv diff --git a/itests/fevm_address_test.go b/itests/fevm_address_test.go index a23e96860..9eaac4647 100644 --- a/itests/fevm_address_test.go +++ b/itests/fevm_address_test.go @@ -6,7 +6,6 @@ import ( "encoding/hex" "os" "testing" - "time" "github.com/stretchr/testify/require" "golang.org/x/crypto/sha3" @@ -44,14 +43,43 @@ func effectiveEthAddressForCreate(t *testing.T, sender address.Address) ethtypes panic("unreachable") } +func createAndDeploy(ctx context.Context, t *testing.T, client *kit.TestFullNode, fromAddr address.Address, contract []byte) *api.MsgLookup { + // Create and deploy evm actor + + method := builtintypes.MethodsEAM.CreateExternal + contractParams := abi.CborBytes(contract) + params, actorsErr := actors.SerializeParams(&contractParams) + require.NoError(t, actorsErr) + + createMsg := &types.Message{ + To: builtintypes.EthereumAddressManagerActorAddr, + From: fromAddr, + Value: big.Zero(), + Method: method, + Params: params, + } + smsg, err := client.MpoolPushMessage(ctx, createMsg, nil) + require.NoError(t, err) + + wait, err := client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false) + require.NoError(t, err) + require.Equal(t, exitcode.Ok, wait.Receipt.ExitCode) + return wait +} + +func getEthAddressTX(ctx context.Context, t *testing.T, client *kit.TestFullNode, wait *api.MsgLookup, ethAddr ethtypes.EthAddress) ethtypes.EthAddress { + // Check if eth address returned from CreateExternal is the same as eth address predicted at the start + var createExternalReturn eam.CreateExternalReturn + err := createExternalReturn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)) + require.NoError(t, err) + + createdEthAddr, err := ethtypes.CastEthAddress(createExternalReturn.EthAddress[:]) + require.NoError(t, err) + return createdEthAddr +} + func TestAddressCreationBeforeDeploy(t *testing.T) { - kit.QuietMiningLogs() - - blockTime := 100 * time.Millisecond - client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) - ens.InterconnectAll().BeginMining(blockTime) - - ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() // install contract @@ -72,22 +100,11 @@ func TestAddressCreationBeforeDeploy(t *testing.T) { contractFilAddr, err := ethAddr.ToFilecoinAddress() require.NoError(t, err) - // Send contract address some funds - + //transfer half the wallet balance bal, err := client.WalletBalance(ctx, client.DefaultKey.Address) require.NoError(t, err) sendAmount := big.Div(bal, big.NewInt(2)) - - sendMsg := &types.Message{ - From: fromAddr, - To: contractFilAddr, - Value: sendAmount, - } - signedMsg, err := client.MpoolPushMessage(ctx, sendMsg, nil) - require.NoError(t, err) - mLookup, err := client.StateWaitMsg(ctx, signedMsg.Cid(), 3, api.LookbackNoLimit, true) - require.NoError(t, err) - require.Equal(t, exitcode.Ok, mLookup.Receipt.ExitCode) + client.EVM().TransferValueOrFail(ctx, fromAddr, contractFilAddr, sendAmount) // Check if actor at new address is a placeholder actor actor, err := client.StateGetActor(ctx, contractFilAddr, types.EmptyTSK) @@ -95,40 +112,69 @@ func TestAddressCreationBeforeDeploy(t *testing.T) { require.True(t, builtin.IsPlaceholderActor(actor.Code)) // Create and deploy evm actor - - method := builtintypes.MethodsEAM.CreateExternal - contractParams := abi.CborBytes(contract) - params, err := actors.SerializeParams(&contractParams) - require.NoError(t, err) - - createMsg := &types.Message{ - To: builtintypes.EthereumAddressManagerActorAddr, - From: fromAddr, - Value: big.Zero(), - Method: method, - Params: params, - } - smsg, err := client.MpoolPushMessage(ctx, createMsg, nil) - require.NoError(t, err) - - wait, err := client.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false) - require.NoError(t, err) - require.Equal(t, exitcode.Ok, wait.Receipt.ExitCode) + wait := createAndDeploy(ctx, t, client, fromAddr, contract) // Check if eth address returned from CreateExternal is the same as eth address predicted at the start - var createExternalReturn eam.CreateExternalReturn - err = createExternalReturn.UnmarshalCBOR(bytes.NewReader(wait.Receipt.Return)) - require.NoError(t, err) - - createdEthAddr, err := ethtypes.CastEthAddress(createExternalReturn.EthAddress[:]) - require.NoError(t, err) + createdEthAddr := getEthAddressTX(ctx, t, client, wait, ethAddr) require.Equal(t, ethAddr, createdEthAddr) // Check if newly deployed actor still has funds actorPostCreate, err := client.StateGetActor(ctx, contractFilAddr, types.EmptyTSK) require.NoError(t, err) - require.Equal(t, actorPostCreate.Balance, sendAmount) require.True(t, builtin.IsEvmActor(actorPostCreate.Code)) } + +func TestDeployAddressMultipleTimes(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + // install contract + contractHex, err := os.ReadFile("contracts/SimpleCoin.hex") + require.NoError(t, err) + + contract, err := hex.DecodeString(string(contractHex)) + require.NoError(t, err) + + fromAddr, err := client.WalletDefaultAddress(ctx) + require.NoError(t, err) + + // We hash the f1/f3 address into the EVM's address space when deploying contracts from + // accounts. + effectiveEvmAddress := effectiveEthAddressForCreate(t, fromAddr) + ethAddr := client.EVM().ComputeContractAddress(effectiveEvmAddress, 1) + + contractFilAddr, err := ethAddr.ToFilecoinAddress() + require.NoError(t, err) + + // Send contract address small funds to init + sendAmount := big.NewInt(2) + client.EVM().TransferValueOrFail(ctx, fromAddr, contractFilAddr, sendAmount) + + // Check if actor at new address is a placeholder actor + actor, err := client.StateGetActor(ctx, contractFilAddr, types.EmptyTSK) + require.NoError(t, err) + require.True(t, builtin.IsPlaceholderActor(actor.Code)) + + // Create and deploy evm actor + wait := createAndDeploy(ctx, t, client, fromAddr, contract) + + // Check if eth address returned from CreateExternal is the same as eth address predicted at the start + createdEthAddr := getEthAddressTX(ctx, t, client, wait, ethAddr) + require.Equal(t, ethAddr, createdEthAddr) + + // Check if newly deployed actor still has funds + actorPostCreate, err := client.StateGetActor(ctx, contractFilAddr, types.EmptyTSK) + require.NoError(t, err) + require.Equal(t, actorPostCreate.Balance, sendAmount) + require.True(t, builtin.IsEvmActor(actorPostCreate.Code)) + + // Create and deploy evm actor + wait = createAndDeploy(ctx, t, client, fromAddr, contract) + + // Check that this time eth address returned from CreateExternal is not the same as eth address predicted at the start + createdEthAddr = getEthAddressTX(ctx, t, client, wait, ethAddr) + require.NotEqual(t, ethAddr, createdEthAddr) + +} diff --git a/itests/fevm_events_test.go b/itests/fevm_events_test.go index 079a7a699..458ac3470 100644 --- a/itests/fevm_events_test.go +++ b/itests/fevm_events_test.go @@ -64,20 +64,23 @@ func TestFEVMEvents(t *testing.T) { require.Empty(res.Results) // log a zero topic event with data - ret := client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x00}, nil) + ret, err := client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x00}, nil) + require.NoError(err) require.True(ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") require.NotNil(ret.Receipt.EventsRoot) fmt.Println(ret) fmt.Printf("Events:\n %+v\n", client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot)) // log a zero topic event with no data - ret = client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x01}, nil) + ret, err = client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x01}, nil) + require.NoError(err) require.True(ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") fmt.Println(ret) fmt.Printf("Events:\n %+v\n", client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot)) // log a four topic event with data - ret = client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x02}, nil) + ret, err = client.EVM().InvokeSolidity(ctx, fromAddr, idAddr, []byte{0x00, 0x00, 0x00, 0x02}, nil) + require.NoError(err) require.True(ret.Receipt.ExitCode.IsSuccess(), "contract execution failed") fmt.Println(ret) fmt.Printf("Events:\n %+v\n", client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot)) diff --git a/itests/fevm_test.go b/itests/fevm_test.go index 7fc04e86d..de11fd618 100644 --- a/itests/fevm_test.go +++ b/itests/fevm_test.go @@ -1,15 +1,17 @@ package itests import ( + "bytes" "context" "encoding/binary" "encoding/hex" + "fmt" "testing" - "time" "github.com/stretchr/testify/require" "github.com/filecoin-project/go-address" + "github.com/filecoin-project/go-state-types/big" builtintypes "github.com/filecoin-project/go-state-types/builtin" "github.com/filecoin-project/go-state-types/exitcode" "github.com/filecoin-project/go-state-types/manifest" @@ -38,19 +40,139 @@ func inputDataFromFrom(ctx context.Context, t *testing.T, client *kit.TestFullNo return inputData } -func setupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *kit.TestFullNode) { - kit.QuietMiningLogs() - blockTime := 5 * time.Millisecond - client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC()) - ens.InterconnectAll().BeginMiningMustPost(blockTime) - ctx, cancel := context.WithTimeout(context.Background(), time.Minute) - return ctx, cancel, client +func decodeOutputToUint64(output []byte) (uint64, error) { + var result uint64 + buf := bytes.NewReader(output[len(output)-8:]) + err := binary.Read(buf, binary.BigEndian, &result) + return result, err +} +func buildInputFromuint64(number uint64) []byte { + // Convert the number to a binary uint64 array + binaryNumber := make([]byte, 8) + binary.BigEndian.PutUint64(binaryNumber, number) + return inputDataFromArray(binaryNumber) +} + +// recursive delegate calls that fail due to gas limits are currently getting to 229 iterations +// before running out of gas +func recursiveDelegatecallFail(ctx context.Context, t *testing.T, client *kit.TestFullNode, filename string, count uint64) { + expectedIterationsBeforeFailing := int(229) + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + t.Log("recursion count - ", count) + inputData := buildInputFromuint64(count) + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", inputData) + + require.NoError(t, err) + + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "totalCalls()", []byte{}) + require.NoError(t, err) + + resultUint, err := decodeOutputToUint64(result) + require.NoError(t, err) + + require.NotEqual(t, int(resultUint), int(count)) + require.Equal(t, expectedIterationsBeforeFailing, int(resultUint)) +} +func recursiveDelegatecallSuccess(ctx context.Context, t *testing.T, client *kit.TestFullNode, filename string, count uint64) { + t.Log("Count - ", count) + + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + inputData := buildInputFromuint64(count) + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", inputData) + require.NoError(t, err) + + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "totalCalls()", []byte{}) + require.NoError(t, err) + + resultUint, err := decodeOutputToUint64(result) + require.NoError(t, err) + + require.Equal(t, int(count), int(resultUint)) +} + +// TestFEVMRecursive does a basic fevm contract installation and invocation +func TestFEVMRecursive(t *testing.T) { + callCounts := []uint64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 230, 330} + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + filename := "contracts/Recursive.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + + // Successful calls + for _, callCount := range callCounts { + callCount := callCount // linter unhappy unless callCount is local to loop + t.Run(fmt.Sprintf("TestFEVMRecursive%d", callCount), func(t *testing.T) { + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", buildInputFromuint64(callCount)) + require.NoError(t, err) + }) + } + +} + +func TestFEVMRecursiveFail(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + filename := "contracts/Recursive.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + + // Unsuccessful calls + failCallCounts := []uint64{340, 400, 600, 850, 1000} + for _, failCallCount := range failCallCounts { + failCallCount := failCallCount // linter unhappy unless callCount is local to loop + t.Run(fmt.Sprintf("TestFEVMRecursiveFail%d", failCallCount), func(t *testing.T) { + _, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursiveCall(uint256)", buildInputFromuint64(failCallCount)) + require.Error(t, err) + require.Equal(t, exitcode.ExitCode(23), wait.Receipt.ExitCode) + }) + } +} + +func TestFEVMRecursive1(t *testing.T) { + callCount := 1 + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + filename := "contracts/Recursive.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + _, ret, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursive1()", []byte{}) + require.NoError(t, err) + events := client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot) + require.Equal(t, callCount, len(events)) +} +func TestFEVMRecursive2(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + filename := "contracts/Recursive.hex" + fromAddr, idAddr := client.EVM().DeployContractFromFilename(ctx, filename) + _, ret, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "recursive2()", []byte{}) + require.NoError(t, err) + events := client.EVM().LoadEvents(ctx, *ret.Receipt.EventsRoot) + require.Equal(t, 2, len(events)) +} + +// TestFEVMBasic does a basic fevm contract installation and invocation +// recursive delegate call succeeds up to 238 times +func TestFEVMRecursiveDelegatecall(t *testing.T) { + + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + filename := "contracts/RecursiveDelegeatecall.hex" + + //success with 238 or fewer calls + for i := uint64(1); i <= 238; i += 30 { + recursiveDelegatecallSuccess(ctx, t, client, filename, i) + } + recursiveDelegatecallSuccess(ctx, t, client, filename, uint64(238)) + + for i := uint64(239); i <= 800; i += 40 { + recursiveDelegatecallFail(ctx, t, client, filename, i) + } } // TestFEVMBasic does a basic fevm contract installation and invocation func TestFEVMBasic(t *testing.T) { - ctx, cancel, client := setupFEVMTest(t) + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() filename := "contracts/SimpleCoin.hex" @@ -60,7 +182,8 @@ func TestFEVMBasic(t *testing.T) { // invoke the contract with owner { inputData := inputDataFromFrom(ctx, t, client, fromAddr) - result := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData) + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData) + require.NoError(t, err) expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000002710") require.NoError(t, err) @@ -70,8 +193,9 @@ func TestFEVMBasic(t *testing.T) { // invoke the contract with non owner { inputData := inputDataFromFrom(ctx, t, client, fromAddr) - inputData[31]++ // change the pub address to one that has 0 balance by incrementing the last byte of the address - result := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData) + inputData[31]++ // change the pub address to one that has 0 balance by modifying the last byte of the address + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, idAddr, "getBalance(address)", inputData) + require.NoError(t, err) expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") require.NoError(t, err) @@ -81,7 +205,7 @@ func TestFEVMBasic(t *testing.T) { // TestFEVMETH0 tests that the ETH0 actor is in genesis func TestFEVMETH0(t *testing.T) { - ctx, cancel, client := setupFEVMTest(t) + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() eth0id, err := address.NewIDAddress(1001) @@ -100,7 +224,47 @@ func TestFEVMETH0(t *testing.T) { // TestFEVMDelegateCall deploys two contracts and makes a delegate call transaction func TestFEVMDelegateCall(t *testing.T) { - ctx, cancel, client := setupFEVMTest(t) + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameActor := "contracts/DelegatecallActor.hex" + fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + //install contract Storage + filenameStorage := "contracts/DelegatecallStorage.hex" + fromAddrStorage, storageAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + require.Equal(t, fromAddr, fromAddrStorage) + + //call Contract Storage which makes a delegatecall to contract Actor + //this contract call sets the "counter" variable to 7, from default value 0 + inputDataContract := inputDataFromFrom(ctx, t, client, actorAddr) + inputDataValue := inputDataFromArray([]byte{7}) + inputData := append(inputDataContract, inputDataValue...) + + //verify that the returned value of the call to setvars is 7 + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "setVars(address,uint256)", inputData) + require.NoError(t, err) + expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000007") + require.NoError(t, err) + require.Equal(t, result, expectedResult) + + //test the value is 7 a second way by calling the getter + result, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "getCounter()", []byte{}) + require.NoError(t, err) + require.Equal(t, result, expectedResult) + + //test the value is 0 via calling the getter on the Actor contract + result, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "getCounter()", []byte{}) + require.NoError(t, err) + expectedResultActor, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + require.Equal(t, result, expectedResultActor) +} + +// TestFEVMDelegateCallRevert makes a delegatecall action and then calls revert. +// the state should not have changed because of the revert +func TestFEVMDelegateCallRevert(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() //install contract Actor @@ -119,20 +283,247 @@ func TestFEVMDelegateCall(t *testing.T) { inputData := append(inputDataContract, inputDataValue...) //verify that the returned value of the call to setvars is 7 - result := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "setVars(address,uint256)", inputData) - expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000007") - require.NoError(t, err) - require.Equal(t, result, expectedResult) + _, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "setVarsRevert(address,uint256)", inputData) + require.Error(t, err) + require.Equal(t, exitcode.ExitCode(33), wait.Receipt.ExitCode) - //test the value is 7 via calling the getter - result = client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "getCounter()", []byte{}) + //test the value is 0 via calling the getter and was not set to 7 + expectedResult, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + result, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, storageAddr, "getCounter()", []byte{}) + require.NoError(t, err) require.Equal(t, result, expectedResult) //test the value is 0 via calling the getter on the Actor contract - result = client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "getCounter()", []byte{}) - expectedResultActor, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") + result, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "getCounter()", []byte{}) require.NoError(t, err) - require.Equal(t, result, expectedResultActor) + require.Equal(t, result, expectedResult) +} + +// TestFEVMSimpleRevert makes a call that is a simple revert +func TestFEVMSimpleRevert(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/DelegatecallStorage.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //call revert + _, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "revert()", []byte{}) + + require.Equal(t, wait.Receipt.ExitCode, exitcode.ExitCode(33)) + require.Error(t, err) +} + +// TestFEVMSelfDestruct creates a contract that just has a self destruct feature and calls it +func TestFEVMSelfDestruct(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/SelfDestruct.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //call destroy + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "destroy()", []byte{}) + require.NoError(t, err) + + //call destroy a second time and also no error + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "destroy()", []byte{}) + require.NoError(t, err) +} + +// TestFEVMTestApp deploys a fairly complex app contract and confirms it works as expected +func TestFEVMTestApp(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/TestApp.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + inputData, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000700000000000000000000000000000000000000000000000000000000000000066162636465660000000000000000000000000000000000000000000000000000") // sending string "abcdef" and int 7 - constructed using remix + require.NoError(t, err) + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "new_Test(string,uint256)", inputData) + require.NoError(t, err) + + inputData, err = hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "get_Test_N(uint256)", inputData) + require.NoError(t, err) + +} + +// TestFEVMTestApp creates a contract that just has a self destruct feature and calls it +func TestFEVMTestConstructor(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/Constructor.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //input = uint256{7}. set value and confirm tx success + inputData, err := hex.DecodeString("0000000000000000000000000000000000000000000000000000000000000007") + require.NoError(t, err) + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "new_Test(uint256)", inputData) + require.NoError(t, err) + +} + +// TestFEVMAutoSelfDestruct creates a contract that just has a self destruct feature and calls it +func TestFEVMAutoSelfDestruct(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameStorage := "contracts/AutoSelfDestruct.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //call destroy + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "destroy()", []byte{}) + require.NoError(t, err) +} + +// TestFEVMTestApp creates a contract that just has a self destruct feature and calls it +func TestFEVMTestSendToContract(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + bal, err := client.WalletBalance(ctx, client.DefaultKey.Address) + require.NoError(t, err) + + //install contract TestApp + filenameStorage := "contracts/SelfDestruct.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //transfer half balance to contract + + sendAmount := big.Div(bal, big.NewInt(2)) + client.EVM().TransferValueOrFail(ctx, fromAddr, contractAddr, sendAmount) + + //call self destruct which should return balance + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "destroy()", []byte{}) + require.NoError(t, err) + + finalBalanceMinimum := types.FromFil(uint64(99_999_999)) // 100 million FIL - 1 FIL for gas upper bounds + finalBal, err := client.WalletBalance(ctx, client.DefaultKey.Address) + require.NoError(t, err) + require.Equal(t, true, finalBal.GreaterThan(finalBalanceMinimum)) +} + +// creates a contract that would fail when tx are sent to it +// on eth but on fevm it succeeds +// example failing on testnet https://goerli.etherscan.io/address/0x2ff1525e060169dbf97b9461758c8f701f107cd2 +func TestFEVMTestNotPayable(t *testing.T) { + + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + fromAddr := client.DefaultKey.Address + t.Log("from - ", fromAddr) + + //create contract A + filenameStorage := "contracts/NotPayable.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + sendAmount := big.NewInt(10_000_000) + + client.EVM().TransferValueOrFail(ctx, fromAddr, contractAddr, sendAmount) + +} + +// tx to non function succeeds +func TestFEVMSendCall(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract + filenameActor := "contracts/GasSendTest.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "x()", []byte{}) + require.NoError(t, err) +} + +// creates a contract that would fail when tx are sent to it +// on eth but on fevm it succeeds +// example on goerli of tx failing https://goerli.etherscan.io/address/0xec037bdc9a79420985a53a49fdae3ccf8989909b +func TestFEVMSendGasLimit(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract + filenameActor := "contracts/GasLimitSend.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + //send $ to contract + //transfer 1 attoFIL to contract + sendAmount := big.MustFromString("1") + + client.EVM().TransferValueOrFail(ctx, fromAddr, contractAddr, sendAmount) + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "getDataLength()", []byte{}) + require.NoError(t, err) + +} + +// TestFEVMDelegateCall deploys the two contracts in TestFEVMDelegateCall but instead of A calling B, A calls A which should cause A to cause A in an infinite loop and should give a reasonable error +// XXX should not be fatal errors +func TestFEVMDelegateCallRecursiveFail(t *testing.T) { + //TODO change the gas limit of this invocation and confirm that the number of errors is different + //also TODO should we not have fatal error show up here? + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract Actor + filenameActor := "contracts/DelegatecallStorage.hex" + fromAddr, actorAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + //any data will do for this test that fails + inputDataContract := inputDataFromFrom(ctx, t, client, actorAddr) + inputDataValue := inputDataFromArray([]byte{7}) + inputData := append(inputDataContract, inputDataValue...) + + //verify that the returned value of the call to setvars is 7 + _, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, actorAddr, "setVarsSelf(address,uint256)", inputData) + require.Error(t, err) + require.Equal(t, exitcode.SysErrorIllegalArgument, wait.Receipt.ExitCode) + + //assert no fatal errors but still there are errors:: + errorAny := "fatal error" + require.NotContains(t, err.Error(), errorAny) +} + +// XXX Currently fails as self destruct has a bug +// TestFEVMTestSendValueThroughContracts creates A and B contract and exchanges value +// and self destructs and accounts for value sent +func TestFEVMTestSendValueThroughContractsAndDestroy(t *testing.T) { + + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + fromAddr := client.DefaultKey.Address + t.Log("from - ", fromAddr) + + //create contract A + filenameStorage := "contracts/ValueSender.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameStorage) + + //create contract B + ret, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "createB()", []byte{}) + require.NoError(t, err) + + ethAddr, err := ethtypes.CastEthAddress(ret[12:]) + require.NoError(t, err) + contractBAddress, err := ethAddr.ToFilecoinAddress() + require.NoError(t, err) + t.Log("contractBAddress - ", contractBAddress) + + //self destruct contract B + _, _, err = client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractBAddress, "selfDestruct()", []byte{}) + require.NoError(t, err) + } func TestEVMRpcDisable(t *testing.T) { @@ -144,7 +535,7 @@ func TestEVMRpcDisable(t *testing.T) { // TestFEVMRecursiveFuncCall deploys a contract and makes a recursive function calls func TestFEVMRecursiveFuncCall(t *testing.T) { - ctx, cancel, client := setupFEVMTest(t) + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() //install contract Actor @@ -155,7 +546,6 @@ func TestFEVMRecursiveFuncCall(t *testing.T) { return func(t *testing.T) { inputData := make([]byte, 32) binary.BigEndian.PutUint64(inputData[24:], uint64(n)) - client.EVM().InvokeContractByFuncNameExpectExit(ctx, fromAddr, actorAddr, "exec1(uint256)", inputData, ex) } } @@ -170,7 +560,7 @@ func TestFEVMRecursiveFuncCall(t *testing.T) { // TestFEVMRecursiveActorCall deploys a contract and makes a recursive actor calls func TestFEVMRecursiveActorCall(t *testing.T) { - ctx, cancel, client := setupFEVMTest(t) + ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() //install contract Actor diff --git a/itests/kit/evm.go b/itests/kit/evm.go index b3693ea45..6c27da557 100644 --- a/itests/kit/evm.go +++ b/itests/kit/evm.go @@ -7,8 +7,11 @@ import ( "encoding/hex" "fmt" "os" + "testing" + "time" "github.com/ipfs/go-cid" + logging "github.com/ipfs/go-log/v2" "github.com/multiformats/go-varint" "github.com/stretchr/testify/require" cbg "github.com/whyrusleeping/cbor-gen" @@ -101,13 +104,13 @@ func (e *EVM) DeployContractFromFilename(ctx context.Context, binFilename string return fromAddr, idAddr } -func (e *EVM) InvokeSolidity(ctx context.Context, sender address.Address, target address.Address, selector []byte, inputData []byte) *api.MsgLookup { - require := require.New(e.t) - +func (e *EVM) InvokeSolidity(ctx context.Context, sender address.Address, target address.Address, selector []byte, inputData []byte) (*api.MsgLookup, error) { params := append(selector, inputData...) var buffer bytes.Buffer err := cbg.WriteByteArray(&buffer, params) - require.NoError(err) + if err != nil { + return nil, err + } params = buffer.Bytes() msg := &types.Message{ @@ -121,13 +124,17 @@ func (e *EVM) InvokeSolidity(ctx context.Context, sender address.Address, target e.t.Log("sending invoke message") smsg, err := e.MpoolPushMessage(ctx, msg, nil) - require.NoError(err) + if err != nil { + return nil, err + } e.t.Log("waiting for message to execute") wait, err := e.StateWaitMsg(ctx, smsg.Cid(), 0, 0, false) - require.NoError(err) + if err != nil { + return nil, err + } - return wait + return wait, nil } // LoadEvents loads all events in an event AMT. @@ -237,18 +244,25 @@ func (e *EVM) ComputeContractAddress(deployer ethtypes.EthAddress, nonce uint64) return *(*ethtypes.EthAddress)(hasher.Sum(nil)[12:]) } -func (e *EVM) InvokeContractByFuncName(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte) []byte { +func (e *EVM) InvokeContractByFuncName(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte) ([]byte, *api.MsgLookup, error) { entryPoint := CalcFuncSignature(funcSignature) - wait := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData) - require.True(e.t, wait.Receipt.ExitCode.IsSuccess(), "contract execution failed: %d", wait.Receipt.ExitCode) + wait, err := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData) + if err != nil { + return nil, wait, err + } + if !wait.Receipt.ExitCode.IsSuccess() { + return nil, wait, fmt.Errorf("contract execution failed - %v", wait.Receipt.ExitCode) + } result, err := cbg.ReadByteArray(bytes.NewBuffer(wait.Receipt.Return), uint64(len(wait.Receipt.Return))) - require.NoError(e.t, err) - return result + if err != nil { + return nil, wait, err + } + return result, wait, nil } func (e *EVM) InvokeContractByFuncNameExpectExit(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte, exit exitcode.ExitCode) { entryPoint := CalcFuncSignature(funcSignature) - wait := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData) + wait, _ := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData) require.Equal(e.t, exit, wait.Receipt.ExitCode) } @@ -310,3 +324,40 @@ func removeLeadingZeros(data []byte) []byte { } return data[firstNonZeroIndex:] } + +func SetupFEVMTest(t *testing.T) (context.Context, context.CancelFunc, *TestFullNode) { + //make all logs extra quiet for fevm tests + lvl, err := logging.LevelFromString("error") + if err != nil { + panic(err) + } + logging.SetAllLoggers(lvl) + + blockTime := 100 * time.Millisecond + client, _, ens := EnsembleMinimal(t, MockProofs(), ThroughRPC()) + ens.InterconnectAll().BeginMining(blockTime) + ctx, cancel := context.WithTimeout(context.Background(), time.Minute) + + // require that the initial balance is 100 million FIL in setup + // this way other tests can count on this initial wallet balance + fromAddr := client.DefaultKey.Address + bal, err := client.WalletBalance(ctx, fromAddr) + require.NoError(t, err) + originalBalance := types.FromFil(uint64(100_000_000)) // 100 million FIL + require.Equal(t, originalBalance, bal) + + return ctx, cancel, client +} + +func (e *EVM) TransferValueOrFail(ctx context.Context, fromAddr address.Address, toAddr address.Address, sendAmount big.Int) { + sendMsg := &types.Message{ + From: fromAddr, + To: toAddr, + Value: sendAmount, + } + signedMsg, err := e.MpoolPushMessage(ctx, sendMsg, nil) + require.NoError(e.t, err) + mLookup, err := e.StateWaitMsg(ctx, signedMsg.Cid(), 3, api.LookbackNoLimit, true) + require.NoError(e.t, err) + require.Equal(e.t, exitcode.Ok, mLookup.Receipt.ExitCode) +}