DeFiFoundry
20,000 USDC
View results
Submission Details
Severity: low
Invalid

Precision and Rounding Issues

Summary

The contract uses SafeMath for arithmetic operations, but it still relies on uint256, which may lead to precision loss for very large numbers.

Vulnerability Details

The use of precision constants and division operations could potentially lead to rounding errors, especially in the calculation of multiplier and claimable tokens. If the number of tokens is small compared to the bids, some users may end up with less than expected due to rounding.

Impact

Tools Used

Recommendations

  1. The ues of larger precision constant: The contract uses a precision constant PRECISION_18 = 1e18. This is already a high precision, but you can consider using an even larger precision constant if dealing with very small token amounts. This will help reduce the impact of rounding errors in fractional token calculations.

uint256 public constant PRECISION_36 = 1e36;

You would then adjust the calculations in the auctionEnd and claimTokens functions to use this higher precision constant.

2 implementing a more robust approach to handle large numbers.Here's a suggestion:

1. Use Fixed Point Arithmetic: Instead of relying solely on uint256, implement fixed point arithmetic using a custom library like OpenZeppelin's FixedPoint or create your own implementation.

2. Implement Custom Math Library: Create a custom math library that handles large numbers accurately. This library should provide functions for addition, subtraction, multiplication, and division of large numbers.

Here's an example of how you might modify the relevant parts of the contract:

// Import a custom math library or use OpenZeppelin's FixedPoint
import "@openzeppelin/contracts/utils/math/FixedPoint.sol";
// Define constants
uint256 private constant PRECISION = 1e18;
// Replace uint256 with FixedPoint or your custom type
using FixedPoint for uint256;
// Modify the constructor
constructor(
address _fjordPoints,
address _auctionToken,
uint256 _biddingTime,
uint256 _totalTokens
) {
// ... existing code ...
totalTokens = FixedPoint.mul(_totalTokens, PRECISION);
}
// Modify the bid function
function bid(uint256 amount) external {
if (block.timestamp > auctionEndTime) {
revert AuctionAlreadyEnded();
}
bids[msg.sender] = bids[msg.sender].add(amount);
totalBids = totalBids.add(amount);
fjordPoints.transferFrom(msg.sender, address(this), amount);
emit BidAdded(msg.sender, amount);
}
// Modify the claimTokens function
function claimTokens() external {
if (!ended) {
revert AuctionNotYetEnded();
}
uint256 userBids = bids[msg.sender];
if (userBids == 0) {
revert NoTokensToClaim();
}
uint256 claimable = userBids.mul(multiplier).div(PRECISION);
bids[msg.sender] = 0;
auctionToken.transfer(msg.sender, claimable);
emit TokensClaimed(msg.sender, claimable);
}

This approach provides better accuracy for large numbers while maintaining the simplicity of the original contract structure. It also allows for easier scaling when dealing with very large token amounts or auctions with high participation rates.

Updates

Lead Judging Commences

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

Low decimal tokens or super small bids can lead to 0 claims

Support

FAQs

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