Skip to content

Latest commit

 

History

History
87 lines (53 loc) · 3.72 KB

File metadata and controls

87 lines (53 loc) · 3.72 KB

Daring Chartreuse Gecko

Medium

When bids are reduced in the removeExcessBids function, the bids are not reinserted into the sorted linked list based on their new prices

Summary

https://github.com/sherlock-audit/2024-12-plaza-finance/blob/main/plaza-evm/src/Auction.sol#L264C7-L292C4

The Auction contract has an issue related to the bid list ordering after bid reductions. Specifically, when bids are reduced in the removeExcessBids function, the bids are not reinserted into the sorted linked list based on their new prices. This oversight leads to an incorrect bid ordering, which can cause the auction to function improperly and potentially be exploited by malicious actors.

Root Cause

https://github.com/sherlock-audit/2024-12-plaza-finance/blob/main/plaza-evm/src/Auction.sol#L264C7-L292C4

  if (amountToRemove >= sellCouponAmount) {
    // Subtract the sellAmount from amountToRemove
    amountToRemove -= sellCouponAmount;


    // Remove the bid
    _removeBid(currentIndex);


    // Move to the previous bid (higher price)
    currentIndex = prevIndex;
  } else {
    // Calculate the proportion of sellAmount being removed
    uint256 proportion = (amountToRemove * 1e18) / sellCouponAmount;
    
    // Reduce the current bid's amounts
    currentBid.sellCouponAmount = sellCouponAmount - amountToRemove;
    currentCouponAmount -= amountToRemove;


    uint256 reserveReduction = ((currentBid.buyReserveAmount * proportion) / 1e18);
    currentBid.buyReserveAmount = currentBid.buyReserveAmount - reserveReduction;
    totalSellReserveAmount -= reserveReduction;
    
    // Refund the proportional sellAmount
    IERC20(buyCouponToken).safeTransfer(currentBid.bidder, amountToRemove);
    
    amountToRemove = 0;
    emit BidReduced(currentIndex, currentBid.bidder, currentBid.buyReserveAmount, currentBid.sellCouponAmount);
  }
}

}

When the currentCouponAmount exceeds the totalBuyCouponAmount, the auction needs to adjust bids to bring the total coupon amount within the limit. The function iterates from the lowestBidIndex (lowest-priced bid) upwards, removing or reducing bids until the currentCouponAmount is less than or equal to totalBuyCouponAmount.

If the amountToRemove is greater than or equal to the sellCouponAmount of the current bid, the entire bid is removed using the _removeBid function. If not, the bid is reduced by subtracting amountToRemove from sellCouponAmount and proportionally adjusting buyReserveAmount.

Reducing a bid's sellCouponAmount and buyReserveAmount changes the bid's price (buyReserveAmount / sellCouponAmount). After the bid is reduced, the code does not re-insert the bid into the sorted linked list or adjust its position to reflect its new bid price. This omission creates issue that the bids are maintained in a sorted order, as the reduced bid will now be in the wrong position in the list based on its new price. The highestBidIndex and lowestBidIndex pointers will become incorrect as they rely on the bid ordering, potentially leading to incorrect auction behavior.

Internal Pre-conditions

No response

External Pre-conditions

No response

Attack Path

No response

Impact

Reduced bids will be out of order in the linked list, violating the expected sorting based on bid price. Functions that rely on the bid order, such as the logic for awarding winning bids or removing excess bids, will behave incorrectly. The lowestBidIndex and highestBidIndex will no longer accurately point to the correct bids, leading to incorrect iterations and failures.

PoC

No response

Mitigation

Reinsert Reduced Bids into the Sorted Linked List and Update lowestBidIndex and highestBidIndex Appropriately