Reproduced Exploit
Kinetiq: reactivated validator retains stale balance (underflow DoS)
Chain
Other
Category
untagged
Date
Jan 1970
Source
AuditVault
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.
Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: Kinetiq-security-review_2025-02-26. The historical source/toolchain is unavailable; this entry is documentation only and claims no executable Forge PoC.
Vulnerability classes: vuln/logic
Reproduction: a faithful minimal reproduction of the vulnerable finding — the vulnerable code is reproduced verbatim (marked
@>) with faithful minimal doubles; local deploy, no fork.
Root cause#
ValidatorManager.deactivateValidator creates a rebalance withdrawal for the validator's balance but never zeroes validatorData.balance nor subtracts it from totalBalance; OracleManager skips inactive validators, so the stale balance survives. After the withdrawn stake leaves the system (totalBalance correctly reduced) and the validator is reactivated, the routine oracle call totalBalance = totalBalance - oldBalance + balance subtracts the STALE 100e18 from a 40e18 totalBalance -> Solidity 0.8 underflow revert -> permanent DoS on updateValidatorPerformance/generatePerformance for that validator (100e18 of accounting bricked).
Validator storage val = _validators[_validatorIndex[validator] - 1];
// Cache old balance for total balance update
uint256 oldBalance = val.balance;
// Update total balance
totalBalance = totalBalance - oldBalance + balance; // @> VULN: subtracts the STALE stored balance; deactivateValidator never zeroed val.balance, so oldBalance exceeds the already-reduced totalBalance -> underflow revert
val.balance = balance;
Why it's exploitable here#
ValidatorManager.deactivateValidator creates a rebalance withdrawal for the validator's balance but never zeroes validatorData.balance nor subtracts it from totalBalance; OracleManager skips inactive validators, so the stale balance survives. After the withdrawn stake leaves the system (totalBalance correctly reduced) and the validator is reactivated, the routine oracle call totalBalance = totalBalance - oldBalance + balance subtracts the STALE 100e18 from a 40e18 totalBalance -> Solidity 0.8 underflow revert -> permanent DoS on updateValidatorPerformance/generatePerformance for that validator (100e18 of accounting bricked).
Attack path#
Marked-line walkthrough (Playground)#
The EVM Playground pins each step to the exact executed source line in 0x671d353a77…:
- L54 — Setup: validator set membership: Setup: an OZ-style AddressSet tracks validators and pending-rebalance membership.
- L109 — Setup: reactivation event declared: Setup: the manager emits ValidatorReactivated when a deactivated validator is brought back.
- L144 — Setup: validator staked into total: Setup: addValidator records a validator's balance and adds it to the global totalBalance.
- L167 — Withdrawn stake leaves the system: settleRebalanceWithdrawal finalizes a deactivated validator's withdrawal, correctly reducing totalBalance as the HYPE leaves.
- L208 — Validator reactivated with stale balance: reactivateValidator brings the validator back, but deactivateValidator never zeroed its stored balance.
- L252 — Oracle update underflows on stale balance: Root cause: the oracle update subtracts the stale stored oldBalance, which now exceeds the already-reduced totalBalance, causing a 0.8 underflow revert.
- L254 — Performance updates permanently bricked: The revert fires before val.balance is refreshed, so updateValidatorPerformance reverts forever for that validator — a permanent accounting DoS.
PoC#
Registry (Foundry, local deploy — verbatim vulnerable source + harm-asserting test):
cd 58611-h-03-deactivated-validator-retains-old-balance-after-reactiv_exp
forge test -vvv
The browser Playground replays the same synthetic opcode-for-opcode and measures the harm. Both gates are green (registry forge test PASS + Playground _verify-poc VERDICT: PASS).
Sources & further analysis#
Reproductions & code
- No executable Forge reproduction is claimed; the historical source/toolchain was unavailable for this finding.
- AuditVault finding: Kinetiq-security-review_2025-02-26.
- Upstream DeFiHackLabs PoC directory: src/test.
Alerts & third-party analyses
- DeFiHackLabs incident explorer: search "Kinetiq: reactivated validator retains stale balance (underflow DoS)".
- Web3Sec X hacked database: search.
- Rekt leaderboard: search.
- Solodit incident search: search.
These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.