code-423n4 / 2024-07-reserve-validation

0 stars 0 forks source link

Using endtime for order cancelation deadline of gnosis auction could lead to bait and switch bid tactics #200

Open c4-bot-1 opened 1 month ago

c4-bot-1 commented 1 month ago

Lines of code

https://github.com/code-423n4/2024-07-reserve/blob/3f133997e186465f4904553b0f8e86ecb7bbacbf/contracts/plugins/trading/GnosisTrade.sol#L84-L157

Vulnerability details

Impact

Allowing users to cancel orders last moment can lead to bait and switch bids designed to obtain assets below market value

Proof of Concept

GnosisTrade.sol#L84-L157

function init(
    IBroker broker_,
    address origin_,
    IGnosis gnosis_,
    uint48 batchAuctionLength,
    TradeRequest calldata req
) external stateTransition(TradeStatus.NOT_STARTED, TradeStatus.OPEN) {

    ...

    broker = broker_;
    origin = origin_;
    gnosis = gnosis_;
    endTime = uint48(block.timestamp) + batchAuctionLength;

    ...

    auctionId = gnosis.initiateAuction(
        sell,
        buy,
        endTime, <- @audit orderCancellationEndDate
        endTime, <- @audit auctionEndDate
        _sellAmount,
        minBuyAmount,
        minBuyAmtPerOrder,
        0,
        false,
        address(0),
        new bytes(0)
    );
}

Above we see that when creating an auction, both the auction end and order cancellation end are set to the same value.

EasyAuction.sol#L152-L227

function initiateAuction(
    IERC20 _auctioningToken,
    IERC20 _biddingToken,
    uint256 orderCancellationEndDate,
    uint256 auctionEndDate,
    uint96 _auctionedSellAmount,
    uint96 _minBuyAmount,
    uint256 minimumBiddingAmountPerOrder,
    uint256 minFundingThreshold,
    bool isAtomicClosureAllowed,
    address accessManagerContract,
    bytes memory accessManagerContractData
) public returns (uint256) {

    ...

    auctionData[auctionCounter] = AuctionData(
        _auctioningToken,
        _biddingToken,
        orderCancellationEndDate,
        auctionEndDate,
        IterableOrderedOrderSet.encodeOrder(
            userId,
            _minBuyAmount,
            _auctionedSellAmount
        ),
        minimumBiddingAmountPerOrder,
        0,
        IterableOrderedOrderSet.QUEUE_START,
        bytes32(0),
        0,
        false,
        isAtomicClosureAllowed,
        feeNumerator,
        minFundingThreshold
    );

    ...
}

We see from the gnosis auction contract that these unmodified time values are used directly for the auction. The result is that orders can be canceled up the the block before it is finalized. This opens up the ability to carry out a bait and switch MEV tactic on the auction.

  1. Bid entire auction amount with price 10% higher than market value at start of auction
  2. Other parties see that all tokens are "sold" for a price much higher than they are willing to pay. Since bidding requires locking tokens, rational actors won't place lower bids
  3. The block before it settles, cancel the high order and replace it with a bid at the minimum price

This would work particularly well as gnosis auctions can't be utilized by searchers/bots so a majority of bidders would be assumed to be humans.

Tools Used

Manual review

Recommended Mitigation Steps

orderCancellationEndDate should be set to a few minutes before the end of the auction, allowing for others to see the bait and switch and bid accordingly.

Assessed type

MEV