diff --git a/Dockerfile b/Dockerfile index b734e4c35..2502811bb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,8 @@ # Adapted from https://github.com/paradigmxyz/reth/blob/main/Dockerfile # syntax=docker/dockerfile:1.4 +FROM ghcr.io/foundry-rs/foundry:nightly-fe2acca4e379793539db80e032d76ffe0110298b as foundry + FROM --platform=$TARGETPLATFORM rust:1.83.0 AS chef-builder # Install system dependencies @@ -10,10 +12,12 @@ RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg - RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list RUN apt-get update && apt-get -y upgrade && apt-get install -y libclang-dev pkg-config protobuf-compiler nodejs yarn rsync +# copy foundry tool +COPY --from=foundry /usr/local/bin/forge /usr/local/bin/forge + SHELL ["/bin/bash", "-c"] RUN curl -L https://foundry.paradigm.xyz | bash ENV PATH="/root/.foundry/bin:${PATH}" -RUN foundryup -i nightly-fe2acca4e379793539db80e032d76ffe0110298b RUN cargo install cargo-chef --locked diff --git a/bin/rundler/src/cli/pool.rs b/bin/rundler/src/cli/pool.rs index ada573e23..a977d54d3 100644 --- a/bin/rundler/src/cli/pool.rs +++ b/bin/rundler/src/cli/pool.rs @@ -186,6 +186,14 @@ pub struct PoolArgs { env = "POOL_MAX_TIME_IN_POOL_SECS" )] pub max_time_in_pool_secs: Option, + + #[arg( + long = "pool.support_7702", + name = "pool.support_7702", + env = "POOL_SUPPORT_7702", + default_value = "false" + )] + pub support_7702: bool, } impl PoolArgs { @@ -244,6 +252,7 @@ impl PoolArgs { gas_limit_efficiency_reject_threshold: self.gas_limit_efficiency_reject_threshold, max_time_in_pool: self.max_time_in_pool_secs.map(Duration::from_secs), max_expected_storage_slots: common.max_expected_storage_slots.unwrap_or(usize::MAX), + support_7702: self.support_7702, }; let mut pool_configs = vec![]; @@ -255,6 +264,8 @@ impl PoolArgs { num_shards: common.num_builders_v0_6, mempool_channel_configs: mempool_channel_configs .get_for_entry_point(chain_spec.entry_point_address_v0_6), + // always disable 7702 for EP v06. + support_7702: false, ..pool_config_base.clone() }); } diff --git a/crates/pool/proto/op_pool/op_pool.proto b/crates/pool/proto/op_pool/op_pool.proto index d8a14d137..a4fc7fa38 100644 --- a/crates/pool/proto/op_pool/op_pool.proto +++ b/crates/pool/proto/op_pool/op_pool.proto @@ -533,6 +533,7 @@ message MempoolError { PreOpGasLimitEfficiencyTooLow pre_op_gas_limit_efficiency_too_low = 17; ExecutionGasLimitEfficiencyTooLow execution_gas_limit_efficiency_too_low = 18; TooManyExpectedStorageSlots too_many_expected_storage_slots = 19; + UseUnsupportedEIP use_unsupported_eip= 20; } } @@ -600,6 +601,10 @@ message TooManyExpectedStorageSlots { uint64 expected_slots = 2; } +message UseUnsupportedEIP { + string eip_name = 1; +} + // PRECHECK VIOLATIONS message PrecheckViolationError { oneof violation { diff --git a/crates/pool/src/mempool/mod.rs b/crates/pool/src/mempool/mod.rs index 8aa8bed91..38f840c12 100644 --- a/crates/pool/src/mempool/mod.rs +++ b/crates/pool/src/mempool/mod.rs @@ -175,6 +175,8 @@ pub struct PoolConfig { pub max_time_in_pool: Option, /// The maximum number of storage slots that can be expected to be used by a user operation during validation pub max_expected_storage_slots: usize, + /// Whether to enable UO with 7702 auth + pub support_7702: bool, } /// Origin of an operation. diff --git a/crates/pool/src/mempool/pool.rs b/crates/pool/src/mempool/pool.rs index 45624a5f7..9f823fa46 100644 --- a/crates/pool/src/mempool/pool.rs +++ b/crates/pool/src/mempool/pool.rs @@ -48,6 +48,7 @@ pub(crate) struct PoolInnerConfig { throttled_entity_live_blocks: u64, da_gas_tracking_enabled: bool, max_time_in_pool: Option, + support_7702: bool, } impl From for PoolInnerConfig { @@ -61,6 +62,7 @@ impl From for PoolInnerConfig { throttled_entity_live_blocks: config.throttled_entity_live_blocks, da_gas_tracking_enabled: config.da_gas_tracking_enabled, max_time_in_pool: config.max_time_in_pool, + support_7702: config.support_7702, } } } @@ -417,6 +419,20 @@ where Ok(()) } + pub(crate) fn check_eip7702(&self, uo: &UserOperationVariant) -> MempoolResult<()> { + if uo.authorization_tuple().is_some() { + if self.config.support_7702 { + Ok(()) + } else { + Err(MempoolError::EIPNotSupported( + "EIP 7702 is not supported".to_string(), + )) + } + } else { + Ok(()) + } + } + pub(crate) fn mine_operation( &mut self, mined_op: &MinedOp, @@ -1521,6 +1537,7 @@ mod tests { throttled_entity_live_blocks: 10, da_gas_tracking_enabled: false, max_time_in_pool: None, + support_7702: false, } } diff --git a/crates/pool/src/mempool/uo_pool.rs b/crates/pool/src/mempool/uo_pool.rs index 7806c0150..aecfee8f1 100644 --- a/crates/pool/src/mempool/uo_pool.rs +++ b/crates/pool/src/mempool/uo_pool.rs @@ -477,6 +477,9 @@ where // Check if op violates the STO-040 spec rule state.pool.check_multiple_roles_violation(&op)?; + // Check if op use 7702 + state.pool.check_eip7702(&op)?; + // Check if op is already known or replacing another, and if so, ensure its fees are high enough state .pool @@ -959,6 +962,7 @@ mod tests { SimulationError, SimulationResult, SimulationSettings, ViolationError, }; use rundler_types::{ + authorization::Eip7702Auth, chain::ChainSpec, da::DAGasUOData, pool::{PrecheckViolation, SimulationViolation}, @@ -1862,6 +1866,33 @@ mod tests { .unwrap(); } + #[tokio::test] + async fn test_eip_support() { + let mut config = default_config(); + let op = create_op_from_op_v0_6(UserOperation { + call_gas_limit: 50_000, + max_fee_per_gas: 0, + max_priority_fee_per_gas: 0, + authorization_tuple: Some(Eip7702Auth::default()), + ..Default::default() + }); + { + let pool = create_pool_with_config(config.clone(), vec![op.clone()]); + assert!(pool + .add_operation(OperationOrigin::Local, op.clone().op) + .await + .is_err()); + } + { + config.support_7702 = true; + let pool = create_pool_with_config(config.clone(), vec![op.clone()]); + assert!(pool + .add_operation(OperationOrigin::Local, op.clone().op) + .await + .is_ok()); + } + } + #[tokio::test] async fn test_da_gas_ineligible() { let mut config = default_config(); @@ -1917,6 +1948,7 @@ mod tests { gas_limit_efficiency_reject_threshold: 0.0, max_time_in_pool: None, max_expected_storage_slots: usize::MAX, + support_7702: false, } } diff --git a/crates/pool/src/server/remote/error.rs b/crates/pool/src/server/remote/error.rs index b66a8f40b..92c07c01a 100644 --- a/crates/pool/src/server/remote/error.rs +++ b/crates/pool/src/server/remote/error.rs @@ -39,8 +39,9 @@ use super::protos::{ SimulationViolationError as ProtoSimulationViolationError, TooManyExpectedStorageSlots, TotalGasLimitTooHigh, UnintendedRevert, UnintendedRevertWithMessage, UnknownEntryPointError, UnknownRevert, UnstakedAggregator, UnstakedPaymasterContext, UnsupportedAggregatorError, - UsedForbiddenOpcode, UsedForbiddenPrecompile, ValidationRevert as ProtoValidationRevert, - VerificationGasLimitBufferTooLow, VerificationGasLimitTooHigh, WrongNumberOfPhases, + UseUnsupportedEip, UsedForbiddenOpcode, UsedForbiddenPrecompile, + ValidationRevert as ProtoValidationRevert, VerificationGasLimitBufferTooLow, + VerificationGasLimitTooHigh, WrongNumberOfPhases, }; impl TryFrom for PoolError { @@ -139,6 +140,9 @@ impl TryFrom for MempoolError { e.expected_slots.try_into()?, ) } + Some(mempool_error::Error::UseUnsupportedEip(e)) => { + MempoolError::EIPNotSupported(e.eip_name) + } None => bail!("unknown proto mempool error"), }) } @@ -265,6 +269,11 @@ impl From for ProtoMempoolError { )), } } + MempoolError::EIPNotSupported(msg) => ProtoMempoolError { + error: Some(mempool_error::Error::UseUnsupportedEip(UseUnsupportedEip { + eip_name: msg, + })), + }, } } } diff --git a/crates/pool/src/server/remote/protos.rs b/crates/pool/src/server/remote/protos.rs index 6c1cd9a2f..e2e3caa98 100644 --- a/crates/pool/src/server/remote/protos.rs +++ b/crates/pool/src/server/remote/protos.rs @@ -15,7 +15,7 @@ use alloy_primitives::{Address, B256}; use anyhow::{anyhow, Context}; use rundler_task::grpc::protos::{from_bytes, ConversionError, ToProtoBytes}; use rundler_types::{ - authorization::Authorization, + authorization::Eip7702Auth, chain::ChainSpec, da::{ BedrockDAGasUOData as RundlerBedrockDAGasUOData, DAGasUOData as RundlerDAGasUOData, @@ -83,9 +83,9 @@ pub trait TryUoFromProto: Sized { fn try_uo_from_proto(value: T, chain_spec: &ChainSpec) -> Result; } -impl From for Authorization { +impl From for Eip7702Auth { fn from(value: AuthorizationTuple) -> Self { - Authorization { + Eip7702Auth { chain_id: value.chain_id, address: from_bytes(&value.address).unwrap_or_default(), nonce: value.nonce, @@ -103,7 +103,7 @@ impl TryUoFromProto for v0_6::UserOperation { let authorization_tuple = op .authorization_tuple .as_ref() - .map(|authorization| Authorization::from(authorization.clone())); + .map(|authorization| Eip7702Auth::from(authorization.clone())); Ok(v0_6::UserOperationBuilder::new( chain_spec, @@ -164,7 +164,7 @@ impl TryUoFromProto for v0_7::UserOperation { let authorization_tuple = op .authorization_tuple .as_ref() - .map(|authorization| Authorization::from(authorization.clone())); + .map(|authorization| Eip7702Auth::from(authorization.clone())); let mut builder = v0_7::UserOperationBuilder::new( chain_spec, diff --git a/crates/provider/src/alloy/entry_point/v0_6.rs b/crates/provider/src/alloy/entry_point/v0_6.rs index 51e75515b..def2c6563 100644 --- a/crates/provider/src/alloy/entry_point/v0_6.rs +++ b/crates/provider/src/alloy/entry_point/v0_6.rs @@ -532,7 +532,7 @@ fn get_handle_ops_call, T: Transport + Clone>( gas_limit: u64, gas_fees: GasFees, ) -> TransactionRequest { - let mut authorization_list: Vec = vec![]; + let mut eip7702_auth_list: Vec = vec![]; let mut ops_per_aggregator: Vec = ops_per_aggregator .into_iter() .map(|uoa| UserOpsPerAggregatorV0_6 { @@ -541,7 +541,7 @@ fn get_handle_ops_call, T: Transport + Clone>( .into_iter() .map(|op| { if let Some(authorization) = &op.authorization_tuple { - authorization_list.push(SignedAuthorization::from(authorization.clone())); + eip7702_auth_list.push(SignedAuthorization::from(authorization.clone())); } op.into() }) @@ -567,8 +567,8 @@ fn get_handle_ops_call, T: Transport + Clone>( .gas_limit(gas_limit) .max_fee_per_gas(gas_fees.max_fee_per_gas) .max_priority_fee_per_gas(gas_fees.max_priority_fee_per_gas); - if !authorization_list.is_empty() { - txn_request = txn_request.with_authorization_list(authorization_list); + if !eip7702_auth_list.is_empty() { + txn_request = txn_request.with_authorization_list(eip7702_auth_list); } txn_request diff --git a/crates/provider/src/alloy/entry_point/v0_7.rs b/crates/provider/src/alloy/entry_point/v0_7.rs index 13215285f..662ffbd84 100644 --- a/crates/provider/src/alloy/entry_point/v0_7.rs +++ b/crates/provider/src/alloy/entry_point/v0_7.rs @@ -37,7 +37,7 @@ use rundler_contracts::v0_7::{ ENTRY_POINT_SIMULATIONS_V0_7_DEPLOYED_BYTECODE, }; use rundler_types::{ - authorization::Authorization, + authorization::Eip7702Auth, chain::ChainSpec, da::{DAGasBlockData, DAGasUOData}, v0_7::UserOperation, @@ -609,7 +609,7 @@ impl TryFrom for ExecutionResult { fn add_authorization_tuple( sender: Address, - authorization: &Option, + authorization: &Option, state_override: &mut StateOverride, ) { if let Some(authorization) = &authorization { diff --git a/crates/rpc/src/eth/error.rs b/crates/rpc/src/eth/error.rs index d282af2fb..4ceb3dee8 100644 --- a/crates/rpc/src/eth/error.rs +++ b/crates/rpc/src/eth/error.rs @@ -320,6 +320,7 @@ impl From for EthRpcError { MempoolError::TooManyExpectedStorageSlots(_, _) => { Self::InvalidParams(value.to_string()) } + MempoolError::EIPNotSupported(_) => Self::InvalidParams(value.to_string()), } } } diff --git a/crates/rpc/src/types/rpc_authorization.rs b/crates/rpc/src/types/rpc_authorization.rs index 5035e4e86..0dd99d6e3 100644 --- a/crates/rpc/src/types/rpc_authorization.rs +++ b/crates/rpc/src/types/rpc_authorization.rs @@ -1,11 +1,11 @@ use alloy_primitives::{Address, U256, U64, U8}; -use rundler_types::authorization::Authorization; +use rundler_types::authorization::Eip7702Auth; use serde::{Deserialize, Serialize}; /// authorization tuple for 7702 txn support #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default)] #[serde(rename_all = "camelCase")] -pub(crate) struct RpcAuthorization { +pub(crate) struct RpcEip7702Auth { /// The chain ID of the authorization. pub chain_id: U64, /// The address of the authorization. @@ -20,9 +20,9 @@ pub(crate) struct RpcAuthorization { pub s: U256, } -impl From for Authorization { - fn from(val: RpcAuthorization) -> Self { - Authorization { +impl From for Eip7702Auth { + fn from(val: RpcEip7702Auth) -> Self { + Eip7702Auth { chain_id: val.chain_id.to(), address: val.address, nonce: val.nonce.to(), @@ -33,8 +33,8 @@ impl From for Authorization { } } -impl From for RpcAuthorization { - fn from(value: Authorization) -> Self { +impl From for RpcEip7702Auth { + fn from(value: Eip7702Auth) -> Self { Self { chain_id: U64::from(value.chain_id), address: value.address, diff --git a/crates/rpc/src/types/v0_6.rs b/crates/rpc/src/types/v0_6.rs index e7b0c6f79..7ae4a61fb 100644 --- a/crates/rpc/src/types/v0_6.rs +++ b/crates/rpc/src/types/v0_6.rs @@ -22,7 +22,7 @@ use rundler_types::{ }; use serde::{Deserialize, Serialize}; -use super::{rpc_authorization::RpcAuthorization, FromRpc, RpcAddress}; +use super::{rpc_authorization::RpcEip7702Auth, FromRpc, RpcAddress}; /// User operation definition for RPC #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] @@ -38,7 +38,7 @@ pub(crate) struct RpcUserOperation { max_priority_fee_per_gas: U128, paymaster_and_data: Bytes, signature: Bytes, - authorization_tuple: Option, + eip7702_auth: Option, } impl From for RpcUserOperation { @@ -55,7 +55,7 @@ impl From for RpcUserOperation { max_priority_fee_per_gas: U128::from(op.max_priority_fee_per_gas), paymaster_and_data: op.paymaster_and_data, signature: op.signature, - authorization_tuple: op.authorization_tuple.map(|a| a.into()), + eip7702_auth: op.authorization_tuple.map(|a| a.into()), } } } @@ -78,7 +78,7 @@ impl FromRpc for UserOperation { signature: def.signature, }, ExtendedUserOperation { - authorization_tuple: def.authorization_tuple.map(|a| a.into()), + authorization_tuple: def.eip7702_auth.map(|a| a.into()), }, ) .build() @@ -99,7 +99,7 @@ pub(crate) struct RpcUserOperationOptionalGas { max_priority_fee_per_gas: Option, paymaster_and_data: Bytes, signature: Bytes, - authorization_contract: Option
, + eip7702_auth_address: Option
, } impl From for UserOperationOptionalGas { @@ -116,7 +116,7 @@ impl From for UserOperationOptionalGas { max_priority_fee_per_gas: def.max_priority_fee_per_gas.map(|x| x.to()), paymaster_and_data: def.paymaster_and_data, signature: def.signature, - authorization_contract: def.authorization_contract, + eip7702_auth_address: def.eip7702_auth_address, } } } diff --git a/crates/rpc/src/types/v0_7.rs b/crates/rpc/src/types/v0_7.rs index 683e7d34b..c5f52c556 100644 --- a/crates/rpc/src/types/v0_7.rs +++ b/crates/rpc/src/types/v0_7.rs @@ -21,7 +21,7 @@ use rundler_types::{ }; use serde::{Deserialize, Serialize}; -use super::{rpc_authorization::RpcAuthorization, FromRpc, RpcAddress}; +use super::{rpc_authorization::RpcEip7702Auth, FromRpc, RpcAddress}; /// User operation definition for RPC inputs #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] @@ -49,7 +49,7 @@ pub(crate) struct RpcUserOperation { paymaster_data: Option, signature: Bytes, #[serde(skip_serializing_if = "Option::is_none")] - authorization_tuple: Option, + eip7702_auth: Option, } impl From for RpcUserOperation { @@ -87,7 +87,7 @@ impl From for RpcUserOperation { paymaster_post_op_gas_limit: paymaster_post_op_gas_limit.map(|x| U128::from(x)), paymaster_data, signature: op.signature, - authorization_tuple: op.authorization_tuple.map(|a| a.into()), + eip7702_auth: op.authorization_tuple.map(|a| a.into()), } } } @@ -123,8 +123,8 @@ impl FromRpc for UserOperation { if def.factory.is_some() { builder = builder.factory(def.factory.unwrap(), def.factory_data.unwrap_or_default()); } - if def.authorization_tuple.is_some() { - builder = builder.authorization_tuple(def.authorization_tuple.map(|a| a.into())); + if def.eip7702_auth.is_some() { + builder = builder.authorization_tuple(def.eip7702_auth.map(|a| a.into())); } builder.build() } @@ -159,7 +159,7 @@ pub(crate) struct RpcUserOperationOptionalGas { paymaster_post_op_gas_limit: Option, paymaster_data: Option, signature: Bytes, - authorization_contract: Option
, + eip7702_auth: Option, } impl From for UserOperationOptionalGas { @@ -180,7 +180,7 @@ impl From for UserOperationOptionalGas { paymaster_post_op_gas_limit: def.paymaster_post_op_gas_limit.map(|x| x.to()), paymaster_data: def.paymaster_data.unwrap_or_default(), signature: def.signature, - authorization_contract: def.authorization_contract, + eip7702_auth_address: def.eip7702_auth.map(|a| a.address), } } } diff --git a/crates/sim/src/estimation/estimate_call_gas.rs b/crates/sim/src/estimation/estimate_call_gas.rs index fcfff1627..307ae0cd6 100644 --- a/crates/sim/src/estimation/estimate_call_gas.rs +++ b/crates/sim/src/estimation/estimate_call_gas.rs @@ -108,11 +108,11 @@ where let callless_op = self.specialization.get_op_with_no_call_gas(op.clone()); if let Some(authorization_tuple) = op.authorization_tuple().clone() { - let authorization_contract = authorization_tuple.address; + let eip7702_auth_address = authorization_tuple.address; authorization_utils::apply_7702_overrides( &mut state_override, op.sender(), - authorization_contract, + eip7702_auth_address, ); } let mut min_gas = 0; diff --git a/crates/sim/src/estimation/v0_6.rs b/crates/sim/src/estimation/v0_6.rs index faafecf10..61472764e 100644 --- a/crates/sim/src/estimation/v0_6.rs +++ b/crates/sim/src/estimation/v0_6.rs @@ -568,7 +568,7 @@ mod tests { max_priority_fee_per_gas: None, paymaster_and_data: Bytes::new(), signature: Bytes::new(), - authorization_contract: None, + eip7702_auth_address: None, } } diff --git a/crates/sim/src/estimation/v0_7.rs b/crates/sim/src/estimation/v0_7.rs index cb9c294f6..fa04061c4 100644 --- a/crates/sim/src/estimation/v0_7.rs +++ b/crates/sim/src/estimation/v0_7.rs @@ -614,7 +614,7 @@ mod tests { factory: None, factory_data: Bytes::new(), - authorization_contract: None, + eip7702_auth_address: None, } } @@ -847,7 +847,7 @@ mod tests { factory: None, factory_data: Bytes::new(), - authorization_contract: None, + eip7702_auth_address: None, }; let estimation = estimator diff --git a/crates/types/src/authorization.rs b/crates/types/src/authorization.rs index d04f7766c..da6f1382e 100644 --- a/crates/types/src/authorization.rs +++ b/crates/types/src/authorization.rs @@ -19,7 +19,7 @@ use serde::{Deserialize, Serialize}; /// authorization tuple for 7702 txn support #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize, Default)] #[serde(rename_all = "camelCase")] -pub struct Authorization { +pub struct Eip7702Auth { /// The chain ID of the authorization. pub chain_id: u64, /// The address of the authorization. @@ -34,8 +34,8 @@ pub struct Authorization { pub s: U256, } -impl From for alloy_eips::eip7702::SignedAuthorization { - fn from(value: Authorization) -> Self { +impl From for alloy_eips::eip7702::SignedAuthorization { + fn from(value: Eip7702Auth) -> Self { let authorization = alloy_eips::eip7702::Authorization { chain_id: value.chain_id, address: value.address, diff --git a/crates/types/src/pool/error.rs b/crates/types/src/pool/error.rs index 7f9bda8df..583166366 100644 --- a/crates/types/src/pool/error.rs +++ b/crates/types/src/pool/error.rs @@ -103,6 +103,9 @@ pub enum MempoolError { /// Too many expected storage slots #[error("Too many expected storage slots. Maximum: {0}, Actual: {1}")] TooManyExpectedStorageSlots(usize, usize), + /// Use unsupported EIP + #[error("{0} is not supported")] + EIPNotSupported(String), } /// Precheck violation enumeration diff --git a/crates/types/src/user_operation/mod.rs b/crates/types/src/user_operation/mod.rs index 2f05f4134..cb02344c7 100644 --- a/crates/types/src/user_operation/mod.rs +++ b/crates/types/src/user_operation/mod.rs @@ -22,7 +22,7 @@ pub mod v0_6; /// User Operation types for Entry Point v0.7 pub mod v0_7; -use crate::{authorization::Authorization, chain::ChainSpec, Entity}; +use crate::{authorization::Eip7702Auth, chain::ChainSpec, Entity}; /// A user op must be valid for at least this long into the future to be included. pub const TIME_RANGE_BUFFER: Duration = Duration::from_secs(60); @@ -111,7 +111,7 @@ pub trait UserOperation: Debug + Clone + Send + Sync + 'static { } /// Return the authorization list of the UO. empty if it is not 7702 txn. - fn authorization_tuple(&self) -> Option; + fn authorization_tuple(&self) -> Option; /* * Enhanced functions @@ -503,7 +503,7 @@ impl UserOperation for UserOperationVariant { } } - fn authorization_tuple(&self) -> Option { + fn authorization_tuple(&self) -> Option { match self { UserOperationVariant::V0_6(op) => op.authorization_tuple(), UserOperationVariant::V0_7(op) => op.authorization_tuple(), diff --git a/crates/types/src/user_operation/v0_6.rs b/crates/types/src/user_operation/v0_6.rs index 594af96bd..07451e5c4 100644 --- a/crates/types/src/user_operation/v0_6.rs +++ b/crates/types/src/user_operation/v0_6.rs @@ -22,7 +22,7 @@ use super::{ UserOperationVariant, }; use crate::{ - authorization::Authorization, + authorization::Eip7702Auth, chain::ChainSpec, entity::{Entity, EntityType}, EntryPointVersion, @@ -80,7 +80,7 @@ pub struct UserOperation { pub signature: Bytes, /// eip 7702 - list of authorities. - pub authorization_tuple: Option, + pub authorization_tuple: Option, /// Cached calldata gas cost pub calldata_gas_cost: u128, @@ -288,7 +288,7 @@ impl UserOperationTrait for UserOperation { + super::byte_array_abi_len(&self.signature) } - fn authorization_tuple(&self) -> Option { + fn authorization_tuple(&self) -> Option { self.authorization_tuple.clone() } } @@ -402,7 +402,7 @@ pub struct UserOperationOptionalGas { pub signature: Bytes, /// eip 7702 - tuple of authority. - pub authorization_contract: Option
, + pub eip7702_auth_address: Option
, } impl UserOperationOptionalGas { @@ -483,7 +483,7 @@ impl UserOperationOptionalGas { super::default_if_none_or_equal(self.verification_gas_limit, max_verification_gas, 0); let pvg = super::default_if_none_or_equal(self.pre_verification_gas, max_call_gas, 0); - let authorization_tuple = self.authorization_contract.map(|address| Authorization { + let authorization_tuple = self.eip7702_auth_address.map(|address| Eip7702Auth { address, ..Default::default() }); @@ -550,7 +550,7 @@ pub struct UserOperationBuilder<'a> { /// to UO directly but included for implementation's sake. pub struct ExtendedUserOperation { /// EIP 7702: authorization tuples. - pub authorization_tuple: Option, + pub authorization_tuple: Option, } /// User operation required fields @@ -686,7 +686,7 @@ impl<'a> UserOperationBuilder<'a> { } /// Sets the authorization tuple. - pub fn authorization_tuple(mut self, authorization: Option) -> Self { + pub fn authorization_tuple(mut self, authorization: Option) -> Self { self.extended.authorization_tuple = authorization; self } @@ -938,7 +938,7 @@ mod tests { pre_verification_gas: None, max_fee_per_gas: None, max_priority_fee_per_gas: None, - authorization_contract: None, + eip7702_auth_address: None, } .max_fill(&ChainSpec::default()); diff --git a/crates/types/src/user_operation/v0_7.rs b/crates/types/src/user_operation/v0_7.rs index 5ac8123a9..111139d88 100644 --- a/crates/types/src/user_operation/v0_7.rs +++ b/crates/types/src/user_operation/v0_7.rs @@ -19,7 +19,7 @@ use super::{ random_bytes, random_bytes_array, UserOperation as UserOperationTrait, UserOperationId, UserOperationVariant, }; -use crate::{authorization::Authorization, chain::ChainSpec, Entity, EntryPointVersion}; +use crate::{authorization::Eip7702Auth, chain::ChainSpec, Entity, EntryPointVersion}; /// Gas overhead required by the entry point contract for the inner call pub const ENTRY_POINT_INNER_GAS_OVERHEAD: u128 = 10_000; @@ -83,7 +83,7 @@ pub struct UserOperation { /// Paymaster data pub paymaster_data: Bytes, /// eip 7702 - tuple of authority. - pub authorization_tuple: Option, + pub authorization_tuple: Option, /* * Cached fields, not part of the UO @@ -239,7 +239,7 @@ impl UserOperationTrait for UserOperation { + super::byte_array_abi_len(&self.packed.signature) } - fn authorization_tuple(&self) -> Option { + fn authorization_tuple(&self) -> Option { self.authorization_tuple.clone() } } @@ -340,7 +340,7 @@ pub struct UserOperationOptionalGas { /// Paymaster data pub paymaster_data: Bytes, /// 7702 authorization contract address. - pub authorization_contract: Option
, + pub eip7702_auth_address: Option
, } impl UserOperationOptionalGas { @@ -373,15 +373,12 @@ impl UserOperationOptionalGas { vec![255_u8; self.paymaster_data.len()].into(), ); } - if self.authorization_contract.is_some() { - builder = builder.authorization_tuple(Some(Authorization { - address: self.authorization_contract.unwrap(), + if let Some(eip_7702_auth_address) = self.eip7702_auth_address { + builder = builder.authorization_tuple(Some(Eip7702Auth { + address: eip_7702_auth_address, chain_id: chain_spec.id, // fake value for gas estimation. - nonce: 0, - y_parity: 0, - r: U256::from(0), - s: U256::from(0), + ..Default::default() })); } if self.factory.is_some() { @@ -484,8 +481,8 @@ impl UserOperationOptionalGas { self.paymaster_data, ); } - if let Some(contract) = self.authorization_contract { - builder = builder.authorization_tuple(Some(Authorization { + if let Some(contract) = self.eip7702_auth_address { + builder = builder.authorization_tuple(Some(Eip7702Auth { address: contract, ..Default::default() })); @@ -542,7 +539,7 @@ pub struct UserOperationBuilder<'a> { packed_uo: Option, /// eip 7702 - tuple of authority. - authorization_tuple: Option, + authorization_tuple: Option, } /// Required fields for UserOperation v0.7 @@ -731,7 +728,7 @@ impl<'a> UserOperationBuilder<'a> { } /// Sets the authorization list - pub fn authorization_tuple(mut self, authorization_tuple: Option) -> Self { + pub fn authorization_tuple(mut self, authorization_tuple: Option) -> Self { self.authorization_tuple = authorization_tuple; self } diff --git a/crates/utils/src/authorization_utils.rs b/crates/utils/src/authorization_utils.rs index dae6a01de..198908c85 100644 --- a/crates/utils/src/authorization_utils.rs +++ b/crates/utils/src/authorization_utils.rs @@ -21,11 +21,11 @@ use alloy_rpc_types_eth::state::{AccountOverride, StateOverride}; pub fn apply_7702_overrides( state_override: &mut StateOverride, sender: Address, - authorization_contract: Address, + eip7702_auth_address: Address, ) { state_override.entry(sender).or_insert({ let prefix: FixedBytes<3> = fixed_bytes!("ef0100"); - let code: FixedBytes<23> = prefix.concat_const(authorization_contract.into()); + let code: FixedBytes<23> = prefix.concat_const(eip7702_auth_address.into()); AccountOverride { code: Some((code).into()), diff --git a/test/spec-tests/v0_6/bundler-spec-tests b/test/spec-tests/v0_6/bundler-spec-tests index ef0de433a..6bc6dd1d0 160000 --- a/test/spec-tests/v0_6/bundler-spec-tests +++ b/test/spec-tests/v0_6/bundler-spec-tests @@ -1 +1 @@ -Subproject commit ef0de433a6987695b8f98a003423af6ffefa97f1 +Subproject commit 6bc6dd1d02ec5c4cf6344fb0aa316fc24cd6ccb6 diff --git a/test/spec-tests/v0_7/bundler-spec-tests b/test/spec-tests/v0_7/bundler-spec-tests index 0c5e23c8e..b94b46d3d 160000 --- a/test/spec-tests/v0_7/bundler-spec-tests +++ b/test/spec-tests/v0_7/bundler-spec-tests @@ -1 +1 @@ -Subproject commit 0c5e23c8ee060ff3ee2a7abcd295f4dca92ac998 +Subproject commit b94b46d3d06f8d6a2d79fbd4e19eae90a9784364