How User Operation Fees are Estimated and Charged
Authors: Dan Coombs, David Philipson
Reviewed by Brady Werkheiser
In our series of posts on ERC-4337 gas estimation, starting with how ERC-4337 gas estimation works, we’ve discussed step 2 of the “User Operation Flow,” eth_estimateUserOperationGas
, and its complications including the gas token transfer problem and challenges estimating L2 gas. This post will focus on step 3 of the flow, detailing how gas fees are estimated and charged.
For the purpose of this post, we will assume that we are working with a chain that supports EIP-1559. Understanding of EIP-1559 is required background to grasp the fee fields in a user operation.
User operations have the same fee fields as EIP-1559 transactions:
maxFeePerGas
: the maximum total amount a user bids to pay (base fee + priority fee)maxPriorityFeePerGas
: the maximum priority fee or “tip” the user bids
The entry point uses the following formula to calculate the resulting gas price from these two fields:
uint256 maxFeePerGas = mUserOp.maxFeePerGas;
uint256 maxPriorityFeePerGas = mUserOp.maxPriorityFeePerGas;
if (maxFeePerGas == maxPriorityFeePerGas) {
//legacy mode (for networks that don't support basefee opcode)
return maxFeePerGas;
}
return min(maxFeePerGas, maxPriorityFeePerGas + block.basefee);
As you can see, maxFeePerGas
acts as an absolute cap on the gas price, while maxPriorityFeePerGas
acts as a tip on top of the base fee of the block.
Bundle Transactions
When bundlers send bundle transactions to the entry point they are also subject to a gas price derived via EIP-1559 dynamics. Bundlers set a maxFeePerGas
and a maxPriorityFeePerGas
. The final gas price is calculated from those and the base fee of the block the transaction is included in.
Bundlers submit a transaction at one gas price, and then are compensated at a, potentially different, gas price set by each user operation in the bundle. If the user operation gas price is higher, the bundler will profit, else the bundler incurs a loss on that user operation. The maxPriorityFeePerGas
isn’t just a tip to the bundler, its also helping the bundler compensate for the tip it had to pay to the block builder to get the bundle transaction included (unless the bundler is a builder itself).
How are bundlers financially incentivized?
Bundling can be an expensive task, mainly due to the complex simulations needed to ensure bundler safety. To allow bundlers to recoup for these compute costs, and to incentivize a healthy marketplace for user operations (which improves UX by lowering time to inclusion), it is required for there to be financial incentives for bundlers in the form of excess revenue.
This revenue can take multiple forms: priority fees, MEV, and off-chain deals.
1. Priority Fees
Bundlers may require senders to include a priority fee on their operations that is greater than the priority fee the bundler paid on its transaction. Senders who want to improve their chances of being bundled during high congestion periods may increase their priority fee bid.
2. MEV Revenue
Bundlers can extract MEV from operations in the mempool as they have ordering rights in the bundle. They are free to back-run and sandwich operations to pocket this profit.
3. Off-Chain
Bundlers can run private mempools (with features like MEV protection) and make off-chain deals with user operation senders. The fees would be enforced by some off-chain mechanism.
To ensure a healthy network, we’d argue that (1) is a required option for most user operations.
Positive MEV is not available to extract from every user operation type. If we only rely on this incentive, bundlers won’t pick up most user operations. Off-chain deals are centralizing and many users will want to avoid this vector. This leaves Priority Fees.
Alchemy’s Rundler currently defines a dynamic priority fee required for bundling. This fee is based on the current estimated network fees. If a user operation bids less than the estimated network fee, plus a small overhead tip for the bundler, it won’t get bundled and will be left in the mempool.
💡 When the P2P network emerges, this will look more like a marketplace, similar to that of transactions. Senders can analyze previously mined user ops to gauge what the minimum price is. Bundlers can provide hints to users based on the current mempool contents. MEV searchers may also pick user operations out of the mempool that have high associated MEV, but potentially pay less (or zero) in gas (or even require the searcher to pay them). This MEV marketplace could be facilitated by an Orderflow Auction (OFA).
How do bundlers estimate gas fees?
Before bundling, the bundler must perform its own estimation of the fees that it will submit to ensure inclusion of the bundle transaction through the bundle marketplace. Typically a bundler will build for inclusion in the next block, and will bid a decent price to ensure inclusion.
To estimate base fees the bundler can query the network for the current block’s base fee. Typically adding at least a 25% overhead (the max amount the fee can increase in the next 2 blocks) is desirable to ensure the transaction does not get stuck.
To estimate the priority fee the bundler can use eth_maxPriorityFeePerGas
. Similar to base fee, adding a percentage overhead to this is desirable to ensure the transaction gets picked up.
With these fees estimated, the bundler can then query the mempool and filter for user operations that bid enough to be included (including the small bundler “tip”).
💡 This section describes a Bundler that utilizes a bundle marketplace to submit its bundles. Bundlers must use bundle marketplaces (i.e. Flashbots) in order to ensure that their bundle of user operations doesn’t get front-run, causing it to revert on chain and leaving the bundler paying for gas itself.
The dynamics change if a bundler is part of a block builder.
How should senders estimate user operation fees?
Client-side, senders must estimate the fees required for bundling. If they estimate too low, their user operation may be stuck in the mempool. If they estimate too high, specifically for the priority fee, they may be overpaying for inclusion.
We recommend the following approach when interacting with Rundler pre-p2p network:
Estimate the base fee. Add an overhead that you’re comfortable with to ensure mine if the price moves against you. We recommend at least 25%.
Estimate the priority fee using
eth_maxPriorityFeePerGas
. Add an overhead you’re comfortable with. We recommend at least 10%Add the network-dependent bundler “tip” overhead to the priority fee.
Add priority fee to base fee to get
maxFeePerGas
,maxPriorityFeePerGas
is the estimated fee from 2.
Arbitrum Fee Estimation
The Arbitrum sequencer ignores priority fees and eth_maxPriorityFeePerGas
always returns 0. To compensate the bundler we require a priority fee that is a fixed percentage of the bundler’s estimated max base fee. We currently charge 5%.
Optimism Fee Estimation
Optimism has an edge case, described in our previous post of estimating L2 gas, that impacts fee estimation.
On Optimism we set maxPriorityFeePerGas = l1_gas / l2_base_fee
. However, since in a normal Optimism transaction priority fees only apply to the L2 gas component, they may be orders of magnitude higher than the L2 base fee. Thus, we require a bundle’s priority fee to be a fixed percentage of the estimated base fee. We currently charge 5%
💡 More details about Alchemy’s bundler fee logic can be found in our documentation.
P2P Mempool
Once the P2P mempool is running, a separate market will emerge for user operation fees. This may substantially simplify fee estimation for user operations. Instead of running static calculations for priority fee as described above, user can use the fee history to estimate their bid. It no longer matters the criteria that a single bundler is using for choosing user operations, just that some bundler sees a user operation as valuable enough to bundle.
Rundler will support a rundler_userOperationFeeHistory
method (or something similar, could be standardized) similar to eth_feeHistory
that users can query to estimate their bids based on previously bundled operations.
🦀
Continue Reading
If you missed the first three articles in this technical exploration of ERC-4337 gas estimation, learn how ERC-4337 gas estimation and how we overcame complications to provide accurate gas estimations for user operations.
Related articles
Preparing for the Agave 2.0 Upgrade
ERC-1271 Signature Replay Vulnerability
On October 27th 2023, Alchemy discovered a ERC1271 contract signature replay vulnerability that affected a large number of smart contract accounts (SCA), and led to risks when interacting with several applications.
What is RIP-7212? Precompile for secp256r1 Curve Support
RIP-7212 is a core change in the Ethereum protocol that opens up a way to have cheap, secure, and fast P256 curve verification with a precompiled contract.