Summary
When the pool is about to be closed the last user can run into a problem to get his deposit back.
Vulnerability Details
Users can stake their funds and later withdraw them from the pool. While staking assets to the pool there is a check for the ammount:
function _stake(address user_, uint256 poolId_, uint256 amount_, uint256 currentPoolRate_) private {
...
if (pool.isPublic) {
uint256 balanceBefore_ = IERC20(depositToken).balanceOf(address(this));
IERC20(depositToken).safeTransferFrom(_msgSender(), address(this), amount_);
uint256 balanceAfter_ = IERC20(depositToken).balanceOf(address(this));
amount_ = balanceAfter_ - balanceBefore_;
@> require(userData.deposited + amount_ >= pool.minimalStake, "DS: amount too low");
totalDepositedInPublicPools += amount_;
}
...
}
So at least the first depost should be more than pool.minimalStake
. If the is a mim stake is 1000 tokens, user can deposit 1000 for the first time and 2 for the any other time.
While withdrawing the assets from the pool there is another check that requires amount in the pool be equal to 0 or to min stake:
function _withdraw(address user_, uint256 poolId_, uint256 amount_, uint256 currentPoolRate_) private {
...
if (pool.isPublic) {
require(
block.timestamp < pool.payoutStart ||
(block.timestamp > pool.payoutStart + pool.withdrawLockPeriod &&
block.timestamp > userData.lastStake + pool.withdrawLockPeriodAfterStake),
"DS: pool withdraw is locked"
);
uint256 depositTokenContractBalance_ = IERC20(depositToken).balanceOf(address(this));
if (amount_ > depositTokenContractBalance_) {
amount_ = depositTokenContractBalance_;
}
newDeposited_ = deposited_ - amount_;
require(amount_ > 0, "DS: nothing to withdraw");
@> require(newDeposited_ >= pool.minimalStake || newDeposited_ == 0, "DS: invalid withdraw amount");
} else {
newDeposited_ = deposited_ - amount_;
}
...
}
and it can cause problems for the last user to withdraw assets.
Impact
Imagine the situation where user left 1 token in the pool. So for the last user the withdraw process will alwais fail as there is newDeposited_
will never be equal to 0 and user got not enough deposited tokens on the account.
Tools Used
Manual review
Recommendations
If there is a min stake amount for the pool consider checking any deposit amount be higher than pool.minimalStake
.