# The formula used in ````SafeCall.callWithMinGas()```` is wrong

SafeCall.callWithMinGas miscalculates EIP-150 gas forwarding by ignoring CALL base cost and EIP-2929 cold-access, so subcalls receive less than _minGas, risking withdrawal OOG fund loss.

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

**Target:** Solidity library SafeCall.callWithMinGas in contracts-bedrock
**Root cause:** The assertion only applies the 63/64 rule to gasleft(), but the EVM first subtracts CALL base cost (value transfer 9000 minus 2300 stipend, ~6664) and EIP-2929 cold-account cost (2600-100) before applying 63/64, so the forwarded gas can fall below _minGas.
**Steps:**
1. Read SafeCall.callWithMinGas assertion `gas() >= ((_minGas+200)*64)/63`.
2. Note geth callGas subtracts base (gasCall: CallValueTransferGas 9000, cold access 2500) before 63/64 truncation.
3. Deploy test Caller/Callee with forge; call `caller.execute{gas: 64855}(callee, 63000, "")` twice (cold vs warm) and `{gas: 62555, value: 1}`.
4. Observe gasReceived 60582 (cold), 63042 (warm), 56483 (value) all below _minGas 63000.
**How found:** Auditor read the EIP-150 comment in SafeCall and cross-checked geth's callGas/gasCall/operations_acl implementations, realizing base gas and EIP-2929 cold cost are deducted before the 63/64 rule, then wrote a forge PoC measuring gasReceived.
**Exploitation:** A withdrawal transaction finalized with a user-specified gas limit can be executed with less gas than promised; the subcall runs out of gas and the withdrawal fails, potentially losing funds.
**Insight:** When reasoning about EIP-150 gas forwarding, don't assume only 63/64 applies: subtract CALL base costs (value transfer 9000 minus 2300 stipend, new-account, memory expansion) and EIP-2929 cold-access delta before the 63/64 truncation; verify with a forge test logging gasleft() in the callee.
