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

Manipulation of auction bids in`FjordAuction.sol` can be performed to monopolize rewards

Summary

A vulnerability exists in the design of auction system (FjordAuction.sol), where users can bid and unbid with points at any time before the auction ends. This flaw allows a malicious user who has accumulated many points to manipulate the reward distribution by inflating bids early in the auction to mislead other participants that the auction already has a lot of bids and deter them from bidding, and if successful, subsequently retracting most bids just before the auction ends. This allows the malicious user to unfairly claim an unproportional share of the rewards with minimal points.

Vulnerability Details

Based on the auction mechanics, users participate in auctions by bidding with points and can bid or unbid their points at any time before the auction ends. The total rewards are distributed proportionally based on the total number of bids received.

  • A malicious user can initially place a large number of bids, creating the illusion that the chances of earning a significant portion of the reward pool are low. This can deter other users from bidding or lead them to bid less.

  • Just before the auction ends, if the malicious user notices that he has successfully detered others from bidding, the malicious user can unbid most of his points, for example leaving only 1 point in the pool (i.e. totalBids = 1) if no one else ends up bidding. Since the reward pool is distributed proportionally, this single point now represents the entire bid pool. The malicious user ends up unfairly claiming the entire reward pool with just 1 point.

  • The malicious user repeats this tactic on other available auctions.

/**
* @notice Places a bid in the auction.
* @param amount The amount of FjordPoints to bid.
*/
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);
}
/**
* @notice Allows users to withdraw part or all of their bids before the auction ends.
* @param amount The amount of FjordPoints to withdraw.
*/
function unbid(uint256 amount) external {
if (block.timestamp > auctionEndTime) {
revert AuctionAlreadyEnded();
}
uint256 userBids = bids[msg.sender];
if (userBids == 0) {
revert NoBidsToWithdraw();
}
if (amount > userBids) {
revert InvalidUnbidAmount();
}
bids[msg.sender] = bids[msg.sender].sub(amount);
totalBids = totalBids.sub(amount);
fjordPoints.transfer(msg.sender, amount);
emit BidWithdrawn(msg.sender, amount);
}
/**
* @notice Ends the auction and calculates claimable tokens for each bidder based on their bid proportion.
*/
function auctionEnd() external {
if (block.timestamp < auctionEndTime) {
revert AuctionNotYetEnded();
}
if (ended) {
revert AuctionEndAlreadyCalled();
}
ended = true;
emit AuctionEnded(totalBids, totalTokens);
if (totalBids == 0) {
auctionToken.transfer(owner, totalTokens);
return;
}
multiplier = totalTokens.mul(PRECISION_18).div(totalBids);
// Burn the FjordPoints held by the contract
uint256 pointsToBurn = fjordPoints.balanceOf(address(this));
fjordPoints.burn(pointsToBurn);
}
/**
* @notice Allows users to claim their tokens after the auction has ended.
*/
function claimTokens() external {
if (!ended) {
revert AuctionNotYetEnded();
}
uint256 userBids = bids[msg.sender];
if (userBids == 0) {
revert NoTokensToClaim();
}
uint256 claimable = userBids.mul(multiplier).div(PRECISION_18);
bids[msg.sender] = 0;
auctionToken.transfer(msg.sender, claimable);
emit TokensClaimed(msg.sender, claimable);
}
}

https://github.com/Cyfrin/2024-08-fjord/blob/0312fa9dca29fa7ed9fc432fdcd05545b736575d/src/FjordAuction.sol#L139-L223

Impact

This exploit can severely damage user trust in the auction platform, as malicious users can easily manipulate the system in their favour. This renders the auction system ineffective.

Tools Used

Manual review.

Recommendations

Consider introducing the following safeguards:

  • Lock Bids: Implement a locking mechanism where bids cannot be retracted or reduced once placed. This ensures that all bids are final and prevents last-minute manipulation.

  • Penalty for Unbidding: Impose a penalty for unbidding points as the auction nears its conclusion. This can discourage users from retracting bids solely for manipulative purposes.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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