Skip to content

Commit

Permalink
bugfix: Fix native currency tip amount scaling logic for partial fill…
Browse files Browse the repository at this point in the history
…s when using fulfillOrders (#565)

* bugfix: move tips scaling logic to where offer and consideration items are scaled.

* bugfix: extend assertion to validate input parameters.

* bugfix: fix assertion.
  • Loading branch information
naveen-imtb authored Jun 13, 2024
1 parent e7259aa commit b349422
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 15 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@opensea/seaport-js",
"version": "4.0.1",
"version": "4.0.2",
"description": "[Seaport](https://github.com/ProjectOpenSea/seaport) is a new marketplace protocol for safely and efficiently buying and selling NFTs. This is a TypeScript library intended to make interfacing with the contract reasonable and easy.",
"license": "MIT",
"author": "OpenSea Developers",
Expand Down
13 changes: 1 addition & 12 deletions src/seaport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,8 @@ import {
shouldUseBasicFulfill,
validateAndSanitizeFromOrderStatus,
} from "./utils/fulfill";
import { getMaximumSizeForOrder, isCurrencyItem } from "./utils/item";
import { isCurrencyItem } from "./utils/item";
import {
adjustTipsForPartialFills,
areAllCurrenciesSame,
deductFees,
feeToConsiderationItem,
Expand Down Expand Up @@ -1049,16 +1048,6 @@ export class Seaport {
offererBalancesAndApprovals: offerersBalancesAndApprovals[index],
offererOperator: allOffererOperators[index],
};
if (order.tips.length > 0) {
order.tips = adjustTipsForPartialFills(
order.tips,
order.unitsToFill || 1,
// Max total amount to fulfill for scaling
getMaximumSizeForOrder({
...order.order,
}),
);
}

return order;
},
Expand Down
26 changes: 26 additions & 0 deletions src/utils/fulfill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,31 @@ export function fulfillAvailableOrders({
),
}));

const adjustTips = (orderMetadata: {
order: Order;
unitsToFill?: BigNumberish;
orderStatus: OrderStatus;
offerCriteria: InputCriteria[];
considerationCriteria: InputCriteria[];
tips: ConsiderationItem[];
extraData: string;
offererBalancesAndApprovals: BalancesAndApprovals;
offererOperator: string;
}): ConsiderationItem[] => {
if (!orderMetadata.tips || !orderMetadata.tips.length) {
return [];
}

// Max total amount to fulfill for scaling
const maxUnits = getMaximumSizeForOrder(orderMetadata.order);

return adjustTipsForPartialFills(
orderMetadata.tips,
orderMetadata.unitsToFill || 1,
maxUnits,
);
};

const ordersMetadataWithAdjustedFills = sanitizedOrdersMetadata.map(
(orderMetadata) => ({
...orderMetadata,
Expand All @@ -589,6 +614,7 @@ export function fulfillAvailableOrders({
totalFilled: orderMetadata.orderStatus.totalFilled,
totalSize: orderMetadata.orderStatus.totalSize,
}),
tips: adjustTips(orderMetadata),
}),
);

Expand Down
47 changes: 45 additions & 2 deletions test/partial-fulfill.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { describeWithFixture } from "./utils/setup";
import { OPENSEA_DOMAIN, OPENSEA_DOMAIN_TAG } from "./utils/constants";
import { SinonSpy } from "sinon";
import { SeaportABI } from "../src/abi/Seaport";
import { FulfillOrdersMetadata } from "../lib/utils/fulfill";
import { mapInputItemToOfferItem } from "../src/utils/order";

const sinon = require("sinon");

Expand All @@ -24,6 +26,7 @@ describeWithFixture(
let fulfiller: Signer;

let fulfillStandardOrderSpy: SinonSpy;
let fulfillAvailableOrdersSpy: SinonSpy;
let standardCreateOrderInput: CreateOrderInput;
let secondTestErc1155: TestERC1155;

Expand All @@ -33,6 +36,7 @@ describeWithFixture(
[offerer, zone, fulfiller] = await ethers.getSigners();

fulfillStandardOrderSpy = sinon.spy(fulfill, "fulfillStandardOrder");
fulfillAvailableOrdersSpy = sinon.spy(fulfill, "fulfillAvailableOrders");

const TestERC1155 = await ethers.getContractFactory("TestERC1155");
secondTestErc1155 = await TestERC1155.deploy();
Expand All @@ -41,6 +45,7 @@ describeWithFixture(

afterEach(() => {
fulfillStandardOrderSpy.restore();
fulfillAvailableOrdersSpy.restore();
});

describe("An ERC1155 is partially transferred", () => {
Expand Down Expand Up @@ -223,7 +228,6 @@ describeWithFixture(
});

it("ERC1155 <=> ETH adjust tips correctly using fulfillOrders", async () => {
// same test as above, but instead of fulfillOrder we use fulfillOrders
const tips = [
{
amount: parseEther("1").toString(),
Expand Down Expand Up @@ -304,7 +308,46 @@ describeWithFixture(
fulfillReceipt: receipt!,
});

expect(fulfillStandardOrderSpy.calledOnce);
const tipConsiderationItems = tips.map((tip) => ({
...mapInputItemToOfferItem(tip),
recipient: tip.recipient,
}));

const expectedArgs = {
ordersMetadata: [
{
order,
unitsToFill: 2,
tips: tipConsiderationItems,
},
],
};

expect(
fulfillAvailableOrdersSpy.withArgs(
sinon.match(function ({
ordersMetadata,
}: {
ordersMetadata: FulfillOrdersMetadata;
}) {
ordersMetadata.every((metadata, index) => {
expect(metadata.order).to.deep.equal(
expectedArgs.ordersMetadata[index].order,
"order doesn't match expected value",
);
expect(metadata.unitsToFill).to.deep.equal(
expectedArgs.ordersMetadata[index].unitsToFill,
"unitsToFill doesn't match expected value",
);
expect(metadata.tips).to.deep.equal(
expectedArgs.ordersMetadata[index].tips,
"tips doesn't match expected value",
);
});
return true;
}),
).calledOnce,
).to.be.true;
});

it("ERC1155 <=> ETH adjust tips correctly with low denomination", async () => {
Expand Down

0 comments on commit b349422

Please sign in to comment.