Skip to content

Commit 2f5e3dd

Browse files
Jrigadazerosnacks0xferroussashaodessamablr
authored
chore: Upstream a8dc5ae merge (#1159)
* feat(forge): loosen tx gas limit restrictions ahead of Osaka + make enforceable w/ `--enable-tx-gas-limit` (#11427) * fix(anvil): traces' colors (#11614) * Fix CRLF line ending handling in stdin utilities (#11606) Update stdin.rs * chore: update bitflags dependency in Cargo.lock * chore(sol_macro_gen): remove unlinked bytecode workaround (#11613) * chore: proper ws (#11621) * chore(lint): re-use project output (#11563) * chore(lint): re-use project output * patch * upd * fix: lower * update, bless, fix tests to compile with solc * pragma * blessings * j1 * bump * bless * bless * hide * fix: inline config path (#11626) * chore: use Cursor::with_position (#11627) * fix(common): incorrect error message in get_error (#11631) * feat(`anvil`): add `eth_config` rpc endpoint (#11591) * fix(cheatcodes): lock files on reads / writes (#11590) * fix(cheatcodes): ensure file sync on vm.writeFile * Consolidate common fs * chore: update upstream version metadata to track a8dc5ae merge * fix: add missing solar dependencies after upstream merge * fix: resolve build.rs syntax errors and duplicate code paths from merge * Fix version of upstream version * fix unreachable patterns --------- Co-authored-by: zerosnacks <[email protected]> Co-authored-by: 0xferrous <[email protected]> Co-authored-by: sashaodessa <[email protected]> Co-authored-by: Mablr <[email protected]> Co-authored-by: grandizzy <[email protected]> Co-authored-by: DaniPopes <[email protected]> Co-authored-by: Snezhkko <[email protected]>
2 parents 474d305 + cf664c6 commit 2f5e3dd

File tree

89 files changed

+3765
-2903
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+3765
-2903
lines changed

.gitignore

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,11 @@ CLAUDE.md
1111
node_modules
1212
dist
1313
bin
14-
_
14+
_
15+
*.tgz
16+
.zed
17+
.vercel
18+
.vite
19+
.wrangler
20+
build
21+
*.zip

Cargo.toml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ metadata.upstream_version = "1.3.5"
3737
version = "0.0.28" # x-release-please-version
3838
edition = "2024"
3939
# Remember to update clippy.toml as well
40-
rust-version = "1.88"
40+
rust-version = "1.89"
4141
authors = ["Foundry Contributors"]
4242
license = "MIT OR Apache-2.0"
4343
homepage = "https://getfoundry.sh"
@@ -221,12 +221,11 @@ foundry-block-explorers = { version = "0.22.0", default-features = false }
221221
foundry-compilers = { version = "0.19.1", default-features = false }
222222
foundry-fork-db = "0.18"
223223
solang-parser = { version = "=0.3.9", package = "foundry-solang-parser" }
224-
solar = { package = "solar-compiler", version = "=0.1.6", default-features = false }
225-
# TODO: remove in next solar release: https://github.com/paradigmxyz/solar/pull/444
226-
solar-data-structures = { version = "=0.1.6", default-features = false }
227-
solar-interface = { version = "=0.1.6", default-features = false }
228-
solar-parse = { version = "=0.1.6", default-features = false }
229-
solar-sema = { version = "=0.1.6", default-features = false }
224+
solar = { package = "solar-compiler", version = "=0.1.7", default-features = false }
225+
solar-data-structures = { version = "=0.1.7", default-features = false }
226+
solar-interface = { version = "=0.1.7", default-features = false }
227+
solar-parse = { version = "=0.1.7", default-features = false }
228+
solar-sema = { version = "=0.1.7", default-features = false }
230229

231230
## alloy
232231
alloy-consensus = { version = "1.0.23", default-features = false }

clippy.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
msrv = "1.88"
1+
msrv = "1.89"
22

33
# `bytes::Bytes` is included by default and `alloy_primitives::Bytes` is a wrapper around it,
44
# so it is safe to ignore it as well.

crates/anvil/core/src/eth/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,9 @@ pub enum EthRequest {
264264
#[serde(rename = "eth_syncing", with = "empty_params")]
265265
EthSyncing(()),
266266

267+
#[serde(rename = "eth_config", with = "empty_params")]
268+
EthConfig(()),
269+
267270
/// geth's `debug_getRawTransaction` endpoint
268271
#[serde(rename = "debug_getRawTransaction", with = "sequence")]
269272
DebugGetRawTransaction(TxHash),

crates/anvil/src/config.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ pub struct NodeConfig {
9898
pub gas_limit: Option<u64>,
9999
/// If set to `true`, disables the block gas limit
100100
pub disable_block_gas_limit: bool,
101+
/// If set to `true`, enables the tx gas limit as imposed by Osaka (EIP-7825)
102+
pub enable_tx_gas_limit: bool,
101103
/// Default gas price for all txs
102104
pub gas_price: Option<u128>,
103105
/// Default base fee
@@ -443,6 +445,7 @@ impl Default for NodeConfig {
443445
chain_id: None,
444446
gas_limit: None,
445447
disable_block_gas_limit: false,
448+
enable_tx_gas_limit: false,
446449
gas_price: None,
447450
hardfork: None,
448451
signer_accounts: genesis_accounts.clone(),
@@ -622,6 +625,15 @@ impl NodeConfig {
622625
self
623626
}
624627

628+
/// Enable tx gas limit check
629+
///
630+
/// If set to `true`, enables the tx gas limit as imposed by Osaka (EIP-7825)
631+
#[must_use]
632+
pub fn enable_tx_gas_limit(mut self, enable_tx_gas_limit: bool) -> Self {
633+
self.enable_tx_gas_limit = enable_tx_gas_limit;
634+
self
635+
}
636+
625637
/// Sets the gas price
626638
#[must_use]
627639
pub fn with_gas_price(mut self, gas_price: Option<u128>) -> Self {
@@ -1068,6 +1080,10 @@ impl NodeConfig {
10681080
cfg.disable_eip3607 = true;
10691081
cfg.disable_block_gas_limit = self.disable_block_gas_limit;
10701082

1083+
if !self.enable_tx_gas_limit {
1084+
cfg.tx_gas_limit_cap = Some(u64::MAX);
1085+
}
1086+
10711087
if let Some(value) = self.memory_limit {
10721088
cfg.memory_limit = value;
10731089
}

crates/anvil/src/eth/api.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ use alloy_consensus::{
3434
transaction::{Recovered, eip4844::TxEip4844Variant},
3535
};
3636
use alloy_dyn_abi::TypedData;
37-
use alloy_eips::eip2718::Encodable2718;
37+
use alloy_eips::{
38+
eip2718::Encodable2718,
39+
eip7910::{EthConfig, EthForkConfig},
40+
};
3841
use alloy_evm::overrides::{OverrideBlockHashes, apply_state_overrides};
3942
use alloy_network::{
4043
AnyRpcBlock, AnyRpcTransaction, BlockResponse, Ethereum, NetworkWallet, TransactionBuilder,
@@ -313,6 +316,7 @@ impl EthApi {
313316
EthRequest::EthGetLogs(filter) => self.logs(filter).await.to_rpc_result(),
314317
EthRequest::EthGetWork(_) => self.work().to_rpc_result(),
315318
EthRequest::EthSyncing(_) => self.syncing().to_rpc_result(),
319+
EthRequest::EthConfig(_) => self.config().to_rpc_result(),
316320
EthRequest::EthSubmitWork(nonce, pow, digest) => {
317321
self.submit_work(nonce, pow, digest).to_rpc_result()
318322
}
@@ -1472,6 +1476,32 @@ impl EthApi {
14721476
Ok(false)
14731477
}
14741478

1479+
/// Returns the current configuration of the chain.
1480+
/// This is useful for finding out what precompiles and system contracts are available.
1481+
///
1482+
/// Note: the activation timestamp is always 0 as the configuration is set at genesis.
1483+
/// Note: the `fork_id` is always `0x00000000` as this node does not participate in any forking
1484+
/// on the network.
1485+
/// Note: the `next` and `last` fields are always `null` as this node does not participate in
1486+
/// any forking on the network.
1487+
///
1488+
/// Handler for ETH RPC call: `eth_config`
1489+
pub fn config(&self) -> Result<EthConfig> {
1490+
node_info!("eth_config");
1491+
Ok(EthConfig {
1492+
current: EthForkConfig {
1493+
activation_time: 0,
1494+
blob_schedule: self.backend.blob_params(),
1495+
chain_id: self.backend.env().read().evm_env.cfg_env.chain_id,
1496+
fork_id: Bytes::from_static(&[0; 4]),
1497+
precompiles: self.backend.precompiles(),
1498+
system_contracts: self.backend.system_contracts(),
1499+
},
1500+
next: None,
1501+
last: None,
1502+
})
1503+
}
1504+
14751505
/// Used for submitting a proof-of-work solution.
14761506
///
14771507
/// Handler for ETH RPC call: `eth_submitWork`

crates/anvil/src/eth/backend/executor.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use foundry_evm_core::{either_evm::EitherEvm, precompiles::EC_RECOVER};
4040
use op_revm::{L1BlockInfo, OpContext, precompiles::OpPrecompiles};
4141
use revm::{
4242
Database, DatabaseRef, Inspector, Journal,
43-
context::{Block as RevmBlock, BlockEnv, CfgEnv, Evm as RevmEvm, JournalTr, LocalContext},
43+
context::{Block as RevmBlock, BlockEnv, Cfg, CfgEnv, Evm as RevmEvm, JournalTr, LocalContext},
4444
context_interface::result::{EVMError, ExecutionResult, Output},
4545
database::WrapDatabaseRef,
4646
handler::{EthPrecompiles, instructions::EthInstructions},
@@ -174,14 +174,18 @@ impl<DB: Db + ?Sized, V: TransactionValidator> TransactionExecutor<'_, DB, V> {
174174
included.push(tx.transaction.clone());
175175
tx
176176
}
177-
TransactionExecutionOutcome::Exhausted(tx) => {
177+
TransactionExecutionOutcome::BlockGasExhausted(tx) => {
178178
trace!(target: "backend", tx_gas_limit = %tx.pending_transaction.transaction.gas_limit(), ?tx, "block gas limit exhausting, skipping transaction");
179179
continue;
180180
}
181181
TransactionExecutionOutcome::BlobGasExhausted(tx) => {
182182
trace!(target: "backend", blob_gas = %tx.pending_transaction.transaction.blob_gas().unwrap_or_default(), ?tx, "block blob gas limit exhausting, skipping transaction");
183183
continue;
184184
}
185+
TransactionExecutionOutcome::TransactionGasExhausted(tx) => {
186+
trace!(target: "backend", tx_gas_limit = %tx.pending_transaction.transaction.gas_limit(), ?tx, "transaction gas limit exhausting, skipping transaction");
187+
continue;
188+
}
185189
TransactionExecutionOutcome::Invalid(tx, _) => {
186190
trace!(target: "backend", ?tx, "skipping invalid transaction");
187191
invalid.push(tx);
@@ -285,10 +289,12 @@ pub enum TransactionExecutionOutcome {
285289
Executed(ExecutedTransaction),
286290
/// Invalid transaction not executed
287291
Invalid(Arc<PoolTransaction>, InvalidTransactionError),
288-
/// Execution skipped because could exceed gas limit
289-
Exhausted(Arc<PoolTransaction>),
292+
/// Execution skipped because could exceed block gas limit
293+
BlockGasExhausted(Arc<PoolTransaction>),
290294
/// Execution skipped because it exceeded the blob gas limit
291295
BlobGasExhausted(Arc<PoolTransaction>),
296+
/// Execution skipped because it exceeded the transaction gas limit
297+
TransactionGasExhausted(Arc<PoolTransaction>),
292298
/// When an error occurred during execution
293299
DatabaseError(Arc<PoolTransaction>, DatabaseError),
294300
}
@@ -306,10 +312,19 @@ impl<DB: Db + ?Sized, V: TransactionValidator> Iterator for &mut TransactionExec
306312
let env = self.env_for(&transaction.pending_transaction);
307313

308314
// check that we comply with the block's gas limit, if not disabled
309-
let max_gas = self.gas_used.saturating_add(env.tx.base.gas_limit);
310-
if !env.evm_env.cfg_env.disable_block_gas_limit && max_gas > env.evm_env.block_env.gas_limit
315+
let max_block_gas = self.gas_used.saturating_add(env.tx.base.gas_limit);
316+
if !env.evm_env.cfg_env.disable_block_gas_limit
317+
&& max_block_gas > env.evm_env.block_env.gas_limit
318+
{
319+
return Some(TransactionExecutionOutcome::BlockGasExhausted(transaction));
320+
}
321+
322+
// check that we comply with the transaction's gas limit as imposed by Osaka (EIP-7825)
323+
if env.evm_env.cfg_env.tx_gas_limit_cap.is_none()
324+
&& transaction.pending_transaction.transaction.gas_limit()
325+
> env.evm_env.cfg_env().tx_gas_limit_cap()
311326
{
312-
return Some(TransactionExecutionOutcome::Exhausted(transaction));
327+
return Some(TransactionExecutionOutcome::TransactionGasExhausted(transaction));
313328
}
314329

315330
// check that we comply with the block's blob gas limit

crates/anvil/src/eth/backend/mem/inspector.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ fn print_traces(tracer: TracingInspector, decoder: Arc<CallTraceDecoder>) {
112112
});
113113

114114
let traces = SparsedTraceArena { arena, ignored: Default::default() };
115-
node_info!("Traces:");
116-
node_info!("{}", render_trace_arena_inner(&traces, false, true));
115+
let trace = render_trace_arena_inner(&traces, false, true);
116+
node_info!(Traces = %format!("\n{}", trace));
117117
}
118118

119119
impl<CTX> Inspector<CTX, EthInterpreter> for AnvilInspector

crates/anvil/src/eth/backend/mem/mod.rs

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::{
2727
pool::transactions::PoolTransaction,
2828
sign::build_typed_transaction,
2929
},
30-
evm::celo_precompile,
30+
evm::celo_precompile::{self, CELO_TRANSFER_ADDRESS},
3131
inject_precompiles,
3232
mem::{
3333
inspector::AnvilInspector,
@@ -41,7 +41,10 @@ use alloy_consensus::{
4141
proofs::{calculate_receipt_root, calculate_transaction_root},
4242
transaction::Recovered,
4343
};
44-
use alloy_eips::{eip1559::BaseFeeParams, eip4844::kzg_to_versioned_hash, eip7840::BlobParams};
44+
use alloy_eips::{
45+
eip1559::BaseFeeParams, eip4844::kzg_to_versioned_hash, eip7840::BlobParams,
46+
eip7910::SystemContract,
47+
};
4548
use alloy_evm::{
4649
Database, Evm,
4750
eth::EthEvmContext,
@@ -108,14 +111,18 @@ use op_revm::{
108111
use parking_lot::{Mutex, RwLock};
109112
use revm::{
110113
DatabaseCommit, Inspector,
111-
context::{Block as RevmBlock, BlockEnv, TxEnv},
114+
context::{Block as RevmBlock, BlockEnv, Cfg, TxEnv},
112115
context_interface::{
113116
block::BlobExcessGasAndPrice,
114117
result::{ExecutionResult, Output, ResultAndState},
115118
},
116119
database::{CacheDB, WrapDatabaseRef},
117120
interpreter::InstructionResult,
118-
precompile::secp256r1::{P256VERIFY, P256VERIFY_BASE_GAS_FEE},
121+
precompile::{
122+
PrecompileId, PrecompileSpecId, Precompiles,
123+
secp256r1::{P256VERIFY, P256VERIFY_ADDRESS, P256VERIFY_BASE_GAS_FEE},
124+
u64_to_address,
125+
},
119126
primitives::{KECCAK_EMPTY, hardfork::SpecId},
120127
state::AccountInfo,
121128
};
@@ -843,6 +850,56 @@ impl Backend {
843850
self.env.read().is_celo
844851
}
845852

853+
/// Returns the precompiles for the current spec.
854+
pub fn precompiles(&self) -> BTreeMap<String, Address> {
855+
let spec_id = self.env.read().evm_env.cfg_env.spec;
856+
let precompiles = Precompiles::new(PrecompileSpecId::from_spec_id(spec_id));
857+
858+
let mut precompiles_map = BTreeMap::<String, Address>::default();
859+
for (address, precompile) in precompiles.inner() {
860+
precompiles_map.insert(precompile.id().name().to_string(), *address);
861+
}
862+
863+
if self.odyssey {
864+
precompiles_map.insert(
865+
PrecompileId::P256Verify.name().to_string(),
866+
u64_to_address(P256VERIFY_ADDRESS),
867+
);
868+
}
869+
870+
if self.is_celo() {
871+
precompiles_map.insert(
872+
celo_precompile::PRECOMPILE_ID_CELO_TRANSFER.clone().name().to_string(),
873+
CELO_TRANSFER_ADDRESS,
874+
);
875+
}
876+
877+
if let Some(factory) = &self.precompile_factory {
878+
for (precompile, _) in &factory.precompiles() {
879+
precompiles_map.insert(precompile.id().name().to_string(), *precompile.address());
880+
}
881+
}
882+
883+
precompiles_map
884+
}
885+
886+
/// Returns the system contracts for the current spec.
887+
pub fn system_contracts(&self) -> BTreeMap<SystemContract, Address> {
888+
let mut system_contracts = BTreeMap::<SystemContract, Address>::default();
889+
890+
let spec_id = self.env.read().evm_env.cfg_env.spec;
891+
892+
if spec_id >= SpecId::CANCUN {
893+
system_contracts.extend(SystemContract::cancun());
894+
}
895+
896+
if spec_id >= SpecId::PRAGUE {
897+
system_contracts.extend(SystemContract::prague(None));
898+
}
899+
900+
system_contracts
901+
}
902+
846903
/// Returns [`BlobParams`] corresponding to the current spec.
847904
pub fn blob_params(&self) -> BlobParams {
848905
let spec_id = self.env.read().evm_env.cfg_env.spec;
@@ -1534,6 +1591,7 @@ impl Backend {
15341591
///
15351592
/// - `disable_eip3607` is set to `true`
15361593
/// - `disable_base_fee` is set to `true`
1594+
/// - `tx_gas_limit_cap` is set to `Some(u64::MAX)` indicating no gas limit cap
15371595
/// - `nonce` check is skipped if `request.nonce` is None
15381596
fn build_call_env(
15391597
&self,
@@ -1576,6 +1634,7 @@ impl Backend {
15761634
// we want to disable this in eth_call, since this is common practice used by other node
15771635
// impls and providers <https://github.com/foundry-rs/foundry/issues/4388>
15781636
env.evm_env.cfg_env.disable_block_gas_limit = true;
1637+
env.evm_env.cfg_env.tx_gas_limit_cap = Some(u64::MAX);
15791638

15801639
// The basefee should be ignored for calls against state for
15811640
// - eth_call
@@ -3422,7 +3481,7 @@ impl TransactionValidator for Backend {
34223481
return Err(InvalidTransactionError::GasTooLow);
34233482
}
34243483

3425-
// Check gas limit against block gas limit, if block gas limit is set.
3484+
// Check tx gas limit against block gas limit, if block gas limit is set.
34263485
if !env.evm_env.cfg_env.disable_block_gas_limit
34273486
&& tx.gas_limit() > env.evm_env.block_env.gas_limit
34283487
{
@@ -3432,7 +3491,17 @@ impl TransactionValidator for Backend {
34323491
}));
34333492
}
34343493

3435-
// EIP-1559 fee validation (London hard fork and later)
3494+
// Check tx gas limit against tx gas limit cap (Osaka hard fork and later).
3495+
if env.evm_env.cfg_env.tx_gas_limit_cap.is_none()
3496+
&& tx.gas_limit() > env.evm_env.cfg_env().tx_gas_limit_cap()
3497+
{
3498+
warn!(target: "backend", "[{:?}] gas too high", tx.hash());
3499+
return Err(InvalidTransactionError::GasTooHigh(ErrDetail {
3500+
detail: String::from("tx.gas_limit > env.cfg.tx_gas_limit_cap"),
3501+
}));
3502+
}
3503+
3504+
// EIP-1559 fee validation (London hard fork and later).
34363505
if env.evm_env.cfg_env.spec >= SpecId::LONDON {
34373506
if tx.gas_price() < env.evm_env.block_env.basefee.into() && !is_deposit_tx {
34383507
warn!(target: "backend", "max fee per gas={}, too low, block basefee={}",tx.gas_price(), env.evm_env.block_env.basefee);

0 commit comments

Comments
 (0)