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
9 changes: 5 additions & 4 deletions crates/evm/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1533,7 +1533,7 @@ impl<C: sov_modules_api::Context> Evm<C> {
.get(working_set)
.expect("EVM chain config should be set");

let cfg_env = get_cfg_env(cfg, evm_spec_id);
let mut cfg_env = get_cfg_env(cfg, evm_spec_id);

let l1_fee_block_num = match block_number {
// use l1 fee rate of latest block for pending block
Expand Down Expand Up @@ -1573,10 +1573,11 @@ impl<C: sov_modules_api::Context> Evm<C> {
let chain_id = cfg_env.chain_id();

// create tx env
let tx_env = create_txn_env(
let tx_env = prepare_call_env(
&block_env,
request.clone(),
Some(account.balance),
&mut cfg_env,
request,
account.balance,
nonce,
chain_id,
)?;
Expand Down
105 changes: 104 additions & 1 deletion crates/evm/src/tests/queries/trace_call_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::str::FromStr;

use alloy_eips::BlockNumberOrTag;
use alloy_primitives::map::AddressMap;
use alloy_primitives::{Address, TxKind, U256};
use alloy_primitives::{Address, Bytes, TxKind, U256};
use alloy_rpc_types::state::AccountOverride;
use alloy_rpc_types::TransactionRequest;
use alloy_rpc_types_trace::geth::GethDebugTracingCallOptions;
Expand Down Expand Up @@ -77,3 +77,106 @@ fn test_debug_trace_call_with_balance_override_no_gas_limit() {
result_with_override.unwrap_err()
);
}

/// Test that debug_traceCall disables base fee validation.
/// A transaction with gas_price below the base fee should still succeed
#[test]
fn test_debug_trace_call_disables_base_fee() {
let (evm, mut working_set, signer, ledger_db) =
init_evm_single_block(sov_modules_api::SpecId::latest());

let tx_req = TransactionRequest {
from: Some(signer.address()),
to: Some(TxKind::Call(
Address::from_str("0x1111111111111111111111111111111111111111").unwrap(),
)),
value: Some(U256::from(1000)),
gas_price: Some(1), // 1 wei, much lower than the block's base fee
..Default::default()
};
let result = evm.debug_trace_call(
tx_req,
Some(BlockNumberOrTag::Latest.into()),
None,
&mut working_set,
&ledger_db,
);

assert!(
result.is_ok(),
"debug_traceCall should succeed with gas_price below base fee, but got error: {:?}",
result.unwrap_err()
);

// A second call with gas price omitted request
let tx_req_no_gas_price = TransactionRequest {
from: Some(signer.address()),
to: Some(TxKind::Call(
Address::from_str("0x1111111111111111111111111111111111111111").unwrap(),
)),
value: Some(U256::from(1000)),
// gas_price is intentionally omitted to test default handling
..Default::default()
};
let result_no_gas_price = evm.debug_trace_call(
tx_req_no_gas_price,
Some(BlockNumberOrTag::Latest.into()),
None,
&mut working_set,
&ledger_db,
);

assert!(
result_no_gas_price.is_ok(),
"debug_traceCall should succeed with gas_price omitted, but got error: {:?}",
result_no_gas_price.unwrap_err()
);
}

/// Test that debug_traceCall disables EIP-3607 validation.
/// EIP-3607 rejects transactions from senders that have deployed contract code.
#[test]
fn test_debug_trace_call_disables_eip3607() {
let (evm, mut working_set, signer, ledger_db) =
init_evm_single_block(sov_modules_api::SpecId::latest());

// Use a state override to give the sender account some contract code
// This would normally trigger EIP-3607 rejection
let mut state_override = AddressMap::default();
state_override.insert(
signer.address(),
AccountOverride {
// Add some dummy contract code to the sender's account
code: Some(Bytes::from_static(&[0x60, 0x00, 0x60, 0x00, 0xf3])), // PUSH 0, PUSH 0, RETURN
..Default::default()
},
);

let tx_req = TransactionRequest {
from: Some(signer.address()),
to: Some(TxKind::Call(
Address::from_str("0x1111111111111111111111111111111111111111").unwrap(),
)),
value: Some(U256::from(1000)),
..Default::default()
};

let opts = GethDebugTracingCallOptions {
state_overrides: Some(state_override),
..Default::default()
};

let result = evm.debug_trace_call(
tx_req,
Some(BlockNumberOrTag::Latest.into()),
Some(opts),
&mut working_set,
&ledger_db,
);

assert!(
result.is_ok(),
"debug_traceCall should succeed when sender has contract code, but got error: {:?}",
result.unwrap_err()
);
}