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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (rpc) [#562](https://github.com/crypto-org-chain/ethermint/pull/562) Fix nil pointer panic with legacy transaction format.
* (evm) [#567](https://github.com/crypto-org-chain/ethermint/pull/567) Fix nonce management in batch transaction.
* (rpc) [#577](https://github.com/crypto-org-chain/ethermint/pull/577) Fix eth_getLogs miss logs with batch transactions.
* (rpc) [#574](https://github.com/crypto-org-chain/ethermint/pull/574) Fix incorrect spendable balance when debug trace tx.

### Improvements

Expand Down Expand Up @@ -108,6 +109,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* [#549](https://github.com/crypto-org-chain/ethermint/pull/549) Support build without cgo.
* [#551](https://github.com/crypto-org-chain/ethermint/pull/551) Start event stream on demand.
* [#555](https://github.com/crypto-org-chain/ethermint/pull/555) Update cometbft to 0.38.14 and rocksdb to 9.7.4.
* [#576](https://github.com/crypto-org-chain/ethermint/pull/576) Add config `json-rpc.restrict-user-input` to restrict

## v0.21.x-cronos

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ replace (
// use cosmos keyring
github.com/99designs/keyring => github.com/cosmos/keyring v1.2.0
// v0.38.x
github.com/cometbft/cometbft => github.com/yihuang/cometbft v0.38.0-alpha.1.0.20241106081635-f702b8b3f890
github.com/cometbft/cometbft => github.com/crypto-org-chain/cometbft v0.0.0-20241106091515-ce418f845d9a
// release/v1.11.x
github.com/ethereum/go-ethereum => github.com/crypto-org-chain/go-ethereum v1.10.20-0.20241030073450-b9cc632bc183
// Fix upstream GHSA-h395-qcrw-5vmq vulnerability.
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/crypto-org-chain/btree v0.0.0-20240406140148-2687063b042c h1:MOgfS4+FBB8cMkDE2j2VBVsbY+HCkPIu0YsJ/9bbGeQ=
github.com/crypto-org-chain/btree v0.0.0-20240406140148-2687063b042c/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
github.com/crypto-org-chain/cometbft v0.0.0-20241106091515-ce418f845d9a h1:0EN1TkzHTAxpgpGaZJY3G7L4jf4+sYnI7FOmBFLCg4U=
github.com/crypto-org-chain/cometbft v0.0.0-20241106091515-ce418f845d9a/go.mod h1:khbgmtxbgwJfMqDmnGY4rl2sQpTdzpPb1f9nqnfpy1o=
github.com/crypto-org-chain/cosmos-sdk v0.50.6-0.20241015015202-783e224f9517 h1:iRnJMiquXPE3OpVX8ENCrcstfd7mI206yC3Bkl6WeK4=
github.com/crypto-org-chain/cosmos-sdk v0.50.6-0.20241015015202-783e224f9517/go.mod h1:JwwsMeZldLN20b72mmbWPY0EV9rs+v/12hRu1JFttvY=
github.com/crypto-org-chain/cosmos-sdk/store v0.0.0-20241015015202-783e224f9517 h1:y3i8TiU7E60zmbpLyo4PqrnwZaWNU3kizU+1OezuoA8=
Expand Down Expand Up @@ -1110,8 +1112,6 @@ github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yihuang/cometbft v0.38.0-alpha.1.0.20241106081635-f702b8b3f890 h1:JQCpo2LIqYcPCS7QPfxeDheCUfN/NGTB6aUAmlA/fi0=
github.com/yihuang/cometbft v0.38.0-alpha.1.0.20241106081635-f702b8b3f890/go.mod h1:khbgmtxbgwJfMqDmnGY4rl2sQpTdzpPb1f9nqnfpy1o=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down
6 changes: 3 additions & 3 deletions gomod2nix.toml

Large diffs are not rendered by default.

38 changes: 36 additions & 2 deletions rpc/namespaces/ethereum/debug/trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@
import (
"errors"
"os"
"path/filepath"
"runtime/trace"
"strings"

stderrors "github.com/pkg/errors"

srvflags "github.com/evmos/ethermint/server/flags"
)

// StartGoTrace turns on tracing, writing to the given file.
Expand All @@ -33,16 +37,46 @@
a.handler.mu.Lock()
defer a.handler.mu.Unlock()

restrictUserInput := a.ctx.Viper.GetBool(srvflags.JSONRPCRestrictUserInput)

Check warning on line 41 in rpc/namespaces/ethereum/debug/trace.go

View check run for this annotation

Codecov / codecov/patch

rpc/namespaces/ethereum/debug/trace.go#L40-L41

Added lines #L40 - L41 were not covered by tests
if a.handler.traceFile != nil {
a.logger.Debug("trace already in progress")
return errors.New("trace already in progress")
}
fp, err := ExpandHome(file)
var err error
file, err = ExpandHome(file)

Check warning on line 47 in rpc/namespaces/ethereum/debug/trace.go

View check run for this annotation

Codecov / codecov/patch

rpc/namespaces/ethereum/debug/trace.go#L46-L47

Added lines #L46 - L47 were not covered by tests
if err != nil {
a.logger.Debug("failed to get filepath for the CPU profile file", "error", err.Error())
return err
}
f, err := os.Create(fp)

file, err = filepath.Abs(file)
if err != nil {
a.logger.Debug("failed to get absolute path for the CPU profile file", "error", err.Error())
return err
}

Check warning on line 57 in rpc/namespaces/ethereum/debug/trace.go

View check run for this annotation

Codecov / codecov/patch

rpc/namespaces/ethereum/debug/trace.go#L53-L57

Added lines #L53 - L57 were not covered by tests

if restrictUserInput {
// Ensure that the trace file is in the data directory.
absDataDir, err := filepath.Abs(a.ctx.Config.RootDir)
if err != nil {
a.logger.Debug("failed to get absolute path for the data directory", "error", err.Error())
return err
}

Check warning on line 65 in rpc/namespaces/ethereum/debug/trace.go

View check run for this annotation

Codecov / codecov/patch

rpc/namespaces/ethereum/debug/trace.go#L59-L65

Added lines #L59 - L65 were not covered by tests

if !strings.HasPrefix(file, absDataDir) {
a.logger.Debug("trace file must be in the data directory")
return errors.New("trace file must be in the data directory")
}

Check warning on line 70 in rpc/namespaces/ethereum/debug/trace.go

View check run for this annotation

Codecov / codecov/patch

rpc/namespaces/ethereum/debug/trace.go#L67-L70

Added lines #L67 - L70 were not covered by tests
}

var f *os.File
if restrictUserInput {
// Create the file with O_EXCL to ensure that the file does not exist.
f, err = os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o666)
} else {
f, err = os.Create(file)
}

Check warning on line 79 in rpc/namespaces/ethereum/debug/trace.go

View check run for this annotation

Codecov / codecov/patch

rpc/namespaces/ethereum/debug/trace.go#L73-L79

Added lines #L73 - L79 were not covered by tests
if err != nil {
a.logger.Debug("failed to create go trace file", "error", err.Error())
return err
Expand Down
5 changes: 5 additions & 0 deletions server/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@
FixRevertGasRefundHeight int64 `mapstructure:"fix-revert-gas-refund-height"`
// ReturnDataLimit defines maximum number of bytes returned from `eth_call` or similar invocations
ReturnDataLimit int64 `mapstructure:"return-data-limit"`
// RestrictUserInput will restrict some user input to the JSON-RPC debug apis,
// must be set to true if serving debug namespace to the public.
RestrictUserInput bool `mapstructure:"restrict-user-input"`
}

// TLSConfig defines the certificate and matching private key for the server.
Expand Down Expand Up @@ -300,6 +303,7 @@
MetricsAddress: DefaultJSONRPCMetricsAddress,
FixRevertGasRefundHeight: DefaultFixRevertGasRefundHeight,
ReturnDataLimit: DefaultReturnDataLimit,
RestrictUserInput: false,
}
}

Expand Down Expand Up @@ -435,8 +439,9 @@
MetricsAddress: v.GetString("json-rpc.metrics-address"),
FixRevertGasRefundHeight: v.GetInt64("json-rpc.fix-revert-gas-refund-height"),
ReturnDataLimit: v.GetInt64("json-rpc.return-data-limit"),
RestrictUserInput: v.GetBool("json-rpc.restrict-user-input"),
},
TLS: TLSConfig{

Check warning on line 444 in server/config/config.go

View check run for this annotation

Codecov / codecov/patch

server/config/config.go#L442-L444

Added lines #L442 - L444 were not covered by tests
CertificatePath: v.GetString("tls.certificate-path"),
KeyPath: v.GetString("tls.key-path"),
},
Expand Down
4 changes: 4 additions & 0 deletions server/config/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ fix-revert-gas-refund-height = {{ .JSONRPC.FixRevertGasRefundHeight }}
# Maximum number of bytes returned from eth_call or similar invocations.
return-data-limit = {{ .JSONRPC.ReturnDataLimit }}

# RestrictUserInput will restrict some user input to the JSON-RPC debug apis,
# must be set to true if serving debug namespace to the public.
restrict-user-input = {{ .JSONRPC.RestrictUserInput }}

###############################################################################
### TLS Configuration ###
###############################################################################
Expand Down
1 change: 1 addition & 0 deletions server/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const (
JSONRPCEnableMetrics = "metrics"
JSONRPCFixRevertGasRefundHeight = "json-rpc.fix-revert-gas-refund-height"
JSONRPCReturnDataLimit = "json-rpc.return-data-limit"
JSONRPCRestrictUserInput = "json-rpc.restrict-user-input"
)

// EVM flags
Expand Down
1 change: 1 addition & 0 deletions server/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ which accepts a path for the resulting pprof file.
cmd.Flags().Int(srvflags.JSONRPCMaxOpenConnections, config.DefaultMaxOpenConnections, "Sets the maximum number of simultaneous connections for the server listener") //nolint:lll
cmd.Flags().Bool(srvflags.JSONRPCEnableIndexer, false, "Enable the custom tx indexer for json-rpc")
cmd.Flags().Bool(srvflags.JSONRPCAllowIndexerGap, true, "Allow block gap for the custom tx indexer for json-rpc")
cmd.Flags().Bool(srvflags.JSONRPCRestrictUserInput, false, "Restrict some user input to the JSON-RPC debug apis, must be set to true if serving debug namespace to the public") //nolint:lll
cmd.Flags().Bool(srvflags.JSONRPCEnableMetrics, false, "Define if EVM rpc metrics server should be enabled")

cmd.Flags().String(srvflags.EVMTracer, config.DefaultEVMTracer, "the EVM tracer type to collect execution traces from the EVM transaction execution (json|struct|access_list|markdown)") //nolint:lll
Expand Down
19 changes: 19 additions & 0 deletions tests/integration_tests/hardhat/contracts/SelfDestruct.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SelfDestruct {
address payable recipient = payable(0x0F0cb39319129BA867227e5Aae1abe9e7dd5f861);
address payable owner;

constructor() {
owner = payable(msg.sender);
}

receive() external payable {}

function execute() public payable {
require(msg.sender == owner, string(abi.encodePacked("Unauthorized caller: ", msg.sender, " Owner: ", owner)));
payable(recipient).transfer(msg.value);
selfdestruct(owner);
}
}
52 changes: 52 additions & 0 deletions tests/integration_tests/test_tracers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
from concurrent.futures import ThreadPoolExecutor, as_completed

import pytest
from web3 import Web3

from .expected_constants import (
Expand All @@ -24,6 +25,7 @@
send_txs,
sign_transaction,
w3_wait_for_new_blocks,
wait_for_fn,
)


Expand Down Expand Up @@ -191,6 +193,56 @@ def test_trace_tx_reverse_transfer(ethermint):
print(tx_res)


@pytest.mark.flaky(max_runs=10)
def test_destruct(ethermint):
method = "debug_traceTransaction"
tracer = {"tracer": "callTracer"}
receiver = "0x0F0cb39319129BA867227e5Aae1abe9e7dd5f861"
acc = derive_new_account(11) # ethm13c2n7geavjfsqcan290mq74kajjlxehyzhly4p
w3 = ethermint.w3
fund_acc(w3, acc, fund=3077735635376769427)
sender = acc.address
raw_transactions = []
contracts = []
total = 3
for _ in range(total):
contract, _ = deploy_contract(w3, CONTRACTS["SelfDestruct"], key=acc.key)
contracts.append(contract)

nonce = w3.eth.get_transaction_count(sender)

for i in range(total):
tx = (
contracts[i]
.functions.execute()
.build_transaction(
{
"from": sender,
"nonce": nonce,
"gas": 167115,
"gasPrice": 5050000000000,
"value": 353434350000000000,
}
)
)
raw_transactions.append(sign_transaction(w3, tx, acc.key).rawTransaction)
nonce += 1
sended_hash_set = send_raw_transactions(w3, raw_transactions)

def wait_balance():
return w3.eth.get_balance(receiver) > 0

wait_for_fn("wait_balance", wait_balance)
for h in sended_hash_set:
tx_hash = h.hex()
res = w3.provider.make_request(
method,
[tx_hash, tracer],
)
print(tx_hash, res)
assert "insufficient funds" not in res, res


def test_tracecall_insufficient_funds(ethermint, geth):
method = "debug_traceCall"
acc = derive_random_account()
Expand Down
1 change: 1 addition & 0 deletions tests/integration_tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"Random": "Random.sol",
"TestBlockTxProperties": "TestBlockTxProperties.sol",
"FeeCollector": "FeeCollector.sol",
"SelfDestruct": "SelfDestruct.sol",
}


Expand Down
26 changes: 16 additions & 10 deletions x/evm/keeper/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,11 @@ func (k *Keeper) ApplyMessageWithConfig(
leftoverGas := msg.GasLimit
sender := vm.AccountRef(msg.From)
tracer := cfg.GetTracer()
debugFn := func() {
if tracer != nil && cfg.DebugTrace {
stateDB.AddBalance(sender.Address(), new(big.Int).Mul(msg.GasPrice, new(big.Int).SetUint64(leftoverGas)))
}
}
if tracer != nil {
if cfg.DebugTrace {
amount := new(big.Int).Mul(msg.GasPrice, new(big.Int).SetUint64(msg.GasLimit))
Expand All @@ -337,9 +342,7 @@ func (k *Keeper) ApplyMessageWithConfig(
}
tracer.CaptureTxStart(leftoverGas)
defer func() {
if cfg.DebugTrace {
stateDB.AddBalance(sender.Address(), new(big.Int).Mul(msg.GasPrice, new(big.Int).SetUint64(leftoverGas)))
}
debugFn()
tracer.CaptureTxEnd(leftoverGas)
}()
}
Expand Down Expand Up @@ -404,13 +407,6 @@ func (k *Keeper) ApplyMessageWithConfig(
vmError = vmErr.Error()
}

// The dirty states in `StateDB` is either committed or discarded after return
if commit {
if err := stateDB.Commit(); err != nil {
return nil, errorsmod.Wrap(err, "failed to commit stateDB")
}
}

// calculate a minimum amount of gas to be charged to sender if GasLimit
// is considerably higher than GasUsed to stay more aligned with Tendermint gas mechanics
// for more info https://github.com/evmos/ethermint/issues/1085
Expand Down Expand Up @@ -438,6 +434,16 @@ func (k *Keeper) ApplyMessageWithConfig(
// reset leftoverGas, to be used by the tracer
leftoverGas = msg.GasLimit - gasUsed

debugFn()
debugFn = func() {}

// The dirty states in `StateDB` is either committed or discarded after return
if commit {
if err := stateDB.Commit(); err != nil {
return nil, errorsmod.Wrap(err, "failed to commit stateDB")
}
}

return &types.MsgEthereumTxResponse{
GasUsed: gasUsed,
VmError: vmError,
Expand Down
Loading