Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The '_executeNonAtomicOrders' function in SeaportProxy.sol may fail unexpectedly #54

Open
code423n4 opened this issue Nov 11, 2022 · 7 comments
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working edited-by-warden M-01 satisfactory satisfies C4 submission criteria; eligible for awards selected for report This submission will be included/highlighted in the audit report sponsor acknowledged Technically the issue is correct, but we're not going to resolve it for XYZ reasons

Comments

@code423n4
Copy link
Contributor

code423n4 commented Nov 11, 2022

Lines of code

https://github.com/code-423n4/2022-11-looksrare/blob/e3b2c053f722b0ca2dce3a3eb06f64859b8b7a6f/contracts/proxies/SeaportProxy.sol#L224

Vulnerability details

Impact

The '_executeNonAtomicOrders' function in SeaportProxy.sol tries to send fee by batch, this may break the 'NonAtomic' feature.

Proof of Concept

Let's say user want to buy 3 NFTs with following order parameters

NFT_1: price = 100 USDT, fee = 5%
NFT_2: price = 200 USDT, fee = 5%
NFT_3: price = 300 USDT, fee = 5%

Given user only sends 600 USDT, the expected result should be

NFT_1: success
NFT_2: success
NFT_3: failed

But as the fees are batched and sent at last, cause all 3 orders failed.

function _executeNonAtomicOrders(
    BasicOrder[] calldata orders,
    bytes[] calldata ordersExtraData,
    address recipient,
    uint256 feeBp,
    address feeRecipient
) private {
    uint256 fee;
    address lastOrderCurrency;
    for (uint256 i; i < orders.length; ) {
        OrderExtraData memory orderExtraData = abi.decode(ordersExtraData[i], (OrderExtraData));
        AdvancedOrder memory advancedOrder;
        advancedOrder.parameters = _populateParameters(orders[i], orderExtraData);
        advancedOrder.numerator = orderExtraData.numerator;
        advancedOrder.denominator = orderExtraData.denominator;
        advancedOrder.signature = orders[i].signature;

        address currency = orders[i].currency;
        uint256 price = orders[i].price;

        try
            marketplace.fulfillAdvancedOrder{value: currency == address(0) ? price : 0}(
                advancedOrder,
                new CriteriaResolver[](0),
                bytes32(0),
                recipient
            )
        {
            if (feeRecipient != address(0)) {
                uint256 orderFee = (price * feeBp) / 10000;
                if (currency == lastOrderCurrency) {
                    fee += orderFee;
                } else {
                    if (fee > 0) _transferFee(fee, lastOrderCurrency, feeRecipient);

                    lastOrderCurrency = currency;
                    fee = orderFee;
                }
            }
        } catch {}

        unchecked {
            ++i;
        }
    }

    if (fee > 0) _transferFee(fee, lastOrderCurrency, feeRecipient);
}

Tools Used

VS Code

Recommended Mitigation Steps

Don't batch up fees.

@code423n4 code423n4 added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels Nov 11, 2022
code423n4 added a commit that referenced this issue Nov 11, 2022
@0xhiroshi
Copy link

I would treat this as a malicious user trying to buy NFTs without paying for fees as he should be paying 600 x 1.05 = 630 instead of 600. So I think it's ok to just let it revert.

@0xJurassicPunk thoughts?

1 similar comment
@0xhiroshi
Copy link

I would treat this as a malicious user trying to buy NFTs without paying for fees as he should be paying 600 x 1.05 = 630 instead of 600. So I think it's ok to just let it revert.

@0xJurassicPunk thoughts?

@c4-sponsor
Copy link

0xhiroshi marked the issue as sponsor disputed

@c4-sponsor c4-sponsor added sponsor disputed Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue sponsor acknowledged Technically the issue is correct, but we're not going to resolve it for XYZ reasons and removed sponsor disputed Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue labels Nov 23, 2022
@c4-sponsor
Copy link

0xhiroshi marked the issue as sponsor acknowledged

@c4-judge c4-judge added the satisfactory satisfies C4 submission criteria; eligible for awards label Dec 11, 2022
@c4-judge
Copy link
Contributor

Picodes marked the issue as satisfactory

@ydspa
Copy link

ydspa commented Dec 19, 2022

Sorry for not indicated clearly, the reason why i think this may happen is that the NFT price may increase during submitting of tx, not due to a malicious user.

@0xhiroshi
Copy link

Sorry for not indicated clearly, the reason why i think this may happen is that the NFT price may increase during submitting of tx, not due to a malicious user.

Even if the seller submits a new listing with a higher price, the current transaction should still be valid. When there are two listings for the same NFT, they are both valid unless the seller explicitly cancels the original order on-chain, usually through the cancellation of an order nonce.

@C4-Staff C4-Staff added M-01 selected for report This submission will be included/highlighted in the audit report labels Dec 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working edited-by-warden M-01 satisfactory satisfies C4 submission criteria; eligible for awards selected for report This submission will be included/highlighted in the audit report sponsor acknowledged Technically the issue is correct, but we're not going to resolve it for XYZ reasons
Projects
None yet
Development

No branches or pull requests

6 participants