Snowman Merkle Airdrop

First Flight #42
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Impact: medium
Likelihood: medium
Invalid

Unrestricted staking may allow abuse or manipulation

Root + Impact

Description

The stake() function in Snow.sol allows users to call it repeatedly without limitations or cooldown, which may lead to reward manipulation or spam.

n the Snow.sol contract, users can call stake(uint256 amount) as many times as they want without any restrictions or delay. There's no validation to prevent multiple calls or ensure staking is done within specific intervals.


function stake(uint256 amount) external {
require(amount > 0, "ZERO_AMOUNT");
balanceOf[msg.sender] -= amount;
staked[msg.sender] += amount;
totalStaked += amount;
snow.transferFrom(msg.sender, address(this), amount);
}

Risk

Since there's no mechanism to track how often a user stakes or place a cap on staked tokens, a malicious actor could call this repeatedly in small increments to potentially game any reward system that is built on top of staked[msg.sender] or totalStaked.

Proof of Concept

// User can run this in a loop:
for (uint i = 0; i < 100; i++) {
snow.approve(stakingContract, 1);
stakingContract.stake(1);
}

Recommended Mitigation

Introduce one or more of the following to prevent abuse:

  • A cooldown between successive stakes per user

  • A single-entry stake system (i.e., only one active stake per user)

  • Capping the total amount each address can stake

  • Logging stake timestamps and enforcing time-based restrictions

function stake(uint256 amount) external {
require(amount > 0, "ZERO_AMOUNT");
- balanceOf[msg.sender] -= amount;
- staked[msg.sender] += amount;
- totalStaked += amount;
- snow.transferFrom(msg.sender, address(this), amount);
+ require(block.timestamp > lastStake[msg.sender] + 1 days, "Cooldown active");
+ balanceOf[msg.sender] -= amount;
+ staked[msg.sender] += amount;
+ totalStaked += amount;
+ lastStake[msg.sender] = block.timestamp;
+ snow.transferFrom(msg.sender, address(this), amount);
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge
3 months ago
yeahchibyke Lead Judge 3 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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