Reproduced Exploit
ZeroLend — Incorrect reward distribution when t == roundedTimestamp
1. At an exact epoch boundary, t == roundedTimestamp. 2. The loop uses > so it still writes veSupply[t] from the current locker point. 3. Bob locks more after the checkpoint — real supply rises, week supply stays stale. 4. claim = totalReward * balance / veSupply overpays Bob 4x the honest share.
Chain
Other
Category
untagged
Date
Jan 2024
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: 40820-incorrect-reward-distribution-when-t-roundedtimestamp-in-fee. Standalone Foundry PoC and full write-up: 40820-incorrect-reward-distribution-when-t-roundedtimestamp-in-fee_exp in the
evm-hack-registrymirror.
Vulnerability classes: reward-calculation · reward-theft · reward-accounting
Reproduction: self-contained Foundry PoC with only
forge-std— no fork. output.txt · test/40820-…sol.
AuditVault taxonomy: lang/solidity · platform/cantina · severity/high · sector/token · genome: reward-calculation · variant · reward-theft · reward-accounting
Key info#
| Impact | HIGH — late lockers overpaid (e.g. 3 instead of 0.75 of epoch rewards) via stale veSupply |
| Protocol | ZeroLend — FeeDistributor._checkpointTotalSupply |
| Vulnerable code | if (t > roundedTimestamp) break; (should be >=) |
| Bug class | Epoch-boundary off-by-one in week supply checkpoint |
| Finding | Cantina — ZeroLend, Jan 2024 · #40820 · reporter 0xarno |
| Report | cantina_competition_zerolend_jan2024.pdf |
| Source | AuditVault |
| Fix | Break on t >= roundedTimestamp (do not write incomplete week) |
| Compiler | ^0.8.24 (PoC) |
TL;DR#
- At an exact epoch boundary,
t == roundedTimestamp. - The loop uses
>so it still writesveSupply[t]from the current locker point. - Bob locks more after the checkpoint — real supply rises, week supply stays stale.
claim = totalReward * balance / veSupplyoverpays Bob 4x the honest share.
Diagrams#
Impact#
Week-bound total-supply invariance breaks; reward accounting skews toward users who lock after a boundary checkpoint.
Sources#
- AuditVault #40820
- Cantina ZeroLend Jan 2024
- Curve-style
FeeDistributorreduction; sibling Class A #40818 merge inflation already shipped
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 40820-incorrect-reward-distribution-when-t-roundedtimestamp-in-fee_exp (evm-hack-registry mirror).
- AuditVault finding: 40820-incorrect-reward-distribution-when-t-roundedtimestamp-in-fee.
Alerts & third-party analyses
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.