Skip to content

Commit 66cdc55

Browse files
committed
feat: add v0.8 and v0.9 support to user operation type lib
1 parent 01d3bde commit 66cdc55

File tree

24 files changed

+566
-104
lines changed

24 files changed

+566
-104
lines changed

bin/rundler/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ description = """
99
ERC-4337 bundler implementation
1010
"""
1111
publish = false
12+
default-run = "rundler"
1213

1314
[dependencies]
1415
alloy-consensus.workspace = true

bin/rundler/src/cli/pool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ impl PoolArgs {
205205
let pool_config_base = PoolConfig {
206206
// update per entry point
207207
entry_point: Address::ZERO,
208-
entry_point_version: EntryPointVersion::Unspecified,
208+
entry_point_version: EntryPointVersion::V0_6,
209209
mempool_channel_configs: HashMap::new(),
210210
// Base config
211211
chain_spec: chain_spec.clone(),

crates/builder/src/bundle_sender.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -852,6 +852,9 @@ where
852852
.context("builder should remove update entities in the pool")
853853
}
854854

855+
// TODO(entrypoints): In entrypoint v0.8+ we can no longer rely on the user operation hash
856+
// built from a packed user operation to match the mempool hash, as its lacking its authorization
857+
// Either (1) pull the authorization from the reverted transaction or (2) use sender/nonce to remove
855858
async fn process_revert(&self, tx_hash: B256) -> anyhow::Result<()> {
856859
warn!("Bundle transaction {tx_hash:?} reverted onchain");
857860

crates/builder/src/task.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,9 @@ where
230230
bundle_sender_actions.extend(actions);
231231
supported_entry_points.insert(self.args.chain_spec.entry_point_address_v0_7);
232232
}
233-
EntryPointVersion::Unspecified => {
234-
panic!("Unspecified entry point version")
233+
EntryPointVersion::V0_8 | EntryPointVersion::V0_9 => {
234+
// TODO(entrypoints)
235+
todo!("entry point v0.8 and v0.9 are not supported");
235236
}
236237
}
237238
}

crates/contracts/src/v0_7.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ sol!(
158158
) external view returns (DepositInfo memory info);
159159

160160
function balanceOf(address account) external view returns (uint256);
161+
162+
function getUserOpHash(
163+
PackedUserOperation calldata userOp
164+
) public view returns (bytes32);
161165
}
162166

163167
#[allow(missing_docs)]
@@ -257,6 +261,28 @@ sol!(
257261
}
258262
);
259263

264+
mod no_sig {
265+
use alloy_sol_macro::sol;
266+
267+
sol!(
268+
/// Packed user operation without signature
269+
/// Used for hashing the user operation to calculate the correct
270+
/// EIP-712 type hash according to UserOperationLib.sol
271+
#[allow(missing_docs)]
272+
#[derive(Default, Debug, PartialEq, Eq)]
273+
struct PackedUserOperation {
274+
address sender;
275+
uint256 nonce;
276+
bytes initCode;
277+
bytes callData;
278+
bytes32 accountGasLimits;
279+
uint256 preVerificationGas;
280+
bytes32 gasFees;
281+
bytes paymasterAndData;
282+
}
283+
);
284+
}
285+
260286
sol!(
261287
#[allow(missing_docs)]
262288
#[sol(rpc)]
@@ -310,3 +336,20 @@ static __VERIFICATION_GAS_ESTIMATION_HELPER_V0_7_DEPLOYED_BYTECODE: [u8; 5252] =
310336

311337
pub static VERIFICATION_GAS_ESTIMATION_HELPER_V0_7_DEPLOYED_BYTECODE: Bytes =
312338
Bytes::from_static(&__VERIFICATION_GAS_ESTIMATION_HELPER_V0_7_DEPLOYED_BYTECODE);
339+
340+
pub use no_sig::PackedUserOperation as PackedUserOperationNoSig;
341+
342+
impl From<PackedUserOperation> for PackedUserOperationNoSig {
343+
fn from(puo: PackedUserOperation) -> Self {
344+
PackedUserOperationNoSig {
345+
sender: puo.sender,
346+
nonce: puo.nonce,
347+
initCode: puo.initCode,
348+
callData: puo.callData,
349+
accountGasLimits: puo.accountGasLimits,
350+
preVerificationGas: puo.preVerificationGas,
351+
gasFees: puo.gasFees,
352+
paymasterAndData: puo.paymasterAndData,
353+
}
354+
}
355+
}

crates/pool/proto/op_pool/op_pool.proto

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ message UserOperation {
2424
}
2525
}
2626

