Skip to content

Commit 399ef8d

Browse files
committed
restore CI and contain Base behind its feature
1 parent eeccec6 commit 399ef8d

18 files changed

Lines changed: 104 additions & 133 deletions

File tree

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,4 @@ jobs:
131131
args+=(--partition "$NEXTEST_PARTITION")
132132
fi
133133
args+=(--no-fail-fast)
134-
cargo nextest run --locked --features monad "${args[@]}"
134+
cargo nextest run --locked --features base,monad "${args[@]}"

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ CARGO_TARGET_DIR ?= target
1515
# List of features to use when building. Can be overridden via the environment.
1616
# No jemalloc on Windows
1717
ifeq ($(OS),Windows_NT)
18-
FEATURES ?= aws-kms gcp-kms turnkey cli asm-keccak monad optimism
18+
FEATURES ?= aws-kms gcp-kms turnkey cli asm-keccak base monad optimism
1919
else
20-
FEATURES ?= jemalloc aws-kms gcp-kms turnkey cli asm-keccak monad optimism
20+
FEATURES ?= jemalloc aws-kms gcp-kms turnkey cli asm-keccak base monad optimism
2121
endif
2222

2323
##@ Help

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

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,7 @@ pub(crate) fn build_simulated_deposit_receipt<H>(
4040
/// Resolves the deposit nonce and receipt version active at `hardfork`.
4141
///
4242
/// Base is an OP-stack chain, so it gates the same two fields on its own upgrade names.
43-
fn deposit_metadata(
44-
#[cfg_attr(
45-
not(any(feature = "base", feature = "optimism")),
46-
allow(unused_variables)
47-
)]
48-
hardfork: FoundryHardfork,
49-
#[cfg_attr(not(any(feature = "base", feature = "optimism")), allow(unused_variables))]
50-
caller_nonce: u64,
51-
) -> (Option<u64>, Option<u64>) {
43+
fn deposit_metadata(hardfork: FoundryHardfork, caller_nonce: u64) -> (Option<u64>, Option<u64>) {
5244
#[cfg(feature = "base")]
5345
if matches!(hardfork, FoundryHardfork::Base(_)) {
5446
let upgrade = BaseUpgrade::from(hardfork);
@@ -60,10 +52,10 @@ fn deposit_metadata(
6052
#[cfg(feature = "optimism")]
6153
{
6254
let hardfork = OpHardfork::from(hardfork);
63-
return (
55+
(
6456
(hardfork >= OpHardfork::Regolith).then_some(caller_nonce),
6557
(hardfork >= OpHardfork::Canyon).then_some(1),
66-
);
58+
)
6759
}
6860
#[cfg(not(feature = "optimism"))]
6961
(None, None)

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

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ use tempo_revm::{
244244
};
245245
use tokio::{sync::RwLock as AsyncRwLock, task::JoinSet};
246246

247-
/// Network-specific transaction data produced by [`Backend::build_call_env`].
247+
/// Network-specific transaction data produced by [`Backend::build_call_env_with_base`].
248248
#[derive(Default, Clone, Debug)]
249249
struct CallTransactionInfo {
250250
/// OP-compatible deposit fields shared by Base and Optimism RPC requests.
@@ -744,7 +744,7 @@ pub trait BackendInspector<DB: Database>:
744744
+ Inspector<BaseContext<DB>>
745745
+ Inspector<OpEvmContext<DB>>
746746
+ Inspector<TempoContext<DB>>
747-
+ Inspector<MonadContext<DB>>
747+
+ Inspector<alloy_monad_evm::MonadContext<DB>>
748748
{
749749
}
750750
#[cfg(all(feature = "base", feature = "optimism", feature = "monad"))]
@@ -753,7 +753,7 @@ impl<DB: Database, T> BackendInspector<DB> for T where
753753
+ Inspector<BaseContext<DB>>
754754
+ Inspector<OpEvmContext<DB>>
755755
+ Inspector<TempoContext<DB>>
756-
+ Inspector<MonadContext<DB>>
756+
+ Inspector<alloy_monad_evm::MonadContext<DB>>
757757
{
758758
}
759759
#[cfg(all(feature = "base", feature = "optimism", not(feature = "monad")))]
@@ -777,15 +777,15 @@ pub trait BackendInspector<DB: Database>:
777777
Inspector<EthEvmContext<DB>>
778778
+ Inspector<BaseContext<DB>>
779779
+ Inspector<TempoContext<DB>>
780-
+ Inspector<MonadContext<DB>>
780+
+ Inspector<alloy_monad_evm::MonadContext<DB>>
781781
{
782782
}
783783
#[cfg(all(feature = "base", not(feature = "optimism"), feature = "monad"))]
784784
impl<DB: Database, T> BackendInspector<DB> for T where
785785
T: Inspector<EthEvmContext<DB>>
786786
+ Inspector<BaseContext<DB>>
787787
+ Inspector<TempoContext<DB>>
788-
+ Inspector<MonadContext<DB>>
788+
+ Inspector<alloy_monad_evm::MonadContext<DB>>
789789
{
790790
}
791791
#[cfg(all(feature = "base", not(feature = "optimism"), not(feature = "monad")))]
@@ -9483,19 +9483,13 @@ where
94839483
evm_env: &EvmEnv,
94849484
) -> Result<(), InvalidTransactionError> {
94859485
self.validate_pool_transaction_for(tx, account, evm_env)?;
9486-
#[cfg(any(feature = "base", feature = "optimism"))]
9487-
let is_deposit = tx.transaction.as_ref().is_deposit();
9488-
#[cfg(not(any(feature = "base", feature = "optimism")))]
9489-
let is_deposit = false;
9486+
// EIP-8130 counts nonces per channel in the nonce manager, so `tx.nonce()` is not
9487+
// comparable to the account's protocol nonce. Admission already validated the channel.
94909488
#[cfg(feature = "base")]
9491-
let is_eip8130 = tx.transaction.as_ref().is_eip8130();
9492-
#[cfg(not(feature = "base"))]
9493-
let is_eip8130 = false;
9494-
if tx.nonce() > account.nonce
9495-
&& !is_deposit
9496-
&& !is_eip8130
9497-
&& !tx.transaction.as_ref().is_tempo()
9498-
{
9489+
if tx.transaction.as_ref().is_eip8130() {
9490+
return Ok(());
9491+
}
9492+
if tx.nonce() > account.nonce {
94999493
return Err(InvalidTransactionError::NonceTooHigh);
95009494
}
95019495
Ok(())

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,18 @@ pub enum BlockchainError {
112112
"EIP-7702 fields received but is not supported by the current hardfork.\n\nYou can use it by running anvil with '--hardfork prague' or later."
113113
)]
114114
EIP7702TransactionUnsupportedAtHardfork,
115+
// Base is an OP-stack chain and uses the same deposit envelope, so only the hint that names
116+
// the flags able to enable it varies with the compiled-in families.
115117
#[cfg_attr(
116118
all(feature = "base", feature = "optimism"),
117119
error(
118-
"deposit transaction received but is not supported.\n\nYou can use it by running anvil with '--optimism' or '--network base'."
120+
"op-stack deposit tx received but is not supported.\n\nYou can use it by running anvil with '--optimism' or '--network base'."
119121
)
120122
)]
121123
#[cfg_attr(
122124
all(feature = "base", not(feature = "optimism")),
123125
error(
124-
"deposit transaction received but is not supported.\n\nYou can use it by running anvil with '--network base'."
126+
"op-stack deposit tx received but is not supported.\n\nYou can use it by running anvil with '--network base'."
125127
)
126128
)]
127129
#[cfg_attr(

crates/anvil/tests/it/optimism.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ async fn test_deposits_not_supported_if_optimism_disabled() {
8282

8383
let err = provider.send_transaction(tx).await.unwrap_err();
8484
let s = err.to_string();
85-
assert!(s.contains("deposit transaction received but is not supported"), "{s:?}");
85+
assert!(s.contains("op-stack deposit tx received but is not supported"), "{s:?}");
8686
}
8787

8888
#[tokio::test(flavor = "multi_thread")]

crates/cast/src/args.rs

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
#[cfg(feature = "base")]
2+
use crate::cmd::resolve_network;
13
use crate::{
24
Cast, SimpleCast,
3-
cmd::{erc20::IERC20, resolve_network},
5+
cmd::erc20::IERC20,
46
opts::{Cast as CastArgs, CastSubcommand, ToBaseArgs},
57
traces::identifier::SignaturesIdentifier,
68
tx::CastTxSender,
@@ -421,45 +423,43 @@ pub async fn run_command(args: CastArgs) -> Result<()> {
421423
// Can use either --raw or specify raw as a field
422424
let is_raw_block = raw || fields.contains(&"raw".into());
423425
let output = if is_raw_block {
426+
// Base encodes EIP-8130 transactions, so the raw block is only faithful with a
427+
// Base-typed provider. Base is the only family inferred here; every other one
428+
// still comes from `--network` alone.
429+
#[cfg(feature = "base")]
424430
let network = match network {
425-
Some(network) => network,
426-
None => resolve_network(&config).await?,
431+
Some(network) => Some(network),
432+
None => {
433+
resolve_network(&config).await?.is_base().then_some(NetworkVariant::Base)
434+
}
427435
};
428436
match network {
429437
#[cfg(feature = "base")]
430-
NetworkVariant::Base => {
438+
Some(NetworkVariant::Base) => {
431439
let provider =
432440
ProviderBuilder::<BaseNetwork>::from_config(&config)?.build()?;
433441
Cast::new(&provider)
434442
.block_raw(block.unwrap_or(BlockId::Number(Latest)), full)
435443
.await?
436444
}
437445
#[cfg(feature = "optimism")]
438-
NetworkVariant::Optimism => {
446+
Some(NetworkVariant::Optimism) => {
439447
let provider =
440448
ProviderBuilder::<Optimism>::from_config(&config)?.build()?;
441449

442450
Cast::new(&provider)
443451
.block_raw(block.unwrap_or(BlockId::Number(Latest)), full)
444452
.await?
445453
}
446-
NetworkVariant::Tempo => {
454+
Some(NetworkVariant::Tempo) => {
447455
let provider =
448456
ProviderBuilder::<TempoNetwork>::from_config(&config)?.build()?;
449457
Cast::new(&provider)
450458
.block_raw(block.unwrap_or(BlockId::Number(Latest)), full)
451459
.await?
452460
}
453-
NetworkVariant::Ethereum => {
454-
let provider =
455-
ProviderBuilder::<Ethereum>::from_config(&config)?.build()?;
456-
Cast::new(&provider)
457-
.block_raw(block.unwrap_or(BlockId::Number(Latest)), full)
458-
.await?
459-
}
460-
// Monad blocks are Ethereum-shaped, so they use the Ethereum-typed provider.
461-
#[cfg(feature = "monad")]
462-
NetworkVariant::Monad => {
461+
// Ethereum (default) or no --raw flag
462+
_ => {
463463
let provider =
464464
ProviderBuilder::<Ethereum>::from_config(&config)?.build()?;
465465
Cast::new(&provider)
@@ -749,42 +749,39 @@ pub async fn run_command(args: CastArgs) -> Result<()> {
749749
let config = rpc.load_config()?;
750750
// Can use either --raw or specify raw as a field
751751
let is_raw = raw || field.as_ref().is_some_and(|f| f == "raw");
752+
// Base encodes EIP-8130 transactions, so the response is only faithful with a
753+
// Base-typed provider. Base is the only family inferred here; every other one still
754+
// comes from `--network` alone.
755+
#[cfg(feature = "base")]
752756
let network = match network {
753-
Some(network) => network,
754-
None => resolve_network(&config).await?,
757+
Some(network) => Some(network),
758+
None => resolve_network(&config).await?.is_base().then_some(NetworkVariant::Base),
755759
};
756760
let output = match network {
757761
#[cfg(feature = "base")]
758-
NetworkVariant::Base => {
762+
Some(NetworkVariant::Base) => {
759763
let provider = ProviderBuilder::<BaseNetwork>::from_config(&config)?.build()?;
760764
Cast::new(&provider)
761765
.transaction(tx_hash, from, nonce, field, is_raw, to_request, lane)
762766
.await?
763767
}
764768
#[cfg(feature = "optimism")]
765-
NetworkVariant::Optimism => {
769+
Some(NetworkVariant::Optimism) => {
766770
let provider = ProviderBuilder::<Optimism>::from_config(&config)?.build()?;
767771

768772
Cast::new(&provider)
769773
.transaction(tx_hash, from, nonce, field, is_raw, to_request, lane)
770774
.await?
771775
}
772-
NetworkVariant::Tempo => {
776+
Some(NetworkVariant::Tempo) => {
773777
let provider =
774778
ProviderBuilder::<TempoNetwork>::from_config(&config)?.build()?;
775779
Cast::new(&provider)
776780
.transaction(tx_hash, from, nonce, field, is_raw, to_request, lane)
777781
.await?
778782
}
779-
NetworkVariant::Ethereum => {
780-
let provider = utils::get_provider(&config)?;
781-
Cast::new(&provider)
782-
.transaction(tx_hash, from, nonce, field, is_raw, to_request, lane)
783-
.await?
784-
}
785-
// Monad transactions are Ethereum-shaped, so they use the default provider.
786-
#[cfg(feature = "monad")]
787-
NetworkVariant::Monad => {
783+
// Ethereum (default) or no --raw flag
784+
_ => {
788785
let provider = utils::get_provider(&config)?;
789786
Cast::new(&provider)
790787
.transaction(tx_hash, from, nonce, field, is_raw, to_request, lane)

crates/cast/src/cmd/access_list.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use super::auth::confirm_auth_rpc_disclosure;
2+
#[cfg(feature = "base")]
3+
use crate::cmd::resolve_network;
24
use crate::{
35
Cast,
4-
cmd::resolve_network,
56
tx::{CastTxBuilder, SenderKind},
67
};
78
use alloy_ens::NameOrAddress;
@@ -74,13 +75,8 @@ impl AccessListArgs {
7475
return self.run_with_network::<TempoNetwork>().await;
7576
}
7677

77-
let config = self.rpc.load_config()?;
78-
let network = resolve_network(&config).await?;
79-
if network.is_tempo() {
80-
return self.run_with_network::<TempoNetwork>().await;
81-
}
8278
#[cfg(feature = "base")]
83-
if network.is_base() {
79+
if resolve_network(&self.rpc.load_config()?).await?.is_base() {
8480
return self.run_with_network::<BaseNetwork>().await;
8581
}
8682

crates/cast/src/cmd/call.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,15 +1042,16 @@ mod tests {
10421042
assert_eq!(config.chain, Some(Chain::mainnet()));
10431043
}
10441044

1045+
/// Base chain IDs resolved to Optimism before Base support existed, so a build without the
1046+
/// `base` feature — which is what release binaries ship — must keep resolving them that way.
10451047
#[test]
1046-
#[cfg(not(feature = "base"))]
1047-
fn chain_id_rejects_disabled_base_network() {
1048-
let error = infer_network_from_chain_id(NetworkConfigs::default(), 8453).unwrap_err();
1049-
assert_eq!(
1050-
error.to_string(),
1051-
"cannot infer execution network from chain ID 8453: network family `base` is not \
1052-
enabled in this build"
1053-
);
1048+
#[cfg(all(not(feature = "base"), feature = "optimism"))]
1049+
fn chain_id_without_base_still_resolves_to_optimism() {
1050+
for chain_id in [8453, 84532] {
1051+
let networks = infer_network_from_chain_id(NetworkConfigs::default(), chain_id)
1052+
.unwrap_or_else(|error| panic!("chain ID {chain_id} must still resolve: {error}"));
1053+
assert!(networks.is_optimism(), "chain ID {chain_id} must resolve to Optimism");
1054+
}
10541055
}
10551056

10561057
#[test]

crates/cast/src/cmd/da_estimate.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
//! Estimates the data availability size of a block for opstack.
22
3-
use super::resolve_network;
43
use alloy_consensus::BlockHeader;
5-
use alloy_network::{BlockResponse, Ethereum, Network, eip2718::Encodable2718};
4+
use alloy_network::{AnyNetwork, BlockResponse, Ethereum, Network, eip2718::Encodable2718};
65
use alloy_provider::Provider;
76
use alloy_rpc_types::BlockId;
87
#[cfg(feature = "base")]
@@ -34,8 +33,11 @@ impl DAEstimateArgs {
3433
let Self { block, rpc, network } = self;
3534
let config = rpc.load_config()?;
3635
let network = match network {
37-
Some(network) => network,
38-
None => resolve_network(&config).await?,
36+
Some(n) => n,
37+
None => {
38+
let provider = ProviderBuilder::<AnyNetwork>::from_config(&config)?.build()?;
39+
provider.get_chain_id().await?.into()
40+
}
3941
};
4042
match network {
4143
#[cfg(feature = "base")]

0 commit comments

Comments
 (0)