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

Flashloan attack can make the Protocol Loss alot of money

Vulnerability Details

The reward system is dependent on the userStakes[msg.sender] value, there is no check within the smart contract to record when these funds were deposited.

function deposit(uint256 amount) public {
if (loveToken.balanceOf(address(stakingVault)) == 0)
revert Staking__NoMoreRewards();
// No require needed because of overflow protection
userStakes[msg.sender] += amount;
@-> loveToken.transferFrom(msg.sender, address(this), amount);
emit Deposited(msg.sender, amount);
}

so a user can deposit 1 LoveToken for a week and just before they claimReward, they can increase their stake to 5 LoveToken, so they claim 6 LoveToken instead of 1.

This is because the amountToClaim is dependent on the current userStakes[msg.sender] which can be updated anytime

function claimRewards() public {
uint256 soulmateId = soulmateContract.ownerToId(msg.sender);
//@audit lastClaim is set to NFT creation time instead of staking time
// first claim
if (lastClaim[msg.sender] == 0) {
lastClaim[msg.sender] = soulmateContract.idToCreationTimestamp(
soulmateId
);
}
// How many weeks passed since the last claim.
// Thanks to round-down division, it will be the lower amount possible until a week has completly pass.
uint256 timeInWeeksSinceLastClaim = ((block.timestamp -
lastClaim[msg.sender]) / 1 weeks);
if (timeInWeeksSinceLastClaim < 1)
revert Staking__StakingPeriodTooShort();
lastClaim[msg.sender] = block.timestamp;
// Send the same amount of LoveToken as the week waited times the number of token staked
@-> uint256 amountToClaim = userStakes[msg.sender] *
timeInWeeksSinceLastClaim;
loveToken.transferFrom(
address(stakingVault),
msg.sender,
amountToClaim
);
emit RewardsClaimed(msg.sender, amountToClaim);
}

The malicious user can also leverage Flashloans, by pulling a large amount of LoveTokens from lending contracts to cheat the protocol,
A malicious user can stake 1 LoveToken for a week, just before they claimReward they can borrow large amounts of tokens from a lending protocol (e.g 10000 LoveTokens), and claim 10001 LoveTokens instead of 1 LoveTokens, They will do all these in a single Transaction.

##Proof of concept

  • Staking pool has 1M LoveTokens

  • A malicious user Bob has one LoveToken

  • Bob stake for 1 week

  • But before Bob claims his rewards he writes a malicious code to flashloan of 1M LoveToken

  • In one Transaction Bob borrows 1M LoveToken, deposit 1M LoveToken, and claimReward of 1M LoveToken From the protocol

  • The protocol Balance is now 0, and Bob made 1M from 1 LokenToken stake.

Impact

The protocol will lose a lot of funds and potentially drain the whole funds in the staking contract.

Tools Used

Manual Analysis

Recommendations

  • Prevent users who have already deposited from redepositing again i.e if userStakes[msg.sender] > 0 the deposit should revert

  • User should not be able to deposit and Claim Reward in the same transaction

  • StakingPositions Should be Implemented has ERC721, which has the amount of funds staked, the lastClaimed Time

Updates

Lead Judging Commences

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

finding-claimRewards-multi-deposits-time

High severity, this allows users to claim additional rewards without committing to intended weekly staking period via multi-deposit/deposit right before claiming rewards.

Support

FAQs

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