Documentation
🛺

Documentation

Abstract

  1. Version Iteration Record
Version
Change Date
Description
v1.0
2022.12.27
Added abstract and product analysis
v1.1
2023.1.02
Added bundler architecture diagram
v1.2
2023.2.14
Added research document
v1.3
2023.03.07
Added product proposal
  1. Glossary

Uopool: UserOperation Mempool. After users send UserOp, these transactions will first be placed into the cache and wait for the bundler to fetch and package them.

Product Analysis

1. What is Bundler?

Bundler is a component in the ERC4337 standard, similar to infra in traditional EOA transactions.

The ERC4337 standard is an account abstraction protocol that completely avoids changes to the consensus layer protocol. This solution does not add new protocol functionality or change the underlying transaction types, but introduces a pseudo-transaction object called UserOperation (referred to as "UserOp" hereinafter). Users send UserOperation objects to a separate mempool (referred to as Uopool in this document to avoid confusion). A type of role called bundler (which may be a miner or any user who accesses the UserOp Mempool) packages these objects into a transaction, calls the handleOps function in the EntryPoint contract, and sends the transaction to the chain.

2. What are the functions of Bundler?

As a relay before UserOp is placed on the chain, Bundler has the following main functions:

  • Listen to transactions in the UserOp Mempool.
  • Simulate execution.
    • The simulation mentioned here is essentially the calculation of the gas required for execution. Bundler needs to calculate the gas required to execute UserOp and the additional gas required to execute other contract code, and ensure that the gas cost charged from Paymaster is greater than or equal to the gas consumed.
  • Bundle UserOperation arrays.
    • Package UserOp into a queue.
  • Execute the entry contract.
    • Call the handleOps function in the EntryPoint.

3. Why choose to build a bundler?

Why choose to build a bundler?

Bundlers are the infrastructure for the ERC-4337 ecosystem. After wallet service providers construct users' UserOperations, they send this information to bundlers. Bundlers then inspect, verify, and execute these operations before finally calling the EntryPoint contract's handleOps function to perform all operations.

One of the challenges of a bundler is to establish a stable bundler network that can prevent DDoS attacks. Therefore, the design of a bundler also incorporates concepts similar to mempool. By constructing a bundler node network, it can help Ethereum achieve better decentralization.

4. What are the existing Bundler solutions?

4.1 Nethermind

  • Nethermind first implemented a very comprehensive Ethereum client, which can basically be used as an industrial product. Bundler is a plug-in added to the client and can be turned on or off in the configuration. Therefore, Bundler can leverage many existing features of the client, such as the p2p network.
  • The benefit of implementing Bundler in the client is that ordinary client users can also receive UserOps and convert them into transactions. This allows certain UserOps to be sent as a single transaction and broadcast to the entire network, and it also supports bundler as a MEVbundler, only accepting transactions containing MEV that are not sent to the public Uopool.
  • Supports multiple Entrypoints, each corresponding to a different Mempool.
  • Supports paymaster payment function.
  • Supports the reception and broadcasting of UserOps through the p2p network, as well as the discovery and establishment of peer connections in the p2p network.
  • As a client, NetherMind can broadcast UserOps or wait until it mines a block to package them.

