Keen Metal Loris
Medium
In Auction, when sum of sellCouponAmount of all bidders is over totalBuyCouponAmount by new bid, it impact buy/sell rate of lowest bidder.
https://github.com/sherlock-audit/2024-12-plaza-finance/blob/main/plaza-evm/src/Auction.sol#L275
function removeExcessBids() internal {
...
if (amountToRemove >= sellCouponAmount) {
...
} else {
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;
...
}
...
}
uint256 proportion = (amountToRemove * 1e18) / sellCouponAmount; ... uint256 reserveReduction = ((currentBid.buyReserveAmount * proportion) / 1e18);
By the Precision Loss / Rounding Error, the buy/sell rate of previous lowest bidder is changed.
No response
No response
No response
Due to the "Precision Loss / Rounding" issue, the bidder may be removed from bidding. or if the bidder become winner, the auction needs to pay more.
address BidderFirst = address(1); //user 1
vm.startPrank(BidderFirst);
usdc.mint(BidderFirst, 398000000000);
usdc.approve(address(auction), 398000000000);
auction.bid(1000, 398000000000);
vm.stopPrank();
address BidderSecond = address(2); //user 2
uint256 secondBidAmount = 4816;
uint256 secondSellAmount = 602000000000;
vm.startPrank(BidderSecond);
usdc.mint(BidderSecond, secondSellAmount);
usdc.approve(address(auction), secondSellAmount);
auction.bid(secondBidAmount, secondSellAmount);
vm.stopPrank();
(, uint256 buyAmountBefore, uint256 buySellAmountBefore,,,) = auction.bids(2);
console2.log("-----before some is removed------");
console2.log("-- buy Amount : ");
console2.log(buyAmountBefore);
console2.log("-- sell Amount : ");
console2.log(buySellAmountBefore);
console2.log("-- sell/buy rate : ");
console2.log(buySellAmountBefore / buyAmountBefore);
address BidderThird = address(3); //user 3
vm.startPrank(BidderThird);
usdc.mint(BidderThird, 2000000000);
usdc.approve(address(auction), 2000000000);
auction.bid(14, 2000000000);
vm.stopPrank();
(, uint256 buyAmountAfter, uint256 buySellAmountAfter,,,) = auction.bids(2);
console2.log("-----after some is removed------");
console2.log("-- buy Amount : ");
console2.log(buyAmountAfter);
console2.log("-- sell Amount : ");
console2.log(buySellAmountAfter);
console2.log("-- sell/buy rate : ");
console2.log(buySellAmountAfter / buyAmountAfter);
console2.log("-- predict buy amount : ");
console2.log(buyAmountBefore * buySellAmountAfter / buySellAmountBefore);
The result is following. -----before some is removed------ -- buy Amount : 4816 -- sell Amount : 602000000000 -- sell/buy rate : 125000000 -----after some is removed------ -- buy Amount : 4801 -- sell Amount : 600000000000 -- sell/buy rate : 124973963 -- predict buy amount : 4800
When the user2 bid, the sell/buy rate is 125000000, but after new bid, the rate is 124973963. So the buy amount is changed 4801 instead of 4800.
In Auction.sol
function removeExcessBids() internal {
...
if (amountToRemove >= sellCouponAmount) {
...
} else {
- uint256 proportion = (amountToRemove * 1e18) / sellCouponAmount;
// Reduce the current bid's amounts
currentBid.sellCouponAmount = sellCouponAmount - amountToRemove;
currentCouponAmount -= amountToRemove;
- uint256 reserveReduction = ((currentBid.buyReserveAmount * proportion) / 1e18);
+ uint256 reserveReduction = (amountToRemove * currentBid.buyReserveAmount) / sellCouponAmount;
currentBid.buyReserveAmount = currentBid.buyReserveAmount - reserveReduction;
totalSellReserveAmount -= reserveReduction;
...
}
...
}
After modify the code, the result of Poc is following.
-----before some is removed------ -- buy Amount : 4816 -- sell Amount : 602000000000 -- sell/buy rate : 125000000 -----after some is removed------ -- buy Amount : 4800 -- sell Amount : 600000000000 -- sell/buy rate : 125000000 -- predict buy amount : 4800