# Permanent protocol brick via reserve ID exhaustion — dropreserve retires IDs without recycling, causing irreversible initreserve DoS after 64 cumulative markets

K2's monotonic reserve ID counter never recycles dropped IDs, so after 64 cumulative markets init_reserve permanently panics, bricking new market creation.

- Payout: Contest reward
- Severity: medium
- Program: K2
- Credited: starrohan
- Disclosed: 2026-08-20
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2026-04-k2#m-04
- Library page: https://bugbountylibrary.com/r/c4%3A2026-04-k2%3AM-04
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:dos

**Target:** Soroban smart contract reserve management (kinetic-router)
**Root cause:** increment_and_get_reserve_id only increments and drop_reserve retires IDs without recycling, while safe_reserve_id hard-panics at id >= 64 (MAX_RESERVES), coupling the u128 2-bit-per-reserve bitmap ceiling to a non-recycled counter.
**Steps:**
1. Call `init_reserve` 32 times to allocate IDs 0-31, then `drop_reserve` each asset; NEXT_RESERVE_ID stays at 32.
2. Call `init_reserve` 32 more times to allocate IDs 32-63; NEXT_RESERVE_ID reaches 64.
3. Call `init_reserve` a 65th time; on first supply `set_using_as_collateral` calls `safe_reserve_id(64)` which panics with MathOverflow.
4. Observe init_reserve is permanently bricked despite only 32 active reserves.
**How found:** Code review of storage.rs increment_and_get_reserve_id and reserve.rs drop_reserve, noting the comment in calculation.rs (EFF-03) confirming IDs are never reused, then tracing safe_reserve_id's hard panic at MAX_RESERVES=64 against the u128 2-bit bitmap ceiling.
**Exploitation:** Not attacker-driven; triggered organically by admin list/delist churn. Each drop_reserve permanently retires an ID; after 64 cumulative reserves, all future init_reserve calls panic at safe_reserve_id, and no admin function resets the counter or compacts the bitmap.
**Insight:** When a bitmap packs N bits per entry into a fixed-width integer, audit the ID allocator for recycling: a monotonic counter plus a non-recycling delete path silently converts a per-slot limit into a lifetime-cumulative DoS ceiling.
