Skip to content

Commit

Permalink
test: Add EIP-158 & EIP-161 test
Browse files Browse the repository at this point in the history
  • Loading branch information
drklee3 committed Feb 27, 2024
1 parent 76c6fe2 commit 876f361
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 8 deletions.
16 changes: 16 additions & 0 deletions contract/contracts/EIP161Test.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract EIP161Test {
function selfDestructTo(address target) public {
// This contract will self-destruct and send its balance to the target address
selfdestruct(payable(target));
}

function callAccount(address target) public payable returns (bytes memory) {
(bool success, bytes memory data) = target.call{value: msg.value}("");
require(success, "Failed to call empty account with value");

return data;
}
}
110 changes: 109 additions & 1 deletion x/evm/keeper/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import (
"math/big"
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
gethparams "github.com/ethereum/go-ethereum/params"

"github.com/ethereum/go-ethereum/common"
"github.com/evmos/ethermint/types"
"github.com/evmos/ethermint/x/evm/testutil"
"github.com/stretchr/testify/suite"
)
Expand All @@ -19,7 +23,7 @@ var test *IntegrationTestSuite
func TestIntegrationTestSuite(t *testing.T) {
test = new(IntegrationTestSuite)
test.EnableFeemarket = false
test.EnableLondonHF = true
test.EnableLondonHF = false
suite.Run(t, test)
}

