ERC-4337 Dummy Signatures and Gas Token Transfers
Authors: Dan Coombs, David Philipson
Reviewed by Brady Werkheiser
In ERC-4337 Gas Estimation we discussed how gas works in ERC-4337 and our method for gas estimation. With this method, we should be able to provide users with accurate values for submitting their user operations. Alas, its not always that simple.
Let’s dive into a few other problems that complicate ERC-4337 gas estimation.
What are dummy signature
values?
In most smart contract account implementations the signature field is computed off-chain by hashing a user operation and signing that hash using some signature scheme (ECDSA being the most popular). This signature is verified onchain by the account contract during the verification phase.
For example, SimpleAccount
uses an EIP-191 signature scheme on the hash that is validated onchain during its validateUserOp
function using OpenZeppelin’s ECDSA library.
This signature must be computed after gas is estimated, as those fields are included in the hash.
However, there are portions of the gas estimation step that require the signature field to be populated: preVerificationGas
and verificationGasLimit
.
preVerificationGas
In the section on preVerificationGas
estimation in part one of this series, we discussed three calculations that the bundler uses to account for unmetered gas.
Notice that steps 2 and 3 (calculating the user ops's share of the calldata gas cost and the user op's share of any execution gas overhead) both directly depend on the length and content of a user operation, including the signature
field.
verificationGasLimit
Almost all useful smart contract account implementations will require some signature verification. This gas needs to be estimated! This estimation process cannot revert or else verification gas cannot be implemented.
How do we choose what signature to use?
How to Calculate Dummy Signature Values
To solve these problems, many ERC-4337 bundlers use a “Dummy Signature” that must be provided by the caller of eth_estimateUserOperationGas
based on the specific account type.
Constraints
This dummy signature has a few constraints:
The dummy value’s length should be the equal to the maximum signature length and must contain the maximum number of non-zero bytes valid for the account.
a. This ensures that thepreVerificationGas
calculations can account for the worst-case signature’s contribution to calldata and entry point overhead costs.The dummy value must, when supplied to the account’s validation function, cause the worst-case gas usage and must not cause a revert.
The dummy value shouldn’t be a valid signature for any valid user operation.
A dummy signature
value for SimpleAccount
can be found in our documentation for the eth_estimateUserOperationGas method.
This dummy signature has the following properties:
It’s the exact length of an ECDSA signature
It has the maximum number of non-zero bytes allowed in an ECDSA signature
It’s a valid ECDSA signature (so that the
.recover()
call does not revertIt’s not a signature for any known user operation, so
SimpleAccount
will always returnSIG_VALIDATION_FAILED
Account implementors need to ensure they write their validation functions such that supplying a dummy signature is possible.
This means:
Only using
REVERT
on signatures that cannot be the dummy signature. ReturnSIG_VALIDATION_FAILED
when the dummy signature is supplied.Taking care to not “short-circuit” failure for the dummy signature. That is, the dummy value should run through the entire validation function and use the maximum amount of gas.
In practice, this means removing any early returns. An account validation function may determine that the signature is invalid early, but it should continue to run the function logic and return the failure at the very end.
How to Calculate Dummy paymasterAndData
Values
The same requirements above apply to the paymasterAndData
field during gas estimation: for any paymaster implementation that relies on the gas fields’ values (i.e. for computing a signature), we must solve the same problem of supplying a dummy value.
Constraints
This dummy paymasterAndData
has a few constraints:
The dummy value’s length should be the equal to the maximum
paymasterAndData
length and must contain the maximum number of non-zero bytes valid for the account.
a. This ensures that thepreVerificationGas
calculations can account for the worst-casepaymasterAndData
contribution to calldata and entry point overhead costs.The dummy value must, when supplied to the paymaster’s validation function, cause the worst-case gas usage and must not cause a revert.
The dummy value shouldn’t be a valid
paymasterAndData
for any valid user operation.
For example, a sponsoring paymaster that relies on the verification of a sponsorship signature over the user operation hash will need to supply a dummy paymasterAndData
value during estimation with similar properties as outlined above:
The dummy value must contain a valid paymaster contract address
Maximum length and byte values for
preVerificationGas
calculationsWhen supplied to the paymaster’s validation function it must consume maximum gas and result in a
SIG_VALIDATION_FAILED
return value
Paymaster implementors need to insure they write their validation functions such that supplying a dummy paymasterAndData
is possible.
This means:
Only using
revert
on data that cannot be part of the dummy. ReturnSIG_VALIDATION_FAILED
instead.Taking care to not “short-circuit” failure for the dummy. That is, the dummy should run through the entire validation function and use the maximum amount of gas.
a. In practice, this means removing any early returns. A paymaster validation function may determine that the signature is invalid early, but it should continue to run the function logic and return the failure at the very end.
Gas Token Transfers
The estimation for verificationGasLimit
must take into account the gas cost of any token transfers during the validation phase. Many user ops involve a transfer of tokens during the validation to pay up front for gas, with a refund at the end of the operation for any gas that wasn’t consumed.
There are two cases:
No Paymaster - this is a transfer of ETH from the sender to the entry point contract.
With a Paymaster - this can be anything (within the allowed rules of the specification) but often takes the form of an ERC-20 token transfer from the sender to the paymaster.
What happens if the account doesn’t have enough funds?
If maxFeePerGas
is set to a non-zero value, the transfer during validation will revert if the account doesn’t hold enough tokens to pay the fee. This means that users must fund their accounts prior to attempting to estimate gas.
A desired workflow that isn’t possible now:
Estimate gas
Fund account for gas
Send operation
A possible solution here is to tell the user to leave maxFeePerGas
unset, or set to zero, when calling eth_estimateUserOperationGas
. However, this will set the gas cost to zero and thus a zero value for whatever token transfer needs to occur. In many account/paymaster types a zero gas cost will skip the call to transfer
. This leads to a gas underestimation when a zero maxFeePerGas
is used.
Another problem has to do with using a non-zero maxFeePerGas
and attempting the binary search estimation approach defined in "Attempt 3: Binary Search," from part 1 of this series.
The first step in that approach is to ensure that the operation is possible by using a maximum gas value. The sender may not have enough assets to pay for gas at that maximum value and the bundler doesn’t always have enough information to determine the balance of the fee token (i.e. the ERC-20 paymaster case) to determine the correct upper bound.
How does Alchemy’s bundler solve gas estimation with the transfer of tokens?
The approach taken by Rundler for eth_estimateUserOperationGas
is as follows:
No Paymaster Case
Rundler will always ignore
maxFeePerGas
andmaxPriorityFeePerGas
and set to 0.Rundler will always add a static 10K gas to
verificationGasLimit
to account for the ETH deposit transfer from sender to entry point.No client-side changes are required.
💡 Bullet #1 is a deviation from the ERC-4337 spec which states “gas limits (and prices) parameters are optional, but are used if specified”
Paymaster Case
Rundler will always ignore
maxFeePerGas
andmaxPriorityFeePerGas
and set to 0.Rundler’s
verificationGasLimit
will always be underestimated if any paymaster logic is conditional on the fee value (like an ERC-20 transfer would be)Users of these paymasters are required to account for any extra gas that would be incurred by a non-zero fee client side.
For example, if using an ERC-20 paymaster that does a transfer during the validation phase always add a static 75K gas to the verificationGasLimit
return value from eth_estimateUserOperationGas
. This requires clients to be aware of the paymaster contract they’re calling into and have prior knowledge of underestimated gas costs due to transfers.
💡 The Alchemy aa-sdk allows paymaster middleware to modify this gas limit accordingly.
What does this mean for developers?
Dummy values and the token transfer problem impacts developers building smart contract accounts, paymasters, and account clients.
Smart Contract Account Developers
Smart contract account developers need to ensure that a dummy signature value is always able to be determined client-side based on how the account validation function is going to run. This signature must not cause a revert and must result in a maximum gas estimate.
Paymaster Developers
Paymaster developers must ensure that a dummy paymasterAndData
value is always able to be determined based on how the paymaster validation function is going to run. This value must not cause a revert and must result in a maximum gas estimate.
💡 Alchemy simplifies this for users in its sponsoring paymaster by combining the gas estimation process and the simulation process via alchemy_requestGasAndPaymasterAndData
Account Client Developers
Account client developers who are integrating with a paymaster that performs transfers during the validation phase (or any other logic based on the fee value), and are using Alchemy’s endpoints for estimation, need to add any potential gas associated with the transfer to the verificationGasLimit
returned by estimation.
Stay tuned for a later post outlining more ERC-4337 gas estimation complications!
🦀
Continue Reading
The next articles in this 4-part series explore the challenges estimating gas on layer 2 blockchains like Optimism and Arbitrum and signature aggregators.
The series concludes with a walkthrough of the user operation fee estimation process. If you missed part one, learn how ERC-4337 gas estimation works!
Related articles
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.
Base Goerli Support Ending 2/9 - Migrate to Sepolia
Base's Goerli testnet is scheduled to be spun down on February 9th. We will keep our nodes running for an extra week after this date.