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

fix(rpc): patch gas used api for block less than upgrade height #1557

Merged
merged 14 commits into from
Jan 16, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (analytics) [#1434](https://github.com/evmos/ethermint/pull/1434) Remove unbound labels from custom tendermint metrics.
* (rpc) [#1484](https://github.com/evmos/ethermint/pull/1484) Align empty account result for old blocks as ethereum instead of return account not found error.
* (rpc) [#1503](https://github.com/evmos/ethermint/pull/1503) Fix block hashes returned on JSON-RPC filter `eth_newBlockFilter`.
* (rpc) [#1557](https://github.com/evmos/ethermint/pull/1557) Patch GasUsed before the fix of revert gas refund logic when transaction reverted for `eth_getTransactionReceipt`.
* (ante) [#1566](https://github.com/evmos/ethermint/pull/1566) Fix `gasWanted` on `EthGasConsumeDecorator` ante handler when running transaction in `ReCheckMode`

## [v0.19.3] - 2022-10-14
Expand Down
16 changes: 13 additions & 3 deletions rpc/backend/tx_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package backend

import (
"fmt"
"math/big"

errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -131,6 +132,17 @@ func (b *Backend) getTransactionByHashPending(txHash common.Hash) (*rpctypes.RPC
return nil, nil
}

// GetGasUsed returns gasUsed from transaction
func (b *Backend) GetGasUsed(res *ethermint.TxResult, price *big.Int, gas uint64) uint64 {
// patch gasUsed if tx is reverted and happened before height on which fixed was introduced
// to return real gas charged
// more info at https://github.com/evmos/ethermint/pull/1557
if res.Failed && res.Height < b.cfg.JSONRPC.FixRevertGasRefundHeight {
return new(big.Int).Mul(price, new(big.Int).SetUint64(gas)).Uint64()
}
return res.GasUsed
}

// GetTransactionReceipt returns the transaction receipt identified by hash.
func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) {
hexTx := hash.Hex()
Expand All @@ -141,7 +153,6 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{
b.logger.Debug("tx not found", "hash", hexTx, "error", err.Error())
return nil, nil
}

resBlock, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(res.Height))
if err != nil {
b.logger.Debug("block not found", "height", res.Height, "error", err.Error())
Expand Down Expand Up @@ -177,7 +188,6 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{
} else {
status = hexutil.Uint(ethtypes.ReceiptStatusSuccessful)
}

chainID, err := b.ChainID()
if err != nil {
return nil, err
Expand Down Expand Up @@ -220,7 +230,7 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{
// They are stored in the chain database.
"transactionHash": hash,
"contractAddress": nil,
"gasUsed": hexutil.Uint64(res.GasUsed),
"gasUsed": hexutil.Uint64(b.GetGasUsed(res, txData.GetGasPrice(), txData.GetGas())),

// Inclusion information: These fields provide information about the inclusion of the
// transaction corresponding to this receipt.
Expand Down
56 changes: 56 additions & 0 deletions rpc/backend/tx_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -598,3 +598,59 @@ func (suite *BackendTestSuite) TestGetTransactionReceipt() {
})
}
}

func (suite *BackendTestSuite) TestGetGasUsed() {
origin := suite.backend.cfg.JSONRPC.FixRevertGasRefundHeight
testCases := []struct {
name string
fixRevertGasRefundHeight int64
txResult *ethermint.TxResult
price *big.Int
gas uint64
exp uint64
}{
{
"success txResult",
1,
&ethermint.TxResult{
Height: 1,
Failed: false,
GasUsed: 53026,
},
new(big.Int).SetUint64(0),
0,
53026,
},
{
"fail txResult before cap",
2,
&ethermint.TxResult{
Height: 1,
Failed: true,
GasUsed: 53026,
},
new(big.Int).SetUint64(200000),
5000000000000,
1000000000000000000,
},
{
"fail txResult after cap",
2,
&ethermint.TxResult{
Height: 3,
Failed: true,
GasUsed: 53026,
},
new(big.Int).SetUint64(200000),
5000000000000,
53026,
},
}
for _, tc := range testCases {
suite.Run(fmt.Sprintf("Case %s", tc.name), func() {
suite.backend.cfg.JSONRPC.FixRevertGasRefundHeight = tc.fixRevertGasRefundHeight
suite.Require().Equal(tc.exp, suite.backend.GetGasUsed(tc.txResult, tc.price, tc.gas))
suite.backend.cfg.JSONRPC.FixRevertGasRefundHeight = origin
})
}
}
76 changes: 43 additions & 33 deletions server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ const (
// DefaultEVMTracer is the default vm.Tracer type
DefaultEVMTracer = ""

// DefaultFixRevertGasRefundHeight is the default height at which to overwrite gas refund
DefaultFixRevertGasRefundHeight = 0

DefaultMaxTxGasWanted = 0

DefaultGasCap uint64 = 25000000
Expand All @@ -59,14 +62,17 @@ const (
DefaultBlockRangeCap int32 = 10000

DefaultEVMTimeout = 5 * time.Second

// default 1.0 eth
DefaultTxFeeCap float64 = 1.0

DefaultHTTPTimeout = 30 * time.Second

DefaultHTTPIdleTimeout = 120 * time.Second

// DefaultAllowUnprotectedTxs value is false
DefaultAllowUnprotectedTxs = false

// DefaultMaxOpenConnections represents the amount of open connections (unlimited = 0)
DefaultMaxOpenConnections = 0
)
Expand Down Expand Up @@ -130,6 +136,8 @@ type JSONRPCConfig struct {
EnableIndexer bool `mapstructure:"enable-indexer"`
// MetricsAddress defines the metrics server to listen on
MetricsAddress string `mapstructure:"metrics-address"`
// FixRevertGasRefundHeight defines the upgrade height for fix of revert gas refund logic when transaction reverted
FixRevertGasRefundHeight int64 `mapstructure:"fix-revert-gas-refund-height"`
}

// TLSConfig defines the certificate and matching private key for the server.
Expand Down Expand Up @@ -215,23 +223,24 @@ func GetAPINamespaces() []string {
// DefaultJSONRPCConfig returns an EVM config with the JSON-RPC API enabled by default
func DefaultJSONRPCConfig() *JSONRPCConfig {
return &JSONRPCConfig{
Enable: true,
API: GetDefaultAPINamespaces(),
Address: DefaultJSONRPCAddress,
WsAddress: DefaultJSONRPCWsAddress,
GasCap: DefaultGasCap,
EVMTimeout: DefaultEVMTimeout,
TxFeeCap: DefaultTxFeeCap,
FilterCap: DefaultFilterCap,
FeeHistoryCap: DefaultFeeHistoryCap,
BlockRangeCap: DefaultBlockRangeCap,
LogsCap: DefaultLogsCap,
HTTPTimeout: DefaultHTTPTimeout,
HTTPIdleTimeout: DefaultHTTPIdleTimeout,
AllowUnprotectedTxs: DefaultAllowUnprotectedTxs,
MaxOpenConnections: DefaultMaxOpenConnections,
EnableIndexer: false,
MetricsAddress: DefaultJSONRPCMetricsAddress,
Enable: true,
API: GetDefaultAPINamespaces(),
Address: DefaultJSONRPCAddress,
WsAddress: DefaultJSONRPCWsAddress,
GasCap: DefaultGasCap,
EVMTimeout: DefaultEVMTimeout,
TxFeeCap: DefaultTxFeeCap,
FilterCap: DefaultFilterCap,
FeeHistoryCap: DefaultFeeHistoryCap,
BlockRangeCap: DefaultBlockRangeCap,
LogsCap: DefaultLogsCap,
HTTPTimeout: DefaultHTTPTimeout,
HTTPIdleTimeout: DefaultHTTPIdleTimeout,
AllowUnprotectedTxs: DefaultAllowUnprotectedTxs,
MaxOpenConnections: DefaultMaxOpenConnections,
EnableIndexer: false,
MetricsAddress: DefaultJSONRPCMetricsAddress,
FixRevertGasRefundHeight: DefaultFixRevertGasRefundHeight,
}
}

Expand Down Expand Up @@ -325,22 +334,23 @@ func GetConfig(v *viper.Viper) (Config, error) {
MaxTxGasWanted: v.GetUint64("evm.max-tx-gas-wanted"),
},
JSONRPC: JSONRPCConfig{
Enable: v.GetBool("json-rpc.enable"),
API: v.GetStringSlice("json-rpc.api"),
Address: v.GetString("json-rpc.address"),
WsAddress: v.GetString("json-rpc.ws-address"),
GasCap: v.GetUint64("json-rpc.gas-cap"),
FilterCap: v.GetInt32("json-rpc.filter-cap"),
FeeHistoryCap: v.GetInt32("json-rpc.feehistory-cap"),
TxFeeCap: v.GetFloat64("json-rpc.txfee-cap"),
EVMTimeout: v.GetDuration("json-rpc.evm-timeout"),
LogsCap: v.GetInt32("json-rpc.logs-cap"),
BlockRangeCap: v.GetInt32("json-rpc.block-range-cap"),
HTTPTimeout: v.GetDuration("json-rpc.http-timeout"),
HTTPIdleTimeout: v.GetDuration("json-rpc.http-idle-timeout"),
MaxOpenConnections: v.GetInt("json-rpc.max-open-connections"),
EnableIndexer: v.GetBool("json-rpc.enable-indexer"),
MetricsAddress: v.GetString("json-rpc.metrics-address"),
Enable: v.GetBool("json-rpc.enable"),
API: v.GetStringSlice("json-rpc.api"),
Address: v.GetString("json-rpc.address"),
WsAddress: v.GetString("json-rpc.ws-address"),
GasCap: v.GetUint64("json-rpc.gas-cap"),
FilterCap: v.GetInt32("json-rpc.filter-cap"),
FeeHistoryCap: v.GetInt32("json-rpc.feehistory-cap"),
TxFeeCap: v.GetFloat64("json-rpc.txfee-cap"),
EVMTimeout: v.GetDuration("json-rpc.evm-timeout"),
LogsCap: v.GetInt32("json-rpc.logs-cap"),
BlockRangeCap: v.GetInt32("json-rpc.block-range-cap"),
HTTPTimeout: v.GetDuration("json-rpc.http-timeout"),
HTTPIdleTimeout: v.GetDuration("json-rpc.http-idle-timeout"),
MaxOpenConnections: v.GetInt("json-rpc.max-open-connections"),
EnableIndexer: v.GetBool("json-rpc.enable-indexer"),
MetricsAddress: v.GetString("json-rpc.metrics-address"),
FixRevertGasRefundHeight: v.GetInt64("json-rpc.fix-revert-gas-refund-height"),
},
TLS: TLSConfig{
CertificatePath: v.GetString("tls.certificate-path"),
Expand Down
3 changes: 3 additions & 0 deletions server/config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ enable-indexer = {{ .JSONRPC.EnableIndexer }}
# Prometheus metrics path: /debug/metrics/prometheus
metrics-address = "{{ .JSONRPC.MetricsAddress }}"

# Upgrade height for fix of revert gas refund logic when transaction reverted.
fix-revert-gas-refund-height = {{ .JSONRPC.FixRevertGasRefundHeight }}

###############################################################################
### TLS Configuration ###
###############################################################################
Expand Down
3 changes: 2 additions & 1 deletion server/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ const (
// JSONRPCEnableMetrics enables EVM RPC metrics server.
// Set to `metrics` which is hardcoded flag from go-ethereum.
// https://github.com/ethereum/go-ethereum/blob/master/metrics/metrics.go#L35-L55
JSONRPCEnableMetrics = "metrics"
JSONRPCEnableMetrics = "metrics"
JSONRPCFixRevertGasRefundHeight = "json-rpc.fix-revert-gas-refund-height"
)

// EVM flags
Expand Down
1 change: 1 addition & 0 deletions tests/integration_tests/configs/default.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
'feehistory-cap': 100,
'block-range-cap': 10000,
'logs-cap': 10000,
'fix-revert-gas-refund-height': 1,
mmsqe marked this conversation as resolved.
Show resolved Hide resolved
},
},
validators: [{
Expand Down