The extend function, which allows a user to extend the duration of an existing lock, does not call _updateBoostState after modifying the user’s voting power and veToken balance. This function updates the lock’s unlock time, recalculates voting power based on the new duration, adjusts the user’s veToken balance via _mint or _burn, and checkpoints the new power. However, unlike the lock and increase functions, it fails to update the boost state (_boostState) to reflect these changes. The _updateBoostState function is responsible for synchronizing the boost-related state—specifically votingPower, totalVotingPower, and totalWeight—and recalculating boost periods.
extend does not invoke _updateBoostState after updating the lock duration and veToken supply, leaving _boostState in an outdated state. Both lock and increase call _updateBoostState to ensure _boostState reflects changes in locked amounts, voting power, and total supply. extend modifies similar state (voting power and totalSupply()) but skips this step, breaking the protocol’s pattern. _boostState relies on totalSupply() (via totalVotingPower) and the user’s voting power, which change in extend due to _mint or _burn, but these updates aren’t captured without _updateBoostState.
Stale Boost State:
_boostState.votingPower: Does not reflect the user’s updated voting power after extending the lock duration, which typically increases power.
_boostState.totalVotingPower: Remains outdated, not accounting for minted or burned veTokens, misrepresenting the total veToken supply.
Manual review
Add _updateBoostState:
Insert _updateBoostState(msg.sender, userLock.amount) after the veToken balance adjustment (_mint/_burn) to capture the updated voting power and totalSupply():
solidity
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.