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

Fix GasMeter reset in AnteHandler - EthGasConsumeDecorator #964

Merged
merged 15 commits into from
Mar 6, 2022
Merged
Show file tree
Hide file tree
Changes from 11 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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Bug Fixes

* (evm) [\#529](https://github.com/tharsis/ethermint/issues/529) Add support return value on trace tx response.
* (ante) [tharsis#964](https://github.com/tharsis/ethermint/pull/964) fix gas meter reset with user provided gas limit in the innermost EthAnteHandler. Fixes block's consumed gas calculation in the block creation phase.
* (rpc) [#970] (https://github.com/tharsis/ethermint/pull/970) Fix unexpected nil reward values on `eth_feeHistory` response
* (evm) [\#529](https://github.com/tharsis/ethermint/issues/529) support return value on trace tx response.

## Improvements

Expand Down
8 changes: 8 additions & 0 deletions app/ante/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,10 @@ func NewEthIncrementSenderSequenceDecorator(ak evmtypes.AccountKeeper) EthIncrem
// AnteHandle handles incrementing the sequence of the signer (i.e sender). If the transaction is a
// contract creation, the nonce will be incremented during the transaction execution and not within
// this AnteHandler decorator.
// being the innermost decorator, it also resets the GasMeter with a limit
// based on user provided gas limit
func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
gasWanted := uint64(0)
for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
Expand All @@ -321,6 +324,8 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
}

gasWanted += txData.GetGas()

// increase sequence of sender
acc := issd.ak.GetAccount(ctx, msgEthTx.GetFrom())
if acc == nil {
Expand All @@ -347,6 +352,9 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
issd.ak.SetAccount(ctx, acc)
}

// Set ctx.GasMeter to 0, with a limit of GasWanted (gasLimit)
ctx = ctx.WithGasMeter(sdk.NewGasMeter(gasWanted))

return next(ctx, tx, simulate)
}

Expand Down
11 changes: 9 additions & 2 deletions app/ante/eth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
return
}

_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewInfiniteGasMeter()), tc.tx, false, nextFn)
if tc.expPass {
suite.Require().NoError(err)
} else {
Expand Down Expand Up @@ -399,31 +399,36 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
testCases := []struct {
name string
tx sdk.Tx
gasLimit uint64
malleate func()
expPass bool
expPanic bool
}{
{
"invalid transaction type",
&invalidTx{},
0,
func() {},
false, false,
},
{
"no signers",
evmtypes.NewTx(suite.app.EvmKeeper.ChainID(), 1, &to, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
0,
func() {},
false, false,
},
{
"account not set to store",
tx,
0,
func() {},
false, false,
},
{
"success - create contract",
contract,
1000,
func() {
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, addr.Bytes())
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
Expand All @@ -433,6 +438,7 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
{
"success - call",
tx2,
1000,
func() {},
true, false,
},
Expand All @@ -449,7 +455,7 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
return
}

_, err := dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)
ctx, err := dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)

if tc.expPass {
suite.Require().NoError(err)
Expand All @@ -463,6 +469,7 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
} else {
suite.Require().Error(err)
}
suite.Require().Equal(tc.gasLimit, ctx.GasMeter().Limit())
})
}
}
Expand Down
11 changes: 2 additions & 9 deletions x/evm/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,16 +470,9 @@ func (suite *EvmTestSuite) TestOutOfGasWhenDeployContract() {
tx := types.NewTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, nil, nil, bytecode, nil)
suite.SignTx(tx)

defer func() {
if r := recover(); r != nil {
// TODO: snapshotting logic
} else {
suite.Require().Fail("panic did not happen")
}
}()
_, err := suite.handler(suite.ctx, tx)

suite.handler(suite.ctx, tx)
suite.Require().Fail("panic did not happen")
suite.Require().Equal("failed to apply transaction: failed to apply ethereum core message: apply message: intrinsic gas too low", err.Error(), "correct error")
}

func (suite *EvmTestSuite) TestErrorWhenDeployContract() {
Expand Down
2 changes: 2 additions & 0 deletions x/evm/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ var _ types.MsgServer = &Keeper{}
// parameter.
func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*types.MsgEthereumTxResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// reset the gas meter set in EthIncrementSenderSequenceDecorator.AnteHandle
ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())

sender := msg.From
tx := msg.AsTransaction()
Expand Down
2 changes: 1 addition & 1 deletion x/evm/keeper/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ func (k *Keeper) ApplyMessageWithConfig(ctx sdk.Context, msg core.Message, trace
}
leftoverGas := msg.Gas() - intrinsicGas

// access list preparaion is moved from ante handler to here, because it's needed when `ApplyMessage` is called
// access list preparation is moved from ante handler to here, because it's needed when `ApplyMessage` is called
// under contexts where ante handlers are not run, for example `eth_call` and `eth_estimateGas`.
if rules := cfg.ChainConfig.Rules(big.NewInt(ctx.BlockHeight()), cfg.ChainConfig.MergeForkBlock != nil); rules.IsBerlin {
stateDB.PrepareAccessList(msg.From(), msg.To(), vm.ActivePrecompiles(rules), msg.AccessList())
Expand Down