# Gas griefing/attack via creating the proposals

Kleidi Timelock lets compromised owners spam schedule() with unique salts, forcing guardian to spend gas cancelling each proposal, enabling griefing/drain.

- Payout: Audit contest
- Severity: medium
- Program: Kleidi
- Credited: Allarious
- Disclosed: 2024-11-20
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2024-10-kleidi#m-01
- Library page: https://bugbountylibrary.com/r/c4%3A2024-10-kleidi%3AM-01
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:race-window vuln:business-logic vuln:dos

**Target:** Timelock.sol schedule/cancel/pause functions
**Root cause:** Each scheduled proposal with a unique salt must be individually cancelled or executed; pause guardian cancel cost scales linearly with attacker-created proposals, and victims cannot pay gas from locked vault funds.
**Steps:**
1. Compromise threshold owner keys of the Safe controlling the Timelock.
2. Call `timelock.schedule(timelockAddress, 0, scheduleData, saltArray[i], MINIMUM_DELAY)` repeatedly with unique salts to queue many proposals.
3. Victim must call `timelock.pause()` or `timelock.cancel(id)` per proposal, spending gas from external funds.
4. If attacker outspends victim's available gas funds, one proposal executes and drains vault.
**How found:** Observed that scheduled proposals persist until cancelled/executed and that cancel cost scales per-proposal, hypothesizing a gas war when owner keys are compromised.
**Exploitation:** Attacker with threshold keys floods schedule() with unique-salt proposals across multiple blocks; victim's guardian must cancel each, but vault funds are locked so gas must come from limited external balance. Attacker outspends and executes a malicious proposal to drain funds.
**Escalation:** Judge's PoC showed attack cost ~7-22x defense cost, but attacker recoups via drain; requires multiple blocks, not single-block.
**Insight:** When a timelock requires per-item cancellation, check whether a single O(1) invalidation (epoch/nonce bump) exists; otherwise compromised signers can force linear defense cost.
