code-423n4 / 2022-06-putty-findings

5 stars 0 forks source link

QA Report #212

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

QA Report

Remarks/Recommendations

Typos

Documentation errors

Low Risk: cancel should fail if fillOrder has been called

Impact

A user may falsely believe that they have cancelled an order even though it has already been filled with fillOrder, since cancel does not revert in this case.

Also a false CancelledOrder event is emitted in this case.

Proof of Concept

Recommended Mitigation Steps

Make the following changes to function cancel:

function cancel(Order memory order) public {
    require(msg.sender == order.maker, "Not your order");
    bytes32 orderHash = hashOrder(order);
    uint256 filledExpiry = positionExpirations[order.isLong ? uint256(orderHash) : uint256(hashOppositeOrder(order))];
    require(filledExpiry == 0, "Order has already been filled");

    // mark the order as cancelled
    cancelledOrders[orderHash] = true;

    emit CancelledOrder(orderHash, order);
}

Low Risk: acceptCounterOffer should check that order is opposite of originalOrder and that order.maker is not the original order maker

Impact

Function acceptCounterOffer will cancel an original order and then call fillOrder on the counter-offer order. However, for this to work properly the counter-offer order must be the opposite kind of order. e.g. a Long if the original was a Short or vice versa. Additionally the maker of the counter-offer should not be the same as the maker of the original order.

If the order is the same kind as originalOrder then caller of acceptCounterOffer is putting themselves in the opposite position of where they wanted to be.

The impact is a potential for user error.

Proof of Concept

Let

If Bob had called fillOrder then Alice would become the recipient of a Long Put Option.

Case 1: Order kind is still Long Put

Instead Bob provides a counter-offer but also makes it a Long Put. He changes the order.maker to himself. Alice now calls acceptCounterOffer.

Line 583 will call fillOrder but it is being called by the original order maker. This is true because otherwise line 579 would revert.

This would be a very easy mistake for Alice to make if they weren't thinking carefully enough.

Unfortunately, she has now put herself in the Short Put position which is not what she desired and could be disadvantageous.

Case 2: originalOrder.maker == order.maker

If the original order maker is equal to the (counter-offer) order maker then when Alice calls fillOrder she now owns both position NFTs which is not desired behaviour.

It does not disadvantage her to any great extent as she can simple exercise and withdraw and will only lose some fees in the process as she will receive both the strike price and assets back.

Recommended Mitigation Steps

Add the following two lines to acceptCounterOffer to prevent these kinds of user error.

require(originalOrder.isCall == order.isCall &&
        originalOrder.isLong != order.isLong, "Counter-offer should be opposite");
require(originalOrder.maker != order.maker, "Counter-offer maker should be different");
outdoteth commented 2 years ago

high quality report