Skip to content

Commit

Permalink
Merge pull request onflow#5273 from onflow/gregor/evm/selfdestruct-test
Browse files Browse the repository at this point in the history
[EVM] Selfdesctruct test
  • Loading branch information
ramtinms authored Feb 21, 2024
2 parents 53dc73e + c323118 commit fce3336
Show file tree
Hide file tree
Showing 5 changed files with 255 additions and 160 deletions.
85 changes: 85 additions & 0 deletions fvm/evm/emulator/emulator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,91 @@ func TestDeployAtFunctionality(t *testing.T) {
})
}

// Self destruct test deploys a contract with a selfdestruct function
// this function is called and we make sure the balance the contract had
// is returned to the address provided, and the contract data stays according to the
// EIP 6780 https://eips.ethereum.org/EIPS/eip-6780 in case where the selfdestruct
// is not caleld in the same transaction as deployment.
func TestSelfdestruct(t *testing.T) {
testutils.RunWithTestBackend(t, func(backend *testutils.TestBackend) {
testutils.RunWithTestFlowEVMRootAddress(t, backend, func(rootAddr flow.Address) {
testutils.RunWithEOATestAccount(t, backend, rootAddr, func(testAccount *testutils.EOATestAccount) {

testContract := testutils.GetStorageTestContract(t)
testAddress := types.NewAddressFromString("testaddr")
startBalance := big.NewInt(0).Mul(big.NewInt(1000), big.NewInt(gethParams.Ether))
deployBalance := big.NewInt(0).Mul(big.NewInt(10), big.NewInt(gethParams.Ether))
var contractAddr types.Address

// setup the test with funded account and deploying a selfdestruct contract.
RunWithNewEmulator(t, backend, rootAddr, func(env *emulator.Emulator) {
RunWithNewBlockView(t, env, func(blk types.BlockView) {
_, err := blk.DirectCall(types.NewDepositCall(testAddress, startBalance, 0))
require.NoError(t, err)
})

RunWithNewBlockView(t, env, func(blk types.BlockView) {
res, err := blk.DirectCall(
types.NewDeployCall(
testAddress,
testContract.ByteCode,
math.MaxUint64,
deployBalance,
0),
)
require.NoError(t, err)
contractAddr = res.DeployedContractAddress
})

RunWithNewReadOnlyBlockView(t, env, func(blk types.ReadOnlyBlockView) {
bal, err := blk.BalanceOf(testAddress)
require.NoError(t, err)
require.Equal(t, big.NewInt(0).Sub(startBalance, deployBalance), bal)

bal, err = blk.BalanceOf(contractAddr)
require.NoError(t, err)
require.Equal(t, deployBalance, bal)
})

// call the destroy method which executes selfdestruct call.
RunWithNewBlockView(t, env, func(blk types.BlockView) {
res, err := blk.DirectCall(&types.DirectCall{
Type: types.DirectCallTxType,
From: testAddress,
To: contractAddr,
Data: testContract.MakeCallData(t, "destroy"),
Value: big.NewInt(0),
GasLimit: 100_000,
})
require.NoError(t, err)
require.False(t, res.Failed())
})

// after calling selfdestruct the balance should be returned to the caller and
// equal initial funded balance of the caller.
RunWithNewReadOnlyBlockView(t, env, func(blk types.ReadOnlyBlockView) {
bal, err := blk.BalanceOf(testAddress)
require.NoError(t, err)
require.Equal(t, startBalance, bal)

bal, err = blk.BalanceOf(contractAddr)
require.NoError(t, err)
require.Equal(t, big.NewInt(0), bal)

nonce, err := blk.NonceOf(contractAddr)
require.NoError(t, err)
require.Equal(t, uint64(1), nonce)

code, err := blk.CodeOf(contractAddr)
require.NoError(t, err)
require.True(t, len(code) > 0)
})
})
})
})
})
}

func TestTransfers(t *testing.T) {
testutils.RunWithTestBackend(t, func(backend *testutils.TestBackend) {
testutils.RunWithTestFlowEVMRootAddress(t, backend, func(rootAddr flow.Address) {
Expand Down
3 changes: 1 addition & 2 deletions fvm/evm/testutils/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import (

gethABI "github.com/ethereum/go-ethereum/accounts/abi"
gethCommon "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"

"github.com/onflow/atree"
"github.com/stretchr/testify/require"

"github.com/onflow/flow-go/fvm/evm/emulator"
"github.com/onflow/flow-go/fvm/evm/testutils/contracts"
Expand Down
6 changes: 5 additions & 1 deletion fvm/evm/testutils/contracts/test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ contract Storage {
return block.prevrandao;
}

function destroy() public {
selfdestruct(payable(msg.sender));
}

function verifyArchCallToFlowBlockHeight(uint64 expected) public view returns (uint64){
(bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("flowBlockHeight()"));
require(ok, "unsuccessful call to arch ");
Expand All @@ -44,4 +48,4 @@ contract Storage {
require(expected == output, "output doesnt match the expected value");
return output;
}
}
}
Loading

0 comments on commit fce3336

Please sign in to comment.