Skip to content

Reward inflation in a governance token

Reward inflation in a governance token

Reward inflation in a governance token

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

Facing mirrors forming an endless corridor of arches, blue light repeating inside

01

The challenge

The challenge

The challenge

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

The approach

The approach

The approach

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

The path

The path

The path

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

A coin press beside an overly tall column of blank discs, the newest rim lit in blue

04

The outcome

The outcome

The outcome

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.

CRITICAL

CRITICAL

Severity

Severity

2025

2025

Disclosed

Disclosed

Included

Included

Retest

Retest