Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

Commit

Permalink
ante: check EnableCreate/EnableCall in ante handler (#1060)
Browse files Browse the repository at this point in the history
* Check EnableCreate/EnableCall in ante handler

WIP: #1045

Reject tx early in ante handler, avoid deduct user fee for vain.

* add unit tests

* update changelog

Co-authored-by: Federico Kunze Küllmer <[email protected]>
Co-authored-by: Federico Kunze Küllmer <[email protected]>
  • Loading branch information
3 people authored May 3, 2022
1 parent 6b1b936 commit 93d15db
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ Ref: https://keepachangelog.com/en/1.0.0/

## Unreleased

### State Machine Breaking

* (ante) [tharsis#1060](https://github.com/tharsis/ethermint/pull/1060) Check `EnableCreate`/`EnableCall` in `AnteHandler` to short-circuit EVM transactions.

### API Breaking

* (rpc) [tharsis#1070](https://github.com/tharsis/ethermint/pull/1070) Refactor `rpc/` package:
Expand Down
137 changes: 136 additions & 1 deletion app/ante/ante_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package ante_test

import (
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"errors"
"math/big"
"strings"

"github.com/cosmos/cosmos-sdk/types/tx/signing"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -685,3 +687,136 @@ func (suite AnteTestSuite) TestAnteHandlerWithDynamicTxFee() {
suite.enableFeemarket = false
suite.enableLondonHF = true
}

func (suite AnteTestSuite) TestAnteHandlerWithParams() {
addr, privKey := tests.NewAddrKey()
to := tests.GenerateAddress()

testCases := []struct {
name string
txFn func() sdk.Tx
enableCall bool
enableCreate bool
expErr error
}{
{
"fail - Contract Creation Disabled",
func() sdk.Tx {
signedContractTx :=
evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
1,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedContractTx.From = addr.Hex()

tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
return tx
},
true, false,
evmtypes.ErrCreateDisabled,
},
{
"success - Contract Creation Enabled",
func() sdk.Tx {
signedContractTx :=
evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
1,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedContractTx.From = addr.Hex()

tx := suite.CreateTestTx(signedContractTx, privKey, 1, false)
return tx
},
true, true,
nil,
},
{
"fail - EVM Call Disabled",
func() sdk.Tx {
signedTx :=
evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(),
1,
&to,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedTx.From = addr.Hex()

tx := suite.CreateTestTx(signedTx, privKey, 1, false)
return tx
},
false, true,
evmtypes.ErrCallDisabled,
},
{
"success - EVM Call Enabled",
func() sdk.Tx {
signedTx :=
evmtypes.NewTx(
suite.app.EvmKeeper.ChainID(),
1,
&to,
big.NewInt(10),
100000,
nil,
big.NewInt(ethparams.InitialBaseFee+1),
big.NewInt(1),
nil,
&types.AccessList{},
)
signedTx.From = addr.Hex()

tx := suite.CreateTestTx(signedTx, privKey, 1, false)
return tx
},
true, true,
nil,
},
}

for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.evmParamsOption = func(params *evmtypes.Params) {
params.EnableCall = tc.enableCall
params.EnableCreate = tc.enableCreate
}
suite.SetupTest() // reset

acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.Require().NoError(acc.SetSequence(1))
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)

suite.ctx = suite.ctx.WithIsCheckTx(true)
suite.app.EvmKeeper.SetBalance(suite.ctx, addr, big.NewInt((ethparams.InitialBaseFee+10)*100000))
_, err := suite.anteHandler(suite.ctx, tc.txFn(), false)
if tc.expErr == nil {
suite.Require().NoError(err)
} else {
suite.Require().Error(err)
suite.Require().True(errors.Is(err, tc.expErr))
}
})
}
suite.evmParamsOption = nil
}
17 changes: 13 additions & 4 deletions app/ante/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,22 +410,31 @@ func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu
txFee := sdk.Coins{}
txGasLimit := uint64(0)

params := vbd.evmKeeper.GetParams(ctx)
chainID := vbd.evmKeeper.ChainID()
ethCfg := params.ChainConfig.EthereumConfig(chainID)
baseFee := vbd.evmKeeper.GetBaseFee(ctx, ethCfg)

for _, msg := range protoTx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid message type %T, expected %T", msg, (*evmtypes.MsgEthereumTx)(nil))
}

txGasLimit += msgEthTx.GetGas()

txData, err := evmtypes.UnpackTxData(msgEthTx.Data)
if err != nil {
return ctx, sdkerrors.Wrap(err, "failed to unpack MsgEthereumTx Data")
}

params := vbd.evmKeeper.GetParams(ctx)
chainID := vbd.evmKeeper.ChainID()
ethCfg := params.ChainConfig.EthereumConfig(chainID)
baseFee := vbd.evmKeeper.GetBaseFee(ctx, ethCfg)
// return error if contract creation or call are disabled through governance
if !params.EnableCreate && txData.GetTo() == nil {
return ctx, sdkerrors.Wrap(evmtypes.ErrCreateDisabled, "failed to create new contract")
} else if !params.EnableCall && txData.GetTo() != nil {
return ctx, sdkerrors.Wrap(evmtypes.ErrCallDisabled, "failed to call contract")
}

if baseFee == nil && txData.TxType() == ethtypes.DynamicFeeTxType {
return ctx, sdkerrors.Wrap(ethtypes.ErrTxTypeNotSupported, "dynamic fee tx not supported")
}
Expand Down
8 changes: 6 additions & 2 deletions app/ante/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type AnteTestSuite struct {
ethSigner ethtypes.Signer
enableFeemarket bool
enableLondonHF bool
evmParamsOption func(*evmtypes.Params)
}

func (suite *AnteTestSuite) StateDB() *statedb.StateDB {
Expand All @@ -71,14 +72,17 @@ func (suite *AnteTestSuite) SetupTest() {
suite.Require().NoError(err)
genesis[feemarkettypes.ModuleName] = app.AppCodec().MustMarshalJSON(feemarketGenesis)
}
evmGenesis := evmtypes.DefaultGenesisState()
if !suite.enableLondonHF {
evmGenesis := evmtypes.DefaultGenesisState()
maxInt := sdk.NewInt(math.MaxInt64)
evmGenesis.Params.ChainConfig.LondonBlock = &maxInt
evmGenesis.Params.ChainConfig.ArrowGlacierBlock = &maxInt
evmGenesis.Params.ChainConfig.MergeForkBlock = &maxInt
genesis[evmtypes.ModuleName] = app.AppCodec().MustMarshalJSON(evmGenesis)
}
if suite.evmParamsOption != nil {
suite.evmParamsOption(&evmGenesis.Params)
}
genesis[evmtypes.ModuleName] = app.AppCodec().MustMarshalJSON(evmGenesis)
return genesis
})

Expand Down

0 comments on commit 93d15db

Please sign in to comment.