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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

* (evm) [#725](https://github.com/crypto-org-chain/ethermint/pull/725) feat(RPC): add authorizationList from eth_getTransactionByHash response for EIP-7702 transactions
* (evm) [#740](https://github.com/crypto-org-chain/ethermint/pull/740) fix: missing tx context during vm initialisation
* (evm) [#742](https://github.com/crypto-org-chain/ethermint/pull/742) fix: prevent nil pointer dereference in tracer hooks

## [v0.22.0] - 2025-08-12

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@
pragma solidity ^0.8.0;

contract TestBlockTxProperties {
event TxDetailsEvent(
address indexed origin,
address indexed sender,
uint value,
bytes data,
uint gas,
uint gasprice,
bytes4 sig
);

function emitTxDetails() public payable {
emit TxDetailsEvent(tx.origin, msg.sender, msg.value, msg.data, gasleft(), tx.gasprice, msg.sig);
}

function getBlockHash(uint256 blockNumber) public view returns (bytes32) {
return blockhash(blockNumber);
}
Expand Down
25 changes: 24 additions & 1 deletion tests/integration_tests/test_block.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from eth_utils.crypto import keccak
from web3 import Web3

from .utils import CONTRACTS, deploy_contract, w3_wait_for_new_blocks
from .utils import ADDRS, CONTRACTS, deploy_contract, w3_wait_for_new_blocks


def test_call(ethermint):
Expand All @@ -11,3 +12,25 @@ def test_call(ethermint):
res = Web3.to_hex(contract.caller.getBlockHash(height))
blk = w3.eth.get_block(height)
assert res == Web3.to_hex(blk.hash), res


def test_block_tx_properties(ethermint):
w3 = ethermint.w3
contract, _ = deploy_contract(w3, CONTRACTS["TestBlockTxProperties"])
acc = ADDRS["community"]
gas_price = w3.eth.gas_price
tx_hash = contract.functions.emitTxDetails().transact(
{"from": acc, "gas": 200000, "gasPrice": gas_price}
)
tx_hash = Web3.to_hex(tx_hash)
tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash)
tx_details_event = contract.events.TxDetailsEvent().process_receipt(tx_receipt)
assert tx_details_event is not None
data = tx_details_event[0]["args"]
print("event_data: ", data)
assert data["origin"].lower() == acc.lower()
assert data["sender"].lower() == acc.lower()
assert data["value"] == 0
expected_sig = keccak(b"emitTxDetails()")[:4]
assert data["sig"] == data["data"] == expected_sig
assert data["gasprice"] == gas_price
98 changes: 98 additions & 0 deletions tests/integration_tests/test_tracers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
EXPECTED_STRUCT_TRACER,
)
from .utils import (
ACCOUNTS,
ADDRS,
CONTRACTS,
create_contract_transaction,
Expand Down Expand Up @@ -754,3 +755,100 @@ def process(w3):
assert isinstance(res[0], exceptions.ContractLogicError)
assert isinstance(res[-1], exceptions.ContractLogicError)
assert str(res[0]) == str(res[-1]) == "('execution reverted', '0x')"


def test_4byte_tracer_intrinsic_gas_too_low(ethermint, geth):
method = "debug_traceCall"
tracer = {"tracer": "4byteTracer"}
acc = derive_new_account(6)

tx = {
"from": ACCOUNTS["community"].address,
"to": acc.address,
"gas": "0x4e29",
}

def process(w3):
tx_res = w3.provider.make_request(method, [tx, "latest", tracer])
return json.dumps(tx_res["error"], sort_keys=True)

providers = [ethermint.w3, geth.w3]
with ThreadPoolExecutor(len(providers)) as exec:
tasks = [exec.submit(process, w3) for w3 in providers]
res = [future.result() for future in as_completed(tasks)]
assert len(res) == len(providers)
res = [json.loads(r) for r in res]
assert res[0]["code"] == res[-1]["code"] == -32000
assert "intrinsic gas too low" in res[0]["message"]
assert "intrinsic gas too low" in res[-1]["message"]


def test_4byte_tracer_success(ethermint, geth):
method = "debug_traceCall"
tracer = {"tracer": "4byteTracer"}
acc = derive_new_account(6)

tx = {
"from": ACCOUNTS["community"].address,
"to": acc.address,
"gas": hex(21000),
}

def process(w3):
tx_res = w3.provider.make_request(method, [tx, "latest", tracer])
return json.dumps(tx_res["result"], sort_keys=True)

providers = [ethermint.w3, geth.w3]
with ThreadPoolExecutor(len(providers)) as exec:
tasks = [exec.submit(process, w3) for w3 in providers]
res = [future.result() for future in as_completed(tasks)]
assert len(res) == len(providers)
assert res[0] == res[-1]


def test_prestate_tracer_block_miner_address(ethermint, geth):
"""
prestateTracer on a tx will include the block miner address
"""
acc = ACCOUNTS["community"]
receiver = derive_new_account(12)

def process(w3):
assert (
w3.eth.get_balance(receiver.address) == 0
), "receiver balance need to be 0"
tx = {
"from": acc.address,
"to": receiver.address,
"value": 1,
}
receipt = send_transaction(w3, tx, key=acc.key)
tx_hash = Web3.to_hex(receipt["transactionHash"])
tracer = {"tracer": "prestateTracer"}
tx_res = w3.provider.make_request("debug_traceTransaction", [tx_hash, tracer])
latest_block = w3.eth.get_block(receipt.blockNumber)
block_miner = latest_block.miner
return [json.dumps(tx_res["result"], sort_keys=True), block_miner]

providers = [ethermint.w3, geth.w3]
with ThreadPoolExecutor(len(providers)) as exec:
tasks = [exec.submit(process, w3) for w3 in providers]
res = [future.result() for future in as_completed(tasks)]
miner_lhs = res[0][1].lower()
miner_rhs = res[1][1].lower()
assert len(res) == len(providers)

from_addr = acc.address.lower()
to_addr = receiver.address.lower()

lhs = json.loads(res[0][0])
rhs = json.loads(res[1][0])

assert len(lhs) == len(rhs) == 3, (lhs, rhs)

assert lhs[from_addr] is not None
assert lhs[to_addr] is not None
assert rhs[from_addr] is not None
assert rhs[to_addr] is not None
assert lhs[miner_lhs] is not None
assert rhs[miner_rhs] is not None
26 changes: 15 additions & 11 deletions x/evm/keeper/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,20 +362,24 @@ func (k *Keeper) ApplyMessageWithConfig(
tracer.OnGasChange(0, msg.GasLimit, tracing.GasChangeTxInitialBalance)
}

tracer.OnTxStart(
evm.GetVMContext(),
ethtypes.NewTx(&ethtypes.LegacyTx{
To: msg.To,
Data: msg.Data,
Value: msg.Value,
Gas: msg.GasLimit,
}),
msg.From,
)
if tracer.OnTxStart != nil {
tracer.OnTxStart(
evm.GetVMContext(),
ethtypes.NewTx(&ethtypes.LegacyTx{
To: msg.To,
Data: msg.Data,
Value: msg.Value,
Gas: msg.GasLimit,
}),
msg.From,
)
}

defer func() {
debugFn()
tracer.OnTxEnd(&ethtypes.Receipt{GasUsed: gasUsed}, err)
if tracer.OnTxEnd != nil {
tracer.OnTxEnd(&ethtypes.Receipt{GasUsed: gasUsed}, err)
}
}()

if cfg.DebugTrace {
Expand Down
Loading