4.2 Stackup

  • The bundler implemented by Stackup is the most complete one I have seen recently, including basic functionalities as well as using debug_traceCall to ensure that the opcode complies with EIP.
  • Although their mempool is still a local single-machine version (https://github.com/stackup-wallet/stackup-bundler/tree/main/pkg/mempool), they have exposed appropriate functions to the public, which suggests that they are likely to implement a P2P version or even a relay for their mempool.
  • https://github.com/stackup-wallet/stackup-bundler/blob/main/pkg/modules/relay/relayer.go In this part, they consider the malicious attacks that bundlers may encounter, such as:
    • Attackers can send a valid UserOp first and then rush to complete the batch of transactions, making the UserOp invalid. This will cause the bundler's transaction to fail and incur gas fees for the failed transaction, resulting in a loss for the bundler.
    • They also consider the malicious attacks that non-block-producers may encounter and use certain unique identifiers (such as IP) to mitigate these attacks.

4.3 Eth-Infinitism bundler

Startup process and main components:

image
image

Main component functions:

BundlerServer:

Main functions:

Uses Express as the httpServer and provides an RPC port for remote procedure calls.

Needs improvement:

  1. The user port is combined with the debug port, which is only suitable for development and cannot be used in production. It needs to be separated.
  2. There is no verification mechanism, rate limiting mechanism, or blacklist to prevent attacks.

ExecutionManager:

Main functions:

Receives userOps and calls the validationManager to validate them. If the validation is successful, the userOps are added to the memory pool, and the bundleManager is called based on the internal maxMempoolSize and autoBundleInterval parameters to send the transactions.

ValidationManager:

Main functions:

  1. Checks the parameters of the userOp.
  2. Checks if the paymaster, aggregator, and deployer have sufficient stake.
  3. Checks UserOp with geth.debug_traceCall('simulateValidation').

MempoolManager:

Main functions:

  1. Stores an array of userOps to store incoming userOps.
  2. Adds, replaces, deletes, clears, and dumps userOps.
  3. Updates the statistics of the reputationManager when adding userOps.

Needs improvement:

When searching for userOps, the array is traversed, which could be improved by using a hash for searching. Also, there is no design to monitor and delete userOps that have been mined at a new height.

ReputationManager:

Main functions:

  1. Records the number of occurrences and inclusion times of userOps using the aggregator, paymaster, and deployer.
  2. Has whitelist and blacklist functions.
  3. The count is reduced by 1/24 every hour (interval set in executionManager).

BundleManager:

Main functions:

  1. Retrieves userOps from mempoolManger and executes handleOps on the entrypoint.
  2. Deletes the successfully executed userOps from the mempoolManager.

4.4 Biconomy Pay-As-You-Go Network

Biconomy has a pay-as-you-go network that uses an AMQP message queue. They added support for EIP-4337, which is a standard for specifying transaction processing fees. For supporting modules like the bundler, they simply added a message consumer for EIP-4337. When the consumer receives a message, it processes it using the configured entry point. The implementation is relatively simple and can be found in the following code paths:

  1. The message consumer retrieves the EIP-4337 OP: https://github.com/bcnmy/relayer-node/blob/main/relayer/src/services/consumer/AAConsumer.ts#L59
  2. The EIP-4337 transaction is processed: https://github.com/bcnmy/relayer-node/blob/main/relayer/src/services/consumer/AAConsumer.ts#L77

4.5 Ethereum Protocol Fellowship #3

4.6 Candide-bundler-and-paymaster-rpc

5. Potential Issues with Bundlers

  • Front-running attack
    • An attacker can send a valid UserOp and then outbid the previous UserOp by paying more gas to the miner during the execution of the handleOps function, making the previous UserOp invalid. This can result in the transactions executed by the bundler failing to be included in a block and the bundler losing gas due to the transaction failure and the lack of compensation from the Paymaster contract.
  • Modifying contract storage or associated contract storage causing the bundler to not receive adequate compensation
    • Another potential security vulnerability for bundlers is that during the validation and execution process, users may modify the storage of the contract or associated contracts, causing the bundler to not receive adequate compensation. For example, if a UserOp sent by a user requires 1 ETH worth of gas and the price of ETH is 1000u, the user's account has 1000u, and the Paymaster is ready to deduct 1000u as gas to pay for the transaction. If the bundler pays 1 ETH gas during execution, but before the transaction is validated and executed, the price of ETH suddenly surges to 2000u, the bundler would still pay 1 ETH worth of gas but the user only needs to pay 1000u as originally intended, resulting in a net loss of 1000u for the bundler. The oracle contract can be considered as the associated contract that undergoes storage modification due to price changes.

6. Ethereum's PBS Architecture

image

7. Layer2 Related Research

Most Bundler solutions focus on Layer1. During the research process, we are considering whether it is possible to build a Layer2-based UserOp P2P network.

8. Other Research

Product Solution

The product is divided into three parts:

  1. P2P Network
  2. Mempool
  3. Bundler Service

P2P Network

  • Why do we need a public mempool and P2P network?
  • The reason for needing a public mempool is for censorship resistance. If some bundlers censor certain users and prevent their UserOps from being included on-chain, other censorship-resistant bundlers will provide services, propagate, and bundle their UserOps. Public explorers (like Etherscan) can monitor the public mempool to ensure UserOps are properly broadcasted. Users can also run a bundler that does not actually package transactions but connects to the public mempool and broadcasts their UserOps, allowing other bundlers to package their UserOps. As long as there is at least one censorship-resistant bundler and the user pays a high enough fee, the UserOp will be bundled.

    Bundlers send Tx bundles to block creators to have their UserOps included on-chain, but bundles may not necessarily be included, depending on the gas fee the Bundler offers to the block creator. Therefore, for regular 4337 wallet users, the best solution is to have their UserOps reach multiple competing bundlers instead of just one, so that no matter which bundler wins, their UserOps can be packaged.

  • What is the standard interface for the P2P network?
  • Overview of the standard interface for the P2P network
image
  • What is the technical implementation plan for the P2P network?
  • Following the P2P interface customized by the ERC4337 working group, the entire standard uses a technology framework that is basically consistent with Ethereum's consensus layer nodes, such as being based on the libp2p library for implementation, having consistent Network Fundamentals, and Interaction domains. The main difference lies in the Gossip domain, as bundlers only need to broadcast UserOp information between nodes, so the entire P2P network only needs to listen to a single Global Topic: user_op_with_entry_point.

    We can isolate the already implemented P2P network part of the Ethereum consensus layer and make it an independent executable program. We can modify the parts that need to be optimized for bundlers and implement interactions with the mempool through internal network RPC ports. This way, we can quickly develop a P2P plug-in independent of the bundler program itself. Bundlers that need to connect to the public mempool and P2P network can independently launch this plug-in, enabling reading and writing to the mempool and interacting with other bundlers following the same rules.

    We can separate the P2P part from PrysmLabs' prysm client, reuse most of the code, and use the Golang language, allowing it to interact with bundlers implemented in other languages (such as JavaScript).

Mempool

The Mempool is divided into two parts:

  • Semi-public Mempool: Third-party wallets or applications can apply to join by providing basic information such as product, official website, contact person, etc. After the review is passed, a key will be sent. This feature point
  • External interface:
    • Keyword "add": add UserOp to the mempool
    • Keyword "get": fetch UserOp from the mempool
  • UserOp validation function:
    • Add a separate validation module
      • Verify whether the account sending the transaction has enough funds to pay for the gas required by the Bundler to execute the transaction
      • Determine if there are other possible gas loss situations (requires discussion)
      • After UserOp enters the mempool, the UserOp's validity must be verified
        • Are the transaction parameters legal?
          • sender
          • nonce
          • initCode
          • callData
          • callGasLimit
          • verificationGasLimit
          • preVerificationGas
          • maxFeePerGas
          • maxPriorityFeePerGas
          • paymasterAndData
          • signature
        • Check for duplicates
  • In addition to the necessary parameters, third parties need to provide the chainId parameter so that bundlers can call the corresponding chain's EntryPoint contract
  • Function to listen to EntryPoint events:
    • If the UserOp has been executed, delete the UserOp from the Mempool

Mempool

The Mempool is divided into two parts:

  • Semi-public Mempool: Third-party wallets or applications can apply to join by providing basic information such as product, official website, contact person, etc. After the review is passed, a key will be sent. This feature point
  • External interface:
    • Keyword "add": add UserOp to the mempool
    • Keyword "get": fetch UserOp from the mempool
  • UserOp validation function:
    • Add a separate validation module
      • Verify whether the account sending the transaction has enough funds to pay for the gas required by the Bundler to execute the transaction
      • Determine if there are other possible gas loss situations (requires discussion)
      • After UserOp enters the mempool, the UserOp's validity must be verified
    • Validate if the parameter legal
      • sender
      • nonce
      • initCode
      • callData
      • callGasLimit
      • verificationGasLimit
      • preVerificationGas
      • maxFeePerGas
      • maxPriorityFeePerGas
      • paymasterAndData
      • signature
      • Check for duplicates
      • In addition to the necessary parameters, third parties need to provide the chainId parameter so that bundlers can call the corresponding chain's EntryPoint contract
    • Function to listen to EntryPoint events:
      • If the UserOp has been executed, delete the UserOp from the Mempool

Bundler Service

The content included in the Bundler core and API Endpoint parts.

Transaction sent to Uopool:

  • Users verify the bundler's status through the initial function (eth_supportedEntryPoints/eth_chainId). The API Endpoint is an HTTP service, and the key is to resist DDoS attacks, which can be achieved using third-party services.
  • The bundler service accepts user UserOp transactions and forwards them to the Bundler Core. The Bundler Core may perform failover recovery or load balancing. After the Bundler Core verifies the UserOp and confirms its validity, it sends it to Uopool. Uopool validates the transaction again and needs to provide an external interface so that data can be exchanged between different mempools.
  • The Bundler fetches UserOps from Uopool, verifies them, and then executes handleops for on-chain processing.
  • If the on-chain status of the UserOp is detected to change, the corresponding UserOp status in the mempool is updated accordingly.
image

image