Skip to content

Commit

Permalink
AA-221: Prevent Paymaster 'postOp' function from reverting the entire…
Browse files Browse the repository at this point in the history
… bundle
  • Loading branch information
forshtat committed Oct 30, 2023
1 parent cb4e7ca commit b8c730f
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 4 deletions.
7 changes: 5 additions & 2 deletions contracts/core/EntryPoint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -662,9 +662,12 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
if (context.length > 0) {
actualGasCost = actualGas * gasPrice;
if (mode != IPaymaster.PostOpMode.postOpReverted) {
IPaymaster(paymaster).postOp{
try IPaymaster(paymaster).postOp{
gas: mUserOp.verificationGasLimit
}(mode, context, actualGasCost);
}(mode, context, actualGasCost)
{} catch (bytes memory reason) {
revert(string(abi.encodePacked("AA96 postOp reverted", reason)));
}
}
}
}
Expand Down
24 changes: 22 additions & 2 deletions contracts/test/TestPaymasterRevertCustomError.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ import "../core/BasePaymaster.sol";
error CustomError();

contract TestPaymasterRevertCustomError is BasePaymaster {
bytes32 private constant INNER_OUT_OF_GAS = hex"deaddead";

enum RevertType {
customError,
entryPointError
}

RevertType private revertType;

// solhint-disable no-empty-blocks
constructor(IEntryPoint _entryPoint) BasePaymaster(_entryPoint)
{}
Expand All @@ -20,8 +29,19 @@ contract TestPaymasterRevertCustomError is BasePaymaster {
context = abi.encodePacked(userOp.sender);
}

function _postOp(PostOpMode, bytes calldata, uint256) internal pure override {
function setRevertType(RevertType _revertType) external {
revertType = _revertType;
}

revert CustomError();
function _postOp(PostOpMode, bytes calldata, uint256) internal view override {
if (revertType == RevertType.customError){
revert CustomError();
}
else if (revertType == RevertType.entryPointError){
assembly {
mstore(0, INNER_OUT_OF_GAS)
revert(0, 32)
}
}
}
}
20 changes: 20 additions & 0 deletions test/entrypoint.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1075,6 +1075,26 @@ describe('EntryPoint', function () {
it('should not revert when paymaster reverts with custom error on postOp', async function () {
const account3Owner = createAccountOwner()
const errorPostOp = await new TestPaymasterRevertCustomError__factory(ethersSigner).deploy(entryPoint.address)
await errorPostOp.setRevertType(0)
await errorPostOp.addStake(globalUnstakeDelaySec, { value: paymasterStake })
await errorPostOp.deposit({ value: ONE_ETH })

const op = await fillAndSign({
paymasterAndData: errorPostOp.address,
callData: accountExecFromEntryPoint.data,
initCode: getAccountInitCode(account3Owner.address, simpleAccountFactory),

verificationGasLimit: 3e6,
callGasLimit: 1e6
}, account3Owner, entryPoint)
const beneficiaryAddress = createAddress()
await entryPoint.handleOps([op], beneficiaryAddress)
})

it('should not revert when paymaster reverts with known EntryPoint error in postOp', async function () {
const account3Owner = createAccountOwner()
const errorPostOp = await new TestPaymasterRevertCustomError__factory(ethersSigner).deploy(entryPoint.address)
await errorPostOp.setRevertType(1)
await errorPostOp.addStake(globalUnstakeDelaySec, { value: paymasterStake })
await errorPostOp.deposit({ value: ONE_ETH })

Expand Down

0 comments on commit b8c730f

Please sign in to comment.