Open c4-bot-9 opened 4 months ago
The report is correct, however the claimed loss is dramatically overstated since it is not expected that the entire TVL of op-mainnet and base are trying to be withdrawn. Additionally the attacker would have to ensure they create a proposal for every unsafe block before they become safe - if a single block is missed all pending withdrawals could be proven against the proposal for that block.
The attacker would also be relying on the batcher submitting transactions that exactly match the unsafe blocks. While this is typically the case and is intended in the smooth operation of a chain, it is not guaranteed. If the actual safe block did differ from the attacker's proposed root the actual root could still be used for a proposal. For any in progress games, the attacker would be at risk of losing the bond for both their root claim and their counter claim, as the value specified in the counter claim would now be invalid, allowing an honest actor to counter it and post their own counter to the root claim.
The attacker would also lose money in gas costs for creating each game (~421k gas each), posting the counter claim to avoid losing their bond (~231k gas each) and then reclaiming their bonds after the lock up period.
I respect the sponsor's perspective here that this issue is unlikely to become a serious concern, but after carefully considering it, I've decided that the ability to create failing games for valid output roots that will block the correct game from being created seems to be a valid issue. I will be downgrading to Medium and accepting.
zobront changed the severity to 2 (Med Risk)
zobront marked the issue as satisfactory
zobront marked the issue as selected for report
the ability to create failing games for valid output roots that will block the correct game from being created seems to be a valid issue
I completely agree with the above and I think this is a really nice finding.
However, the severity should be assessed according to the highest realistic impact and this finding fails to provide one that would qualify it for Medium severity.
Let's examine the costs of this attack. As @ajsutton mentioned, the costs are not limited to the opportunity cost of the significant capital required, but also include the gas cost of creating and resolving claims for every single block, in particular for:
creating each game (~421k gas each), posting the counter claim to avoid losing their bond (~231k gas each) and then reclaiming their bonds after the lock up period.
The latter requires:
resolveClaim()
(~111k gas each)resolve()
(~39k gas)claimCredit()
(~55k gas)All of this put together leads to a total of ~857k gas per censored block, which at an ETH price of $3k, a reasonable gas price of 20 gwei and a 2s L2 block time amount to a cost of $2,2 million per DAY that the attack is ongoing in addition to the already mentioned capital requirements and opportunity loss.
This together with the fact that the attack can be easily mitigated by migrating to a new game type means the likelihood that this is exploited (to no benefit for the attacker) and actually impacts the availability of the protocol is essentially non-existent. (Edit: just a quick note that migrating to a new game is not one of the safeguards that should be considered nonexistent for this audit)
The issue was also brought up here in the previous contest (specific attack vector of the L1 block being too early is mentioned "e.g., the L1 parent block is too early" as well as the inability to create another game, without the DOS claims).
@0xEVom
For the sake of this audit, you should pretend the safeguards don't exist
Under the context of this audit, the max damage could be permanently freezing the l2 fund. So I believe this is a high severity issue @zobront
The attacker would also be relying on the batcher submitting transactions that exactly match the unsafe blocks.
Even they don't match, attacker can still monitor mempool and frontrun batcher's the transaction.
While I agree with @0xEVom that the cost to the attacker is large and doesn't provide obvious benefit (such that I don't think DOS'ing the chain for a year is at all likely), I do believe a Medium severity is justified.
1) As @xuwinnie mentioned, gas prices have dropped a lot. I don't think it's unreasonable to think that 2 gwei will often be a better estimate than 20 gwei.
2) At least to start, every OP Mainnet block doesn't need to be proven. Proposals are created once per hour (https://etherscan.io/address/0xe5965Ab5962eDc7477C8520243A95517CD252fA9), and if we read the op-proposer code (https://github.com/ethereum-optimism/optimism/blob/d283e9be6e3ff9294c61634bda0131c373ecaaf8/op-proposer/proposer/driver.go#L471-L492) we can see that it doesn't matter whether past proposals landed. It just tries at regular interval from config, which is set to 1 hour. Until OP team changed the config and relaunched the proposer, it would only take a couple txs per hour to make sure it was blocked.
3) We can't predict situations where delaying ability to withdraw for some period of time would be harmful.
I agree that this is unlikely and benefit is unclear enough that it shouldn't be a High, but I think Medium is warranted and the code should be corrected, so will keep judging as-is.
I'm staying well out of the debate around severity levels but I think it's worth clarifying:
At least to start, every OP Mainnet block doesn't need to be proven. Proposals are created once per hour
Proposals are permissionless, so any user whose withdrawal is blocked can propose for any L2 block (which could then be used for any pending withdawals). So for this attack to be at all effective you need to create a game for every L2 block, not just the block that winds up being the next safe head. Any user who would be harmed by a delay to their withdrawal would also be incentivised to make their own proposal.
@ajsutton That's fair. I still believe Medium is the right classification, but appreciate the correction.
Lines of code
https://github.com/code-423n4/2024-07-optimism/blob/70556044e5e080930f686c4e5acde420104bb2c4/packages/contracts-bedrock/src/dispute/DisputeGameFactory.sol#L119-L123
Vulnerability details
Brief
When creating a dispute game, the output root should be one of the safe l2 block's. However, attacker can continuously create games for not yet safe l2 blocks. Honest party can no longer propose the root after it becomes safe, since UUID must be unique. As a result, no root can be sucessfully defended, the anchor state can no longer be updated and the fund on L2 will be frozen.
Proof of Concept
When creating a dispute game, the output root should be one of the safe l2 block's. Otherwise, the claim can be attacked.
However, function create needs uuid to be unique.
If an attacker has already made the claim of this block earlier, when the block is still unsafe, the correct claim can no longer be made.
Cost and Impact
Attacker can avoid losing the bond by making a attack move in the same transaction, needing 0.08 (create) + 0.08 (attack) = 0.16eth once. The fund will be withdrawable after 3.5 (game clock) + 7 (weth delay) = 10.5 days. Assume block time is 2s, the capital needed is 0.16 × 10.5 × 24 × 3600 ÷ 2 = 72576eth ≈ 237 million dollars. Assume interest rate is 3%, to freeze l2 fund for one year, the cost would be 237 million × 3% = 7.11 million dollars, while the loss would be 13.54 billion (Optimism + Base TVL) × 3% = 406.2 million dollars.
Fix
Include parentHash in uuid calculation.
Assessed type
Context