# All migrated withdrarwals that require more than 135,175 gas may be bricked

Migrated Optimism withdrawals set inner relayMessage gas to 0 and outer gas to calldata+200k, so withdrawals needing >135,175 gas can be finalized on the Portal while the CrossDomainMessenger call reverts, permanently bricking funds.

- Payout: Contest reward
- Severity: high
- Program: Optimism
- Credited: obront
- Disclosed: 2023-03-20
- Write-up quality: 8/10
- Original: https://github.com/sherlock-audit/2023-03-optimism-judging/issues/93
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-03-optimism%3AH-1
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:sherlock sev:high tech:evm technique:chained technique:source-review vuln:business-logic vuln:dos

**Target:** OptimismPortal.finalizeWithdrawalTransaction / L1CrossDomainMessenger.relayMessage migration path
**Root cause:** MigrateWithdrawal sets the inner relayMessage minGasLimit to 0 and the outer gas limit to calldata cost + 200,000, assuming the CrossDomainMessenger is replayable. When the inner call consumes more than ~135,175 gas, the 1/64 retained gas is insufficient for the messenger's replay SSTOREs, so relayMessage reverts, but the Portal still has enough gas to finalize and mark the withdrawal finalized.
**Steps:**
1. Observe MigrateWithdrawal packs relayMessage with minGasLimit=0 and outer gasLimit = calldataCost + 200,000.
2. Call OptimismPortal.finalizeWithdrawalTransaction with a migrated withdrawal whose inner call needs >135,175 gas.
3. Portal forwards ~200k+calldata to L1CrossDomainMessenger; XDM spends ~41,002 gas before the call, leaving ~158,998.
4. Inner call consumes all forwarded gas (succeeds or reverts); only 158,998/64 ≈ 2,484 gas remains.
5. Remaining execution needs ~23,823 gas for SSTOREs (failedMessages bookkeeping), so relayMessage reverts with OOG.
6. Portal still has ~3,174 gas left, completes, and sets finalizedWithdrawals[hash]=true, permanently locking the withdrawal.
**How found:** Code review of the migration script noticed the inner gas limit hardcoded to 0 under the assumption the messenger is replayable, then traced gas accounting through OptimismPortal.finalizeWithdrawalTransaction and CrossDomainMessenger to find the 1/64 retention was insufficient for the replay SSTOREs while still enough for the Portal to finalize.
**Exploitation:** Attacker (or unlucky user) submits finalizeWithdrawalTransaction with just enough gas for the Portal to finalize but not enough for the CrossDomainMessenger to record the failed message. The withdrawal is marked finalized on the Portal while never relayed, bricking the funds with no replay path.
**Escalation:** A malicious actor could deliberately brick thousands of pending migrated withdrawals by griefing finalization with insufficient gas.
**Insight:** When a contract relies on EIP-150's 1/64 gas retention for a fallback/replay path, compute the exact gas the post-call bookkeeping needs (SSTOREs) versus what the outer frame needs to commit state; a mismatch lets the outer frame finalize while the inner frame reverts, creating a permanent lock rather than a replayable failure.
