# Gas limit check is inaccurate, leading to an operator being able to fail a job intentionally

HolographOperator's gas-left check ignores EIP-150 1/64 rule, letting an operator set a gasLimit that fails bridgeInRequest while executeJob still completes, stranding the token.

- Payout: Contest reward
- Severity: high
- Program: Holograph
- Credited: 0xA5DF
- Disclosed: 2022-12-15
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2022-10-holograph-findings/issues/176
- Library page: https://bugbountylibrary.com/r/c4%3A2022-10-holograph%3AH-08
- Tags: domain:web3 impact:dos impact:integrity kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:dos

**Target:** HolographOperator.sol executeJob / bridgeInRequest gas limit check
**Root cause:** The check at HolographOperator.sol#L316 compares gasleft() to the user-supplied gasLimit, but EIP-150 caps child calls at 63/64 of remaining gas, and two nested external calls consume ~2/64, so the bridge call can run out of gas while executeJob continues.
**Steps:**
1. Operator calls executeJob with a gasLimit close to but below available gas.
2. Check at L316 passes since gasleft() >= gasLimit.
3. nonRevertingBridgeCall and the bridge call each lose 1/64 under EIP-150, so bridgeInRequest receives less than gasLimit and reverts OOG.
4. Catch block marks job failed and emits FailedOperatorJob; executeJob completes.
5. PoC: entryPoint{gas:1000000}() shows ~30k gas left after bridge failure, enough to finish.
**How found:** Code review of the gas check at L316 plus reasoning about EIP-150's 63/64 rule and the two nested external calls; confirmed with a Foundry PoC measuring gas left after a forced bridge failure.
**Exploitation:** A malicious selected operator crafts the gasLimit so the nested bridge call deterministically runs out of gas; the try/catch marks the job failed while executeJob succeeds, and the bridged token owner loses access to the token.
**Insight:** When a contract pre-checks gasleft() against a user-supplied gasLimit before a nested external call, account for EIP-150's 63/64 cap per call frame; a passing check does not guarantee the child call gets that gas, so try/catch can swallow the OOG and let the outer tx succeed.
