High voting power could be usable without minimum lock time
Description
In LockingToken, the function _deposit_for
invokes votingPowerUnlockTime
when it is called by increaseAmount
. However, it does not check whether the newly obtained voting power through votingPowerUnlockTime
remains locked for the MINDAYS
period.
function _deposit_for(
address _addr,
uint256 _value,
uint256 _days
) internal nonReentrant {
// ...
uint256 _vp;
if (_amount == 0) {
_vp = votingPowerLockedDays(_value, _days);
// ...
} else if (_days == 0) {
_vp = votingPowerUnlockTime(_value, _end);
// ...
} else {
_vp = votingPowerLockedDays(_amount, _days);
// ...
}
require(_vp > 0, "No benefit to lock");
_mint(_addr, _vp);
// ...
}
function votingPowerUnlockTime(uint256 _value, uint256 _unlock_time) public view override returns (uint256) {
if (_unlock_time <= block.timestamp) return 0;
uint256 _lockedSeconds = _unlock_time - block.timestamp;
if (_lockedSeconds >= MAXTIME) return _value;
return _value * _lockedSeconds / MAXTIME;
}
function votingPowerLockedDays(uint256 _value, uint256 _days) public pure override returns (uint256) {
if (_days >= MAXDAYS) return _value;
return _value * _days / MAXDAYS;
}
Impact
A malicious user could deposit tokens with MINDAYS
and then wait for time to pass. After time has passed, for example MINDAYS - 1 seconds
, the malicious user could call increaseAmount
with a huge amount of tokens and obtain high voting power that is withdrawable one second later. This could be a potential risk if the voting power is used for governance or other important decisions.
Recommendations
Add a check to ensure that the voting power obtained through votingPowerUnlockTime
remains locked for the MINDAYS
period above.
Remediation
This issue has been acknowledged by Anzen Labs Inc., and a fix was implemented in commit 26ee4c15↗.