Expand All @@ -34,6 +38,7 @@ func (suite *IntegrationTestSuite) TestState_EmptyToEmpty() {
_, rsp, err := suite.CallContract(
testutil.StateTestContract,
addr,
common.Big0,
"tempChangeEmpty",
big.NewInt(1000),
)
Expand All @@ -57,6 +62,7 @@ func (suite *IntegrationTestSuite) TestState_NonEmptyToNonEmpty() {
_, rsp, err := suite.CallContract(
testutil.StateTestContract,
addr,
common.Big0,
"tempChangeNonEmpty",
newValue,
)
Expand All @@ -70,3 +76,105 @@ func (suite *IntegrationTestSuite) TestState_NonEmptyToNonEmpty() {

suite.Equal(storageBefore, storageAfter)
}

// ----------------------------------------------------------------------------
// EIP-161

func (suite *IntegrationTestSuite) TestEIP158_Enabled() {
// Params.ChainConfig.EIP158Block needs to be set for
// EIP-161 to be applied in geth EVM.Call()
params := suite.App.EvmKeeper.GetParams(suite.Ctx)
suite.Require().LessOrEqual(
params.ChainConfig.EIP158Block.Int64(),
suite.Ctx.BlockHeight(),
"EIP-158 should be enabled in params",
)
}

func (suite *IntegrationTestSuite) TestEIP161_CreateNonce() {
addr := suite.DeployContract(testutil.EIP161TestContract)
contractAcc := suite.App.EvmKeeper.GetAccount(suite.Ctx, addr)
suite.Require().NotNil(contractAcc)
suite.Require().Equal(
uint64(1),
contractAcc.Nonce,
"EIP-161: CREATE should increment nonce by 1 over default value (0)",
)
}

func (suite *IntegrationTestSuite) TestEIP161_CallGas() {
addr := suite.DeployContract(testutil.EIP161TestContract)

// Non-existent account
targetAddr := common.Address{1, 2, 3, 4, 5, 6}
targetAcc := suite.App.EvmKeeper.GetAccount(suite.Ctx, targetAddr)
suite.Require().Nil(targetAcc, "target should not exist")

var gasUsed1 uint64

suite.Run("Call 0 value - no 25k gas charge", func() {
_, rsp, err := suite.CallContract(
testutil.EIP161TestContract,
addr,
common.Big0, // no transfer
"callAccount",
targetAddr,
)
suite.Require().NoError(err)
suite.Require().Empty(rsp.VmError)

targetAcc = suite.App.EvmKeeper.GetAccount(suite.Ctx, targetAddr)
suite.Require().Nil(
targetAcc,
"target should still not exist after being called with no value",
)

gasUsed1 = rsp.GasUsed
})

suite.Run("Call >0 value - 25k gas charge", func() {
suite.MintCoinsForAccount(
suite.Ctx,
sdk.AccAddress(suite.Address.Bytes()),
sdk.NewCoins(
sdk.NewCoin(types.AttoPhoton, sdk.NewInt(100000000000)),
),
)

value := big.NewInt(10000)

_, rsp, err := suite.CallContract(
testutil.EIP161TestContract,
addr,
value, // >0 value transfer
"callAccount",
targetAddr,
)
suite.Require().NoError(err)
suite.Require().Empty(rsp.VmError)

// Check account + bal
targetAcc = suite.App.EvmKeeper.GetAccount(suite.Ctx, targetAddr)
suite.Require().NotNil(
targetAcc,
"target should exist after call with value",
)
suite.Require().Equal(
value,
targetAcc.Balance,
"target should have received the value",
)

// Check gas
suite.Require().Greater(
rsp.GasUsed,
gasUsed1,
"call with value transfer should use more gas than 0 value call",
)
suite.Require().GreaterOrEqual(
rsp.GasUsed,
gasUsed1+gethparams.CallNewAccountGas,
"EIP-161: 25k gas charge when transferring >0 value & destination is dead",
)
})
}
4 changes: 4 additions & 0 deletions x/evm/testutil/EIP161Test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"abi": "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"callAccount\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"selfDestructTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
"bin": "608060405234801561001057600080fd5b506103bb806100206000396000f3fe6080604052600436106100295760003560e01c80636f43e2db1461002e578063a28bf7cc1461005e575b600080fd5b610048600480360381019061004391906101bd565b610087565b604051610055919061027a565b60405180910390f35b34801561006a57600080fd5b50610085600480360381019061008091906101bd565b610141565b005b60606000808373ffffffffffffffffffffffffffffffffffffffff16346040516100b0906102cd565b60006040518083038185875af1925050503d80600081146100ed576040519150601f19603f3d011682016040523d82523d6000602084013e6100f2565b606091505b509150915081610137576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161012e90610365565b60405180910390fd5b8092505050919050565b8073ffffffffffffffffffffffffffffffffffffffff16ff5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061018a8261015f565b9050919050565b61019a8161017f565b81146101a557600080fd5b50565b6000813590506101b781610191565b92915050565b6000602082840312156101d3576101d261015a565b5b60006101e1848285016101a8565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610224578082015181840152602081019050610209565b60008484015250505050565b6000601f19601f8301169050919050565b600061024c826101ea565b61025681856101f5565b9350610266818560208601610206565b61026f81610230565b840191505092915050565b600060208201905081810360008301526102948184610241565b905092915050565b600081905092915050565b50565b60006102b760008361029c565b91506102c2826102a7565b600082019050919050565b60006102d8826102aa565b9150819050919050565b600082825260208201905092915050565b7f4661696c656420746f2063616c6c20656d707479206163636f756e742077697460008201527f682076616c756500000000000000000000000000000000000000000000000000602082015250565b600061034f6027836102e2565b915061035a826102f3565b604082019050919050565b6000602082019050818103600083015261037e81610342565b905091905056fea2646970667358221220cfb5ccd351026e6ecddfda020c8ce00e3714e0a5722fd897396563e259d8b1db64736f6c63430008180033"
}
19 changes: 12 additions & 7 deletions x/evm/testutil/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ import (
var (
//go:embed StateTest.json
stateTestContractJSON []byte
StateTestContract types.CompiledContract

// StateTestContract is a compiled contract for testing state changes
StateTestContract types.CompiledContract
//go:embed EIP161Test.json
EIP161TestContractJSON []byte
EIP161TestContract types.CompiledContract
)

func loadContract(jsonBytes []byte) types.CompiledContract {
Expand All @@ -39,6 +41,7 @@ func loadContract(jsonBytes []byte) types.CompiledContract {

func init() {
StateTestContract = loadContract(stateTestContractJSON)
EIP161TestContract = loadContract(EIP161TestContractJSON)
}

// DeployContract deploys a provided contract and returns the contract address
Expand Down Expand Up @@ -108,6 +111,7 @@ func (suite *TestSuite) DeployContract(
func (suite *TestSuite) CallContract(
contract types.CompiledContract,
contractAddr common.Address,
value *big.Int,
method string,
params ...interface{},
) (*types.MsgEthereumTx, *types.MsgEthereumTxResponse, error) {
Expand All @@ -119,9 +123,10 @@ func (suite *TestSuite) CallContract(
return nil, nil, err
}
args, err := json.Marshal(&types.TransactionArgs{
To: &contractAddr,
From: &suite.Address,
Data: (*hexutil.Bytes)(&transferData),
To: &contractAddr,
From: &suite.Address,
Data: (*hexutil.Bytes)(&transferData),
Value: (*hexutil.Big)(value),
})
if err != nil {
return nil, nil, err
Expand All @@ -143,7 +148,7 @@ func (suite *TestSuite) CallContract(
chainID,
nonce,
&contractAddr,
nil,
value,
res.Gas,
nil,
suite.App.FeeMarketKeeper.GetBaseFee(suite.Ctx),
Expand All @@ -156,7 +161,7 @@ func (suite *TestSuite) CallContract(
chainID,
nonce,
&contractAddr,
nil,
value,
res.Gas,
nil,
nil, nil,
Expand Down
23 changes: 23 additions & 0 deletions x/evm/testutil/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
feemarkettypes "github.com/evmos/ethermint/x/feemarket/types"
tmjson "github.com/tendermint/tendermint/libs/json"
Expand Down Expand Up @@ -115,7 +116,12 @@ func (suite *TestSuite) SetupAppWithT(checkTx bool, t require.TestingT) {
genesis[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(feemarketGenesis)
if !suite.EnableLondonHF {
evmGenesis := types.DefaultGenesisState()

zeroInt := sdkmath.NewInt(0)
evmGenesis.Params.ChainConfig.EIP158Block = &zeroInt

maxInt := sdkmath.NewInt(math.MaxInt64)

evmGenesis.Params.ChainConfig.LondonBlock = &maxInt
evmGenesis.Params.ChainConfig.ArrowGlacierBlock = &maxInt
evmGenesis.Params.ChainConfig.GrayGlacierBlock = &maxInt
Expand Down Expand Up @@ -446,3 +452,20 @@ func (suite *TestSuite) GetAllAccountStorage(

return states
}

func (suite *TestSuite) MintCoinsForAccount(
ctx sdk.Context,
addr sdk.AccAddress,
amount sdk.Coins,
) {
err := suite.App.BankKeeper.MintCoins(ctx, minttypes.ModuleName, amount)
suite.Require().NoError(err)

err = suite.App.BankKeeper.SendCoinsFromModuleToAccount(
ctx,
minttypes.ModuleName,
addr,
amount,
)
suite.Require().NoError(err)
}

0 comments on commit 876f361

Please sign in to comment.