Skip to content

feat: feynman base fee #273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jul 22, 2025
9 changes: 3 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions crates/ethereum/node/tests/e2e/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ async fn maintain_txpool_stale_eviction() -> eyre::Result<()> {
.build(),
);
let node_config = NodeConfig::test()
.with_chain(chain_spec)
.with_chain(chain_spec.clone())
.with_unused_ports()
.with_rpc(RpcServerArgs::default().with_unused_ports().with_http());
let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone())
Expand All @@ -67,6 +67,7 @@ async fn maintain_txpool_stale_eviction() -> eyre::Result<()> {
"txpool maintenance task",
reth_transaction_pool::maintain::maintain_transaction_pool_future(
node.inner.provider.clone(),
chain_spec,
txpool.clone(),
node.inner.provider.clone().canonical_state_stream(),
executor.clone(),
Expand Down Expand Up @@ -120,7 +121,7 @@ async fn maintain_txpool_reorg() -> eyre::Result<()> {
);
let genesis_hash = chain_spec.genesis_hash();
let node_config = NodeConfig::test()
.with_chain(chain_spec)
.with_chain(chain_spec.clone())
.with_unused_ports()
.with_rpc(RpcServerArgs::default().with_unused_ports().with_http());
let NodeHandle { node, node_exit_future: _ } = NodeBuilder::new(node_config.clone())
Expand All @@ -139,6 +140,7 @@ async fn maintain_txpool_reorg() -> eyre::Result<()> {
"txpool maintenance task",
reth_transaction_pool::maintain::maintain_transaction_pool_future(
node.inner.provider.clone(),
chain_spec,
txpool.clone(),
node.inner.provider.clone().canonical_state_stream(),
executor.clone(),
Expand Down Expand Up @@ -269,6 +271,7 @@ async fn maintain_txpool_commit() -> eyre::Result<()> {
"txpool maintenance task",
reth_transaction_pool::maintain::maintain_transaction_pool_future(
node.inner.provider.clone(),
MAINNET.clone(),
txpool.clone(),
node.inner.provider.clone().canonical_state_stream(),
executor.clone(),
Expand Down
7 changes: 5 additions & 2 deletions crates/node/builder/src/components/pool.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
//! Pool component for the node builder.

use crate::{BuilderContext, FullNodeTypes};

use alloy_primitives::Address;
use reth_chain_state::CanonStateSubscriptions;
use reth_chainspec::ChainSpecProvider;
use reth_node_api::TxTy;
use reth_transaction_pool::{
blobstore::DiskFileBlobStore, CoinbaseTipOrdering, PoolConfig, PoolTransaction, SubPoolLimit,
TransactionPool, TransactionValidationTaskExecutor, TransactionValidator,
};
use std::{collections::HashSet, future::Future};

use crate::{BuilderContext, FullNodeTypes};

/// A type that knows how to build the transaction pool.
pub trait PoolBuilder<Node: FullNodeTypes>: Send {
/// The transaction pool to build.
Expand Down Expand Up @@ -236,11 +237,13 @@ where
{
let chain_events = ctx.provider().canonical_state_stream();
let client = ctx.provider().clone();
let chain_spec = client.chain_spec();

ctx.task_executor().spawn_critical(
"txpool maintenance task",
reth_transaction_pool::maintain::maintain_transaction_pool_future(
client,
chain_spec,
pool,
chain_events,
ctx.task_executor().clone(),
Expand Down
3 changes: 2 additions & 1 deletion crates/scroll/alloy/evm/src/tx/compression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ use alloy_eips::{Encodable2718, Typed2718};
use alloy_evm::{IntoTxEnv, RecoveredTx};
use alloy_primitives::{Address, Bytes, TxKind, U256};
use revm::context::TxEnv;
use revm_scroll::l1block::TX_L1_FEE_PRECISION_U256;
use scroll_alloy_consensus::{ScrollTxEnvelope, TxL1Message};
pub use zstd_compression::compute_compression_ratio;

#[cfg(feature = "zstd_compression")]
mod zstd_compression {
use super::*;
use std::io::Write;

use revm_scroll::l1block::TX_L1_FEE_PRECISION_U256;
use zstd::{
stream::Encoder,
zstd_safe::{CParameter, ParamSwitch},
Expand Down
2 changes: 1 addition & 1 deletion crates/scroll/alloy/hardforks/src/hardfork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl ScrollHardfork {
(Self::Euclid, ForkCondition::Timestamp(1744815600)),
(Self::EuclidV2, ForkCondition::Timestamp(1745305200)),
// TODO: update
(Self::Feynman, ForkCondition::Timestamp(u64::MAX)),
(Self::Feynman, ForkCondition::Timestamp(6000000000)),
]
}

Expand Down
2 changes: 2 additions & 0 deletions crates/scroll/alloy/rpc-types/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ impl Transaction {
// For l1 messages, we set the `gasPrice` field to 0 in rpc
0
} else {
// TODO: should we get the pool base fee in the case where the transaction is a pending
// transaction here?
base_fee
.map(|base_fee| {
tx.effective_tip_per_gas(base_fee).unwrap_or_default() + base_fee as u128
Expand Down
1 change: 1 addition & 0 deletions crates/scroll/chainspec/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ serde_json = { workspace = true, default-features = false }
serde = { workspace = true, default-features = false, features = ["derive"] }

# misc
auto_impl.workspace = true
derive_more = { workspace = true, default-features = false }
once_cell = { workspace = true, default-features = false }

Expand Down
45 changes: 45 additions & 0 deletions crates/scroll/chainspec/src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
use crate::genesis::L1Config;
use alloy_eips::eip1559::BaseFeeParams;
use alloy_primitives::{address, b256, Address, B256};

/// The transaction fee recipient on the L2.
pub const SCROLL_FEE_VAULT_ADDRESS: Address = address!("5300000000000000000000000000000000000005");

/// The system contract on L2 mainnet.
pub const SCROLL_MAINNET_L2_SYSTEM_CONFIG_CONTRACT_ADDRESS: Address =
address!("331A873a2a85219863d80d248F9e2978fE88D0Ea");

/// The L1 message queue address for Scroll mainnet.
/// <https://etherscan.io/address/0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B>.
pub const SCROLL_MAINNET_L1_MESSAGE_QUEUE_ADDRESS: Address =
address!("0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B");

/// The L1 message queue v2 address for Scroll mainnet.
/// <https://etherscan.io/address/0x56971da63A3C0205184FEF096E9ddFc7A8C2D18a>.
pub const SCROLL_MAINNET_L1_MESSAGE_QUEUE_V2_ADDRESS: Address =
address!("56971da63A3C0205184FEF096E9ddFc7A8C2D18a");

/// The L1 proxy address for Scroll mainnet.
/// <https://etherscan.io/address/0xa13BAF47339d63B743e7Da8741db5456DAc1E556>.
pub const SCROLL_MAINNET_L1_PROXY_ADDRESS: Address =
Expand All @@ -21,6 +31,8 @@ pub const SCROLL_MAINNET_MAX_L1_MESSAGES: u64 = 10;
pub const SCROLL_MAINNET_L1_CONFIG: L1Config = L1Config {
l1_chain_id: alloy_chains::NamedChain::Mainnet as u64,
l1_message_queue_address: SCROLL_MAINNET_L1_MESSAGE_QUEUE_ADDRESS,
l1_message_queue_v2_address: SCROLL_MAINNET_L1_MESSAGE_QUEUE_V2_ADDRESS,
l2_system_config_address: SCROLL_MAINNET_L2_SYSTEM_CONFIG_CONTRACT_ADDRESS,
scroll_chain_address: SCROLL_MAINNET_L1_PROXY_ADDRESS,
num_l1_messages_per_block: SCROLL_MAINNET_MAX_L1_MESSAGES,
};
Expand All @@ -29,11 +41,20 @@ pub const SCROLL_MAINNET_L1_CONFIG: L1Config = L1Config {
pub const SCROLL_MAINNET_GENESIS_HASH: B256 =
b256!("bbc05efd412b7cd47a2ed0e5ddfcf87af251e414ea4c801d78b6784513180a80");

/// The system contract on L2 sepolia.
pub const SCROLL_SEPOLIA_L2_SYSTEM_CONFIG_CONTRACT_ADDRESS: Address =
address!("F444cF06A3E3724e20B35c2989d3942ea8b59124");

/// The L1 message queue address for Scroll sepolia.
/// <https://sepolia.etherscan.io/address/0xF0B2293F5D834eAe920c6974D50957A1732de763>.
pub const SCROLL_SEPOLIA_L1_MESSAGE_QUEUE_ADDRESS: Address =
address!("F0B2293F5D834eAe920c6974D50957A1732de763");

/// The L1 message queue address v2 for Scroll sepolia.
/// <https://sepolia.etherscan.io/address/0xA0673eC0A48aa924f067F1274EcD281A10c5f19F>.
pub const SCROLL_SEPOLIA_L1_MESSAGE_QUEUE_V2_ADDRESS: Address =
address!("A0673eC0A48aa924f067F1274EcD281A10c5f19F");

/// The L1 proxy address for Scroll sepolia.
/// <https://sepolia.etherscan.io/address/0x2D567EcE699Eabe5afCd141eDB7A4f2D0D6ce8a0>
pub const SCROLL_SEPOLIA_L1_PROXY_ADDRESS: Address =
Expand All @@ -46,14 +67,24 @@ pub const SCROLL_SEPOLIA_MAX_L1_MESSAGES: u64 = 10;
pub const SCROLL_SEPOLIA_L1_CONFIG: L1Config = L1Config {
l1_chain_id: alloy_chains::NamedChain::Sepolia as u64,
l1_message_queue_address: SCROLL_SEPOLIA_L1_MESSAGE_QUEUE_ADDRESS,
l1_message_queue_v2_address: SCROLL_SEPOLIA_L1_MESSAGE_QUEUE_V2_ADDRESS,
l2_system_config_address: SCROLL_SEPOLIA_L2_SYSTEM_CONFIG_CONTRACT_ADDRESS,
scroll_chain_address: SCROLL_SEPOLIA_L1_PROXY_ADDRESS,
num_l1_messages_per_block: SCROLL_SEPOLIA_MAX_L1_MESSAGES,
};

/// The system contract on devnet.
pub const SCROLL_DEV_L2_SYSTEM_CONFIG_CONTRACT_ADDRESS: Address =
address!("0000000000000000000000000000000000000000");

/// The L1 message queue address for Scroll dev.
pub const SCROLL_DEV_L1_MESSAGE_QUEUE_ADDRESS: Address =
address!("0000000000000000000000000000000000000000");

/// The L1 message queue v2 address for Scroll dev.
pub const SCROLL_DEV_L1_MESSAGE_QUEUE_V2_ADDRESS: Address =
address!("0000000000000000000000000000000000000000");

/// The L1 proxy address for Scroll dev.
pub const SCROLL_DEV_L1_PROXY_ADDRESS: Address =
address!("0000000000000000000000000000000000000000");
Expand All @@ -65,10 +96,24 @@ pub const SCROLL_DEV_MAX_L1_MESSAGES: u64 = 10;
pub const SCROLL_DEV_L1_CONFIG: L1Config = L1Config {
l1_chain_id: alloy_chains::NamedChain::Goerli as u64,
l1_message_queue_address: SCROLL_DEV_L1_MESSAGE_QUEUE_ADDRESS,
l1_message_queue_v2_address: SCROLL_DEV_L1_MESSAGE_QUEUE_V2_ADDRESS,
scroll_chain_address: SCROLL_DEV_L1_PROXY_ADDRESS,
l2_system_config_address: SCROLL_DEV_L2_SYSTEM_CONFIG_CONTRACT_ADDRESS,
num_l1_messages_per_block: SCROLL_DEV_MAX_L1_MESSAGES,
};

/// The Scroll Sepolia genesis hash
pub const SCROLL_SEPOLIA_GENESIS_HASH: B256 =
b256!("aa62d1a8b2bffa9e5d2368b63aae0d98d54928bd713125e3fd9e5c896c68592c");

/// The base fee params for Feynman.
pub const SCROLL_BASE_FEE_PARAMS_FEYNMAN: BaseFeeParams = BaseFeeParams::new(
SCROLL_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_FEYNMAN,
SCROLL_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER_FEYNMAN,
);

/// The scroll EIP1559 max change denominator for Feynman.
pub const SCROLL_EIP1559_BASE_FEE_MAX_CHANGE_DENOMINATOR_FEYNMAN: u128 = 8;

/// The scroll EIP1559 default elasticity multiplier for Feynman.
pub const SCROLL_EIP1559_DEFAULT_ELASTICITY_MULTIPLIER_FEYNMAN: u128 = 2;
15 changes: 10 additions & 5 deletions crates/scroll/chainspec/src/dev.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
//! Chain specification in dev mode for custom chain.

use alloc::sync::Arc;
use crate::{
constants::SCROLL_BASE_FEE_PARAMS_FEYNMAN, make_genesis_header, LazyLock, ScrollChainConfig,
ScrollChainSpec,
};
use alloc::{sync::Arc, vec};

use alloy_chains::Chain;
use alloy_primitives::U256;
use reth_chainspec::{BaseFeeParams, BaseFeeParamsKind, ChainSpec};
use reth_chainspec::{BaseFeeParamsKind, ChainSpec, Hardfork};
use reth_primitives_traits::SealedHeader;
use reth_scroll_forks::DEV_HARDFORKS;

use crate::{make_genesis_header, LazyLock, ScrollChainConfig, ScrollChainSpec};
use scroll_alloy_hardforks::ScrollHardfork;

/// Scroll dev testnet specification
///
Expand All @@ -24,7 +27,9 @@ pub static SCROLL_DEV: LazyLock<Arc<ScrollChainSpec>> = LazyLock::new(|| {
genesis,
paris_block_and_final_difficulty: Some((0, U256::from(0))),
hardforks: DEV_HARDFORKS.clone(),
base_fee_params: BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()),
base_fee_params: BaseFeeParamsKind::Variable(
vec![(ScrollHardfork::Feynman.boxed(), SCROLL_BASE_FEE_PARAMS_FEYNMAN)].into(),
),
..Default::default()
},
config: ScrollChainConfig::dev(),
Expand Down
13 changes: 13 additions & 0 deletions crates/scroll/chainspec/src/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,14 @@ pub struct L1Config {
/// The L1 contract address of the contract that handles the message queue targeting the Scroll
/// rollup.
pub l1_message_queue_address: Address,
/// The L1 contract address of the contract that handles the message queue v2 targeting the
/// Scroll rollup, used post Euclid fork.
pub l1_message_queue_v2_address: Address,
/// The L1 contract address of the proxy contract which is responsible for Scroll rollup
/// settlement.
pub scroll_chain_address: Address,
/// The address of the L2 system contract.
pub l2_system_config_address: Address,
/// The maximum number of L1 messages to be consumed per L2 rollup block.
pub num_l1_messages_per_block: u64,
}
Expand Down Expand Up @@ -157,6 +162,8 @@ impl TryFrom<&OtherFields> for ScrollChainConfig {
#[cfg(test)]
mod tests {
use super::*;
use crate::SCROLL_MAINNET_L2_SYSTEM_CONFIG_CONTRACT_ADDRESS;

use alloy_primitives::address;

#[test]
Expand Down Expand Up @@ -205,6 +212,8 @@ mod tests {
"l1Config": {
"l1ChainId": 1,
"l1MessageQueueAddress": "0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B",
"l1MessageQueueV2Address": "0x56971da63A3C0205184FEF096E9ddFc7A8C2D18a",
"l2SystemConfigAddress": "0x331A873a2a85219863d80d248F9e2978fE88D0Ea",
"scrollChainAddress": "0xa13BAF47339d63B743e7Da8741db5456DAc1E556",
"numL1MessagesPerBlock": 10
}
Expand All @@ -231,6 +240,10 @@ mod tests {
l1_config: L1Config {
l1_chain_id: 1,
l1_message_queue_address: address!("0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B"),
l1_message_queue_v2_address: address!(
"56971da63A3C0205184FEF096E9ddFc7A8C2D18a"
),
l2_system_config_address: SCROLL_MAINNET_L2_SYSTEM_CONFIG_CONTRACT_ADDRESS,
scroll_chain_address: address!("a13BAF47339d63B743e7Da8741db5456DAc1E556"),
num_l1_messages_per_block: 10,
},
Expand Down
Loading