sherlock-audit / 2024-03-axis-finance-judging

1 stars 0 forks source link

sl1 - Permanent DoS of `claimBids()` and `settle()` functions for an auction lot with an expired `LinearVesting` derivative. #222

Closed sherlock-admin3 closed 5 months ago

sherlock-admin3 commented 6 months ago

sl1

medium

Permanent DoS of claimBids() and settle() functions for an auction lot with an expired LinearVesting derivative.

Summary

Currently, an auction lot can be set up with the use of LinearVesting derivative. If such a derivative module is enabled on an auction lot, the payment will be sent in the form of linearly vesting tokens. The problem is if the derivative expires the bidders won't be able to claim their winning bids.

Vulnerability Detail

When an auction is settled, winning bidders can claim their bids through a call to claimBids(). If an auction had a partially filled bidder, his payout is sent during a call to settle(). AuctionHouse.sol#L425-L442

if (bidClaim.payout > 0) {
    // Allocate quote and protocol fees for bid
    _allocateQuoteFees(
        protocolFee,
        referrerFee,
        bidClaim.referrer,
        routing.seller,
        routing.quoteToken,
        bidClaim.paid
    );
    // Reduce funding by the payout amount
    unchecked {
        routing.funding -= bidClaim.payout;
    }
    // Send the payout to the bidder
    _sendPayout(
        bidClaim.bidder,
        bidClaim.payout,
        routing,
        auctionOutput
    );

AuctionHouse.sol#L503-L529

if (settlement.pfBidder != address(0)) {
    _allocateQuoteFees(
        feeData.protocolFee,
        feeData.referrerFee,
        settlement.pfReferrer,
        routing.seller,
        routing.quoteToken,
        uint96(
            Math.mulDivDown(
                settlement.pfPayout,
                settlement.totalIn,
                settlement.totalOut
            )
        )
    );
    // Reduce funding by the payout amount
    unchecked {
        routing.funding -= uint96(settlement.pfPayout);
    }
    // Send refund and payout to the bidder
    Transfer.transfer(
        routing.quoteToken,
        settlement.pfBidder,
        settlement.pfRefund,
        false
    );
    // @audit-info Send baseTokens to bidder
    _sendPayout(
        settlement.pfBidder,
        settlement.pfPayout,
        routing,
        auctionOutput
    );
}

If a derivative module was enabled on the auction lot, _sendPayout() will try to mint derivative tokens to the bidder. AuctionHouse.sol#L800-L831

DerivativeModule module = DerivativeModule(
    _getModuleIfInstalled(derivativeReference)
);
// Approve the module to transfer payout tokens when minting
Transfer.approve(baseToken, address(module), payoutAmount_);
// Call the module to mint derivative tokens to the recipient
module.mint(
    recipient_,
    address(baseToken),
    routingParams_.derivativeParams,
    payoutAmount_,
    routingParams_.wrapDerivative
);

mint function of the LinearVesting derivative, validates that the expiry of the derivative is in the future, and reverts if it's not. LinearVesting.sol#L262-L264

if (_validate(underlyingToken_, params) == false) {
    revert InvalidParams();
}

LinearVesting.sol#L534-L535

// Check that the expiry time is in the future
if (data_.expiry < block.timestamp) return false;

If the derivative token expires, claiming will be DoS'ed for the winners, leaving them without a way to rescue their funds.

Impact

Claiming of winnings bids will be DoS'ed.

Code Snippet

https://github.com/sherlock-audit/2024-03-axis-finance/blob/cadf331f12b485bac184111cdc9ba1344d9fbf01/moonraker/src/modules/derivatives/LinearVesting.sol#L262-L264 https://github.com/sherlock-audit/2024-03-axis-finance/blob/cadf331f12b485bac184111cdc9ba1344d9fbf01/moonraker/src/modules/derivatives/LinearVesting.sol#L521-L541

Tool used

Manual Review

Recommendation

During the creation of the auction lot, check that the expiry of the derivative is greater than the conclusion of the auction lot, or allow minting derivative tokens even after expiry.

Duplicate of #178