The EntryPoint contract version (encoded in contract bytecode) reverts entire EntryPoint.handleOps() bundles if an EntryPoint.innerHandleOp() call reverts and returns an error of less than 32 bytes in length. This is due to EntryPoint version v0.6 attempting to mload a full word from the revert's return data, which renders it unable to process reverts less than the full word.
To take advantage of this, MEV bots watching the balance of MagicSpend can submit WithdrawRequests at a moment where they are able to target the right amount of balance depletion to trigger the only error returning such a revert length within MagicSpend.validatePaymasterUserOp()- the Solady SafeTransferLib.ETHTransferFailed() error (solely 4 byte error selector).
Despite directly draining bundler balance and MagicSpend paymaster reputation, this issue is marked "medium" since its balance will presumably generally be kept high enough to block all but the most formidable of whales. It is also presumably unlikely that the MagicSpend owner would sign a flash loan WithdrawRequest and such reverts should be easy to filter out at simulation.
Proof of Concept
The following test file is designed for integration with the audit repository by being placed in a new "PoC" or other name dir within 2024-03-coinbase/test/SmartWallet/ and then run to observe the ability to deterministically grief attack by overloading insufficient prefund. This type of payload can be used by a malicious bundler or to target a bundler and expend their balance as well as reputation-ban the MagicSend paymaster.
alter || override the Solady error invocation with one using a parameter pushing the revert return data over 32 bytes, or
upgrade the protocol by changing entryPoint() to the v0.7 EntryPoint contract version, which addresses this issue by adding a check for revert returndatasize()
Lines of code
https://github.com/eth-infinitism/account-abstraction/blob/abff2aca61a8f0934e533d0d352978055fddbd96/contracts/core/EntryPoint.sol#L69 https://github.com/Vectorized/solady/blob/ec85d4a731c5f69aaa9a324d673f92dac0c29593/src/utils/SafeTransferLib.sol#L105-L112
Vulnerability details
Impact
The EntryPoint contract version (encoded in contract bytecode) reverts entire
EntryPoint.handleOps()
bundles if anEntryPoint.innerHandleOp()
call reverts and returns an error of less than 32 bytes in length. This is due to EntryPoint version v0.6 attempting tomload
a full word from the revert's return data, which renders it unable to process reverts less than the full word.To take advantage of this, MEV bots watching the balance of MagicSpend can submit WithdrawRequests at a moment where they are able to target the right amount of balance depletion to trigger the only error returning such a revert length within
MagicSpend.validatePaymasterUserOp()
- the SoladySafeTransferLib.ETHTransferFailed()
error (solely 4 byte error selector).Despite directly draining bundler balance and MagicSpend paymaster reputation, this issue is marked "medium" since its balance will presumably generally be kept high enough to block all but the most formidable of whales. It is also presumably unlikely that the MagicSpend owner would sign a flash loan WithdrawRequest and such reverts should be easy to filter out at simulation.
Proof of Concept
The following test file is designed for integration with the audit repository by being placed in a new "PoC" or other name dir within
2024-03-coinbase/test/SmartWallet/
and then run to observe the ability to deterministically grief attack by overloading insufficient prefund. This type of payload can be used by a malicious bundler or to target a bundler and expend their balance as well as reputation-ban the MagicSend paymaster.Tools Used
Manual review
Recommended Mitigation Steps
Either:
entryPoint()
to the v0.7 EntryPoint contract version, which addresses this issue by adding a check for revertreturndatasize()
Further reading:
https://github.com/pimlicolabs/erc20-paymaster/pull/2#issuecomment-1522235565
Assessed type
DoS