# Keepers will suffer significant losses due to miss compensation for L1 rollup fees

Perennial's Kept modifier compensates keepers only for L2 gas, ignoring L1 rollup data fees, so keepers lose money and stop submitting oracle prices/orders.

- Payout: Contest reward
- Severity: high
- Program: Perennial
- Credited: KingNFT
- Disclosed: 2023-07-17
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2023-07-perennial-judging/issues/91
- Library page: https://bugbountylibrary.com/r/sherlock%3A2023-07-perennial%3AH-6
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:sherlock sev:high tech:evm tech:solidity vuln:accounting-error vuln:business-logic vuln:reward-distribution

**Target:** Solidity Kept modifier / PythOracle.commitRequested / MultiInvoker._executeOrder on L2 rollups
**Root cause:** Keeper fee is computed as gasUsed * multiplier + buffer, times ether price times block.basefee, which only reflects L2 execution gas; the L1 data/rollup fee (driven by calldata size and smoothed L1 gas price) is never included.
**Steps:**
1. Inspect Kept.sol keep() modifier L40-57: keeperFee = (gasUsed*multiplier + buffer) * etherPrice * block.basefee.
2. Note commitRequested passes a 1700+ byte VAA calldata, incurring large L1 data fee on Optimism/Arbitrum.
3. Compare a real Optimism tx: L2 fee ~6,806 Gwei vs L1 fee ~65,656 Gwei (~964% of L2).
4. Observe L1/L2 gas price ratio varies from ~e1 to ~e9 across blocks, so no fixed buffer can track it.
5. When ratio spikes, keeper reward < actual cost; keepers stop submitting, blocking oracle updates and order execution.
**How found:** Code reading of the keep() modifier revealed only block.basefee (L2) is used; researcher then pulled real Optimism transactions to quantify L1 vs L2 fee disparity and gathered historical gas price tables showing ratio spans e1-e9.
**Exploitation:** Not an attacker exploit; economic griefing where keepers rationally halt when L1/L2 ratio makes reward negative, stalling price submission and order settlement. Escalation also notes when ratio is low, keeperReward > settlementFee enables self-trading 1 wei orders to drain protocol via keeper reward.
**Escalation:** Researcher showed fixed buffer cannot compensate because L1GasPrice and L2GasPrice are independent; also noted over-compensation periods create a keeperReward > settlementFee drain vector.
**Insight:** On L2 deployments, any gas-refund or keeper-incentive formula based solely on block.basefee systematically under/over-pays because L1 data fee depends on calldata length and an independent smoothed L1 gas price; check refund math on rollups for missing L1 component.
