From 3b164f30dc19ba741f6b4164aa6a8f6c24010a6f Mon Sep 17 00:00:00 2001 From: Dan Oved Date: Mon, 16 Oct 2023 10:13:33 -0700 Subject: [PATCH 1/4] Premint - show how to decode creator attribution event (#260) * fix preminter tests to use the fork only (since deployment is tricky with libs * Added example in viem for how to decode the emitted CreatorAttribution event * better comments * fix preminter tests * format --- packages/1155-contracts/.env.anvil | 4 +- packages/1155-contracts/package.json | 2 +- .../package/batchPublish.test.ts | 2 +- .../1155-contracts/package/preminter.test.ts | 257 ++++++++++-------- yarn.lock | 21 +- 5 files changed, 167 insertions(+), 119 deletions(-) diff --git a/packages/1155-contracts/.env.anvil b/packages/1155-contracts/.env.anvil index 0c2078aa6..ce8d9a6d7 100644 --- a/packages/1155-contracts/.env.anvil +++ b/packages/1155-contracts/.env.anvil @@ -1,2 +1,2 @@ -FORK_RPC_URL="https://testnet.rpc.zora.co/" -FORK_BLOCK_NUMBER=916572 \ No newline at end of file +FORK_RPC_URL="https://rpc.zora.co/" +FORK_BLOCK_NUMBER=5141442 \ No newline at end of file diff --git a/packages/1155-contracts/package.json b/packages/1155-contracts/package.json index 84b485b58..cf49acf77 100644 --- a/packages/1155-contracts/package.json +++ b/packages/1155-contracts/package.json @@ -58,7 +58,7 @@ "tsup": "^7.2.0", "tsx": "^3.13.0", "typescript": "^5.0.4", - "viem": "^1.6.0", + "viem": "^1.16.2", "vite": "^4.1.4", "vitest": "~0.30.1" }, diff --git a/packages/1155-contracts/package/batchPublish.test.ts b/packages/1155-contracts/package/batchPublish.test.ts index 2820e12c4..c9131e96b 100644 --- a/packages/1155-contracts/package/batchPublish.test.ts +++ b/packages/1155-contracts/package/batchPublish.test.ts @@ -193,7 +193,7 @@ function parseCreate1155Receipt(receipt: TransactionReceipt): { return { tokenId, contractAddress }; } -describe("ZoraCreator1155Preminter", () => { +describe("Zora1155", () => { it( "can batch publish tokens", async () => { diff --git a/packages/1155-contracts/package/preminter.test.ts b/packages/1155-contracts/package/preminter.test.ts index d1ed9cf34..79c94b6d8 100644 --- a/packages/1155-contracts/package/preminter.test.ts +++ b/packages/1155-contracts/package/preminter.test.ts @@ -3,8 +3,13 @@ import { http, createWalletClient, createPublicClient, + keccak256, + Hex, + concat, + recoverAddress, + hashDomain, } from "viem"; -import { foundry, zoraTestnet } from "viem/chains"; +import { foundry, zora } from "viem/chains"; import { describe, it, beforeEach, expect } from "vitest"; import { parseEther } from "viem"; import { @@ -14,12 +19,7 @@ import { zoraCreator1155FactoryImplAddress, zoraCreator1155FactoryImplConfig, } from "./wagmiGenerated"; -import ZoraCreator1155Attribution from "../out/ZoraCreator1155Attribution.sol/ZoraCreator1155Attribution.json"; -import zoraCreator1155PremintExecutor from "../out/ZoraCreator1155PremintExecutorImpl.sol/ZoraCreator1155PremintExecutorImpl.json"; -import zoraCreator1155Impl from "../out/ZoraCreator1155Impl.sol/ZoraCreator1155Impl.json"; -import zoraCreator1155FactoryImpl from "../out/ZoraCreator1155FactoryImpl.sol/ZoraCreator1155FactoryImpl.json"; -import zoraCreatorFixedPriceSaleStrategy from "../out/ZoraCreatorFixedPriceSaleStrategy.sol/ZoraCreatorFixedPriceSaleStrategy.json"; -import protocolRewards from "../out/ProtocolRewards.sol/ProtocolRewards.json"; + import { ContractCreationConfig, PremintConfig, @@ -50,15 +50,9 @@ const publicClient = createPublicClient({ type Address = `0x${string}`; -const zeroAddress: Address = "0x0000000000000000000000000000000000000000"; - // JSON-RPC Account -const [ - deployerAccount, - creatorAccount, - collectorAccount, - mintFeeRecipientAccount, -] = (await walletClient.getAddresses()) as [Address, Address, Address, Address]; +const [deployerAccount, creatorAccount, collectorAccount] = + (await walletClient.getAddresses()) as [Address, Address, Address, Address]; type TestContext = { preminterAddress: `0x${string}`; @@ -68,81 +62,6 @@ type TestContext = { fixedPriceMinterAddress: Address; }; -const deployContractAndGetAddress = async ( - args: Parameters[0] -) => { - const hash = await walletClient.deployContract(args); - return ( - await publicClient.waitForTransactionReceipt({ - hash, - }) - ).contractAddress!; -}; - -export const deployFactoryProxy = async () => { - console.log("deploying protocol rewards"); - const protocolRewardsAddress = await deployContractAndGetAddress({ - abi: protocolRewards.abi, - bytecode: protocolRewards.bytecode.object as `0x${string}`, - account: deployerAccount, - args: [], - }); - - console.log("deploying attribution lib"); - const attributionAddress = await deployContractAndGetAddress({ - abi: ZoraCreator1155Attribution.abi, - bytecode: ZoraCreator1155Attribution.bytecode.object as `0x${string}`, - account: deployerAccount, - }); - - console.log("attribution address is ", attributionAddress); - - console.log("deploying 1155"); - const zora1155Address = await deployContractAndGetAddress({ - abi: zoraCreator1155Impl.abi, - bytecode: zoraCreator1155Impl.bytecode.object as `0x${string}`, - account: deployerAccount, - args: [0n, mintFeeRecipientAccount, zeroAddress, protocolRewardsAddress], - }); - - console.log("deploying fixed priced minter"); - const fixedPriceMinterAddress = await deployContractAndGetAddress({ - abi: zoraCreatorFixedPriceSaleStrategy.abi, - bytecode: zoraCreatorFixedPriceSaleStrategy.bytecode - .object as `0x${string}`, - account: deployerAccount, - }); - - console.log("deploying factory impl"); - const factoryImplAddress = await deployContractAndGetAddress({ - abi: zoraCreator1155FactoryImpl.abi, - bytecode: zoraCreator1155FactoryImpl.bytecode.object as `0x${string}`, - account: deployerAccount, - args: [zora1155Address, zeroAddress, fixedPriceMinterAddress, zeroAddress], - }); - - const factoryProxyAddress = factoryImplAddress!; - - return { factoryProxyAddress, zora1155Address, fixedPriceMinterAddress }; -}; - -export const deployPreminterContract = async (factoryProxyAddress: Address) => { - const deployPreminterHash = await walletClient.deployContract({ - abi: zoraCreator1155PremintExecutor.abi, - bytecode: zoraCreator1155PremintExecutor.bytecode.object as `0x${string}`, - account: deployerAccount, - args: [factoryProxyAddress], - }); - - const receipt = await publicClient.waitForTransactionReceipt({ - hash: deployPreminterHash, - }); - - const preminterAddress = receipt.contractAddress!; - - return { preminterAddress, factoryProxyAddress }; -}; - // create token and contract creation config: const defaultContractConfig = ({ contractAdmin, @@ -176,8 +95,6 @@ const defaultPremintConfig = (fixedPriceMinter: Address): PremintConfig => ({ version: 0, }); -const useForkContract = true; - describe("ZoraCreator1155Preminter", () => { beforeEach(async (ctx) => { // deploy signature minter contract @@ -186,35 +103,22 @@ describe("ZoraCreator1155Preminter", () => { value: parseEther("10"), }); - ctx.forkedChainId = zoraTestnet.id; + ctx.forkedChainId = zora.id; ctx.anvilChainId = foundry.id; - let preminterAddress: Address; - - if (useForkContract) { - const factoryProxyAddress = - zoraCreator1155FactoryImplAddress[ctx.forkedChainId]; - ctx.fixedPriceMinterAddress = await publicClient.readContract({ - abi: zoraCreator1155FactoryImplConfig.abi, - address: zoraCreator1155FactoryImplAddress[ctx.forkedChainId], - functionName: "fixedPriceMinter", - }); - const deployed = await deployPreminterContract(factoryProxyAddress); - preminterAddress = deployed.preminterAddress; - } else { - const factoryProxyAddress = (await deployFactoryProxy()) - .factoryProxyAddress; - const deployed = await deployPreminterContract(factoryProxyAddress); - preminterAddress = deployed.preminterAddress; - } - + ctx.fixedPriceMinterAddress = await publicClient.readContract({ + abi: zoraCreator1155FactoryImplConfig.abi, + address: zoraCreator1155FactoryImplAddress[ctx.forkedChainId], + functionName: "fixedPriceMinter", + }); ctx.zoraMintFee = parseEther("0.000777"); - ctx.preminterAddress = preminterAddress; + ctx.preminterAddress = + zoraCreator1155PremintExecutorAddress[ctx.forkedChainId]; }, 20 * 1000); // skip for now - we need to make this work on zora testnet chain too - it.skip( + it( "can sign on the forked premint contract", async ({ fixedPriceMinterAddress, forkedChainId }) => { const premintConfig = defaultPremintConfig(fixedPriceMinterAddress); @@ -474,4 +378,129 @@ describe("ZoraCreator1155Preminter", () => { // 10 second timeout 40 * 1000 ); + + it("can decode the CreatorAttribution event", async ({ + zoraMintFee, + anvilChainId, + preminterAddress: preminterAddress, + fixedPriceMinterAddress, + }) => { + const premintConfig = defaultPremintConfig(fixedPriceMinterAddress); + const contractConfig = defaultContractConfig({ + contractAdmin: creatorAccount, + }); + + // lets make it a random number to not break the existing tests that expect fresh data + premintConfig.uid = Math.round(Math.random() * 1000000); + + let contractAddress = await publicClient.readContract({ + abi: preminterAbi, + address: preminterAddress, + functionName: "getContractAddress", + args: [contractConfig], + }); + + // have creator sign the message to create the contract + // and the token + const signedMessage = await walletClient.signTypedData({ + ...preminterTypedDataDefinition({ + verifyingContract: contractAddress, + // we need to sign here for the anvil chain, cause thats where it is run on + chainId: anvilChainId, + premintConfig, + }), + account: creatorAccount, + }); + + const quantityToMint = 2n; + + const valueToSend = + (zoraMintFee + premintConfig.tokenConfig.pricePerToken) * quantityToMint; + + const comment = "I love this!"; + + await testClient.setBalance({ + address: collectorAccount, + value: parseEther("10"), + }); + + // now have the collector execute the first signed message; + // it should create the contract, the token, + // and min the quantity to mint tokens to the collector + // the signature along with contract + token creation + // parameters are required to call this function + const mintHash = await walletClient.writeContract({ + abi: preminterAbi, + functionName: "premint", + account: collectorAccount, + address: preminterAddress, + args: [ + contractConfig, + premintConfig, + signedMessage, + quantityToMint, + comment, + ], + value: valueToSend, + }); + + // ensure it succeeded + const receipt = await publicClient.waitForTransactionReceipt({ + hash: mintHash, + }); + + expect(receipt.status).toBe("success"); + + // get the CreatorAttribution event from the erc1155 contract: + const topics = await publicClient.getContractEvents({ + abi: zoraCreator1155ImplABI, + address: contractAddress, + eventName: "CreatorAttribution", + }); + + expect(topics.length).toBe(1); + + const creatorAttributionEvent = topics[0]!; + + const { creator, domainName, signature, structHash, version } = + creatorAttributionEvent.args; + + const chainId = anvilChainId; + + // hash the eip712 domain based on the parameters emitted from the event: + const hashedDomain = hashDomain({ + domain: { + chainId, + name: domainName, + verifyingContract: contractAddress, + version, + }, + types: { + EIP712Domain: [ + { name: "name", type: "string" }, + { name: "version", type: "string" }, + { + name: "chainId", + type: "uint256", + }, + { + name: "verifyingContract", + type: "address", + }, + ], + }, + }); + + // re-build the eip-712 typed data hash, consisting of the hashed domain and the structHash emitted from the event: + const parts: Hex[] = ["0x1901", hashedDomain, structHash!]; + + const hashedTypedData = keccak256(concat(parts)); + + const recoveredSigner = await recoverAddress({ + hash: hashedTypedData, + signature: signature!, + }); + + expect(recoveredSigner).toBe(creator); + }); }); diff --git a/yarn.lock b/yarn.lock index aa89b14c2..81dc7ae64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2468,6 +2468,11 @@ isomorphic-ws@5.0.0: resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== +isows@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.3.tgz#93c1cf0575daf56e7120bab5c8c448b0809d0d74" + integrity sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg== + jackspeak@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" @@ -4090,7 +4095,7 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -viem@^1.0.0, viem@^1.6.0: +viem@^1.0.0: version "1.14.0" resolved "https://registry.yarnpkg.com/viem/-/viem-1.14.0.tgz#e4b305c4cce500e04a66b951c01856d7b04ab403" integrity sha512-4d+4/H3lnbkSAbrpQ15i1nBA7hne06joLFy3L3m0ZpMc+g+Zr3D4nuSTyeiqbHAYs9m2P9Kjap0HlyGkehasgg== @@ -4105,6 +4110,20 @@ viem@^1.0.0, viem@^1.6.0: isomorphic-ws "5.0.0" ws "8.13.0" +viem@^1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/viem/-/viem-1.16.2.tgz#7e9719dd19e7464284b94d9c00f94f86f5858ccd" + integrity sha512-ZQ8kemNvRVwucwcsj4/SjKohK+wZv9Vxx/gXAlwqGMCW7r+niOeECtFku/1L7UPTmPgdmq4kic9R71t6XQDmGw== + dependencies: + "@adraffy/ens-normalize" "1.9.4" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.2" + "@scure/bip32" "1.3.2" + "@scure/bip39" "1.2.1" + abitype "0.9.8" + isows "1.0.3" + ws "8.13.0" + vite-node@0.30.1: version "0.30.1" resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.30.1.tgz#ab0ed1553019c7d81ac95529c57ab8ac9e82347d" From b214a4e02141312d01c824780656830de11fd08b Mon Sep 17 00:00:00 2001 From: Dan Oved Date: Tue, 17 Oct 2023 11:30:47 -0700 Subject: [PATCH 2/4] Speed up testing by turning off optimizer on dev mode (#272) running `yarn dev` in the root runs test in all projects in watch mode without optimizer, and running `yarn dev` in a project folder does it for that project --- packages/1155-contracts/foundry.toml | 18 ++++-------------- packages/1155-contracts/package.json | 2 +- packages/protocol-rewards/foundry.toml | 13 ++++--------- packages/protocol-rewards/package.json | 1 + 4 files changed, 10 insertions(+), 24 deletions(-) diff --git a/packages/1155-contracts/foundry.toml b/packages/1155-contracts/foundry.toml index e69cfc703..f91822c2e 100644 --- a/packages/1155-contracts/foundry.toml +++ b/packages/1155-contracts/foundry.toml @@ -4,25 +4,15 @@ libs = ['_imagine', 'node_modules', 'script'] allow_paths = ["node_modules/@zoralabs/protocol-rewards"] optimizer = true optimizer_runs = 50 -out = 'out' -solc_version = '0.8.17' -src = 'src' via_ir = true - -[profile.optimized] -optimizer = true -optimizer_runs = 50 -out = 'out' -script = 'src' solc_version = '0.8.17' +out = 'out' src = 'src' -test = 'src' -via_ir = true -[profile.fast_compilation] -optimizer_runs = 50 +[profile.dev] +optimizer = false +optimizer_runs = 0 via_ir = false -solc_version = '0.8.17' [rpc_endpoints] goerli = "https://eth-goerli.g.alchemy.com/v2/${ALCHEMY_KEY}" diff --git a/packages/1155-contracts/package.json b/packages/1155-contracts/package.json index cf49acf77..75d5cef34 100644 --- a/packages/1155-contracts/package.json +++ b/packages/1155-contracts/package.json @@ -9,7 +9,7 @@ "type": "module", "scripts": { "test": "forge test", - "dev": "forge test --watch -vvv", + "dev": "FOUNDRY_PROFILE=dev forge test --watch -vvv", "test:fork": "forge test -vvv --match-test fork", "test-gas": "forge test --gas-report", "prettier:check": "prettier --check 'src/**/*.sol' 'test/**/*.sol' 'package/**/*.ts' 'wagmi.config.ts'", diff --git a/packages/protocol-rewards/foundry.toml b/packages/protocol-rewards/foundry.toml index 62d40400e..821d1fb21 100644 --- a/packages/protocol-rewards/foundry.toml +++ b/packages/protocol-rewards/foundry.toml @@ -10,15 +10,10 @@ script = 'script' src = 'src' via_ir = true -[profile.optimized] -auto_detect_solc = true -optimizer = true -optimizer_runs = 500000 -out = 'out' -script = 'src' -src = 'src' -test = 'src' -via_ir = true +[profile.dev] +optimizer = false +optimizer_runs = 0 +via_ir = false [fmt] bracket_spacing = true diff --git a/packages/protocol-rewards/package.json b/packages/protocol-rewards/package.json index 77d1279aa..f377b19dd 100644 --- a/packages/protocol-rewards/package.json +++ b/packages/protocol-rewards/package.json @@ -10,6 +10,7 @@ "scripts": { "build": "forge build", "build:sizes": "forge build --sizes", + "dev": "FOUNDRY_PROFILE=dev forge test --watch -vvv", "test": "forge test", "build:contracts": "forge build", "prettier:check": "prettier --check 'src/**/*.sol' 'test/**/*.sol' 'script/**/*.sol'", From 9495c34cfb1c09c88266545c0c9c37223fc4509b Mon Sep 17 00:00:00 2001 From: Rohan Kulkarni Date: Wed, 18 Oct 2023 13:40:40 -0400 Subject: [PATCH 3/4] refactor: deprecate supply royalty (#267) before margin: 0.117 kb ~available margin: 0.839 kb~ available margin: 0.576 kb --- .changeset/great-camels-impress.md | 5 + .../src/nft/ZoraCreator1155Impl.sol | 50 +--- .../src/royalties/CreatorRoyaltiesControl.sol | 4 +- .../test/factory/ZoraCreator1155Factory.t.sol | 24 +- .../test/fixtures/Zora1155PremintFixtures.sol | 2 +- .../test/nft/ZoraCreator1155.t.sol | 229 ++---------------- .../royalties/CreatorRoyaltiesControl.t.sol | 93 ------- 7 files changed, 53 insertions(+), 354 deletions(-) create mode 100644 .changeset/great-camels-impress.md delete mode 100644 packages/1155-contracts/test/royalties/CreatorRoyaltiesControl.t.sol diff --git a/.changeset/great-camels-impress.md b/.changeset/great-camels-impress.md new file mode 100644 index 000000000..9672b1f6f --- /dev/null +++ b/.changeset/great-camels-impress.md @@ -0,0 +1,5 @@ +--- +"@zoralabs/zora-1155-contracts": minor +--- + +Supply royalties are no longer supported diff --git a/packages/1155-contracts/src/nft/ZoraCreator1155Impl.sol b/packages/1155-contracts/src/nft/ZoraCreator1155Impl.sol index b2d83005b..d87c22557 100644 --- a/packages/1155-contracts/src/nft/ZoraCreator1155Impl.sol +++ b/packages/1155-contracts/src/nft/ZoraCreator1155Impl.sol @@ -388,6 +388,7 @@ contract ZoraCreator1155Impl is _requireAdminOrRole(msg.sender, tokenIds[i], PERMISSION_BIT_MINTER); } } + _mintBatch(recipient, tokenIds, quantities, data); } @@ -553,61 +554,36 @@ contract ZoraCreator1155Impl is return super.supportsInterface(interfaceId) || interfaceId == type(IZoraCreator1155).interfaceId || ERC1155Upgradeable.supportsInterface(interfaceId); } - function _handleSupplyRoyalty(uint256 tokenId, uint256 mintAmount, bytes memory data) internal returns (uint256 totalRoyaltyMints) { - uint256 royaltyMintSchedule = royalties[tokenId].royaltyMintSchedule; - if (royaltyMintSchedule == 0) { - royaltyMintSchedule = royalties[CONTRACT_BASE_ID].royaltyMintSchedule; - } - if (royaltyMintSchedule == 0) { - // If we still have no schedule, return 0 supply royalty. - return 0; - } - uint256 maxSupply = tokens[tokenId].maxSupply; - uint256 totalMinted = tokens[tokenId].totalMinted; - - totalRoyaltyMints = (mintAmount + (totalMinted % royaltyMintSchedule)) / (royaltyMintSchedule - 1); - totalRoyaltyMints = MathUpgradeable.min(totalRoyaltyMints, maxSupply - (mintAmount + totalMinted)); - if (totalRoyaltyMints > 0) { - address royaltyRecipient = royalties[tokenId].royaltyRecipient; - if (royaltyRecipient == address(0)) { - royaltyRecipient = royalties[CONTRACT_BASE_ID].royaltyRecipient; - } - // If we have no recipient set, return 0 supply royalty. - if (royaltyRecipient == address(0)) { - return 0; - } - super._mint(royaltyRecipient, tokenId, totalRoyaltyMints, data); - } - } - /// Generic 1155 function overrides /// - /// @notice Mint function that 1) checks quantity and 2) handles supply royalty 3) keeps track of allowed tokens + /// @notice Mint function that 1) checks quantity 2) keeps track of allowed tokens /// @param to to mint to /// @param id token id to mint /// @param amount of tokens to mint /// @param data as specified by 1155 standard function _mint(address to, uint256 id, uint256 amount, bytes memory data) internal virtual override { - uint256 supplyRoyaltyMints = _handleSupplyRoyalty(id, amount, data); - _requireCanMintQuantity(id, amount + supplyRoyaltyMints); + _requireCanMintQuantity(id, amount); + + tokens[id].totalMinted += amount; super._mint(to, id, amount, data); - tokens[id].totalMinted += amount + supplyRoyaltyMints; } - /// @notice Mint batch function that 1) checks quantity and 2) handles supply royalty 3) keeps track of allowed tokens + /// @notice Mint batch function that 1) checks quantity and 2) keeps track of allowed tokens /// @param to to mint to /// @param ids token ids to mint /// @param amounts of tokens to mint /// @param data as specified by 1155 standard function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual override { - super._mintBatch(to, ids, amounts, data); + uint256 numTokens = ids.length; - for (uint256 i = 0; i < ids.length; ++i) { - uint256 supplyRoyaltyMints = _handleSupplyRoyalty(ids[i], amounts[i], data); - _requireCanMintQuantity(ids[i], amounts[i] + supplyRoyaltyMints); - tokens[ids[i]].totalMinted += amounts[i] + supplyRoyaltyMints; + for (uint256 i; i < numTokens; ++i) { + _requireCanMintQuantity(ids[i], amounts[i]); + + tokens[ids[i]].totalMinted += amounts[i]; } + + super._mintBatch(to, ids, amounts, data); } /// @notice Burns a batch of tokens diff --git a/packages/1155-contracts/src/royalties/CreatorRoyaltiesControl.sol b/packages/1155-contracts/src/royalties/CreatorRoyaltiesControl.sol index f41029551..fd1717e17 100644 --- a/packages/1155-contracts/src/royalties/CreatorRoyaltiesControl.sol +++ b/packages/1155-contracts/src/royalties/CreatorRoyaltiesControl.sol @@ -33,8 +33,8 @@ abstract contract CreatorRoyaltiesControl is CreatorRoyaltiesStorageV1, SharedBa } function _updateRoyalties(uint256 tokenId, RoyaltyConfiguration memory configuration) internal { - // Don't allow 100% supply royalties - if (configuration.royaltyMintSchedule == 1) { + // Deprecate supply royalty support + if (configuration.royaltyMintSchedule != 0) { revert InvalidMintSchedule(); } // Don't allow setting royalties to burn address diff --git a/packages/1155-contracts/test/factory/ZoraCreator1155Factory.t.sol b/packages/1155-contracts/test/factory/ZoraCreator1155Factory.t.sol index 72367b789..89d445102 100644 --- a/packages/1155-contracts/test/factory/ZoraCreator1155Factory.t.sol +++ b/packages/1155-contracts/test/factory/ZoraCreator1155Factory.t.sol @@ -77,19 +77,11 @@ contract ZoraCreator1155FactoryTest is Test { assertEq(address(minters[2]), address(3)); } - function test_createContract( - string memory contractURI, - string memory name, - uint32 royaltyBPS, - uint32 royaltyMintSchedule, - address royaltyRecipient, - address payable admin - ) external { + function test_createContract(string memory contractURI, string memory name, uint32 royaltyBPS, address royaltyRecipient, address payable admin) external { // If the factory is the admin, the admin flag is cleared // during multicall breaking a further test assumption. // Additionally, this case makes no sense from a user perspective. vm.assume(admin != payable(address(factory))); - vm.assume(royaltyMintSchedule != 1); // Assume royalty recipient is not 0 vm.assume(royaltyRecipient != payable(address(0))); bytes[] memory initSetup = new bytes[](1); @@ -97,18 +89,14 @@ contract ZoraCreator1155FactoryTest is Test { address deployedAddress = factory.createContract( contractURI, name, - ICreatorRoyaltiesControl.RoyaltyConfiguration({ - royaltyBPS: royaltyBPS, - royaltyRecipient: royaltyRecipient, - royaltyMintSchedule: royaltyMintSchedule - }), + ICreatorRoyaltiesControl.RoyaltyConfiguration({royaltyBPS: royaltyBPS, royaltyRecipient: royaltyRecipient, royaltyMintSchedule: 0}), admin, initSetup ); ZoraCreator1155Impl target = ZoraCreator1155Impl(deployedAddress); ICreatorRoyaltiesControl.RoyaltyConfiguration memory config = target.getRoyalties(0); - assertEq(config.royaltyMintSchedule, royaltyMintSchedule); + assertEq(config.royaltyMintSchedule, 0); assertEq(config.royaltyBPS, royaltyBPS); assertEq(config.royaltyRecipient, royaltyRecipient); assertEq(target.permissions(0, admin), target.PERMISSION_BIT_ADMIN()); @@ -170,7 +158,7 @@ contract ZoraCreator1155FactoryTest is Test { ICreatorRoyaltiesControl.RoyaltyConfiguration memory royaltyConfig = ICreatorRoyaltiesControl.RoyaltyConfiguration({ royaltyBPS: 10, royaltyRecipient: vm.addr(5), - royaltyMintSchedule: 100 + royaltyMintSchedule: 0 }); bytes[] memory initSetup = new bytes[](1); initSetup[0] = abi.encodeWithSelector(IZoraCreator1155.setupNewToken.selector, "ipfs://asdfadsf", 100); @@ -220,7 +208,7 @@ contract ZoraCreator1155FactoryTest is Test { ICreatorRoyaltiesControl.RoyaltyConfiguration memory royaltyConfig = ICreatorRoyaltiesControl.RoyaltyConfiguration({ royaltyBPS: 10, royaltyRecipient: vm.addr(5), - royaltyMintSchedule: 100 + royaltyMintSchedule: 0 }); bytes[] memory initSetup = new bytes[](1); initSetup[0] = abi.encodeWithSelector(IZoraCreator1155.setupNewToken.selector, "ipfs://asdfadsf", 100); @@ -241,7 +229,7 @@ contract ZoraCreator1155FactoryTest is Test { ICreatorRoyaltiesControl.RoyaltyConfiguration memory royaltyConfig = ICreatorRoyaltiesControl.RoyaltyConfiguration({ royaltyBPS: 10, royaltyRecipient: vm.addr(5), - royaltyMintSchedule: 100 + royaltyMintSchedule: 0 }); bytes[] memory initSetup = new bytes[](1); initSetup[0] = abi.encodeWithSelector(IZoraCreator1155.setupNewToken.selector, "ipfs://asdfadsf", 100); diff --git a/packages/1155-contracts/test/fixtures/Zora1155PremintFixtures.sol b/packages/1155-contracts/test/fixtures/Zora1155PremintFixtures.sol index 71a42bd9c..0e01c8fd2 100644 --- a/packages/1155-contracts/test/fixtures/Zora1155PremintFixtures.sol +++ b/packages/1155-contracts/test/fixtures/Zora1155PremintFixtures.sol @@ -18,7 +18,7 @@ library Zora1155PremintFixtures { } function defaultRoyaltyConfig(address royaltyRecipient) internal pure returns (ICreatorRoyaltiesControl.RoyaltyConfiguration memory) { - return ICreatorRoyaltiesControl.RoyaltyConfiguration({royaltyBPS: 10, royaltyRecipient: royaltyRecipient, royaltyMintSchedule: 100}); + return ICreatorRoyaltiesControl.RoyaltyConfiguration({royaltyBPS: 10, royaltyRecipient: royaltyRecipient, royaltyMintSchedule: 0}); } function makeDefaultTokenCreationConfig(IMinter1155 fixedPriceMinter, address royaltyRecipient) internal pure returns (TokenCreationConfig memory) { diff --git a/packages/1155-contracts/test/nft/ZoraCreator1155.t.sol b/packages/1155-contracts/test/nft/ZoraCreator1155.t.sol index eac8816c4..4370496dc 100644 --- a/packages/1155-contracts/test/nft/ZoraCreator1155.t.sol +++ b/packages/1155-contracts/test/nft/ZoraCreator1155.t.sol @@ -112,14 +112,8 @@ contract ZoraCreator1155Test is Test { target.initialize("test", "test", ICreatorRoyaltiesControl.RoyaltyConfiguration(0, 0, address(0)), admin, _emptyInitData()); } - function init(uint32 royaltySchedule, uint32 royaltyBps, address royaltyRecipient) internal { - target.initialize( - "test", - "test", - ICreatorRoyaltiesControl.RoyaltyConfiguration(royaltySchedule, royaltyBps, royaltyRecipient), - admin, - _emptyInitData() - ); + function init(uint32 royaltyBps, address royaltyRecipient) internal { + target.initialize("test", "test", ICreatorRoyaltiesControl.RoyaltyConfiguration(0, royaltyBps, royaltyRecipient), admin, _emptyInitData()); } function test_packageJsonVersion() public { @@ -127,38 +121,21 @@ contract ZoraCreator1155Test is Test { assertEq(package.readString(".version"), target.contractVersion()); } - function test_initialize(uint32 royaltySchedule, uint32 royaltyBPS, address royaltyRecipient, address payable defaultAdmin) external { - vm.assume(royaltySchedule != 1); - vm.assume(royaltyRecipient != address(0) && royaltySchedule != 0 && royaltyBPS != 0); - ICreatorRoyaltiesControl.RoyaltyConfiguration memory config = ICreatorRoyaltiesControl.RoyaltyConfiguration( - royaltySchedule, - royaltyBPS, - royaltyRecipient - ); + function test_initialize(uint32 royaltyBPS, address royaltyRecipient, address payable defaultAdmin) external { + vm.assume(royaltyRecipient != address(0) && royaltyBPS != 0); + ICreatorRoyaltiesControl.RoyaltyConfiguration memory config = ICreatorRoyaltiesControl.RoyaltyConfiguration(0, royaltyBPS, royaltyRecipient); target.initialize("contract name", "test", config, defaultAdmin, _emptyInitData()); assertEq(target.contractURI(), "test"); assertEq(target.name(), "contract name"); - (uint32 fetchedSchedule, uint256 fetchedBps, address fetchedRecipient) = target.royalties(0); - assertEq(fetchedSchedule, royaltySchedule); + (, uint256 fetchedBps, address fetchedRecipient) = target.royalties(0); assertEq(fetchedBps, royaltyBPS); assertEq(fetchedRecipient, royaltyRecipient); } - function test_initialize_withSetupActions( - uint32 royaltySchedule, - uint32 royaltyBPS, - address royaltyRecipient, - address payable defaultAdmin, - uint256 maxSupply - ) external { - vm.assume(royaltySchedule != 1); - vm.assume(royaltyRecipient != address(0) && royaltySchedule != 0 && royaltyBPS != 0); - ICreatorRoyaltiesControl.RoyaltyConfiguration memory config = ICreatorRoyaltiesControl.RoyaltyConfiguration( - royaltySchedule, - royaltyBPS, - royaltyRecipient - ); + function test_initialize_withSetupActions(uint32 royaltyBPS, address royaltyRecipient, address payable defaultAdmin, uint256 maxSupply) external { + vm.assume(royaltyRecipient != address(0) && royaltyBPS != 0); + ICreatorRoyaltiesControl.RoyaltyConfiguration memory config = ICreatorRoyaltiesControl.RoyaltyConfiguration(0, royaltyBPS, royaltyRecipient); bytes[] memory setupActions = new bytes[](1); setupActions[0] = abi.encodeWithSelector(IZoraCreator1155.setupNewToken.selector, "test", maxSupply); target.initialize("", "test", config, defaultAdmin, setupActions); @@ -167,19 +144,9 @@ contract ZoraCreator1155Test is Test { assertEq(tokenData.maxSupply, maxSupply); } - function test_initialize_revertAlreadyInitialized( - uint32 royaltySchedule, - uint32 royaltyBPS, - address royaltyRecipient, - address payable defaultAdmin - ) external { - vm.assume(royaltySchedule != 1); - vm.assume(royaltyRecipient != address(0) && royaltySchedule != 0 && royaltyBPS != 0); - ICreatorRoyaltiesControl.RoyaltyConfiguration memory config = ICreatorRoyaltiesControl.RoyaltyConfiguration( - royaltySchedule, - royaltyBPS, - royaltyRecipient - ); + function test_initialize_revertAlreadyInitialized(uint32 royaltyBPS, address royaltyRecipient, address payable defaultAdmin) external { + vm.assume(royaltyRecipient != address(0) && royaltyBPS != 0); + ICreatorRoyaltiesControl.RoyaltyConfiguration memory config = ICreatorRoyaltiesControl.RoyaltyConfiguration(0, royaltyBPS, royaltyRecipient); target.initialize("test", "test", config, defaultAdmin, _emptyInitData()); vm.expectRevert(); @@ -408,37 +375,35 @@ contract ZoraCreator1155Test is Test { function test_adminMintWithScheduleSmall() external { uint256 quantity = 100; address royaltyRecipient = address(0x3334); - // every 10 royalty 100/10 = 10 tokens minted - init(10, 0, royaltyRecipient); + + init(0, royaltyRecipient); vm.prank(admin); uint256 tokenId = target.setupNewToken("test", quantity); vm.prank(admin); - target.adminMint(recipient, tokenId, 90, ""); + target.adminMint(recipient, tokenId, quantity, ""); IZoraCreator1155TypesV1.TokenData memory tokenData = target.getTokenInfo(tokenId); - assertEq(tokenData.totalMinted, 100); - assertEq(target.balanceOf(recipient, tokenId), (quantity * 9) / 10); - assertEq(target.balanceOf(royaltyRecipient, tokenId), (quantity * 1) / 10); + assertEq(tokenData.totalMinted, quantity); + assertEq(target.balanceOf(recipient, tokenId), quantity); } function test_adminMintWithSchedule() external { uint256 quantity = 1000; address royaltyRecipient = address(0x3334); - // every 10 tokens, mint 1 to royalty 1000/10 = 100 tokens minted to royalty recipient - init(10, 0, royaltyRecipient); + + init(0, royaltyRecipient); vm.prank(admin); uint256 tokenId = target.setupNewToken("test", 1000); vm.prank(admin); - target.adminMint(recipient, tokenId, (quantity * 9) / 10, ""); + target.adminMint(recipient, tokenId, quantity, ""); IZoraCreator1155TypesV1.TokenData memory tokenData = target.getTokenInfo(tokenId); assertEq(tokenData.totalMinted, 1000); - assertEq(target.balanceOf(recipient, tokenId), (quantity * 9) / 10); - assertEq(target.balanceOf(royaltyRecipient, tokenId), (quantity * 1) / 10); + assertEq(target.balanceOf(recipient, tokenId), quantity); } function test_adminMint_revertOnlyAdminOrRole() external { @@ -574,8 +539,8 @@ contract ZoraCreator1155Test is Test { vm.assume(quantity2 < 900); address royaltyRecipient = address(0x3334); - // every 10th token is a token for the royalty recipient - init(10, 0, royaltyRecipient); + + init(0, royaltyRecipient); vm.prank(admin); uint256 tokenId1 = target.setupNewToken("test", 1000); @@ -596,12 +561,10 @@ contract ZoraCreator1155Test is Test { IZoraCreator1155TypesV1.TokenData memory tokenData1 = target.getTokenInfo(tokenId1); IZoraCreator1155TypesV1.TokenData memory tokenData2 = target.getTokenInfo(tokenId2); - assertEq(tokenData1.totalMinted, quantity1 + (quantity1 / 9)); - assertEq(tokenData2.totalMinted, quantity2 + (quantity2 / 9)); + assertEq(tokenData1.totalMinted, quantity1); + assertEq(tokenData2.totalMinted, quantity2); assertEq(target.balanceOf(recipient, tokenId1), quantity1); assertEq(target.balanceOf(recipient, tokenId2), quantity2); - assertEq(target.balanceOf(royaltyRecipient, tokenId1), quantity1 / 9); - assertEq(target.balanceOf(royaltyRecipient, tokenId2), quantity2 / 9); } function test_adminMintWithInvalidScheduleSkipsSchedule() external { @@ -611,8 +574,7 @@ contract ZoraCreator1155Test is Test { } function test_adminMintWithEmptyScheduleSkipsSchedule() external { - // every 0th token is sent so no tokens - init(0, 0, address(0x99a)); + init(0, address(0x99a)); vm.prank(admin); uint256 tokenId1 = target.setupNewToken("test", 1000); @@ -1447,143 +1409,4 @@ contract ZoraCreator1155Test is Test { vm.prank(admin); target.adminMint(address(0x1234), tokenId, 1, ""); } - - function test_SupplyRoyaltyScheduleCannotBeOne() external { - init(); - - vm.prank(admin); - uint256 tokenId = target.setupNewToken("test", 100); - - SimpleMinter minter = new SimpleMinter(); - vm.prank(admin); - target.addPermission(tokenId, address(minter), adminRole); - - vm.prank(admin); - vm.expectRevert(ICreatorRoyaltiesControl.InvalidMintSchedule.selector); - target.updateRoyaltiesForToken( - tokenId, - ICreatorRoyaltiesControl.RoyaltyConfiguration({royaltyMintSchedule: 1, royaltyBPS: 0, royaltyRecipient: admin}) - ); - } - - function test_SupplyRoyaltyMint(uint32 royaltyMintSchedule, uint32 editionSize, uint256 mintQuantity) external { - vm.assume(royaltyMintSchedule > 1 && royaltyMintSchedule <= editionSize && editionSize <= 100000 && mintQuantity > 0 && mintQuantity <= editionSize); - uint256 totalRoyaltyMintsForSale = editionSize / royaltyMintSchedule; - vm.assume(mintQuantity <= editionSize - totalRoyaltyMintsForSale); - - init(); - - vm.prank(admin); - uint256 tokenId = target.setupNewToken("test", editionSize); - - SimpleMinter minter = new SimpleMinter(); - vm.prank(admin); - target.addPermission(tokenId, address(minter), adminRole); - - vm.startPrank(admin); - target.updateRoyaltiesForToken( - tokenId, - ICreatorRoyaltiesControl.RoyaltyConfiguration({royaltyMintSchedule: royaltyMintSchedule, royaltyBPS: 0, royaltyRecipient: admin}) - ); - - uint256 totalReward = target.computeTotalReward(mintQuantity); - vm.deal(admin, totalReward); - - target.mint{value: totalReward}(minter, tokenId, mintQuantity, abi.encode(recipient)); - - uint256 totalRoyaltyMintsForPurchase = mintQuantity / (royaltyMintSchedule - 1); - totalRoyaltyMintsForPurchase = MathUpgradeable.min(totalRoyaltyMintsForPurchase, editionSize - mintQuantity); - - assertEq(target.balanceOf(recipient, tokenId), mintQuantity); - assertEq(target.balanceOf(admin, tokenId), totalRoyaltyMintsForPurchase); - - vm.stopPrank(); - } - - function test_SupplyRoyaltyMintCleanNumbers() external { - init(); - - vm.prank(admin); - uint256 tokenId = target.setupNewToken("test", 100); - - SimpleMinter minter = new SimpleMinter(); - vm.prank(admin); - target.addPermission(tokenId, address(minter), adminRole); - - uint256 totalReward = target.computeTotalReward(80); - vm.deal(admin, totalReward); - - vm.startPrank(admin); - target.updateRoyaltiesForToken( - tokenId, - ICreatorRoyaltiesControl.RoyaltyConfiguration({royaltyMintSchedule: 5, royaltyBPS: 0, royaltyRecipient: admin}) - ); - target.mint{value: totalReward}(minter, tokenId, 80, abi.encode(recipient)); - - assertEq(target.balanceOf(recipient, tokenId), 80); - assertEq(target.balanceOf(admin, tokenId), 20); - - vm.stopPrank(); - } - - function test_SupplyRoyaltyMintEdgeCaseNumbers() external { - init(); - - vm.prank(admin); - uint256 tokenId = target.setupNewToken("test", 137); - - SimpleMinter minter = new SimpleMinter(); - vm.prank(admin); - target.addPermission(tokenId, address(minter), adminRole); - - uint256 totalReward = target.computeTotalReward(92); - vm.deal(admin, totalReward); - - vm.startPrank(admin); - target.updateRoyaltiesForToken( - tokenId, - ICreatorRoyaltiesControl.RoyaltyConfiguration({royaltyMintSchedule: 3, royaltyBPS: 0, royaltyRecipient: admin}) - ); - - target.mint{value: totalReward}(minter, tokenId, 92, abi.encode(recipient)); - - assertEq(target.balanceOf(recipient, tokenId), 92); - assertEq(target.balanceOf(admin, tokenId), 45); - - vm.stopPrank(); - } - - function test_SupplyRoyaltyMintEdgeCaseNumbersOpenEdition() external { - init(); - - vm.prank(admin); - uint256 tokenId = target.setupNewToken("test", type(uint256).max); - - SimpleMinter minter = new SimpleMinter(); - vm.prank(admin); - target.addPermission(tokenId, address(minter), adminRole); - - uint256 totalReward = target.computeTotalReward(92); - vm.deal(admin, totalReward); - - vm.startPrank(admin); - target.updateRoyaltiesForToken( - tokenId, - ICreatorRoyaltiesControl.RoyaltyConfiguration({royaltyMintSchedule: 3, royaltyBPS: 0, royaltyRecipient: admin}) - ); - - target.mint{value: totalReward}(minter, tokenId, 92, abi.encode(recipient)); - - assertEq(target.balanceOf(recipient, tokenId), 92); - assertEq(target.balanceOf(admin, tokenId), 46); - - vm.deal(admin, 0.000777 ether); - - target.mint{value: 0.000777 ether}(minter, tokenId, 1, abi.encode(recipient)); - - assertEq(target.balanceOf(recipient, tokenId), 93); - assertEq(target.balanceOf(admin, tokenId), 46); - - vm.stopPrank(); - } } diff --git a/packages/1155-contracts/test/royalties/CreatorRoyaltiesControl.t.sol b/packages/1155-contracts/test/royalties/CreatorRoyaltiesControl.t.sol deleted file mode 100644 index 162a7afaa..000000000 --- a/packages/1155-contracts/test/royalties/CreatorRoyaltiesControl.t.sol +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.17; - -import "forge-std/Test.sol"; -import {ProtocolRewards} from "@zoralabs/protocol-rewards/src/ProtocolRewards.sol"; -import {ZoraCreator1155Impl} from "../../src/nft/ZoraCreator1155Impl.sol"; -import {Zora1155} from "../../src/proxies/Zora1155.sol"; -import {IZoraCreator1155Errors} from "../../src/interfaces/IZoraCreator1155Errors.sol"; -import {IZoraCreator1155TypesV1} from "../../src/nft/IZoraCreator1155TypesV1.sol"; -import {ICreatorRoyaltiesControl} from "../../src/interfaces/ICreatorRoyaltiesControl.sol"; -import {IZoraCreator1155Factory} from "../../src/interfaces/IZoraCreator1155Factory.sol"; -import {IMintFeeManager} from "../../src/interfaces/IMintFeeManager.sol"; -import {SimpleMinter} from "../mock/SimpleMinter.sol"; - -contract CreatorRoyaltiesControlTest is Test { - ProtocolRewards internal protocolRewards; - ZoraCreator1155Impl internal zoraCreator1155Impl; - ZoraCreator1155Impl internal target; - address payable internal admin; - address internal recipient; - uint256 internal adminRole; - uint256 internal minterRole; - uint256 internal fundsManagerRole; - - function setUp() external { - protocolRewards = new ProtocolRewards(); - admin = payable(vm.addr(0x1)); - recipient = vm.addr(0x2); - } - - function _emptyInitData() internal pure returns (bytes[] memory response) { - response = new bytes[](0); - } - - /// @notice Returns the supply royalty information for a given token. - /// @param tokenId The token ID to get the royalty information for. - /// @param mintAmount The amount of tokens being minted. - /// @param totalSupply The total supply of the token, - function supplyRoyaltyInfo(uint256 tokenId, uint256 totalSupply, uint256 mintAmount) public view returns (address receiver, uint256 royaltyAmount) { - ICreatorRoyaltiesControl.RoyaltyConfiguration memory config = target.getRoyalties(tokenId); - if (config.royaltyMintSchedule == 0) { - return (config.royaltyRecipient, 0); - } - uint256 totalRoyaltyMints = (mintAmount + (totalSupply % config.royaltyMintSchedule)) / (config.royaltyMintSchedule - 1); - return (config.royaltyRecipient, totalRoyaltyMints); - } - - function test_GetsRoyaltiesInfoGlobalDefault() external { - address royaltyPayout = address(0x999); - - zoraCreator1155Impl = new ZoraCreator1155Impl(recipient, address(0), address(protocolRewards)); - target = ZoraCreator1155Impl(address(new Zora1155(address(zoraCreator1155Impl)))); - adminRole = target.PERMISSION_BIT_ADMIN(); - target.initialize("", "test", ICreatorRoyaltiesControl.RoyaltyConfiguration(10, 10, address(royaltyPayout)), admin, _emptyInitData()); - - vm.prank(admin); - uint256 tokenId = target.setupNewToken("test", 100); - - (address royaltyRecipient, uint256 amount) = target.royaltyInfo(tokenId, 1 ether); - (, uint256 supplyAmount) = supplyRoyaltyInfo(tokenId, 0, 100); - assertEq(amount, 0.001 ether); - assertEq(royaltyRecipient, royaltyPayout); - assertEq(supplyAmount, 11); - } - - function test_GetsRoyaltiesInfoSpecificToken() external { - address royaltyPayout = address(0x999); - zoraCreator1155Impl = new ZoraCreator1155Impl(recipient, address(0), address(protocolRewards)); - target = ZoraCreator1155Impl(address(new Zora1155(address(zoraCreator1155Impl)))); - adminRole = target.PERMISSION_BIT_ADMIN(); - target.initialize("", "test", ICreatorRoyaltiesControl.RoyaltyConfiguration(100, 10, address(royaltyPayout)), admin, _emptyInitData()); - - vm.startPrank(admin); - uint256 tokenIdFirst = target.setupNewToken("test", 100); - uint256 tokenIdSecond = target.setupNewToken("test", 100); - - target.updateRoyaltiesForToken(tokenIdSecond, ICreatorRoyaltiesControl.RoyaltyConfiguration(10, 100, address(0x992))); - - vm.stopPrank(); - - (address royaltyRecipient, uint256 amount) = target.royaltyInfo(tokenIdFirst, 1 ether); - (, uint256 supplyAmount) = supplyRoyaltyInfo(tokenIdFirst, 0, 100); - assertEq(amount, 0.001 ether); - assertEq(supplyAmount, 1); - assertEq(royaltyRecipient, royaltyPayout); - - (address royaltyRecipientSecond, uint256 amountSecond) = target.royaltyInfo(tokenIdSecond, 1 ether); - (, uint256 supplyAmountSecond) = supplyRoyaltyInfo(tokenIdSecond, 0, 100); - assertEq(amountSecond, 0.01 ether); - assertEq(supplyAmountSecond, 11); - assertEq(royaltyRecipientSecond, address(0x992)); - } -} From 7276360d7b73ed6c12c8420bdd9ace7d294b06c8 Mon Sep 17 00:00:00 2001 From: Dan Oved Date: Wed, 18 Oct 2023 10:42:26 -0700 Subject: [PATCH 4/4] Skip royalty mint schedule check (#274) We dont need to check royalty mint schedule in second if / else statement --- .../1155-contracts/src/royalties/CreatorRoyaltiesControl.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/1155-contracts/src/royalties/CreatorRoyaltiesControl.sol b/packages/1155-contracts/src/royalties/CreatorRoyaltiesControl.sol index fd1717e17..0d1659c51 100644 --- a/packages/1155-contracts/src/royalties/CreatorRoyaltiesControl.sol +++ b/packages/1155-contracts/src/royalties/CreatorRoyaltiesControl.sol @@ -38,7 +38,7 @@ abstract contract CreatorRoyaltiesControl is CreatorRoyaltiesStorageV1, SharedBa revert InvalidMintSchedule(); } // Don't allow setting royalties to burn address - if (configuration.royaltyRecipient == address(0) && (configuration.royaltyMintSchedule > 0 || configuration.royaltyBPS > 0)) { + if (configuration.royaltyRecipient == address(0) && configuration.royaltyBPS > 0) { revert InvalidMintSchedule(); } royalties[tokenId] = configuration;