Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
- [\#648](https://github.com/cosmos/evm/pull/648) Move all `ante` logic such as `NewAnteHandler` from the `evmd` package to `evm/ante` so it can be used as library functions.
- [\#659](https://github.com/cosmos/evm/pull/659) Move configs out of EVMD and deduplicate configs
- [\#664](https://github.com/cosmos/evm/pull/664) Add EIP-7702 integration test
- [\#684](https://github.com/cosmos/evm/pull/684) Add unit test cases for EIP-7702

### FEATURES

Expand Down
94 changes: 91 additions & 3 deletions tests/integration/x/vm/test_msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ package vm
import (
"math/big"

ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/holiman/uint256"

"github.com/cosmos/evm/testutil/integration/evm/utils"
"github.com/cosmos/evm/x/vm/types"

sdkmath "cosmossdk.io/math"

sdktypes "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
Expand All @@ -27,10 +32,11 @@ func (s *KeeperTestSuite) TestEthereumTx() {
name string
getMsg func() *types.MsgEthereumTx
expectedErr error
postCheck func()
}{
{
"success - transfer funds tx",
func() *types.MsgEthereumTx {
name: "success - transfer funds tx",
getMsg: func() *types.MsgEthereumTx {
recipient := s.Keyring.GetAddr(1)
args := types.EvmTxArgs{
To: &recipient,
Expand All @@ -40,12 +46,90 @@ func (s *KeeperTestSuite) TestEthereumTx() {
s.Require().NoError(err)
return tx.GetMsgs()[0].(*types.MsgEthereumTx)
},
nil,
expectedErr: nil,
postCheck: nil,
},
{
name: "success - set code authorization tx (EIP-7702)",
getMsg: func() *types.MsgEthereumTx {
authority := s.Keyring.GetKey(0)
target := s.Keyring.GetAddr(1)

accResp, err := s.Handler.GetEvmAccount(authority.Addr)
s.Require().NoError(err)

auth := ethtypes.SetCodeAuthorization{
ChainID: *uint256.NewInt(types.GetChainConfig().GetChainId()),
Address: target,
Nonce: accResp.GetNonce(),
}
signedAuth := s.SignSetCodeAuthorization(authority, auth)

args := types.EvmTxArgs{
To: &target,
AuthorizationList: []ethtypes.SetCodeAuthorization{signedAuth},
}
tx, err := s.Factory.GenerateSignedEthTx(s.Keyring.GetPrivKey(0), args)
s.Require().NoError(err)
return tx.GetMsgs()[0].(*types.MsgEthereumTx)
},
expectedErr: nil,
postCheck: func() {
authorityAddr := s.Keyring.GetAddr(0)
targetAddr := s.Keyring.GetAddr(1)
codeHash := s.Network.App.GetEVMKeeper().GetCodeHash(s.Network.GetContext(), authorityAddr)
code := s.Network.App.GetEVMKeeper().GetCode(s.Network.GetContext(), codeHash)
delegationAddr, ok := ethtypes.ParseDelegation(code)
s.Require().True(ok)
s.Require().Equal(targetAddr, delegationAddr)
},
},
{
name: "fail - unsigned set code authorization",
getMsg: func() *types.MsgEthereumTx {
authority := s.Keyring.GetKey(0)
target := s.Keyring.GetAddr(1)

accResp, err := s.Handler.GetEvmAccount(authority.Addr)
s.Require().NoError(err)

auth := ethtypes.SetCodeAuthorization{
ChainID: *uint256.NewInt(types.GetChainConfig().GetChainId()),
Address: target,
Nonce: accResp.GetNonce(),
}

args := types.EvmTxArgs{
To: &target,
AuthorizationList: []ethtypes.SetCodeAuthorization{auth},
}
tx, err := s.Factory.GenerateSignedEthTx(s.Keyring.GetPrivKey(0), args)
s.Require().NoError(err)
return tx.GetMsgs()[0].(*types.MsgEthereumTx)
},
expectedErr: nil,
postCheck: func() {
authorityAddr := s.Keyring.GetAddr(0)
codeHash := s.Network.App.GetEVMKeeper().GetCodeHash(s.Network.GetContext(), authorityAddr)
code := s.Network.App.GetEVMKeeper().GetCode(s.Network.GetContext(), codeHash)
_, ok := ethtypes.ParseDelegation(code)
s.Require().False(ok)
s.Require().Len(code, 0)
},
},
}

for _, tc := range testCases {
s.Run(tc.name, func() {
// Fund fee collector account
ctx := s.Network.GetContext()
coins := sdktypes.NewCoins(sdktypes.NewCoin(types.GetEVMCoinDenom(), sdkmath.NewInt(1e18)))
err := s.Network.App.GetBankKeeper().MintCoins(ctx, "mint", coins)
s.Require().NoError(err)
err = s.Network.App.GetBankKeeper().SendCoinsFromModuleToModule(ctx, "mint", "fee_collector", coins)
s.Require().NoError(err)

// Get EthereumTx msg
msg := tc.getMsg()

// Function to be tested
Expand All @@ -66,6 +150,10 @@ func (s *KeeperTestSuite) TestEthereumTx() {
s.Require().True(utils.ContainsEventType(events.ToABCIEvents(), sdktypes.EventTypeMessage))
}

if tc.postCheck != nil {
tc.postCheck()
}

err = s.Network.NextBlock()
s.Require().NoError(err)
})
Expand Down
95 changes: 90 additions & 5 deletions tests/integration/x/vm/test_state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
ethtypes "github.com/ethereum/go-ethereum/core/types"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/holiman/uint256"

"github.com/cometbft/cometbft/crypto/tmhash"
tmproto "github.com/cometbft/cometbft/proto/tendermint/types"
Expand Down Expand Up @@ -837,6 +838,7 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() {
expErr bool
expVMErr bool
expectedGasUsed uint64
postCheck func()
}{
{
"success - messsage applied ok with default params",
Expand All @@ -855,6 +857,87 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() {
false,
false,
params.TxGas,
nil,
},
{
"success - applies set code authorization (EIP-7702)",
func() core.Message {
authority := s.Keyring.GetKey(0)
target := s.Keyring.GetAddr(1)

accResp, err := s.Handler.GetEvmAccount(authority.Addr)
s.Require().NoError(err)

auth := ethtypes.SetCodeAuthorization{
ChainID: *uint256.NewInt(types.GetChainConfig().GetChainId()),
Address: target,
Nonce: accResp.GetNonce(),
}

signedAuth := s.SignSetCodeAuthorization(authority, auth)

msg, err := s.Factory.GenerateGethCoreMsg(authority.Priv, types.EvmTxArgs{
To: &common.Address{},
AuthorizationList: []ethtypes.SetCodeAuthorization{signedAuth},
})
s.Require().NoError(err)
return *msg
},
types.DefaultParams,
feemarkettypes.DefaultParams,
false,
false,
params.TxGas + params.CallNewAccountGas -
keeper.GasToRefund(
params.CallNewAccountGas-params.TxAuthTupleGas,
params.TxGas+params.CallNewAccountGas,
params.RefundQuotientEIP3529,
),
func() {
authorityAddr := s.Keyring.GetAddr(0)
targetAddr := s.Keyring.GetAddr(1)
codeHash := s.Network.App.GetEVMKeeper().GetCodeHash(s.Network.GetContext(), authorityAddr)
code := s.Network.App.GetEVMKeeper().GetCode(s.Network.GetContext(), codeHash)
delegationAddr, ok := ethtypes.ParseDelegation(code)
s.Require().True(ok)
s.Require().Equal(targetAddr, delegationAddr)
},
},
{
"fail - unsigned set code authorization is ignored (EIP-7702)",
func() core.Message {
authority := s.Keyring.GetKey(0)
target := s.Keyring.GetAddr(1)

accResp, err := s.Handler.GetEvmAccount(authority.Addr)
s.Require().NoError(err)

auth := ethtypes.SetCodeAuthorization{
ChainID: *uint256.NewInt(types.GetChainConfig().GetChainId()),
Address: target,
Nonce: accResp.GetNonce(),
}

msg, err := s.Factory.GenerateGethCoreMsg(authority.Priv, types.EvmTxArgs{
To: &common.Address{},
AuthorizationList: []ethtypes.SetCodeAuthorization{auth},
})
s.Require().NoError(err)
return *msg
},
types.DefaultParams,
feemarkettypes.DefaultParams,
false,
false,
params.TxGas + params.CallNewAccountGas,
func() {
authorityAddr := s.Keyring.GetAddr(0)
codeHash := s.Network.App.GetEVMKeeper().GetCodeHash(s.Network.GetContext(), authorityAddr)
code := s.Network.App.GetEVMKeeper().GetCode(s.Network.GetContext(), codeHash)
_, ok := ethtypes.ParseDelegation(code)
s.Require().False(ok)
s.Require().Len(code, 0)
},
},
{
"call contract tx with config param EnableCall = false",
Expand Down Expand Up @@ -882,6 +965,7 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() {
false,
true,
0,
nil,
},
{
"create contract tx with config param EnableCreate = false",
Expand All @@ -907,6 +991,7 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() {
false,
true,
0,
nil,
},
{
"fail - fix panic when minimumGasUsed is not uint64",
Expand All @@ -931,6 +1016,7 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() {
true,
false,
0,
nil,
},
}

Expand Down Expand Up @@ -970,14 +1056,13 @@ func (s *KeeperTestSuite) TestApplyMessageWithConfig() {
s.Require().NoError(err)
s.Require().False(res.Failed())
s.Require().Equal(tc.expectedGasUsed, res.GasUsed)
}

err = s.Network.NextBlock()
if tc.expVMErr {
s.Require().NotEmpty(res.VmError)
return
if tc.postCheck != nil {
tc.postCheck()
}
}

err = s.Network.NextBlock()
if tc.expVMErr {
s.Require().NotEmpty(res.VmError)
return
Expand Down
17 changes: 17 additions & 0 deletions tests/integration/x/vm/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"

"github.com/cosmos/evm/crypto/ethsecp256k1"
servercfg "github.com/cosmos/evm/server/config"
testKeyring "github.com/cosmos/evm/testutil/keyring"
utiltx "github.com/cosmos/evm/testutil/tx"
"github.com/cosmos/evm/x/vm/keeper/testdata"
"github.com/cosmos/evm/x/vm/statedb"
Expand Down Expand Up @@ -204,3 +206,18 @@ func (s *KeeperTestSuite) DeployTestMessageCall(t require.TestingT) common.Addre
require.Empty(t, rsp.VmError)
return crypto.CreateAddress(addr, nonce)
}

func (s *KeeperTestSuite) SignSetCodeAuthorization(authority testKeyring.Key, auth ethtypes.SetCodeAuthorization) ethtypes.SetCodeAuthorization {
s.T().Helper()

privKey, ok := authority.Priv.(*ethsecp256k1.PrivKey)
s.Require().True(ok)

ecdsaPriv, err := privKey.ToECDSA()
s.Require().NoError(err)

signedAuth, err := ethtypes.SignSetCode(ecdsaPriv, auth)
s.Require().NoError(err)

return signedAuth
}
9 changes: 5 additions & 4 deletions testutil/integration/evm/factory/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ func (tf *IntegrationTxFactory) GenerateDefaultTxTypeArgs(sender common.Address,
// EstimateGasLimit estimates the gas limit for a tx with the provided address and txArgs
func (tf *IntegrationTxFactory) EstimateGasLimit(from *common.Address, txArgs *evmtypes.EvmTxArgs) (uint64, error) {
args, err := json.Marshal(evmtypes.TransactionArgs{
Data: (*hexutil.Bytes)(&txArgs.Input),
From: from,
To: txArgs.To,
AccessList: txArgs.Accesses,
Data: (*hexutil.Bytes)(&txArgs.Input),
From: from,
To: txArgs.To,
AccessList: txArgs.Accesses,
AuthorizationList: txArgs.AuthorizationList,
})
if err != nil {
return 0, errorsmod.Wrap(err, "failed to marshal tx args")
Expand Down
Loading