Summary
_lockingDuration
does not revert if maximum is exceeded, as expected and outlined in the comments.
Vulnerability Details
The _createLock
function does not include an explicit check for the maximum allowable _lockingDuration
. Instead, it depends on the getBoostAmount
function to calculate the boost amount based on the _amount
and _lockingDuration
:
File : contracts/core/sdlPool/base/SDLPool.sol
* @notice creates a new lock
@> * @dev reverts if `_lockingDuration` exceeds maximum
* @param _amount amount to stake
* @param _lockingDuration duration of lock
*/
function _createLock(uint256 _amount, uint64 _lockingDuration) internal view returns (Lock memory) {
uint256 boostAmount = boostController.getBoostAmount(_amount, _lockingDuration);
uint64 startTime = _lockingDuration != 0 ? uint64(block.timestamp) : 0;
return Lock(_amount, boostAmount, startTime, _lockingDuration, 0);
}
https://github.com/Cyfrin/2023-12-stake-link/blob/549b2b8c4a5b841686fceb9c311dca9ac58225df/contracts/core/sdlPool/base/SDLPool.sol#L385-L396
However, the getBoostAmount
function's implementation details, where the reversion logic might exist, are not provided in the snippet:
File : contracts/core/interfaces/IBoostController.sol
function getBoostAmount(uint256 _amount, uint64 _lockingDuration) external view returns (uint256);
https://github.com/Cyfrin/2023-12-stake-link/blob/549b2b8c4a5b841686fceb9c311dca9ac58225df/contracts/core/interfaces/IBoostController.sol#L5
Impact
The creation of locks with excessively long durations could result from the absence of a maximum duration check.
Tools Used
Manual Review
Recommendations
This behaviour can be mitigated by implementing the following require()
statement:
function _createLock(
uint256 _amount,
uint64 _lockingDuration,
+ Lock memory _lock
) internal view returns (Lock memory) {
+ if (_lock.expiry > block.timestamp) {
+ revert InvalidLockingDuration();
+ }
uint256 boostAmount = boostController.getBoostAmount(_amount, _lockingDuration);
uint64 startTime = _lockingDuration != 0 ? uint64(block.timestamp) : 0;
return Lock(_amount, boostAmount, startTime, _lockingDuration, 0);
}