Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: low
Invalid

```Staking::withdraw``` missing control on the withdraw ```amount```

Summary

The Staking::withdraw function accepts any withdraw amount as input. If the user tries to withdraw an amount greater than the deposit the function goes and then fails. The user wastes money in a transaction that reverts and doesn't receive their LoveToken.

Vulnerability Details

function withdraw(uint256 amount) public {
@> userStakes[msg.sender] -= amount;
loveToken.transfer(msg.sender, amount);
emit Withdrew(msg.sender, amount);
}

Impact

Although the function works as expected (it fails if the user tries to withdraw an amount greater than the deposit), the user wastes money in a transaction that in the end reverts without receiving anything.
The test below shows this:

function testWithdrawAGreaterAmount() public {
//Mint an NFT - 2 soulmates are reunited
_mintOneTokenForBothSoulmates();
vm.startPrank(soulmate1);
//Give love token to soulmate1
vm.warp(block.timestamp + 14 days);
airdropContract.claim();
uint256 solmate1Amount = loveToken.balanceOf(soulmate1);
console2.log("soulmate1 loveToken amount after airdrop claim", solmate1Amount);
//Soulmate1 deposits the LoveToken
loveToken.approve(address(stakingContract), solmate1Amount);
stakingContract.deposit(solmate1Amount);
console2.log("soulmate1 loveToken after deposit", loveToken.balanceOf(soulmate1));
//Soulmate1 tries to withdraw more token than deposited
vm.expectRevert();
stakingContract.withdraw(solmate1Amount + 1);
console2.log("soulmate1 loveToken after withdraw", loveToken.balanceOf(soulmate1));
vm.stopPrank();
}
function _mintOneTokenForBothSoulmates() internal {
vm.prank(soulmate1);
soulmateContract.mintSoulmateToken();
vm.prank(soulmate2);
soulmateContract.mintSoulmateToken();
}
Running 1 test for test/unit/StakingTest.t.sol:StakingTest
[PASS] testWithdrawAGreaterAmount() (gas: 335495)
Logs:
soulmate1 loveToken amount after airdrop claim 14000000000000000000
soulmate1 loveToken after deposit 0
soulmate1 loveToken after withdraw 0

Tools Used

Manual review

Recommendations

Add a requirement statement that checks the withdrawal amount. The withdraw amount must be less / equal then the deposited amount.

function withdraw(uint256 amount) public {
+ require(amount <= userStakes[msg.sender] && amount > 0, "Wrong amount");
userStakes[msg.sender] -= amount;
loveToken.transfer(msg.sender, amount);
emit Withdrew(msg.sender, amount);
}
Updates

Lead Judging Commences

0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Other

Support

FAQs

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