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

Failure to Reduce Points When Users Unstake

Summary

The current implementation in main.js only handles the staking event and increases user points. It fails to account for unstaking events, which should result in a reduction of user points.

Vulnerability Details

.....
steaking.on(STAKED, async (_, amount, onBehalfOf) => {
let steakPoints = await steakPointsModel.findOne({ walletAddress: onBehalfOf });
if (!steakPoints) {
steakPoints = new steakPointsModel({
walletAddress: onBehalfOf,
points: +ethers.formatEther(amount) * PRECISION,
});
} else {
steakPoints.points += +ethers.formatEther(amount) * PRECISION;
}
await steakPoints.save();
});
//// NO CHECKS ON UNSTAKING EVENT CAUSING POINTS REMAINS SAME
//// USERS GOING TO TAKE UNFAIR ADVANTANGE
.....

The main.js file only listens for and processes the STAKED event. There is no mechanism to handle unstaking events and reduce the user's points accordingly.

This leads to an inaccurate representation of user stakes in the points system. User can stake and unstake multiple time. As unstaking don't reduce points, so user points gonna increase everytime he stakes.

POC

  1. User stakes 1 ETH, receives 1000 points.

  2. User unstakes 0.5 ETH.

  3. User's points remain at 1000 instead of decreasing to 500.

// Simulate staking
await steaking.emit(STAKED, ethers.utils.parseEther("1"), "0x1234...");
// Simulate unstaking (currently not handled)
await steaking.emit(UNSTAKED, ethers.utils.parseEther("0.5"), "0x1234...");
// Check points (will still be 1000 instead of 500)
const userPoints = await steakPointsModel.findOne({ walletAddress: "0x1234..." });
console.log(userPoints.points); // Outputs 1000

Impact

  • Inaccurate Point Representation: Users who unstake will have inflated point totals that don't reflect their current stake.

  • Unfair Advantage: Users could unstake their ETH while retaining the points, potentially gaining much more tokens in airdrop than legit users

  • Project Integrity: The discrepancy between actual stakes and point totals compromises the integrity of the entire staking reward system and project.

Tools Used

Manual Review

Recommendations

  • Implement event listner on unstaking event which will reduce the amount

steaking.on(UNSTAKED, async (_, amount, onBehalfOf) => {
try {
let steakPoints = await steakPointsModel.findOne({ walletAddress: onBehalfOf });
if (steakPoints) {
const pointsToReduce = +ethers.formatEther(amount) * PRECISION;
steakPoints.points = Math.max(0, steakPoints.points - pointsToReduce);
await steakPoints.save();
console.log(`Reduced points for ${onBehalfOf}: unstaked ${ethers.utils.formatEther(amount)} ETH`);
} else {
console.error(`No stake found for address ${onBehalfOf} during unstake event`);
}
} catch (error) {
console.error(`Error processing unstake event: ${error.message}`);
// Implement error reporting mechanism
}
});
Updates

Lead Judging Commences

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Steaking server is not taking unstakes into account

Support

FAQs

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