# Gas issuance is inflated and will halt the chain or lead to incorrect base fee

TaikoL2.anchor() multiplies gas issuance by the L1 block gap since last sync, inflating base fee and halting the chain on mismatch.

- Payout: Contest reward
- Severity: high
- Program: Taiko
- Credited: monrel
- Disclosed: 2024-04-26
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2024-03-taiko-findings/issues/276
- Library page: https://bugbountylibrary.com/r/c4%3A2024-03-taiko%3AH-01
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:regression technique:source-review vuln:business-logic

**Target:** TaikoL2.sol anchor() base fee calculation
**Root cause:** _calc1559BaseFee issues numL1Blocks * gasTargetPerL1Block where numL1Blocks = _l1BlockId - lastSyncedBlock, but lastSyncedBlock only updates every 5 blocks, so issuance is over-counted across the sync window.
**Steps:**
1. Call anchor() on consecutive L2 blocks while lastSyncedBlock stays fixed (updates only when _l1BlockId > lastSyncedBlock + BLOCK_SYNC_THRESHOLD).
2. Each call computes numL1Blocks = _l1BlockId - lastSyncedBlock, re-issuing gasTargetPerL1Block for the same L1 blocks repeatedly.
3. Over 5 blocks total issuance becomes 15 * gasTargetPerL1Block instead of 5 * gasTargetPerL1Block.
4. Compare computed basefee to block.basefee: mismatch reverts L2_BASEFEE_MISMATCH, halting the chain.
5. PoC: run forge test --match-test testIssuance asserting expectedIssuance*3 == issuance.
**How found:** Code review of the 1559 base fee math in anchor(); noticed lastSyncedBlock is only updated past a sync threshold while issuance uses the full block delta, then wrote a Foundry test to quantify the 3x over-issuance.
**Insight:** When a state variable used in a rate/issuance formula is only updated conditionally (threshold-gated), check whether the delta multiplied against it double-counts the un-updated window.
