Beginner FriendlyFoundryDeFi
100 EXP
View results
Submission Details
Severity: low
Invalid

Precision Issues in JavaScript Server for ETH Amounts Affecting Point Calculations

Summary

The JavaScript server responsible for processing and storing accumulated points for the Steaking contract may face precision issues due to the limitations of the JavaScript Number type when handling large ETH amounts. This issue can affect the accuracy of point calculations.

Vulnerability Details

The server code uses the JavaScript Number type for handling ETH amounts and performing arithmetic operations. The Number type has limitations in accurately representing very large integers, which can lead to precision errors in calculations, especially when dealing with large ETH values.

let steakPoints;
steakPoints = await steakPointsModel.findOne({ walletAddress: onBehalfOf });
if (!steakPoints) {
steakPoints = new steakPointsModel({
walletAddress: onBehalfOf,
points: +ethers.formatEther(amount) * PRECISION, // Potential precision issue
});
} else {
steakPoints.points += +ethers.formatEther(amount) * PRECISION; // Potential precision issue
}

Impact

Precision errors can lead to inaccuracies in point calculations, potentially causing financial discrepancies and incorrect point totals for users. This may impact user trust and the overall reliability of the staking system.

Recommendations

To mitigate precision issues, use the BigInt type for handling large numbers in JavaScript. Update the code to perform calculations using BigInt to ensure accurate arithmetic operations with large ETH values. Since MongoDB doesn't support BigInt, store the result as a string to preserve precision. Storing as a string ensures that large numbers are not truncated or rounded, and they can be accurately converted back to BigInt when needed.

steaking.on(STAKED, async (_, amount, onBehalfOf) => {
let steakPoints;
steakPoints = await steakPointsModel.findOne({ walletAddress: onBehalfOf });
// Convert the amount from wei to ether and then to BigInt
+ const amountInEther = ethers.formatEther(amount);
+ const amountInPoints = ethers.utils.parseUnits(amountInEther, PRECISION);
if (!steakPoints) {
steakPoints = new steakPointsModel({
walletAddress: onBehalfOf,
- points: +ethers.formatEther(amount) * PRECISION,
+ points: amountInPoints.toString()
});
} else {
- steakPoints.points += +ethers.formatEther(amount) * PRECISION;
+ const currentPoints = BigInt(steakPoints.points);
// Add new points
+ const updatedPoints = currentPoints + amountInPoints;
// Update points and store as string
+ steakPoints.points = updatedPoints.toString();
}
await steakPoints.save();
});
Updates

Lead Judging Commences

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Precision

Support

FAQs

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