Reputation-Related Risk

In this page, we explore reputation-related risk in general paymaster.

Reputation attack through submission of UserOp with a low gas price

If a user submits a UserOperation with a low gas price to the mempool, the bundler may not include it in the bundle due to its relatively low value, leaving it to wait in the mempool.

As a result, opsSeen increases while opsIncluded does not (check here), which negatively impacts the reputation of the related entities. Ultimately, this can be considered an attack on the reputation system.

The reason this type of attack is possible is that if an issue arises with the userOp, the reputation of the entities being referenced is reduced, unless the entity is staked.

  • Mitigation: If a userOp remains in the mempool for an extended period, the reason should be carefully examined before deciding which entity’s reputation to decrease. Additionally, the opsSeen for entities without fault should be reduced.

Although it’s specified in the document, it is a detail that service operators might overlook.


Temporary DoS when signer changes

When the paymaster’s validation logic involves signing, changing the signer can temporarily cause a DoS for pending UserOp operations in the mempool that were signed by the old signer but have not yet been processed. This type of DoS can impact the reputation of the involved entities.

  • Mitigation: Cache the value of the oldSigner within the setSigner function for temporary use.

function setSigner(address _newVerifyingSigner) external payable override onlyOwner {
    ...
    oldSigner = verifyingSigner;
    assembly ("memory-safe") {
        sstore(verifyingSigner.slot, _newVerifyingSigner) 
    }
    ...
}


Reputation attack through withdrawal in a singleton Paymaster

In a singleton Paymaster contract(e.g. Sponsorship paymaster), where funds are shared among multiple userOps, if the funds required for executing these userOps are withdrawn via the withdraw function while the userOps are still in the mempool, many userOps may revert during the second validation due to insufficient funds, leading to a decrease in the Paymaster’s reputation.

  • Mitigation: To prevent a sudden lack of funds before all userOps in the mempool are processed, introduce a waiting period for users, such as service operators, who have the ability to withdraw all funds via the withdraw function, instead of processing the withdrawal request immediately.


Incorrect validation due to unupdated funds during the validation phase

If the validatePaymasterUserOp function does not deduct the user's funds during validation, an issue may arise during the 2nd validation phase. In the EntryPoint contract’s handleOps function, user operations within a bundle are validated through a for loop. Since the user’s funds deposited in the paymaster are not deducted during this process, all userOps can pass validation—even if the user lacks sufficient funds.

This can lead to underflow when the funds are deducted in the postOp stage. If the calculation isn't performed within an unchecked block, the underflow will trigger a revert. Consequently, the opsSeen counter for the paymaster will increment, but the opsIncluded counter will not, leaving the paymaster vulnerable to reputation attacks.

  • Mitigation: Deduct the user's funds during the validation phase, or add a variable to track state changes during the validation phase.

function _validatePaymasterUserOp(
    PackedUserOperation calldata userOp,
    bytes32 userOpHash,
    uint256 requiredPreFund
)
    internal
    view
    override 
    returns (bytes memory context, uint256 validationData)
{
    ...
    
    uint256 effectiveCost = (requiredPreFund * priceMarkup) / PRICE_DENOMINATOR;
    if (effectiveCost > paymasterIdBalances[paymasterId]) {
        revert InsufficientFundsForPaymasterId();
    }
    paymasterIdBalances[paymasterId] -= effectiveCost;
    
    ...
}

Last updated