diff --git a/package-lock.json b/package-lock.json index eac2a18c..83f60452 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6924,6 +6924,7 @@ "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.5.tgz", "integrity": "sha512-HTm14iMQKK2FjFLRTM5lAVcyaUzOnqbPtesFIvREgXpJHdQm8bWS+GkQgIkfaBYRHuCnea7w8UVNfwiAQhlr9A==", "dev": true, + "hasInstallScript": true, "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" @@ -7286,6 +7287,7 @@ "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.7.tgz", "integrity": "sha512-vLt1O5Pp+flcArHGIyKEQq883nBt8nN8tVBcoL0qUXj2XT1n7p70yGIq2VK98I5FdZ1YHc0wk/koOnHjnXWk1Q==", "dev": true, + "hasInstallScript": true, "optional": true, "dependencies": { "node-gyp-build": "^4.3.0" diff --git a/src/constants.ts b/src/constants.ts index a081a1dc..eb72b7cb 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,4 +1,4 @@ -import { BigNumber } from "ethers"; +import { BigNumber, constants } from "ethers"; export const SEAPORT_CONTRACT_NAME = "Seaport"; export const SEAPORT_CONTRACT_VERSION_V1_4 = "1.4"; @@ -108,9 +108,8 @@ export enum BasicOrderRouteType { export const MAX_INT = BigNumber.from( "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", ); -export const ONE_HUNDRED_PERCENT_BP = 10000; -export const NO_CONDUIT = - "0x0000000000000000000000000000000000000000000000000000000000000000"; +export const ONE_HUNDRED_PERCENT_BP = 10_000; +export const NO_CONDUIT = constants.HashZero; // Supply here any known conduit keys as well as their conduits export const KNOWN_CONDUIT_KEYS_TO_CONDUIT = { diff --git a/src/seaport.ts b/src/seaport.ts index c8682776..8796d13f 100644 --- a/src/seaport.ts +++ b/src/seaport.ts @@ -563,19 +563,21 @@ export class Seaport { * @param orders list of order components * @param accountAddress optional account address from which to cancel the orders from. * @param domain optional domain to be hashed and appended to calldata + * @param overrides any transaction overrides the client wants, ignored if not set * @returns the set of transaction methods that can be used */ public cancelOrders( orders: OrderComponents[], accountAddress?: string, domain?: string, + overrides?: PayableOverrides, ): TransactionMethods> { const signer = this._getSigner(accountAddress); return getTransactionMethods( this.contract.connect(signer), "cancel", - [orders], + [orders, overrides], domain, ); } @@ -584,11 +586,13 @@ export class Seaport { * Bulk cancels all existing orders for a given account * @param offerer the account to bulk cancel orders on * @param domain optional domain to be hashed and appended to calldata + * @param overrides any transaction overrides the client wants, ignored if not set * @returns the set of transaction methods that can be used */ public bulkCancelOrders( offerer?: string, domain?: string, + overrides?: PayableOverrides, ): TransactionMethods< ContractMethodReturnType > { @@ -597,7 +601,7 @@ export class Seaport { return getTransactionMethods( this.contract.connect(signer), "incrementCounter", - [], + [overrides], domain, ); } @@ -608,19 +612,21 @@ export class Seaport { * @param orders list of order structs * @param accountAddress optional account address to approve orders. * @param domain optional domain to be hashed and appended to calldata + * @param overrides any transaction overrides the client wants, ignored if not set * @returns the set of transaction methods that can be used */ public validate( orders: Order[], accountAddress?: string, domain?: string, + overrides?: PayableOverrides, ): TransactionMethods> { const signer = this._getSigner(accountAddress); return getTransactionMethods( this.contract.connect(signer), "validate", - [orders], + [orders, overrides], domain, ); } @@ -780,7 +786,7 @@ export class Seaport { * Defaults to the zero address which means the offer goes to the fulfiller * @param input.domain optional domain to be hashed and appended to calldata * @param input.exactApproval optional boolean to indicate whether the approval should be exact or not - * @param input.overrides any overrides the client wants, will ignore value + * @param input.overrides any transaction overrides the client wants, ignored if not set * @returns a use case containing the set of approval actions and fulfillment action */ public async fulfillOrder({ @@ -1082,7 +1088,7 @@ export class Seaport { * @param input * @param input.orders the list of orders to match * @param input.fulfillments the list of fulfillments to match offer and considerations - * @param input.overrides any overrides the client wants, will need to pass in value for matching orders with ETH. + * @param input.overrides any transaction overrides the client wants, will need to pass in value for matching orders with ETH. * @param input.accountAddress Optional address for which to match the order with * @param input.domain optional domain to be hashed and appended to calldata * @returns set of transaction methods for matching orders @@ -1112,9 +1118,17 @@ export class Seaport { ); } + /** + * Set a domain on the canonical domain registry. + * @param domain The domain to set + * @param accountAddress Address to send the transaction from + * @param overrides Any transaction overrides the client wants, ignored if not set + * @returns The domain tag (4 byte keccak hash of the domain) + */ public setDomain( domain: string, accountAddress?: string, + overrides?: PayableOverrides, ): TransactionMethods< ContractMethodReturnType > { @@ -1123,29 +1137,40 @@ export class Seaport { return getTransactionMethods( this.domainRegistry.connect(signer), "setDomain", - [domain], + [domain, overrides], ); } + /** + * Get the number of domains registered under a domain tag. + * @param tag The domain tag. + * @returns The number of domains registered under the tag. + */ public async getNumberOfDomains(tag: string): Promise { return this.domainRegistry.getNumberOfDomains(tag); } + /** + * Gets the domain at a given index under a domain tag. + * @param tag The domain tag. + * @param index The index. + * @returns The domain at the index for the given tag. + */ public getDomain(tag: string, index: number): Promise { return this.domainRegistry.getDomain(tag, index); } - public async getDomains( - tag: string, - shouldThrow?: boolean, - ): Promise { + /** + * Gets the domains registered under a tag. + * @param tag The domain tag. + * @returns The domains registered under the tag. + */ + public async getDomains(tag: string): Promise { try { - if (shouldThrow) { - throw Error; - } - return this.domainRegistry.getDomains(tag); } catch (error) { + // If there are too many domains set under the tag, it will revert when trying to return in memory. + // This fallback will manually query each index to get the full list of domains. const totalDomains = ( await this.domainRegistry.getNumberOfDomains(tag) ).toNumber(); diff --git a/test/basic-fulfill.spec.ts b/test/basic-fulfill.spec.ts index 306d61a4..4085132e 100644 --- a/test/basic-fulfill.spec.ts +++ b/test/basic-fulfill.spec.ts @@ -12,6 +12,7 @@ import { verifyBalancesAfterFulfill, } from "./utils/balance"; import { describeWithFixture } from "./utils/setup"; +import { OPENSEA_DOMAIN, OVERRIDE_GAS_LIMIT } from "./utils/constants"; const sinon = require("sinon"); @@ -27,8 +28,6 @@ describeWithFixture( let fulfillStandardOrderSpy: sinon.SinonSpy; // eslint-disable-line no-undef const nftId = "1"; const erc1155Amount = "3"; - const OPENSEA_DOMAIN = "opensea.io"; - const overrideGasLimit = 10_000_000; beforeEach(async () => { fulfillBasicOrderSpy = sinon.spy(fulfill, "fulfillBasicOrder"); @@ -207,7 +206,7 @@ describeWithFixture( order, accountAddress: fulfiller.address, domain: OPENSEA_DOMAIN, - overrides: { gasLimit: overrideGasLimit }, + overrides: { gasLimit: OVERRIDE_GAS_LIMIT }, }); const approvalAction = actions[0]; @@ -250,7 +249,7 @@ describeWithFixture( fulfillReceipt: receipt, }); expect(fulfillBasicOrderSpy).calledOnce; - expect(transaction.gasLimit).equal(overrideGasLimit); + expect(transaction.gasLimit).equal(OVERRIDE_GAS_LIMIT); }); it("ERC721 <=> ERC20 (already validated order)", async () => { diff --git a/test/cancel.spec.ts b/test/cancel.spec.ts index b482402a..6b332cc8 100644 --- a/test/cancel.spec.ts +++ b/test/cancel.spec.ts @@ -5,6 +5,7 @@ import { ethers } from "hardhat"; import { ItemType } from "../src/constants"; import { CreateOrderInput } from "../src/types"; import { describeWithFixture } from "./utils/setup"; +import { OVERRIDE_GAS_LIMIT } from "./utils/constants"; describeWithFixture("As a user I want to cancel an order", (fixture) => { let offerer: SignerWithAddress; @@ -58,8 +59,17 @@ describeWithFixture("As a user I want to cancel an order", (fixture) => { // Remove signature onChainOrder.signature = "0x"; - await seaport.validate([onChainOrder], offerer.address).transact(); - await seaport.bulkCancelOrders(offerer.address).transact(); + const overrides = { gasLimit: OVERRIDE_GAS_LIMIT }; + + const validateTx = await seaport + .validate([onChainOrder], offerer.address, undefined, overrides) + .transact(); + expect(validateTx.gasLimit).to.eq(OVERRIDE_GAS_LIMIT); + + const bulkCancelOrdersTx = await seaport + .bulkCancelOrders(offerer.address, undefined, overrides) + .transact(); + expect(bulkCancelOrdersTx.gasLimit).to.eq(OVERRIDE_GAS_LIMIT); const { executeAllActions: executeAllFulfillActionsOffChainOrder } = await seaport.fulfillOrder({ @@ -101,10 +111,14 @@ describeWithFixture("As a user I want to cancel an order", (fixture) => { true, ); - await seaport.cancelOrders([order.parameters], offerer.address).transact(); + const overrides = { gasLimit: OVERRIDE_GAS_LIMIT }; + const cancelOrdersTx = await seaport + .cancelOrders([order.parameters], offerer.address, undefined, overrides) + .transact(); expect(await seaport.getOrderStatus(orderHash)).to.have.property( "isCancelled", true, ); + expect(cancelOrdersTx.gasLimit).to.eq(OVERRIDE_GAS_LIMIT); }); }); diff --git a/test/create-order.spec.ts b/test/create-order.spec.ts index b636a8c9..9eaf31ed 100644 --- a/test/create-order.spec.ts +++ b/test/create-order.spec.ts @@ -9,6 +9,7 @@ import { } from "../src/types"; import { generateRandomSalt } from "../src/utils/order"; import { describeWithFixture } from "./utils/setup"; +import { OPENSEA_DOMAIN, OPENSEA_DOMAIN_TAG } from "./utils/constants"; describeWithFixture("As a user I want to create an order", (fixture) => { it("should create the order after setting needed approvals", async () => { @@ -921,9 +922,6 @@ describeWithFixture("As a user I want to create an order", (fixture) => { }); }); -const OPENSEA_DOMAIN = "opensea.io"; -const OPENSEA_TAG = "360c6ebe"; - describeWithFixture( "As a user I want to create and fulfill an order using contract wallet", (fixture) => { @@ -1005,11 +1003,10 @@ describeWithFixture( const exchangeTransaction = await exchange.transactionMethods.buildTransaction(); - expect(exchangeTransaction.data?.slice(-8)).to.eq(OPENSEA_TAG); + expect(exchangeTransaction.data?.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const transaction = await exchange.transactionMethods.transact(); - - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); expect(await testErc721.ownerOf(nftId)).to.equal( testERC1271Wallet.address, diff --git a/test/domain-registry.spec.ts b/test/domain-registry.spec.ts index 007e343a..5d1982d2 100644 --- a/test/domain-registry.spec.ts +++ b/test/domain-registry.spec.ts @@ -3,15 +3,17 @@ import { expect } from "chai"; import { keccak256, toUtf8Bytes } from "ethers/lib/utils"; import { ethers } from "hardhat"; import { describeWithFixture } from "./utils/setup"; +import { + OPENSEA_DOMAIN, + OPENSEA_DOMAIN_TAG, + OVERRIDE_GAS_LIMIT, +} from "./utils/constants"; describeWithFixture( "As a user I want to register or look up a domain", (fixture) => { let user: SignerWithAddress; - const OPENSEA_DOMAIN = "opensea.io"; - const OPENSEA_TAG = keccak256(toUtf8Bytes(OPENSEA_DOMAIN)).slice(0, 10); - const expectedExampleDomainArray = [ "join_tg_invmru_haha_fd06787(address,bool)", "func_2093253501(bytes)", @@ -27,9 +29,11 @@ describeWithFixture( [user] = await ethers.getSigners(); - await seaport - .setDomain(expectedExampleDomainArray[0], user.address) + const overrides = { gasLimit: OVERRIDE_GAS_LIMIT }; + const setDomainTxWithOverrides = await seaport + .setDomain(expectedExampleDomainArray[0], user.address, overrides) .transact(); + expect(setDomainTxWithOverrides.gasLimit).to.eq(OVERRIDE_GAS_LIMIT); await seaport .setDomain(expectedExampleDomainArray[1], user.address) @@ -49,7 +53,9 @@ describeWithFixture( await seaport.setDomain(OPENSEA_DOMAIN, user.address).transact(); - expect(await seaport.getDomain(OPENSEA_TAG, 0)).to.eq(OPENSEA_DOMAIN); + expect(await seaport.getDomain(`0x${OPENSEA_DOMAIN_TAG}`, 0)).to.eq( + OPENSEA_DOMAIN, + ); expect(await seaport.getDomain(exampleTag, 0)).to.eq( expectedExampleDomainArray[0], @@ -82,10 +88,17 @@ describeWithFixture( expect(await seaport.getNumberOfDomains(exampleTag)).to.eq(4); }); - it("Should return an array of domains even if getDomains should throw", async () => { + it("Should return an array of domains even if getDomains throws", async () => { const { seaport } = fixture; - expect(await seaport.getDomains(exampleTag, true)).to.deep.eq( + (seaport.domainRegistry as any) = { + ...seaport.domainRegistry, + getDomains: () => { + throw new Error(); + }, + }; + + expect(await seaport.getDomains(exampleTag)).to.deep.eq( expectedExampleDomainArray, ); }); diff --git a/test/fulfill-orders.spec.ts b/test/fulfill-orders.spec.ts index 91ae3da9..4ae16e8f 100644 --- a/test/fulfill-orders.spec.ts +++ b/test/fulfill-orders.spec.ts @@ -9,6 +9,7 @@ import { CreateOrderInput, CurrencyItem } from "../src/types"; import * as fulfill from "../src/utils/fulfill"; import { getTagFromDomain } from "../src/utils/usecase"; import { describeWithFixture } from "./utils/setup"; +import { OPENSEA_DOMAIN, OPENSEA_DOMAIN_TAG } from "./utils/constants"; const sinon = require("sinon"); @@ -31,9 +32,6 @@ describeWithFixture( const erc1155Amount = "3"; const erc1155Amount2 = "7"; - const OPENSEA_DOMAIN = "opensea.io"; - const OPENSEA_TAG = "360c6ebe"; - beforeEach(async () => { fulfillAvailableOrdersSpy = sinon.spy(fulfill, "fulfillAvailableOrders"); @@ -153,18 +151,15 @@ describeWithFixture( expect(actions.length).to.eq(1); const action = actions[0]; - expect(action.type).eq("exchange"); - expect( (await action.transactionMethods.buildTransaction()).data?.slice( -8, ), - ).to.eq(OPENSEA_TAG); + ).to.eq(OPENSEA_DOMAIN_TAG); const transaction = await action.transactionMethods.transact(); - - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const owners = await Promise.all([ testErc721.ownerOf(nftId), @@ -285,12 +280,11 @@ describeWithFixture( ( await fulfillAction.transactionMethods.buildTransaction() ).data?.slice(-8), - ).to.eq(OPENSEA_TAG); + ).to.eq(OPENSEA_DOMAIN_TAG); const transaction = await fulfillAction.transactionMethods.transact(); - - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const owners = await Promise.all([ testErc721.ownerOf(nftId), @@ -481,11 +475,10 @@ describeWithFixture( ( await fulfillAction.transactionMethods.buildTransaction() ).data?.slice(-8), - ).to.eq(OPENSEA_TAG); + ).to.eq(OPENSEA_DOMAIN_TAG); const transaction = await fulfillAction.transactionMethods.transact(); - - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const owners = await Promise.all([ testErc721.ownerOf(nftId), @@ -619,11 +612,10 @@ describeWithFixture( (await action.transactionMethods.buildTransaction()).data?.slice( -8, ), - ).to.eq(OPENSEA_TAG); + ).to.eq(OPENSEA_DOMAIN_TAG); const transaction = await action.transactionMethods.transact(); - - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const balances = await Promise.all([ testErc1155.balanceOf(fulfiller.address, nftId), @@ -735,12 +727,11 @@ describeWithFixture( ( await fulfillAction.transactionMethods.buildTransaction() ).data?.slice(-8), - ).to.eq(OPENSEA_TAG); + ).to.eq(OPENSEA_DOMAIN_TAG); const transaction = await fulfillAction.transactionMethods.transact(); - - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const balances = await Promise.all([ testErc1155.balanceOf(fulfiller.address, nftId), @@ -936,12 +927,12 @@ describeWithFixture( await fulfillAction.transactionMethods.buildTransaction() ).data?.slice(-8); expect(dataForBuildTransaction).to.not.eq(emptyDomainTag); - expect(dataForBuildTransaction).to.not.eq(OPENSEA_TAG); + expect(dataForBuildTransaction).to.not.eq(OPENSEA_DOMAIN_TAG); const transaction = await fulfillAction.transactionMethods.transact(); expect(transaction.data.slice(-8)).to.not.eq(emptyDomainTag); - expect(transaction.data.slice(-8)).to.not.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.not.eq(OPENSEA_DOMAIN_TAG); const balances = await Promise.all([ testErc1155.balanceOf(offerer.address, nftId), diff --git a/test/partial-fulfill.spec.ts b/test/partial-fulfill.spec.ts index 390a1d39..9cf4cdd0 100644 --- a/test/partial-fulfill.spec.ts +++ b/test/partial-fulfill.spec.ts @@ -13,6 +13,7 @@ import { verifyBalancesAfterFulfill, } from "./utils/balance"; import { describeWithFixture } from "./utils/setup"; +import { OPENSEA_DOMAIN, OPENSEA_DOMAIN_TAG } from "./utils/constants"; const sinon = require("sinon"); @@ -30,9 +31,6 @@ describeWithFixture( const nftId = "1"; - const OPENSEA_DOMAIN = "opensea.io"; - const OPENSEA_TAG = "360c6ebe"; - beforeEach(async () => { [offerer, zone, fulfiller] = await ethers.getSigners(); multicallProvider = new providers.MulticallProvider(ethers.provider); @@ -117,11 +115,10 @@ describeWithFixture( }); const transaction = await action.transactionMethods.transact(); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const receipt = await transaction.wait(); - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); - const offererErc1155Balance = await testErc1155.balanceOf( offerer.address, nftId, @@ -296,8 +293,7 @@ describeWithFixture( }); const transaction = await fulfillAction.transactionMethods.transact(); - - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const receipt = await transaction.wait(); @@ -424,8 +420,7 @@ describeWithFixture( }); const transaction = await fulfillAction.transactionMethods.transact(); - - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const receipt = await transaction.wait(); @@ -567,8 +562,7 @@ describeWithFixture( }); const transaction = await fulfillAction.transactionMethods.transact(); - - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const receipt = await transaction.wait(); @@ -677,8 +671,7 @@ describeWithFixture( }); const transaction = await action.transactionMethods.transact(); - - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const receipt = await transaction.wait(); @@ -793,8 +786,7 @@ describeWithFixture( }); const transaction = await fulfillAction.transactionMethods.transact(); - - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const receipt = await transaction.wait(); @@ -974,8 +966,7 @@ describeWithFixture( }); const transaction = await fulfillAction.transactionMethods.transact(); - - expect(transaction.data.slice(-8)).to.eq(OPENSEA_TAG); + expect(transaction.data.slice(-8)).to.eq(OPENSEA_DOMAIN_TAG); const receipt = await transaction.wait(); diff --git a/test/utils/constants.ts b/test/utils/constants.ts new file mode 100644 index 00000000..7e43b90a --- /dev/null +++ b/test/utils/constants.ts @@ -0,0 +1,4 @@ +export const OPENSEA_DOMAIN = "opensea.io"; +export const OPENSEA_DOMAIN_TAG = "360c6ebe"; + +export const OVERRIDE_GAS_LIMIT = 10_000_000;