A lending protocol was launching a governance token with a holding-reward feature that granted a multiplier for longer-held balances. We were asked to find a way to manipulate the reward logic before it went live with real liquidity.
Client
DeFi protocol
Industry
Web3
Service
Smart contract audit
Severity
CRITICAL

01
Most of the contract used standard, well-reviewed libraries. The reward logic did not. A custom hook notified an external contract during a transfer, and the holder’s recorded state was updated after that external call returned. That ordering is the whole vulnerability.
The checks-effects-interactions pattern exists because an external call hands control to code the contract does not own, and if state has not been settled before that hand-off, the external code observes a version of reality the contract intends to overwrite a moment later. A reward that is calculated from a balance the contract still believes it holds, at a moment the contract has not yet reconciled, can be claimed against value that is only present for the length of a single transaction. The individual functions are correct. The order in which they run is not, and order is not something a library can enforce for you.
02
A smart contract audit is a reading exercise before it is a testing one. We read the reward path against the pattern it deviated from, then modelled the deviation on a fork so the finding was demonstrated, not asserted.
Trace every path where an external call precedes a state update
Confirm which reward calculations could observe unsettled balances during that window
Model the economic outcome on a fork, to distinguish a theoretical ordering flaw from one with real consequence
Check whether re-entrancy protection existed on the state-changing functions at all
Delivered with the modelled transaction and the resulting balances, so the development team could reproduce the outcome and confirm the fix against the same test.
03
01
Read the reward-claim path
02
Found an external call before the state update
03
Modelled reward inflation on a fork
04
Reordered to settle first, retested

04
The reward path was reordered to settle state before any external call, re-entrancy protection was applied to the state-changing functions, and the reward was rebased on a time-weighted average balance so a balance that exists for a single transaction can no longer earn a holding multiplier. The last change makes the flaw structurally impossible rather than merely guarded.
We retested the reward path on a fork after the fix. Reported as CRITICAL in 2025. Retest included in the engagement.
Case Studies