27+
enum EntryPointVersion {
28+
ENTRY_POINT_VERSION_UNSPECIFIED = 0;
29+
ENTRY_POINT_VERSION_V0_6 = 1;
30+
ENTRY_POINT_VERSION_V0_7 = 2;
31+
ENTRY_POINT_VERSION_V0_8 = 3;
32+
ENTRY_POINT_VERSION_V0_9 = 4;
33+
}
34+
2735
message UserOperationPermissions {
2836
bool trusted = 1;
2937
optional uint64 max_allowed_in_pool_for_sender = 2;
@@ -125,6 +133,9 @@ message UserOperationV07 {
125133
AuthorizationTuple authorization_tuple = 18;
126134
// aggregator
127135
bytes aggregator = 19;
136+
137+
// Entry point version
138+
EntryPointVersion entry_point_version = 20;
128139
}
129140

130141
enum EntityType {

crates/pool/src/chain.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,11 @@ impl<P: EvmProvider> Chain<P> {
883883
Some(EntryPointVersion::V0_7) => {
884884
Self::load_v0_7(log, &mut mined_ops, &mut entity_balance_updates)
885885
}
886-
Some(EntryPointVersion::Unspecified) | None => {
886+
Some(EntryPointVersion::V0_8) | Some(EntryPointVersion::V0_9) => {
887+
// TODO(entrypoints)
888+
todo!("entry point v0.8 and v0.9 are not supported");
889+
}
890+
None => {
887891
warn!(
888892
"Log with unknown entry point address: {:?}. Ignoring.",
889893
log.address()

crates/pool/src/server/local.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -709,8 +709,9 @@ impl LocalPoolServerRunner {
709709
break 'resp Err(anyhow::anyhow!("Invalid user operation version for mempool v0.7 {:?}", op.uo_type()).into());
710710
}
711711
}
712-
EntryPointVersion::Unspecified => {
713-
panic!("Found mempool with unspecified entry point version")
712+
EntryPointVersion::V0_8 | EntryPointVersion::V0_9 => {
713+
// TODO(entrypoints)
714+
todo!("entry point v0.8 and v0.9 are not supported");
714715
}
715716
}
716717

crates/pool/src/server/remote/protos.rs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ use rundler_types::{
3030
},
3131
v0_6, v0_7, BundlerSponsorship as RundlerBundlerSponsorship, Entity as RundlerEntity,
3232
EntityInfos, EntityType as RundlerEntityType, EntityUpdate as RundlerEntityUpdate,
33-
EntityUpdateType as RundlerEntityUpdateType, StakeInfo as RundlerStakeInfo, UserOperation as _,
33+
EntityUpdateType as RundlerEntityUpdateType, EntryPointVersion as RundlerEntryPointVersion,
34+
StakeInfo as RundlerStakeInfo, UserOperation as _,
3435
UserOperationPermissions as RundlerUserOperationPermissions, UserOperationVariant,
3536
ValidTimeRange,
3637
};
@@ -173,6 +174,7 @@ impl From<&v0_7::UserOperation> for UserOperation {
173174
.aggregator()
174175
.map(|a| a.to_proto_bytes())
175176
.unwrap_or_default(),
177+
entry_point_version: EntryPointVersion::from(op.entry_point_version()).into(),
176178
};
177179
UserOperation {
178180
uo: Some(user_operation::Uo::V07(op)),
@@ -190,8 +192,12 @@ impl TryUoFromProto<UserOperationV07> for v0_7::UserOperation {
190192
.as_ref()
191193
.map(|authorization| Eip7702Auth::from(authorization.clone()));
192194

195+
let ep_version = EntryPointVersion::try_from(op.entry_point_version)
196+
.map_err(|_| ConversionError::InvalidEnumValue(op.entry_point_version))?;
197+
193198
let mut builder = v0_7::UserOperationBuilder::new(
194199
chain_spec,
200+
ep_version.try_into()?,
195201
v0_7::UserOperationRequiredFields {
196202
sender: from_bytes(&op.sender)?,
197203
nonce: from_bytes(&op.nonce)?,
@@ -718,3 +724,30 @@ impl TryFrom<PoolOperationSummary> for RundlerPoolOperationSummary {
718724
})
719725
}
720726
}
727+
728+
impl From<RundlerEntryPointVersion> for EntryPointVersion {
729+
fn from(version: RundlerEntryPointVersion) -> Self {
730+
match version {
731+
RundlerEntryPointVersion::V0_6 => EntryPointVersion::V06,
732+
RundlerEntryPointVersion::V0_7 => EntryPointVersion::V07,
733+
RundlerEntryPointVersion::V0_8 => EntryPointVersion::V08,
734+
RundlerEntryPointVersion::V0_9 => EntryPointVersion::V09,
735+
}
736+
}
737+
}
738+
739+
impl TryFrom<EntryPointVersion> for RundlerEntryPointVersion {
740+
type Error = ConversionError;
741+
742+
fn try_from(version: EntryPointVersion) -> Result<Self, Self::Error> {
743+
match version {
744+
EntryPointVersion::V06 => Ok(RundlerEntryPointVersion::V0_6),
745+
EntryPointVersion::V07 => Ok(RundlerEntryPointVersion::V0_7),
746+
EntryPointVersion::V08 => Ok(RundlerEntryPointVersion::V0_8),
747+
EntryPointVersion::V09 => Ok(RundlerEntryPointVersion::V0_9),
748+
EntryPointVersion::Unspecified => {
749+
Err(ConversionError::InvalidEnumValue(version as i32))
750+
}
751+
}
752+
}
753+
}

crates/pool/src/task.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
use std::{collections::HashMap, net::SocketAddr, sync::Arc, time::Duration};
1515

16-
use anyhow::{bail, Context};
16+
use anyhow::Context;
1717
use futures::FutureExt;
1818
use rundler_provider::{EntryPoint, Providers, ProvidersWithEntryPointT};
1919
use rundler_sim::{
@@ -148,8 +148,9 @@ where
148148

149149
mempools.insert(pool_config.entry_point, pool);
150150
}
151-
EntryPointVersion::Unspecified => {
152-
bail!("Unsupported entry point version");
151+
EntryPointVersion::V0_8 | EntryPointVersion::V0_9 => {
152+
// TODO(entrypoints)
153+
todo!("entry point v0.8 and v0.9 are not supported");
153154
}
154155
}
155156
}

0 commit comments

Comments
 (0)