# Causing users lose fund if bridging long message from L2 to L1 due to uncontrolled out-of-gas error

OptimismPortal's baseGas ignores memory-expansion cost of hashing long L2→L1 messages, so a relayer can supply gas that passes the portal check but OOGs in L1CrossDomainMessenger, bricking the withdrawal.

- Payout: Contest reward
- Severity: medium
- Program: Optimism
- Credited: HE1M
- Disclosed: 2023-03-20
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-03-optimism-judging/issues/5
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-03-optimism%3AM-6
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic vuln:dos

**Target:** OptimismPortal.finalizeWithdrawalTransaction / L1CrossDomainMessenger.relayMessage
**Root cause:** baseGas on L2 only accounts for minGasLimit and messageLength*16 plus fixed overhead, ignoring the quadratic memory-expansion cost of hashing a long message in relayMessage. The portal's callWithMinGas check can pass while the inner relayMessage gas check fails.
**Steps:**
1. Craft a withdrawal with a long message (~684kb, mostly non-zero, version 0) so hashing gas ~11.8M.
2. Set _minGasLimit low (e.g. 21000).
3. Relayer calls OptimismPortal.finalizeWithdrawalTransaction with G in range 11_659_592 < G < 12_112_900.
4. Portal passes callWithMinGas check, sets finalizedWithdrawals[hash]=true, low-level call to L1CrossDomainMessenger.relayMessage.
5. relayMessage OOGs at its own gas check (line 361), reverts, so failedMessages[versionedHash] stays false.
6. Portal ignores the failed low-level call; withdrawal is finalized but neither successful nor failed, so it cannot be replayed.
**How found:** Code-reading of baseGas vs. actual relayMessage gas consumption; noticed hashing/memory-expansion cost scales with message length and is not reflected in baseGas, then derived the gas inequality window where portal passes but messenger reverts.
**Exploitation:** Attacker (relayer) supplies a gas amount in the narrow window between the portal's gas check and the messenger's gas check for a long message, causing the inner relay to OOG while the outer finalize succeeds, permanently bricking the user's withdrawal.
**Insight:** When a two-layer gas check exists (outer callWithMinGas + inner relayMessage check), compare the gas formulas: any per-message cost not modeled in the outer baseGas (memory expansion, hashing) opens a window where the outer succeeds and inner OOGs, and if the outer ignores the inner failure the message becomes unreplayable.
