Skip to content

Commit

Permalink
fix(evm): gas prices (#1982)
Browse files Browse the repository at this point in the history
* fix(evm): mempool fee checker

* Update evmante_handler.go

* feat: add GetEffectiveGasPrice to MsgEthereumTx

* refactor: use less local variables by inlining expressions

* fix: set correct block gas used

* refactor: remove GetBaseFeeNoCfg

* feat(evm): add global_min_gas_price

* refactor: rename K to EvmKeeper in tests

* refactor: clean up doc and rename test

* feat(evm): default 1unibi for global gas price

* feat(evm): add GlobalGasPriceDecorator ante handler

* feat(evm): add GlobalGasPriceDecorator ante handler

* feat(evm): hard-code baseFee to 1unibi for now

* Update CHANGELOG.md

* fix: bigint to dec comparison

* fix: base fee query default

* fix: adjust for gas price in e2e tests

* chore(evm): rip out GlobalGasPriceDecorator

* chore(evm): rip out GlobalMinGasPrice

* Update gas_fees.go

* Update evmante_handler.go
  • Loading branch information
k-yang authored Aug 6, 2024
1 parent 3c73f03 commit d7092f3
Show file tree
Hide file tree
Showing 24 changed files with 248 additions and 271 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [#1976](https://github.com/NibiruChain/nibiru/pull/1976) - refactor(evm): unique chain ids for all networks
- [#1977](https://github.com/NibiruChain/nibiru/pull/1977) - fix(localnet): rolled back change of evm validator address with cosmos derivation path
- [#1981](https://github.com/NibiruChain/nibiru/pull/1981) - fix(evm): remove isCheckTx() short circuit on `AnteDecVerifyEthAcc`
- [#1979](https://github.com/NibiruChain/nibiru/pull/1979) -refactor(db): use pebbledb as the default db in integration tests
- [#1979](https://github.com/NibiruChain/nibiru/pull/1979) - refactor(db): use pebbledb as the default db in integration tests
- [#1982](https://github.com/NibiruChain/nibiru/pull/1982) - feat(evm): add GlobalMinGasPrices

#### Dapp modules: perp, spot, oracle, etc

Expand Down
98 changes: 0 additions & 98 deletions app/evmante/evmante_fees.go

This file was deleted.

3 changes: 1 addition & 2 deletions app/evmante/evmante_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ func NewAnteHandlerEVM(
return sdk.ChainAnteDecorators(
// outermost AnteDecorator. SetUpContext must be called first
NewEthSetUpContextDecorator(&options.EvmKeeper),
// Check eth effective gas price against the global MinGasPrice
NewEthMinGasPriceDecorator(&options.EvmKeeper),
NewMempoolGasPriceDecorator(&options.EvmKeeper),
NewEthValidateBasicDecorator(&options.EvmKeeper),
NewEthSigVerificationDecorator(&options.EvmKeeper),
NewAnteDecVerifyEthAcc(&options.EvmKeeper, options.AccountKeeper),
Expand Down
72 changes: 72 additions & 0 deletions app/evmante/evmante_mempool_fees.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) 2023-2024 Nibi, Inc.
package evmante

import (
"cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
errortypes "github.com/cosmos/cosmos-sdk/types/errors"

"github.com/NibiruChain/nibiru/x/evm"
)

var _ sdk.AnteDecorator = MempoolGasPriceDecorator{}

// MempoolGasPriceDecorator will check if the transaction's fee is at least as large
// as the mempool MinGasPrices param. If fee is too low, decorator returns error and tx
// is rejected. This applies to CheckTx only.
// If fee is high enough, then call next AnteHandler
type MempoolGasPriceDecorator struct {
evmKeeper EVMKeeper
}

// NewMempoolGasPriceDecorator creates a new MinGasPriceDecorator instance used only for
// Ethereum transactions.
func NewMempoolGasPriceDecorator(k EVMKeeper) MempoolGasPriceDecorator {
return MempoolGasPriceDecorator{
evmKeeper: k,
}
}

// AnteHandle ensures that the effective fee from the transaction is greater than the
// local mempool gas prices, which is defined by the MinGasPrice (parameter) * GasLimit (tx argument).
func (d MempoolGasPriceDecorator) AnteHandle(
ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler,
) (newCtx sdk.Context, err error) {
// only run on CheckTx
if !ctx.IsCheckTx() && !simulate {
return next(ctx, tx, simulate)
}

minGasPrice := ctx.MinGasPrices().AmountOf(d.evmKeeper.GetParams(ctx).EvmDenom)
// if MinGasPrices is not set, skip the check
if minGasPrice.IsZero() {
return next(ctx, tx, simulate)
}

baseFee := d.evmKeeper.GetBaseFee(ctx)

for _, msg := range tx.GetMsgs() {
ethTx, ok := msg.(*evm.MsgEthereumTx)
if !ok {
return ctx, errors.Wrapf(
errortypes.ErrUnknownRequest,
"invalid message type %T, expected %T",
msg, (*evm.MsgEthereumTx)(nil),
)
}

effectiveGasPrice := ethTx.GetEffectiveGasPrice(baseFee)

if sdk.NewDecFromBigInt(effectiveGasPrice).LT(minGasPrice) {
return ctx, errors.Wrapf(
errortypes.ErrInsufficientFee,
"provided gas price < minimum local gas price (%s < %s). "+
"Please increase the priority tip (for EIP-1559 txs) or the gas prices "+
"(for access list or legacy txs)",
effectiveGasPrice.String(), minGasPrice.String(),
)
}
}

return next(ctx, tx, simulate)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/NibiruChain/nibiru/x/evm/evmtest"
)

func (s *TestSuite) TestEthMinGasPriceDecorator() {
func (s *TestSuite) TestMempoolGasFeeDecorator() {
testCases := []struct {
name string
txSetup func(deps *evmtest.TestDeps) sdk.Tx
Expand Down Expand Up @@ -82,7 +82,7 @@ func (s *TestSuite) TestEthMinGasPriceDecorator() {
for _, tc := range testCases {
s.Run(tc.name, func() {
deps := evmtest.NewTestDeps()
anteDec := evmante.NewEthMinGasPriceDecorator(&deps.Chain.AppKeepers.EvmKeeper)
anteDec := evmante.NewMempoolGasPriceDecorator(&deps.Chain.AppKeepers.EvmKeeper)

tx := tc.txSetup(&deps)

Expand Down
2 changes: 1 addition & 1 deletion app/evmante/evmante_validate_basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ func (s *TestSuite) TestEthValidateBasicDecorator() {
tc.ctxSetup(&deps)
}
if tc.paramsSetup != nil {
deps.K.SetParams(deps.Ctx, tc.paramsSetup(&deps))
deps.EvmKeeper.SetParams(deps.Ctx, tc.paramsSetup(&deps))
}
_, err := anteDec.AnteHandle(
deps.Ctx, tx, false, evmtest.NextNoOpAnteHandler,
Expand Down
4 changes: 1 addition & 3 deletions e2e/evm/test/basic_queries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ describe("Basic Queries", () => {
const senderBalanceAfter = await provider.getBalance(account)
const recipientBalanceAfter = await provider.getBalance(alice)

// TODO: https://github.com/NibiruChain/nibiru/issues/1902
// gas is not deducted regardless the gas limit, check this
const expectedSenderBalance = senderBalanceBefore - amountToSend
const expectedSenderBalance = senderBalanceBefore - amountToSend - 50000n // 50k gas for the transaction
expect(senderBalanceAfter).toEqual(expectedSenderBalance)
expect(recipientBalanceAfter).toEqual(amountToSend)
}, 20e3)
Expand Down
20 changes: 10 additions & 10 deletions e2e/evm/test/contract_send_nibi.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it } from "bun:test"; // eslint-disable-line import/no-unresolved
import { ethers, toBigInt } from "ethers";
import { toBigInt, Wallet } from "ethers";
import { SendNibiCompiled__factory } from "../types/ethers-contracts";
import { account, provider } from "./setup";

Expand All @@ -10,7 +10,7 @@ describe("Send NIBI via smart contract", async () => {
expect(contract.getAddress()).resolves.toBeDefined()

it("should send via transfer method", async () => {
const recipient = ethers.Wallet.createRandom()
const recipient = Wallet.createRandom()
const transferValue = toBigInt(100e6) // NIBI

const ownerBalanceBefore = await provider.getBalance(account) // NIBI
Expand All @@ -20,16 +20,16 @@ describe("Send NIBI via smart contract", async () => {
const tx = await contract.sendViaTransfer(recipient, {
value: transferValue,
})
await tx.wait(1, 5e3)
const receipt = await tx.wait(1, 5e3)

expect(provider.getBalance(account)).resolves.toBe(
ownerBalanceBefore - transferValue,
ownerBalanceBefore - transferValue - receipt.gasUsed,
)
expect(provider.getBalance(recipient)).resolves.toBe(transferValue)
}, 20e3)

it("should send via send method", async () => {
const recipient = ethers.Wallet.createRandom()
const recipient = Wallet.createRandom()
const transferValue = toBigInt(100e6) // NIBI

const ownerBalanceBefore = await provider.getBalance(account) // NIBI
Expand All @@ -39,16 +39,16 @@ describe("Send NIBI via smart contract", async () => {
const tx = await contract.sendViaSend(recipient, {
value: transferValue,
})
await tx.wait(1, 5e3)
const receipt = await tx.wait(1, 5e3)

expect(provider.getBalance(account)).resolves.toBe(
ownerBalanceBefore - transferValue,
ownerBalanceBefore - transferValue - receipt.gasUsed,
)
expect(provider.getBalance(recipient)).resolves.toBe(transferValue)
}, 20e3)

it("should send via transfer method", async () => {
const recipient = ethers.Wallet.createRandom()
const recipient = Wallet.createRandom()
const transferValue = toBigInt(100e6) // NIBI

const ownerBalanceBefore = await provider.getBalance(account) // NIBI
Expand All @@ -58,10 +58,10 @@ describe("Send NIBI via smart contract", async () => {
const tx = await contract.sendViaCall(recipient, {
value: transferValue,
})
await tx.wait(1, 5e3)
const receipt = await tx.wait(1, 5e3)

expect(provider.getBalance(account)).resolves.toBe(
ownerBalanceBefore - transferValue,
ownerBalanceBefore - transferValue - receipt.gasUsed,
)
expect(provider.getBalance(recipient)).resolves.toBe(transferValue)
}, 20e3)
Expand Down
Loading

0 comments on commit d7092f3

Please sign in to comment.