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

Direct reliance on `block.timestamp` in `Staking::claimRewards` for Couple duration of staking a `LoveToken` token thus jeopardising the reward allocation.

Description: The code utilizes block.timestamp as a source of randomness for determining reward distribution. However, block.timestamp is deterministic and publicly visibile, making it predictable and susceptible to manipulation. This approach lacks cryptographic strength. As a result, malicious actors could exploit this vulnerability by strategically timing their interactions with the contract to maximize rewards or manipulate outcomes in their favor. This undermines the fairness and integrity of the reward system, potentially leading to LoveToken losses.

function claimRewards() public {
uint256 soulmateId = soulmateContract.ownerToId(msg.sender);
if (lastClaim[msg.sender] == 0) {
lastClaim[msg.sender] = soulmateContract.idToCreationTimestamp(soulmateId);
}
uint256 timeInWeeksSinceLastClaim = (( @> block.timestamp - lastClaim[msg.sender]) / 1 weeks);
if (timeInWeeksSinceLastClaim < 1) {
revert Staking__StakingPeriodTooShort();
}
@> lastClaim[msg.sender] = block.timestamp;
uint256 amountToClaim = userStakes[msg.sender] * timeInWeeksSinceLastClaim;
loveToken.transferFrom(address(stakingVault), msg.sender, amountToClaim);
emit RewardsClaimed(msg.sender, amountToClaim);
}

Impact: This vulnerability can lead to exploitable behaviour, compromising the integrity of reward distribution and potentially enabling malicious actors to game the system.

Proof of Concept:

  1. The _depositSoulmateAndAttackerTokenToStake function deposits tokens for both a regular user and the attacker in the staking contract.

  2. The attacker alters the block.timestamp to simulate a longer staking duration than actual.

  3. By invoking Staking::claimRewards function, the attacker attempts to exploit the vulnerability.

  4. Assertion verifies whether the attacker's balance matches the expected value, which is the product of weekOfStaking and balancePerSoulmates, indicating successful manipulation of rewards.

Proof Of Code

Place the following into the StakingTest.t.sol

function test_UserCanClaimMoreRewardsthanRequiredThroughAlteringblockTimeStamp() public {
uint256 balancePerSoulmates = 5 ether;
uint256 weekOfStaking = 5;
_depositSoulmateAndAttackerTokenToStake(balancePerSoulmates);
// The attacker alters the `block.timestamp` to simulate a longer staking duration than actual (Which is 5 weeks).
vm.warp(block.timestamp + weekOfStaking * 1 weeks + 1 seconds);
vm.prank(attacker);
stakingContract.claimRewards();
assertTrue(loveToken.balanceOf(attacker) == weekOfStaking * balancePerSoulmates);
}

Recommended Mitigation: Utilize oracles for unbiased randomness to prevent manipulation.

Updates

Lead Judging Commences

0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Other
oxenzo Submitter
over 1 year ago
0xnevi Lead Judge
over 1 year ago
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.