20,000 USDC
View results
Submission Details
Severity: high

Anyone can drain the staking pool by calling `withdraw()`

Summary

Anyone can drain the staking pool by calling Staking.withdraw() as there is no check whether the caller has any balance.

Vulnerability Details

There is no check when calling Staking.withdraw() whether the caller has any tokens to withdraw so they can withdraw the whole amount of the pool without causing a revert.

function withdraw(uint _amount) external {
updateFor(msg.sender);
balances[msg.sender] -= _amount;
TKN.transfer(msg.sender, _amount);
}

updateFor(msg.sender) calls the update() function which sets the index and balance.
updateFor if there is no balances[recipient] just sets the supplyIndex like so:

function updateFor(address recipient) public {
update();
uint256 _supplied = balances[recipient];
if (_supplied > 0) {
....
} else {
supplyIndex[recipient] = index;
}
}

Impact

A malicious user can empty the pool funds so this is a high severity issue.

Tools Used

Manual review

Recommendations

Add the following check in the withdraw function:

function withdraw(uint _amount) external {
updateFor(msg.sender);
++ if balances[msg.sender] > _amount {
balances[msg.sender] -= _amount;
TKN.transfer(msg.sender, _amount);
++ }
}

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.