The contract uses two different storage mechanisms to maintain user lock information. It declares a public mapping locks while internally using _lockState.locks from the LockManager library. In some functions, such as lock(), extend(), and withdraw(), the internal _lockState.locks is used, whereas in the increase() function the public mapping locks is referenced. This inconsistency may lead to incorrect boost recalculations since the public mapping is never updated alongside the internal storage.
The contract declares a public mapping:
However, it also utilizes an internal storage structure:
Most functions (e.g., lock(), extend(), and withdraw()) interact with the user locks via _lockState.locks[msg.sender]. For example, in lock():
In contrast, the increase() function calls:
This line references locks[msg.sender] (the public mapping) instead of _lockState.locks[msg.sender]. Since the public mapping locks is never updated in the other functions, it remains at its default value (likely zero), causing boost recalculations to be based on an incorrect value.
The public mapping locks is declared at the contract level.
The internal storage _lockState is also declared and used in functions like lock(), extend(), and withdraw().
The increase() function uses the public mapping locks when calling _updateBoostState, creating a discrepancy.
Due to this inconsistency, boost calculations that rely on the locked amount may use incorrect (zero) values instead of the actual locked token amount. This could lead to inaccurate voting power or reward distribution for users, potentially impacting the fairness of boost rewards and overall governance outcomes. In worst-case scenarios, it might be exploited to manipulate reward distribution if the boost mechanism is a critical component of the protocol's incentive structure.
Manual Review
Ensure that all functions referencing user lock data use the same storage structure. Either update the public mapping locks whenever _lockState.locks is modified or refactor the code to remove the public mapping entirely and expose necessary data through functions that read from _lockState.locks.
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.