From 64d9f77c4b99bb79b8fc4d3de2700d2abab4f7bf Mon Sep 17 00:00:00 2001 From: zajck Date: Mon, 4 Sep 2023 12:35:42 +0200 Subject: [PATCH 1/4] access new private variables without getters --- test/util/upgrade.js | 67 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/test/util/upgrade.js b/test/util/upgrade.js index 84eba16a8..2abd6ee76 100644 --- a/test/util/upgrade.js +++ b/test/util/upgrade.js @@ -799,7 +799,8 @@ async function getProtocolContractState( getProtocolLookupsPrivateContractState( protocolDiamondAddress, { mockToken, mockTwinTokens }, - { sellers, DRs, agents, buyers, offers, groups, twins } + { sellers, DRs, agents, buyers, offers, groups, twins }, + groupHandler ), ]); @@ -1283,7 +1284,8 @@ async function getProtocolStatusPrivateContractState(protocolDiamondAddress) { async function getProtocolLookupsPrivateContractState( protocolDiamondAddress, { mockToken, mockTwinTokens }, - { sellers, DRs, agents, buyers, offers, groups, twins } + { sellers, DRs, agents, buyers, offers, groups, twins }, + groupHandler ) { /* ProtocolLookups storage layout @@ -1321,8 +1323,11 @@ async function getProtocolLookupsPrivateContractState( #29 [ ] // placeholder for pendingAddressUpdatesBySeller #30 [ ] // placeholder for pendingAuthTokenUpdatesBySeller #31 [ ] // placeholder for pendingAddressUpdatesByDisputeResolver - #32 [X] // placeholder for additionalCollections - #33 [ ] // placeholder for rangeIdByTwin + #32 [ ] // placeholder for rangeIdByTwin + #33 [ ] // placeholder for conditionalCommitsByTokenId + #34 [X] // placeholder for additionalCollections + #35 [ ] // placeholder for sellerSalt + #36 [ ] // placeholder for isUsedSellerSalt */ // starting slot @@ -1520,10 +1525,16 @@ async function getProtocolLookupsPrivateContractState( allowedSellerIndex.push(sellerStatus); } - // offerIdIndexByGroup + // offerIdIndexByGroup, conditionalCommitsByTokenId let offerIdIndexByGroup = []; + let conditionalCommitsByTokenId = []; + decache("../../scripts/domain/Condition.js"); + Condition = require("../../scripts/domain/Condition.js"); + for (const group of groups) { const id = group.id; + + // offerIdIndexByGroup const firstMappingStorageSlot = BigInt( getMappingStoragePosition(protocolLookupsSlotNumber + 28n, id, paddingType.START) ); @@ -1538,6 +1549,26 @@ async function getProtocolLookupsPrivateContractState( ); } offerIdIndexByGroup.push(offerIndices); + + // conditionalCommitsByTokenId + // get condition + let [, , condition] = await groupHandler.getGroup(id); + condition = Condition.fromStruct(condition); + let commitsPerTokenId = []; + for (let tokenId = condition.minTokenId; tokenId <= condition.maxTokenId; tokenId++) { + const firstMappingStorageSlot = BigInt( + getMappingStoragePosition(protocolLookupsSlotNumber + 33n, tokenId, paddingType.START) + ); + + commitsPerTokenId.push( + await getStorageAt( + protocolDiamondAddress, + getMappingStoragePosition(firstMappingStorageSlot, id, paddingType.START) + ) + ); + } + + conditionalCommitsByTokenId.push(commitsPerTokenId); } // pendingAddressUpdatesBySeller, pendingAuthTokenUpdatesBySeller, pendingAddressUpdatesByDisputeResolver @@ -1581,7 +1612,7 @@ async function getProtocolLookupsPrivateContractState( // BosonTypes.DisputeResolver has 8 fields structFields.push(await getStorageAt(protocolDiamondAddress, structStorageSlot + i)); } - structFields[6] = await getStorageAt(protocolDiamondAddress, keccak256(ethersId(structStorageSlot + 6n))); // represents field string metadataUri. Technically this value represents the length of the string, but since it should be 0, we don't do further decoding + structFields[6] = await getStorageAt(protocolDiamondAddress, ethersId(structStorageSlot + 6n)); // represents field string metadataUri. Technically this value represents the length of the string, but since it should be 0, we don't do further decoding pendingAddressUpdatesByDisputeResolver.push(structFields); } @@ -1592,11 +1623,30 @@ async function getProtocolLookupsPrivateContractState( rangeIdByTwin.push( await getStorageAt( protocolDiamondAddress, - getMappingStoragePosition(protocolLookupsSlotNumber + 33n, id, paddingType.START) + getMappingStoragePosition(protocolLookupsSlotNumber + 32n, id, paddingType.START) ) ); } + // sellerSalt, isUsedSellerSalt + let sellerSalt = []; + let isUsedSellerSalt = {}; + for (const seller of sellers) { + // sellerSalt + const { id } = seller; + const salt = await getStorageAt( + protocolDiamondAddress, + getMappingStoragePosition(protocolLookupsSlotNumber + 35n, id, paddingType.START) + ); + sellerSalt.push(salt); + + // isUsedSellerSalt + isUsedSellerSalt[salt] = await getStorageAt( + protocolDiamondAddress, + getMappingStoragePosition(protocolLookupsSlotNumber + 36n, salt, paddingType.START) + ); + } + return { exchangeIdsByOfferState, groupIdByOfferState, @@ -1615,6 +1665,9 @@ async function getProtocolLookupsPrivateContractState( pendingAuthTokenUpdatesBySeller, pendingAddressUpdatesByDisputeResolver, rangeIdByTwin, + conditionalCommitsByTokenId, + sellerSalt, + isUsedSellerSalt, }; } From 2542afeb310bba3f4b2b9fb2f9e1445e921dbce6 Mon Sep 17 00:00:00 2001 From: zajck Date: Wed, 6 Sep 2023 18:53:44 +0200 Subject: [PATCH 2/4] enable all test + on demand twin mint --- test/upgrade/01_generic.js | 1 - test/upgrade/2.2.1-2.3.0.js | 75 +++++++++++++++++++++++-------------- test/util/upgrade.js | 42 ++++++++++++++++----- 3 files changed, 79 insertions(+), 39 deletions(-) diff --git a/test/upgrade/01_generic.js b/test/upgrade/01_generic.js index 1c04d63b0..12edcc636 100644 --- a/test/upgrade/01_generic.js +++ b/test/upgrade/01_generic.js @@ -51,7 +51,6 @@ function getGenericContext( // Create new protocol entities. Existing data should not be affected context("📋 New data after the upgrade do not corrupt the data from before the upgrade", async function () { - this.timeout(1000000); let protocolContractStateAfterUpgradeAndActions; before(async function () { diff --git a/test/upgrade/2.2.1-2.3.0.js b/test/upgrade/2.2.1-2.3.0.js index 1b6a7173a..ffe7a4a83 100644 --- a/test/upgrade/2.2.1-2.3.0.js +++ b/test/upgrade/2.2.1-2.3.0.js @@ -412,7 +412,7 @@ describe("[@skip-on-coverage] After facet upgrade, everything is still operation }); }); - context.skip("Protocol limits", async function () { + context("Protocol limits", async function () { let wallets; let sellers, DRs, sellerWallet; @@ -527,25 +527,31 @@ describe("[@skip-on-coverage] After facet upgrade, everything is still operation }); it("can create a bundle with more offers than maxOffersPerBundle", async function () { - const { maxOffersPerBundle } = protocolLimits; + const { maxOffersPerBundle, maxOffersPerBatch } = protocolLimits; const offerCount = Number(maxOffersPerBundle) + 1; const twinId = await twinHandler.getNextTwinId(); const startingOfferId = await offerHandler.getNextOfferId(); const offerIds = [...Array(offerCount).keys()].map((i) => startingOfferId + BigInt(i)); const { offer, offerDates, offerDurations } = await mockOffer({ refreshModule: true }); - const offers = new Array(offerCount).fill(offer); - const offerDatesList = new Array(offerCount).fill(offerDates); - const offerDurationsList = new Array(offerCount).fill(offerDurations); - const disputeResolverIds = new Array(offerCount).fill(DRs[0].id); - const agentIds = new Array(offerCount).fill("0"); + const maxOffersPerBatchInt = Number(maxOffersPerBatch); + const offers = new Array(maxOffersPerBatchInt).fill(offer); + const offerDatesList = new Array(maxOffersPerBatchInt).fill(offerDates); + const offerDurationsList = new Array(maxOffersPerBatchInt).fill(offerDurations); + const disputeResolverIds = new Array(maxOffersPerBatchInt).fill(DRs[0].id); + const agentIds = new Array(maxOffersPerBatchInt).fill("0"); // Create offers in batch + let offersToCreate = offerCount; + while (offersToCreate > maxOffersPerBatchInt) { + await offerHandler + .connect(sellerWallet) + .createOfferBatch(offers, offerDatesList, offerDurationsList, disputeResolverIds, agentIds); + offersToCreate -= maxOffersPerBatchInt; + } await offerHandler .connect(sellerWallet) - .createOfferBatch(offers, offerDatesList, offerDurationsList, disputeResolverIds, agentIds, { - gasLimit: 100000000, // increase gas limit to avoid out of gas error - }); + .createOfferBatch(offers, offerDatesList, offerDurationsList, disputeResolverIds, agentIds); // At list one twin is needed to create a bundle const [twinContract] = await deployMockTokens(["Foreign721"]); @@ -560,18 +566,26 @@ describe("[@skip-on-coverage] After facet upgrade, everything is still operation }); it("can add more offers to a group than maxOffersPerGroup", async function () { - const { maxOffersPerBundle } = protocolLimits; + const { maxOffersPerBundle, maxOffersPerBatch } = protocolLimits; const offerCount = Number(maxOffersPerBundle) + 1; const startingOfferId = await offerHandler.getNextOfferId(); const offerIds = [...Array(offerCount).keys()].map((i) => startingOfferId + BigInt(i)); const { offer, offerDates, offerDurations } = await mockOffer(); - const offers = new Array(offerCount).fill(offer); - const offerDatesList = new Array(offerCount).fill(offerDates); - const offerDurationsList = new Array(offerCount).fill(offerDurations); - const disputeResolverIds = new Array(offerCount).fill(DRs[0].id); - const agentIds = new Array(offerCount).fill("0"); + const maxOffersPerBatchInt = Number(maxOffersPerBatch); + const offers = new Array(maxOffersPerBatchInt).fill(offer); + const offerDatesList = new Array(maxOffersPerBatchInt).fill(offerDates); + const offerDurationsList = new Array(maxOffersPerBatchInt).fill(offerDurations); + const disputeResolverIds = new Array(maxOffersPerBatchInt).fill(DRs[0].id); + const agentIds = new Array(maxOffersPerBatchInt).fill("0"); // Create offers in batch + let offersToCreate = offerCount; + while (offersToCreate > maxOffersPerBatchInt) { + await offerHandler + .connect(sellerWallet) + .createOfferBatch(offers, offerDatesList, offerDurationsList, disputeResolverIds, agentIds); + offersToCreate -= maxOffersPerBatchInt; + } await offerHandler .connect(sellerWallet) .createOfferBatch(offers, offerDatesList, offerDurationsList, disputeResolverIds, agentIds); @@ -579,10 +593,13 @@ describe("[@skip-on-coverage] After facet upgrade, everything is still operation // Create a group with more offers than maxOffersPerGroup const group = new Group("1", sellers[0].seller.id, offerIds); const { mockConditionalToken } = mockContracts; - const condition = mockCondition({ - tokenAddress: await mockConditionalToken.getAddress(), - maxCommits: "10", - }); + const condition = mockCondition( + { + tokenAddress: await mockConditionalToken.getAddress(), + maxCommits: "10", + }, + { refreshModule: true } + ); await expect(groupHandler.connect(sellerWallet).createGroup(group, condition)).to.not.be.reverted; }); @@ -640,18 +657,20 @@ describe("[@skip-on-coverage] After facet upgrade, everything is still operation const emptyAuthToken = mockAuthToken(); const voucherInitValues = mockVoucherInitValues(); - await Promise.all( - wallets.slice(0, sellerCount).map(async (wallet) => { - const walletAddress = await wallet.getAddress(); - const seller = mockSeller(walletAddress, walletAddress, ZeroAddress, walletAddress, true); - await provider.send("hardhat_setBalance", [walletAddress, toHexString(parseEther("10"))]); - return accountHandler.connect(wallet).createSeller(seller, emptyAuthToken, voucherInitValues); - }) - ); + for (const wallet of wallets.slice(0, sellerCount)) { + const walletAddress = await wallet.getAddress(); + const seller = mockSeller(walletAddress, walletAddress, ZeroAddress, walletAddress, true, "", { + refreshModule: true, + }); + await provider.send("hardhat_setBalance", [walletAddress, toHexString(parseEther("10"))]); + await accountHandler.connect(wallet).createSeller(seller, emptyAuthToken, voucherInitValues); + } const disputeResolverFees = [new DisputeResolverFee(ZeroAddress, "Native", "0")]; const disputeResolver = mockDisputeResolver(rando.address, rando.address, ZeroAddress, rando.address); + console.log("we here"); + await expect( accountHandler.connect(rando).createDisputeResolver(disputeResolver, disputeResolverFees, sellerAllowList) ).to.not.be.reverted; diff --git a/test/util/upgrade.js b/test/util/upgrade.js index 2abd6ee76..90f8981ef 100644 --- a/test/util/upgrade.js +++ b/test/util/upgrade.js @@ -610,15 +610,15 @@ async function populateProtocolContract( // mint tokens to be transferred on redeem // ToDo: for the future, change this to shorten the test - let tokensToMint = BigInt(minSupplyAvailable); - let tokenIdToMint = BigInt(twin721.tokenId); - while (tokensToMint > 500n) { - await mockTwinTokens[j % 2].connect(seller.wallet).mint(tokenIdToMint, 500n); - tokensToMint -= 500n; - tokenIdToMint += 500n; - } - - await mockTwinTokens[j % 2].connect(seller.wallet).mint(tokenIdToMint, tokensToMint); + // let tokensToMint = BigInt(minSupplyAvailable); + // let tokenIdToMint = BigInt(twin721.tokenId); + // while (tokensToMint > 500n) { + // await mockTwinTokens[j % 2].connect(seller.wallet).mint(tokenIdToMint, 500n); + // tokensToMint -= 500n; + // tokenIdToMint += 500n; + // } + + // await mockTwinTokens[j % 2].connect(seller.wallet).mint(tokenIdToMint, tokensToMint); await twinHandler.connect(seller.wallet).createTwin(twin721); twins.push(twin721); @@ -655,7 +655,6 @@ async function populateProtocolContract( twin1155.id = twinId; // mint tokens to be transferred on redeem - await mockTwin1155.connect(seller.wallet).mint(twin1155.tokenId, twin1155.supplyAvailable); await twinHandler.connect(seller.wallet).createTwin(twin1155); twins.push(twin1155); @@ -718,6 +717,29 @@ async function populateProtocolContract( // redeem some vouchers #4 for (const id of [2, 5, 11, 8]) { const exchange = exchanges[id - 1]; + + // If exchange has twins, mint them so the transfer can succeed + // const offer = offers[Number(exchange.offerId) - 1]; + const offer = offers.find((o) => o.offer.id == exchange.offerId); + const seller = sellers.find((s) => s.seller.id == offer.offer.sellerId); + if (twinHandler && Number(seller.id) % 2 == 1) { + const bundle = bundles.find((b) => b.sellerId == seller.id); + const twinsIds = bundle.twinIds; + for (const twinId of twinsIds) { + const [, twin] = await twinHandler.getTwin(twinId); + if (twin.tokenType == TokenType.NonFungibleToken) { + await mockTwinTokens[0] + .connect(seller.wallet) + .mint(BigInt(twin.tokenId) + BigInt(twin.supplyAvailable) - 1n, 1); + await mockTwinTokens[1] + .connect(seller.wallet) + .mint(BigInt(twin.tokenId) + BigInt(twin.supplyAvailable) - 1n, 1); + } else if (twin.tokenType == TokenType.MultiToken) { + await mockTwin1155.connect(seller.wallet).mint(twin.tokenId, twin.supplyAvailable); + } + } + } + await exchangeHandler .connect(buyers[exchange.buyerIndex].wallet) .redeemVoucher(exchange.exchangeId, { gasLimit: 10000000 }); From 3b9820024c2f4c7c7d2cf486f3bd5a1bf4bdaafc Mon Sep 17 00:00:00 2001 From: zajck Date: Thu, 7 Sep 2023 15:52:57 +0200 Subject: [PATCH 3/4] remove comments + console.log --- test/upgrade/2.2.1-2.3.0.js | 2 -- test/util/upgrade.js | 11 ----------- 2 files changed, 13 deletions(-) diff --git a/test/upgrade/2.2.1-2.3.0.js b/test/upgrade/2.2.1-2.3.0.js index ffe7a4a83..0861c91be 100644 --- a/test/upgrade/2.2.1-2.3.0.js +++ b/test/upgrade/2.2.1-2.3.0.js @@ -669,8 +669,6 @@ describe("[@skip-on-coverage] After facet upgrade, everything is still operation const disputeResolverFees = [new DisputeResolverFee(ZeroAddress, "Native", "0")]; const disputeResolver = mockDisputeResolver(rando.address, rando.address, ZeroAddress, rando.address); - console.log("we here"); - await expect( accountHandler.connect(rando).createDisputeResolver(disputeResolver, disputeResolverFees, sellerAllowList) ).to.not.be.reverted; diff --git a/test/util/upgrade.js b/test/util/upgrade.js index 90f8981ef..bf68e06b5 100644 --- a/test/util/upgrade.js +++ b/test/util/upgrade.js @@ -608,17 +608,6 @@ async function populateProtocolContract( twin721.tokenAddress = await mockTwinTokens[j % 2].getAddress(); // oscilate between twins twin721.id = twinId; - // mint tokens to be transferred on redeem - // ToDo: for the future, change this to shorten the test - // let tokensToMint = BigInt(minSupplyAvailable); - // let tokenIdToMint = BigInt(twin721.tokenId); - // while (tokensToMint > 500n) { - // await mockTwinTokens[j % 2].connect(seller.wallet).mint(tokenIdToMint, 500n); - // tokensToMint -= 500n; - // tokenIdToMint += 500n; - // } - - // await mockTwinTokens[j % 2].connect(seller.wallet).mint(tokenIdToMint, tokensToMint); await twinHandler.connect(seller.wallet).createTwin(twin721); twins.push(twin721); From 64acada57616ef1fbf34cec8e327fdf63e0dc54d Mon Sep 17 00:00:00 2001 From: zajck Date: Fri, 8 Sep 2023 08:45:14 +0200 Subject: [PATCH 4/4] update seller salt tests --- test/upgrade/2.2.1-2.3.0.js | 64 +++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/test/upgrade/2.2.1-2.3.0.js b/test/upgrade/2.2.1-2.3.0.js index 0861c91be..256b73b95 100644 --- a/test/upgrade/2.2.1-2.3.0.js +++ b/test/upgrade/2.2.1-2.3.0.js @@ -309,7 +309,7 @@ describe("[@skip-on-coverage] After facet upgrade, everything is still operation ); const equalCustomTypes = { - "t_struct(Range)12648_storage": "t_struct(Range)14241_storage", + "t_struct(Range)12648_storage": "t_struct(Range)14254_storage", }; context( @@ -939,7 +939,6 @@ describe("[@skip-on-coverage] After facet upgrade, everything is still operation wallet: sellerWallet, id: sellerId, voucherInitValues, - seller, voucherContractAddress: expectedDefaultAddress, } = sellers[0]; const externalId = "new-collection"; @@ -948,7 +947,7 @@ describe("[@skip-on-coverage] After facet upgrade, everything is still operation const expectedCollectionAddress = calculateCloneAddress( await accountHandler.getAddress(), beaconProxyAddress, - seller.admin, + sellerWallet.address, voucherInitValues.collectionSalt, voucherInitValues.collectionSalt ); @@ -987,6 +986,65 @@ describe("[@skip-on-coverage] After facet upgrade, everything is still operation }); }); + context("Update seller salt", async function () { + let beaconProxyAddress; + before(async function () { + // Get the beacon proxy address + beaconProxyAddress = await calculateBosonProxyAddress(protocolDiamondAddress); + }); + + it("New seller can update sellers salt", async function () { + const seller = mockSeller(assistant.address, assistant.address, ZeroAddress, assistant.address); + seller.id = await accountHandler.getNextAccountId(); + const emptyAuthToken = mockAuthToken(); + const voucherInitValues = mockVoucherInitValues(); + + await accountHandler.connect(assistant).createSeller(seller, emptyAuthToken, voucherInitValues); + + const externalId = "new-collection"; + voucherInitValues.collectionSalt = encodeBytes32String(externalId); + + const newSellerSalt = encodeBytes32String("new-seller-salt"); + await accountHandler.connect(assistant).updateSellerSalt(seller.id, newSellerSalt); // assistant is also the admin in this test + + const expectedCollectionAddress = calculateCloneAddress( + await accountHandler.getAddress(), + beaconProxyAddress, + seller.admin, + voucherInitValues.collectionSalt, + newSellerSalt + ); + const tx = await accountHandler.connect(assistant).createNewCollection(externalId, voucherInitValues); + + await expect(tx) + .to.emit(accountHandler, "CollectionCreated") + .withArgs(Number(seller.id), 1, expectedCollectionAddress, externalId, assistant.address); + }); + + it("old seller can create update seller salt", async function () { + const { sellers } = preUpgradeEntities; + const { wallet: sellerWallet, id: sellerId, voucherInitValues } = sellers[0]; + + const newSellerSalt = encodeBytes32String("new-seller-salt"); + await accountHandler.connect(sellerWallet).updateSellerSalt(sellerId, newSellerSalt); + + const externalId = "new-collection"; + voucherInitValues.collectionSalt = encodeBytes32String(externalId); + beaconProxyAddress = await calculateBosonProxyAddress(protocolDiamondAddress); + const expectedCollectionAddress = calculateCloneAddress( + await accountHandler.getAddress(), + beaconProxyAddress, + sellerWallet.address, + voucherInitValues.collectionSalt, + newSellerSalt + ); + + await expect(accountHandler.connect(sellerWallet).createNewCollection(externalId, voucherInitValues)) + .to.emit(accountHandler, "CollectionCreated") + .withArgs(sellerId, 1, expectedCollectionAddress, externalId, sellerWallet.address); + }); + }); + it("New sellers uses create2 to calculate voucher address", async function () { const seller = mockSeller(assistant.address, assistant.address, ZeroAddress, assistant.address); seller.id = await accountHandler.getNextAccountId();