From 079a5968ae5bf6e31fbcb07e9c8fad3d46218a90 Mon Sep 17 00:00:00 2001 From: Dan Oved Date: Wed, 20 Mar 2024 09:02:42 -0700 Subject: [PATCH] Move interfaces/entities/utils to shared-contracts (#264) * move to shared contracts * added a changeset --- .changeset/thin-brooms-drive.md | 5 + packages/1155-contracts/package.json | 2 + packages/1155-contracts/remappings.txt | 2 + .../delegation/ZoraCreator1155Attribution.sol | 112 ++--------------- .../ZoraCreator1155PremintExecutorImpl.sol | 114 +++++++++--------- .../ZoraCreator1155PremintExecutorImplLib.sol | 50 ++++---- .../src/interfaces/IZoraCreator1155Errors.sol | 47 +------- .../IZoraCreator1155PremintExecutor.sol | 42 +------ .../test/nft/ZoraCreator1155.t.sol | 17 ++- .../Zora1155PremintExecutorProxy.t.sol | 49 +++----- .../ZoraCreator1155PremintExecutor.t.sol | 59 +++------ .../ZoraCreator1155PremintExecutor_aa.t.sol | 49 ++++++-- packages/1155-deployments/package.json | 6 +- packages/1155-deployments/remappings.txt | 2 + .../script/DeployProxiesToNewChain.s.sol | 7 +- .../script/DeployTestContracts.s.sol | 7 +- .../src/DeploymentTestingUtils.sol | 22 ++-- .../1155-deployments/test/UpgradesTest.t.sol | 7 +- ...raCreator1155PremintExecutorForkTest.t.sol | 14 ++- packages/shared-contracts/package.json | 22 ++++ packages/shared-contracts/remappings.txt | 4 + .../shared-contracts/src/entities/Premint.sol | 100 +++++++++++++++ .../src/interfaces/ICreatorCommands.sol | 30 +++++ .../src/interfaces/IERC165Upgradeable.sol | 23 ++++ .../src/interfaces/IGetContractAddress.sol | 8 ++ .../interfaces/IImmutableCreate2Factory.sol | 59 +++++++++ .../src/interfaces/ILegacyNaming.sol | 8 ++ .../src/interfaces/IMinter1155.sol | 17 +++ .../src/interfaces/IVersionedContract.sol | 6 + .../IZoraCreator1155PremintExecutorV2.sol | 25 ++++ .../src/interfaces/errors/IMinterErrors.sol | 13 ++ .../errors/IZoraCreator1155Errors.sol | 55 +++++++++ .../src/mocks/ReceiveRejector.sol | 8 ++ .../src/premint/PremintEncoding.sol | 27 +++++ .../utils/ImmutableCreate2FactoryUtils.sol | 57 +++++++++ yarn.lock | 7 +- 36 files changed, 689 insertions(+), 393 deletions(-) create mode 100644 .changeset/thin-brooms-drive.md create mode 100644 packages/shared-contracts/package.json create mode 100644 packages/shared-contracts/remappings.txt create mode 100644 packages/shared-contracts/src/entities/Premint.sol create mode 100644 packages/shared-contracts/src/interfaces/ICreatorCommands.sol create mode 100644 packages/shared-contracts/src/interfaces/IERC165Upgradeable.sol create mode 100644 packages/shared-contracts/src/interfaces/IGetContractAddress.sol create mode 100644 packages/shared-contracts/src/interfaces/IImmutableCreate2Factory.sol create mode 100644 packages/shared-contracts/src/interfaces/ILegacyNaming.sol create mode 100644 packages/shared-contracts/src/interfaces/IMinter1155.sol create mode 100644 packages/shared-contracts/src/interfaces/IVersionedContract.sol create mode 100644 packages/shared-contracts/src/interfaces/IZoraCreator1155PremintExecutorV2.sol create mode 100644 packages/shared-contracts/src/interfaces/errors/IMinterErrors.sol create mode 100644 packages/shared-contracts/src/interfaces/errors/IZoraCreator1155Errors.sol create mode 100644 packages/shared-contracts/src/mocks/ReceiveRejector.sol create mode 100644 packages/shared-contracts/src/premint/PremintEncoding.sol create mode 100644 packages/shared-contracts/src/utils/ImmutableCreate2FactoryUtils.sol diff --git a/.changeset/thin-brooms-drive.md b/.changeset/thin-brooms-drive.md new file mode 100644 index 000000000..076bf9116 --- /dev/null +++ b/.changeset/thin-brooms-drive.md @@ -0,0 +1,5 @@ +--- +"@zoralabs/zora-1155-contracts": patch +--- + +Moved shared functionality into shared-contracts. premintWithSignerContract takes firstMinter as an argument diff --git a/packages/1155-contracts/package.json b/packages/1155-contracts/package.json index f6b7e374c..c116f7ea8 100644 --- a/packages/1155-contracts/package.json +++ b/packages/1155-contracts/package.json @@ -38,7 +38,9 @@ "solmate": "6.1.0", "forge-std": "https://github.com/foundry-rs/forge-std#705263c95892a906d7af65f0f73ce8a4a0c80b80", "ds-test": "https://github.com/dapphub/ds-test#cd98eff28324bfac652e63a239a60632a761790b", + "@zoralabs/mints-contracts": "*", "@zoralabs/protocol-rewards": "*", + "@zoralabs/shared-contracts": "*", "@zoralabs/openzeppelin-contracts-upgradeable": "4.8.4", "@openzeppelin/contracts": "4.9.2" }, diff --git a/packages/1155-contracts/remappings.txt b/packages/1155-contracts/remappings.txt index 6985dcb8b..403fe0314 100644 --- a/packages/1155-contracts/remappings.txt +++ b/packages/1155-contracts/remappings.txt @@ -2,6 +2,8 @@ ds-test/=node_modules/ds-test/src/ forge-std/=node_modules/forge-std/src/ @zoralabs/openzeppelin-contracts-upgradeable/=node_modules/@zoralabs/openzeppelin-contracts-upgradeable/ @zoralabs/protocol-rewards/src/=node_modules/@zoralabs/protocol-rewards/src/ +@zoralabs/mints-contracts/src/=node_modules/@zoralabs/mints-contracts/src/ +@zoralabs/shared-contracts/=node_modules/@zoralabs/shared-contracts/src/ @openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ _imagine=_imagine/ solemate/=/node_modules/solemate/src/ diff --git a/packages/1155-contracts/src/delegation/ZoraCreator1155Attribution.sol b/packages/1155-contracts/src/delegation/ZoraCreator1155Attribution.sol index 3114b562f..d596e1dff 100644 --- a/packages/1155-contracts/src/delegation/ZoraCreator1155Attribution.sol +++ b/packages/1155-contracts/src/delegation/ZoraCreator1155Attribution.sol @@ -7,100 +7,14 @@ import {IZoraCreator1155Errors} from "../interfaces/IZoraCreator1155Errors.sol"; import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol"; import {ECDSAUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/ECDSAUpgradeable.sol"; import {ZoraCreatorFixedPriceSaleStrategy} from "../minters/fixed-price/ZoraCreatorFixedPriceSaleStrategy.sol"; +import {PremintEncoding} from "@zoralabs/shared-contracts/premint/PremintEncoding.sol"; import {IERC1271} from "../interfaces/IERC1271.sol"; -struct ContractCreationConfig { - // Creator/admin of the created contract. Must match the account that signed the message - address contractAdmin; - // Metadata URI for the created contract - string contractURI; - // Name of the created contract - string contractName; -} - -struct PremintConfig { - // The config for the token to be created - TokenCreationConfig tokenConfig; - // Unique id of the token, used to ensure that multiple signatures can't be used to create the same intended token. - // only one signature per token id, scoped to the contract hash can be executed. - uint32 uid; - // Version of this premint, scoped to the uid and contract. Not used for logic in the contract, but used externally to track the newest version - uint32 version; - // If executing this signature results in preventing any signature with this uid from being minted. - bool deleted; -} - -struct TokenCreationConfig { - // Metadata URI for the created token - string tokenURI; - // Max supply of the created token - uint256 maxSupply; - // Max tokens that can be minted for an address, 0 if unlimited - uint64 maxTokensPerAddress; - // Price per token in eth wei. 0 for a free mint. - uint96 pricePerToken; - // The start time of the mint, 0 for immediate. Prevents signatures from being used until the start time. - uint64 mintStart; - // The duration of the mint, starting from the first mint of this token. 0 for infinite - uint64 mintDuration; - // deperecated field; will be ignored. - uint32 royaltyMintSchedule; - // RoyaltyBPS for created tokens. The royalty amount in basis points for secondary sales. - uint32 royaltyBPS; - // This is the address that will be set on the `royaltyRecipient` for the created token on the 1155 contract, - // which is the address that receives creator rewards and secondary royalties for the token, - // and on the `fundsRecipient` on the ZoraCreatorFixedPriceSaleStrategy contract for the token, - // which is the address that receives paid mint funds for the token. - address royaltyRecipient; - // Fixed price minter address - address fixedPriceMinter; -} - -struct PremintConfigV2 { - // The config for the token to be created - TokenCreationConfigV2 tokenConfig; - // Unique id of the token, used to ensure that multiple signatures can't be used to create the same intended token. - // only one signature per token id, scoped to the contract hash can be executed. - uint32 uid; - // Version of this premint, scoped to the uid and contract. Not used for logic in the contract, but used externally to track the newest version - uint32 version; - // If executing this signature results in preventing any signature with this uid from being minted. - bool deleted; -} - -struct TokenCreationConfigV2 { - // Metadata URI for the created token - string tokenURI; - // Max supply of the created token - uint256 maxSupply; - // Max tokens that can be minted for an address, 0 if unlimited - uint64 maxTokensPerAddress; - // Price per token in eth wei. 0 for a free mint. - uint96 pricePerToken; - // The start time of the mint, 0 for immediate. Prevents signatures from being used until the start time. - uint64 mintStart; - // The duration of the mint, starting from the first mint of this token. 0 for infinite - uint64 mintDuration; - // RoyaltyBPS for created tokens. The royalty amount in basis points for secondary sales. - uint32 royaltyBPS; - // This is the address that will be set on the `royaltyRecipient` for the created token on the 1155 contract, - // which is the address that receives creator rewards and secondary royalties for the token, - // and on the `fundsRecipient` on the ZoraCreatorFixedPriceSaleStrategy contract for the token, - // which is the address that receives paid mint funds for the token. - address payoutRecipient; - // Fixed price minter address - address fixedPriceMinter; - // create referral - address createReferral; -} +import {PremintConfig, ContractCreationConfig, TokenCreationConfig, PremintConfigV2, TokenCreationConfigV2} from "@zoralabs/shared-contracts/entities/Premint.sol"; library ZoraCreator1155Attribution { string internal constant NAME = "Preminter"; bytes32 internal constant HASHED_NAME = keccak256(bytes(NAME)); - string internal constant VERSION_1 = "1"; - bytes32 internal constant HASHED_VERSION_1 = keccak256(bytes(VERSION_1)); - string internal constant VERSION_2 = "2"; - bytes32 internal constant HASHED_VERSION_2 = keccak256(bytes(VERSION_2)); /** * @dev Returns the domain separator for the specified chain. @@ -164,7 +78,7 @@ library ZoraCreator1155Attribution { (signatory, recoverError) = ECDSAUpgradeable.tryRecover(digest, signature); if (recoverError != ECDSAUpgradeable.RecoverError.NoError) { - revert IZoraCreator1155Errors.InvalidSignature(recoverError); + revert IZoraCreator1155Errors.InvalidSignature(); } } } @@ -367,16 +281,6 @@ library PremintTokenSetup { } } -library PremintEncoding { - function encodePremintV1(PremintConfig memory premintConfig) internal pure returns (bytes memory encodedPremintConfig, bytes32 hashedVersion) { - return (abi.encode(premintConfig), ZoraCreator1155Attribution.HASHED_VERSION_1); - } - - function encodePremintV2(PremintConfigV2 memory premintConfig) internal pure returns (bytes memory encodedPremintConfig, bytes32 hashedVersion) { - return (abi.encode(premintConfig), ZoraCreator1155Attribution.HASHED_VERSION_2); - } -} - struct DecodedCreatorAttribution { bytes32 structHash; string domainName; @@ -416,11 +320,11 @@ library DelegatedTokenCreation { // based on version of encoded premint config, decode corresponding premint config, // and then recover signer from the signature, and then build token setup actions based // on the decoded premint config. - if (premintVersion == ZoraCreator1155Attribution.HASHED_VERSION_1) { + if (premintVersion == PremintEncoding.HASHED_VERSION_1) { PremintConfig memory premintConfig = abi.decode(premintConfigEncoded, (PremintConfig)); creatorAttribution = recoverCreatorAttribution( - ZoraCreator1155Attribution.VERSION_1, + PremintEncoding.VERSION_1, ZoraCreator1155Attribution.hashPremint(premintConfig), tokenContract, signature, @@ -432,7 +336,7 @@ library DelegatedTokenCreation { PremintConfigV2 memory premintConfig = abi.decode(premintConfigEncoded, (PremintConfigV2)); creatorAttribution = recoverCreatorAttribution( - ZoraCreator1155Attribution.VERSION_2, + PremintEncoding.VERSION_2, ZoraCreator1155Attribution.hashPremint(premintConfig), tokenContract, signature, @@ -449,8 +353,8 @@ library DelegatedTokenCreation { function _supportedPremintSignatureVersions() internal pure returns (string[] memory versions) { versions = new string[](2); - versions[0] = ZoraCreator1155Attribution.VERSION_1; - versions[1] = ZoraCreator1155Attribution.VERSION_2; + versions[0] = PremintEncoding.VERSION_1; + versions[1] = PremintEncoding.VERSION_2; } function recoverCreatorAttribution( diff --git a/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol b/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol index e5305bd25..58dbd5d76 100644 --- a/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol +++ b/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol @@ -13,11 +13,15 @@ import {ZoraCreatorFixedPriceSaleStrategy} from "../minters/fixed-price/ZoraCrea import {IMinter1155} from "../interfaces/IMinter1155.sol"; import {ERC1155DelegationStorageV1} from "../delegation/ERC1155DelegationStorageV1.sol"; import {ZoraCreator1155PremintExecutorImplLib} from "./ZoraCreator1155PremintExecutorImplLib.sol"; -import {PremintEncoding, ZoraCreator1155Attribution, DelegatedTokenCreation, ContractCreationConfig, PremintConfig, PremintConfigV2, TokenCreationConfig, TokenCreationConfigV2} from "./ZoraCreator1155Attribution.sol"; +import {ZoraCreator1155Attribution, DelegatedTokenCreation} from "./ZoraCreator1155Attribution.sol"; +import {PremintEncoding, EncodedPremintConfig} from "@zoralabs/shared-contracts/premint/PremintEncoding.sol"; +import {ContractCreationConfig, PremintConfig, PremintConfigV2, TokenCreationConfig, TokenCreationConfigV2, MintArguments, PremintResult} from "@zoralabs/shared-contracts/entities/Premint.sol"; import {IZoraCreator1155PremintExecutor} from "../interfaces/IZoraCreator1155PremintExecutor.sol"; import {IZoraCreator1155DelegatedCreationLegacy, IHasSupportedPremintSignatureVersions} from "../interfaces/IZoraCreator1155DelegatedCreation.sol"; import {ZoraCreator1155FactoryImpl} from "../factory/ZoraCreator1155FactoryImpl.sol"; import {IRewardsErrors} from "@zoralabs/protocol-rewards/src/interfaces/IRewardsErrors.sol"; +import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; /// @title Enables creation of and minting tokens on Zora1155 contracts transactions using eip-712 signatures. /// Signature must provided by the contract creator, or an account that's permitted to create new tokens on the contract. @@ -62,37 +66,36 @@ contract ZoraCreator1155PremintExecutorImpl is bytes calldata signature, uint256 quantityToMint, MintArguments calldata mintArguments, + address firstMinter, address signerContract ) public payable returns (PremintResult memory result) { - (bytes memory encodedPremint, bytes32 premintVersion) = PremintEncoding.encodePremintV2(premintConfig); - address fixedPriceMinter = premintConfig.tokenConfig.fixedPriceMinter; - uint32 uid = premintConfig.uid; + result = ZoraCreator1155PremintExecutorImplLib.getOrCreateContractAndToken( + zora1155Factory, + contractConfig, + PremintEncoding.encodePremintV2(premintConfig), + signature, + firstMinter, + signerContract + ); - // we wrap this here to get around stack too deep issues - { - result = ZoraCreator1155PremintExecutorImplLib.premint({ - zora1155Factory: zora1155Factory, - contractConfig: contractConfig, - encodedPremintConfig: encodedPremint, - premintVersion: premintVersion, - signature: signature, - quantityToMint: quantityToMint, - fixedPriceMinter: fixedPriceMinter, - mintArguments: mintArguments, - signerContract: signerContract - }); + if (quantityToMint > 0) { + ZoraCreator1155PremintExecutorImplLib.mintWithEth( + IZoraCreator1155(result.contractAddress), + premintConfig.tokenConfig.fixedPriceMinter, + result.tokenId, + quantityToMint, + mintArguments + ); } - { - emit PremintedV2({ - contractAddress: result.contractAddress, - tokenId: result.tokenId, - createdNewContract: result.createdNewContract, - uid: uid, - minter: msg.sender, - quantityMinted: quantityToMint - }); - } + emit PremintedV2({ + contractAddress: result.contractAddress, + tokenId: result.tokenId, + createdNewContract: result.createdNewContract, + uid: premintConfig.uid, + minter: firstMinter, + quantityMinted: quantityToMint + }); } /// @notice Creates a new token on the given erc1155 contract on behalf of a creator, and mints x tokens to the executor of this transaction. @@ -113,7 +116,7 @@ contract ZoraCreator1155PremintExecutorImpl is uint256 quantityToMint, MintArguments calldata mintArguments ) external payable returns (PremintResult memory result) { - return premintV2WithSignerContract(contractConfig, premintConfig, signature, quantityToMint, mintArguments, address(0)); + return premintV2WithSignerContract(contractConfig, premintConfig, signature, quantityToMint, mintArguments, msg.sender, address(0)); } /// Creates a new token on the given erc1155 contract on behalf of a creator, and mints x tokens to the executor of this transaction. @@ -134,40 +137,39 @@ contract ZoraCreator1155PremintExecutorImpl is uint256 quantityToMint, MintArguments calldata mintArguments ) external payable returns (PremintResult memory result) { - (bytes memory encodedPremint, bytes32 premintVersion) = PremintEncoding.encodePremintV1(premintConfig); - address fixedPriceMinter = premintConfig.tokenConfig.fixedPriceMinter; - uint32 uid = premintConfig.uid; + result = ZoraCreator1155PremintExecutorImplLib.getOrCreateContractAndToken( + zora1155Factory, + contractConfig, + PremintEncoding.encodePremintV1(premintConfig), + signature, + msg.sender, + address(0) + ); - { - result = ZoraCreator1155PremintExecutorImplLib.premint({ - zora1155Factory: zora1155Factory, - contractConfig: contractConfig, - encodedPremintConfig: encodedPremint, - premintVersion: premintVersion, - signature: signature, - quantityToMint: quantityToMint, - fixedPriceMinter: fixedPriceMinter, - mintArguments: mintArguments, - signerContract: address(0) - }); + if (quantityToMint > 0) { + ZoraCreator1155PremintExecutorImplLib.mintWithEth( + IZoraCreator1155(result.contractAddress), + premintConfig.tokenConfig.fixedPriceMinter, + result.tokenId, + quantityToMint, + mintArguments + ); } - { - emit PremintedV2({ - contractAddress: result.contractAddress, - tokenId: result.tokenId, - createdNewContract: result.createdNewContract, - uid: uid, - minter: msg.sender, - quantityMinted: quantityToMint - }); - } + emit PremintedV2({ + contractAddress: result.contractAddress, + tokenId: result.tokenId, + createdNewContract: result.createdNewContract, + uid: premintConfig.uid, + minter: msg.sender, + quantityMinted: quantityToMint + }); } /// @notice Gets the deterministic contract address for the given contract creation config. /// Contract address is generated deterministically from a hash based on the contract uri, contract name, /// contract admin, and the msg.sender, which is this contract's address. - function getContractAddress(ContractCreationConfig calldata contractConfig) public view returns (address) { + function getContractAddress(ContractCreationConfig calldata contractConfig) public view override returns (address) { return ZoraCreator1155PremintExecutorImplLib.getContractAddress(zora1155Factory, contractConfig); } @@ -192,7 +194,7 @@ contract ZoraCreator1155PremintExecutorImpl is ZoraCreator1155Attribution.hashPremint(premintConfig), signature, contractAddress, - ZoraCreator1155Attribution.HASHED_VERSION_1, + PremintEncoding.HASHED_VERSION_1, block.chainid, address(0) ); @@ -241,7 +243,7 @@ contract ZoraCreator1155PremintExecutorImpl is // try get token id for uid 0 - if call fails, we know this didn't support premint try ERC1155DelegationStorageV1(contractAddress).delegatedTokenId(uint32(0)) returns (uint256) { versions = new string[](1); - versions[0] = ZoraCreator1155Attribution.VERSION_1; + versions[0] = PremintEncoding.VERSION_1; } catch { versions = new string[](0); } diff --git a/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImplLib.sol b/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImplLib.sol index 86b267d74..457e7bc05 100644 --- a/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImplLib.sol +++ b/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImplLib.sol @@ -1,14 +1,16 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.17; -import {ContractCreationConfig, PremintConfig} from "./ZoraCreator1155Attribution.sol"; +import {ContractCreationConfig, PremintConfig} from "@zoralabs/shared-contracts/entities/Premint.sol"; import {IZoraCreator1155} from "../interfaces/IZoraCreator1155.sol"; import {IZoraCreator1155Factory} from "../interfaces/IZoraCreator1155Factory.sol"; import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol"; import {IMinter1155} from "../interfaces/IMinter1155.sol"; import {IZoraCreator1155PremintExecutor} from "../interfaces/IZoraCreator1155PremintExecutor.sol"; import {IZoraCreator1155DelegatedCreation, IZoraCreator1155DelegatedCreationLegacy, ISupportsAABasedDelegatedTokenCreation} from "../interfaces/IZoraCreator1155DelegatedCreation.sol"; +import {EncodedPremintConfig} from "@zoralabs/shared-contracts/premint/PremintEncoding.sol"; import {IMintWithRewardsRecipients} from "../interfaces/IMintWithRewardsRecipients.sol"; +import {MintArguments, PremintResult} from "@zoralabs/shared-contracts/entities/Premint.sol"; interface ILegacyZoraCreator1155DelegatedMinter { function delegateSetupNewToken(PremintConfig calldata premintConfig, bytes calldata signature, address sender) external returns (uint256 newTokenId); @@ -77,22 +79,20 @@ library ZoraCreator1155PremintExecutorImplLib { return ILegacyZoraCreator1155DelegatedMinter(contractAddress).delegateSetupNewToken(premintConfig, signature, msg.sender); } - function premint( + function getOrCreateContractAndToken( IZoraCreator1155Factory zora1155Factory, ContractCreationConfig calldata contractConfig, - bytes memory encodedPremintConfig, - bytes32 premintVersion, + EncodedPremintConfig memory encodedPremintConfig, bytes calldata signature, - uint256 quantityToMint, - address fixedPriceMinter, - IZoraCreator1155PremintExecutor.MintArguments memory mintArguments, + address firstMinter, address signerContract - ) internal returns (IZoraCreator1155PremintExecutor.PremintResult memory) { + ) internal returns (PremintResult memory premintResult) { // get or create the contract with the given params // contract address is deterministic. (IZoraCreator1155 tokenContract, bool isNewContract) = getOrCreateContract(zora1155Factory, contractConfig); - uint256 newTokenId; + premintResult.contractAddress = address(tokenContract); + premintResult.createdNewContract = isNewContract; if (tokenContract.supportsInterface(type(ISupportsAABasedDelegatedTokenCreation).interfaceId)) { // if the contract supports the new interface, we can use it to create the token. @@ -100,11 +100,11 @@ library ZoraCreator1155PremintExecutorImplLib { // pass the signature and the premint config to the token contract to create the token. // The token contract will verify the signature and that the signer has permission to create a new token. // and then create and setup the token using the given token config. - newTokenId = ISupportsAABasedDelegatedTokenCreation(tokenContract).delegateSetupNewToken( - encodedPremintConfig, - premintVersion, + premintResult.tokenId = ISupportsAABasedDelegatedTokenCreation(tokenContract).delegateSetupNewToken( + encodedPremintConfig.premintConfig, + encodedPremintConfig.premintConfigVersion, signature, - msg.sender, + firstMinter, signerContract ); } else if (tokenContract.supportsInterface(type(IZoraCreator1155DelegatedCreationLegacy).interfaceId)) { @@ -112,30 +112,26 @@ library ZoraCreator1155PremintExecutorImplLib { revert("Smart contract signing not supported on version of 1155 contract"); } - newTokenId = IZoraCreator1155DelegatedCreationLegacy(address(tokenContract)).delegateSetupNewToken( - encodedPremintConfig, - premintVersion, + premintResult.tokenId = IZoraCreator1155DelegatedCreationLegacy(address(tokenContract)).delegateSetupNewToken( + encodedPremintConfig.premintConfig, + encodedPremintConfig.premintConfigVersion, signature, - msg.sender + firstMinter ); } else { // otherwise, we need to use the legacy interface. - newTokenId = legacySetupNewToken(address(tokenContract), encodedPremintConfig, signature); + premintResult.tokenId = legacySetupNewToken(address(tokenContract), encodedPremintConfig.premintConfig, signature); } - - _performMint(tokenContract, fixedPriceMinter, newTokenId, quantityToMint, mintArguments); - - return IZoraCreator1155PremintExecutor.PremintResult({contractAddress: address(tokenContract), tokenId: newTokenId, createdNewContract: isNewContract}); } - function _performMint( + function mintWithEth( IZoraCreator1155 tokenContract, address fixedPriceMinter, uint256 tokenId, uint256 quantityToMint, - IZoraCreator1155PremintExecutor.MintArguments memory mintArguments + MintArguments memory mintArguments ) internal { - bytes memory mintSettings = abi.encode(mintArguments.mintRecipient, mintArguments.mintComment); + bytes memory mintSettings = _toMintSettings(mintArguments); if (quantityToMint != 0) { if (tokenContract.supportsInterface(type(IMintWithRewardsRecipients).interfaceId)) { tokenContract.mint{value: msg.value}(IMinter1155(fixedPriceMinter), tokenId, quantityToMint, mintArguments.mintRewardsRecipients, mintSettings); @@ -147,4 +143,8 @@ library ZoraCreator1155PremintExecutorImplLib { } } } + + function _toMintSettings(MintArguments memory mintArguments) internal pure returns (bytes memory) { + return abi.encode(mintArguments.mintRecipient, mintArguments.mintComment); + } } diff --git a/packages/1155-contracts/src/interfaces/IZoraCreator1155Errors.sol b/packages/1155-contracts/src/interfaces/IZoraCreator1155Errors.sol index 7532c9502..b23f991cc 100644 --- a/packages/1155-contracts/src/interfaces/IZoraCreator1155Errors.sol +++ b/packages/1155-contracts/src/interfaces/IZoraCreator1155Errors.sol @@ -1,47 +1,4 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.17; +pragma solidity 0.8.17; -import {ICreatorRoyaltyErrors} from "./ICreatorRoyaltiesControl.sol"; -import {ILimitedMintPerAddressErrors} from "./ILimitedMintPerAddress.sol"; -import {IMinterErrors} from "./IMinterErrors.sol"; -import {ECDSAUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/ECDSAUpgradeable.sol"; - -interface IZoraCreator1155Errors is ICreatorRoyaltyErrors, ILimitedMintPerAddressErrors, IMinterErrors { - error Call_TokenIdMismatch(); - error TokenIdMismatch(uint256 expected, uint256 actual); - error UserMissingRoleForToken(address user, uint256 tokenId, uint256 role); - - error Config_TransferHookNotSupported(address proposedAddress); - - error Mint_InsolventSaleTransfer(); - error Mint_ValueTransferFail(); - error Mint_TokenIDMintNotAllowed(); - error Mint_UnknownCommand(); - - error Burn_NotOwnerOrApproved(address operator, address user); - - error NewOwnerNeedsToBeAdmin(); - - error Sale_CannotCallNonSalesContract(address targetContract); - - error CallFailed(bytes reason); - error Renderer_NotValidRendererContract(); - - error ETHWithdrawFailed(address recipient, uint256 amount); - error FundsWithdrawInsolvent(uint256 amount, uint256 contractValue); - error ProtocolRewardsWithdrawFailed(address caller, address recipient, uint256 amount); - - error CannotMintMoreTokens(uint256 tokenId, uint256 quantity, uint256 totalMinted, uint256 maxSupply); - - error MintNotYetStarted(); - error PremintDeleted(); - - // DelegatedMinting related errors - error InvalidSignatureVersion(); - error premintSignerContractNotAContract(); - error InvalidSignature(ECDSAUpgradeable.RecoverError recoverError); - error InvalidSigner(bytes4 magicValue); - error premintSignerContractFailedToRecoverSigner(); - - error ERC1155_MINT_TO_ZERO_ADDRESS(); -} +import {IZoraCreator1155Errors} from "@zoralabs/shared-contracts/interfaces/errors/IZoraCreator1155Errors.sol"; diff --git a/packages/1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol b/packages/1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol index 045c1984c..f5c41f281 100644 --- a/packages/1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol +++ b/packages/1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol @@ -4,6 +4,9 @@ pragma solidity ^0.8.17; import {PremintEncoding, ZoraCreator1155Attribution, ContractCreationConfig, PremintConfig, PremintConfigV2, TokenCreationConfig, TokenCreationConfigV2} from "../delegation/ZoraCreator1155Attribution.sol"; import {IOwnable2StepUpgradeable} from "../utils/ownable/IOwnable2StepUpgradeable.sol"; import {IZoraCreator1155Factory} from "./IZoraCreator1155Factory.sol"; +import {IGetContractAddress} from "@zoralabs/shared-contracts/interfaces/IGetContractAddress.sol"; +import {MintArguments, PremintResult} from "@zoralabs/shared-contracts/entities/Premint.sol"; +import {IZoraCreator1155PremintExecutorV2} from "@zoralabs/shared-contracts/interfaces/IZoraCreator1155PremintExecutorV2.sol"; // this contains functions we have removed, but want to keep around for for testing purposes interface IRemovedZoraCreator1155PremintExecutorFunctions { @@ -44,48 +47,17 @@ interface IZoraCreator1155PremintExecutorV1 { PremintConfig calldata premintConfig, bytes calldata signature, uint256 quantityToMint, - IZoraCreator1155PremintExecutor.MintArguments calldata mintArguments - ) external payable returns (IZoraCreator1155PremintExecutor.PremintResult memory); -} - -interface IZoraCreator1155PremintExecutorV2 { - function premintV2( - ContractCreationConfig calldata contractConfig, - PremintConfigV2 calldata premintConfig, - bytes calldata signature, - uint256 quantityToMint, - IZoraCreator1155PremintExecutor.MintArguments calldata mintArguments - ) external payable returns (IZoraCreator1155PremintExecutor.PremintResult memory); - - function premintV2WithSignerContract( - ContractCreationConfig calldata contractConfig, - PremintConfigV2 calldata premintConfig, - bytes calldata signature, - uint256 quantityToMint, - IZoraCreator1155PremintExecutor.MintArguments calldata mintArguments, - address signerContract - ) external payable returns (IZoraCreator1155PremintExecutor.PremintResult memory result); + MintArguments calldata mintArguments + ) external payable returns (PremintResult memory); } interface IZoraCreator1155PremintExecutor is ILegacyZoraCreator1155PremintExecutor, + IGetContractAddress, IZoraCreator1155PremintExecutorV1, IZoraCreator1155PremintExecutorV2, IOwnable2StepUpgradeable { - struct MintArguments { - address mintRecipient; - string mintComment; - /// array of accounts to receive rewards - mintReferral is first argument, and platformReferral is second. platformReferral isn't supported as of now but will be in a future release. - address[] mintRewardsRecipients; - } - - struct PremintResult { - address contractAddress; - uint256 tokenId; - bool createdNewContract; - } - event PremintedV2( address indexed contractAddress, uint256 indexed tokenId, @@ -97,8 +69,6 @@ interface IZoraCreator1155PremintExecutor is function zora1155Factory() external view returns (IZoraCreator1155Factory); - function getContractAddress(ContractCreationConfig calldata contractConfig) external view returns (address); - function supportedPremintSignatureVersions(address contractAddress) external view returns (string[] memory); function mintFee(address contractAddress) external view returns (uint256); diff --git a/packages/1155-contracts/test/nft/ZoraCreator1155.t.sol b/packages/1155-contracts/test/nft/ZoraCreator1155.t.sol index add616912..5d178f1e0 100644 --- a/packages/1155-contracts/test/nft/ZoraCreator1155.t.sol +++ b/packages/1155-contracts/test/nft/ZoraCreator1155.t.sol @@ -11,8 +11,9 @@ import {ITransferHookReceiver} from "../../src/interfaces/ITransferHookReceiver. import {Zora1155} from "../../src/proxies/Zora1155.sol"; import {ZoraCreatorFixedPriceSaleStrategy} from "../../src/minters/fixed-price/ZoraCreatorFixedPriceSaleStrategy.sol"; import {UpgradeGate} from "../../src/upgrades/UpgradeGate.sol"; -import {PremintConfigV2, TokenCreationConfigV2} from "../../src/delegation/ZoraCreator1155Attribution.sol"; -import {ZoraCreator1155Attribution, PremintEncoding} from "../../src/delegation/ZoraCreator1155Attribution.sol"; +import {PremintConfigV2, TokenCreationConfigV2} from "@zoralabs/shared-contracts/entities/Premint.sol"; +import {PremintEncoding, EncodedPremintConfig} from "@zoralabs/shared-contracts/premint/PremintEncoding.sol"; +import {ZoraCreator1155Attribution} from "../../src/delegation/ZoraCreator1155Attribution.sol"; import {IZoraCreator1155Errors} from "../../src/interfaces/IZoraCreator1155Errors.sol"; import {IZoraCreator1155} from "../../src/interfaces/IZoraCreator1155.sol"; @@ -1098,7 +1099,7 @@ contract ZoraCreator1155Test is Test { ZoraCreator1155Attribution.premintHashedTypeDataV4( ZoraCreator1155Attribution.hashPremint(premintConfig), address(target), - ZoraCreator1155Attribution.HASHED_VERSION_2, + PremintEncoding.HASHED_VERSION_2, chainId ) ); @@ -1109,8 +1110,14 @@ contract ZoraCreator1155Test is Test { uint256 tokenId; { - (bytes memory premintConfigEncoded, bytes32 version) = PremintEncoding.encodePremintV2(premintConfig); - tokenId = target.delegateSetupNewToken(premintConfigEncoded, version, signature, collectors[0], address(0)); + EncodedPremintConfig memory premintConfigEncoded = PremintEncoding.encodePremintV2(premintConfig); + tokenId = target.delegateSetupNewToken( + premintConfigEncoded.premintConfig, + premintConfigEncoded.premintConfigVersion, + signature, + collectors[0], + address(0) + ); } RewardsSettings memory settings = target.computeFreeMintRewards(quantity); diff --git a/packages/1155-contracts/test/premint/Zora1155PremintExecutorProxy.t.sol b/packages/1155-contracts/test/premint/Zora1155PremintExecutorProxy.t.sol index 100bb79de..807113b8a 100644 --- a/packages/1155-contracts/test/premint/Zora1155PremintExecutorProxy.t.sol +++ b/packages/1155-contracts/test/premint/Zora1155PremintExecutorProxy.t.sol @@ -11,13 +11,14 @@ import {ZoraCreator1155PremintExecutorImpl} from "../../src/delegation/ZoraCreat import {Zora1155Factory} from "../../src/proxies/Zora1155Factory.sol"; import {IMinter1155} from "../../src/interfaces/IMinter1155.sol"; import {ProxyShim} from "../../src/utils/ProxyShim.sol"; -import {ZoraCreator1155Attribution, ContractCreationConfig, TokenCreationConfigV2, PremintConfigV2, PremintConfig} from "../../src/delegation/ZoraCreator1155Attribution.sol"; +import {ZoraCreator1155Attribution, PremintEncoding, ContractCreationConfig, TokenCreationConfigV2, PremintConfigV2, PremintConfig} from "../../src/delegation/ZoraCreator1155Attribution.sol"; import {IOwnable2StepUpgradeable} from "../../src/utils/ownable/IOwnable2StepUpgradeable.sol"; import {IHasContractName} from "../../src/interfaces/IContractMetadata.sol"; import {ZoraCreator1155PremintExecutorImplLib} from "../../src/delegation/ZoraCreator1155PremintExecutorImplLib.sol"; import {IUpgradeGate} from "../../src/interfaces/IUpgradeGate.sol"; import {IProtocolRewards} from "@zoralabs/protocol-rewards/src/interfaces/IProtocolRewards.sol"; import {IZoraCreator1155PremintExecutor, ILegacyZoraCreator1155PremintExecutor, IRemovedZoraCreator1155PremintExecutorFunctions} from "../../src/interfaces/IZoraCreator1155PremintExecutor.sol"; +import {MintArguments} from "@zoralabs/shared-contracts/entities/Premint.sol"; contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { address internal owner; @@ -28,9 +29,11 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { Zora1155Factory internal factoryProxy; ZoraCreator1155FactoryImpl factoryAtProxy; uint256 internal mintFeeAmount = 0.000777 ether; + uint256 initialTokenId = 777; + uint256 initialTokenPrice = 0.000777 ether; ZoraCreator1155PremintExecutorImpl preminterAtProxy; - IZoraCreator1155PremintExecutor.MintArguments defaultMintArguments; + MintArguments defaultMintArguments; function setUp() external { zora = makeAddr("zora"); @@ -53,11 +56,7 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { preminterAtProxy = ZoraCreator1155PremintExecutorImpl(address(proxy)); preminterAtProxy.initialize(owner); - defaultMintArguments = IZoraCreator1155PremintExecutor.MintArguments({ - mintRecipient: collector, - mintComment: "blah", - mintRewardsRecipients: new address[](0) - }); + defaultMintArguments = MintArguments({mintRecipient: collector, mintComment: "blah", mintRewardsRecipients: new address[](0)}); } function test_canInvokeImplementationMethods() external { @@ -76,11 +75,7 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { address deterministicAddress = preminterAtProxy.getContractAddress(contractConfig); // sign the premint - bytes memory signature = _signPremint( - ZoraCreator1155Attribution.hashPremint(premintConfig), - ZoraCreator1155Attribution.HASHED_VERSION_2, - deterministicAddress - ); + bytes memory signature = _signPremint(ZoraCreator1155Attribution.hashPremint(premintConfig), PremintEncoding.HASHED_VERSION_2, deterministicAddress); uint256 quantityToMint = 1; @@ -138,11 +133,7 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { address deterministicAddress = forkedPreminterProxy.getContractAddress(contractConfig); PremintConfig memory premintConfig = Zora1155PremintFixtures.makeDefaultV1PremintConfig(fixedPriceMinter, creator); - bytes memory signature = _signPremint( - ZoraCreator1155Attribution.hashPremint(premintConfig), - ZoraCreator1155Attribution.HASHED_VERSION_1, - deterministicAddress - ); + bytes memory signature = _signPremint(ZoraCreator1155Attribution.hashPremint(premintConfig), PremintEncoding.HASHED_VERSION_1, deterministicAddress); // create 1155 contract via premint, using legacy interface uint256 quantityToMint = 1; @@ -183,7 +174,7 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { uint32 existingUid = premintConfig.uid; premintConfig = Zora1155PremintFixtures.makeDefaultV1PremintConfig(fixedPriceMinter, creator); premintConfig.uid = existingUid + 1; - signature = _signPremint(ZoraCreator1155Attribution.hashPremint(premintConfig), ZoraCreator1155Attribution.HASHED_VERSION_1, deterministicAddress); + signature = _signPremint(ZoraCreator1155Attribution.hashPremint(premintConfig), PremintEncoding.HASHED_VERSION_1, deterministicAddress); // execute the premint vm.deal(collector, mintFeeAmount); @@ -217,11 +208,7 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { address deterministicAddress = forkedPreminterProxy.getContractAddress(contractConfig); PremintConfig memory premintConfig = Zora1155PremintFixtures.makeDefaultV1PremintConfig(fixedPriceMinter, creator); - bytes memory signature = _signPremint( - ZoraCreator1155Attribution.hashPremint(premintConfig), - ZoraCreator1155Attribution.HASHED_VERSION_1, - deterministicAddress - ); + bytes memory signature = _signPremint(ZoraCreator1155Attribution.hashPremint(premintConfig), PremintEncoding.HASHED_VERSION_1, deterministicAddress); // use old mint fee - this is prior to having the `mintFee` functino on premint executor mintFeeAmount = 0.000777 ether; @@ -299,11 +286,7 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { deleted: false }); - bytes memory signature = _signPremint( - ZoraCreator1155Attribution.hashPremint(premintConfig), - ZoraCreator1155Attribution.HASHED_VERSION_2, - deterministicAddress - ); + bytes memory signature = _signPremint(ZoraCreator1155Attribution.hashPremint(premintConfig), PremintEncoding.HASHED_VERSION_2, deterministicAddress); // create 1155 contract via premint, using legacy interface uint256 quantityToMint = 1; @@ -316,6 +299,11 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { forkedPreminterProxy.premintV2{value: mintFeeAmount}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); // 2. upgrade to current version of preminter + // first upgrade 1155 factory to current version + (, , ZoraCreator1155FactoryImpl newFactoryVersion) = Zora1155FactoryFixtures.setupNew1155AndFactory(zora, IUpgradeGate(address(0)), fixedPriceMinter); + ZoraCreator1155FactoryImpl factory = ZoraCreator1155FactoryImpl(address(forkedPreminterProxy.zora1155Factory())); + vm.prank(factory.owner()); + factory.upgradeTo(address(newFactoryVersion)); // now contract has been created; upgrade to latest version of premint executor ZoraCreator1155PremintExecutorImpl newVersion = new ZoraCreator1155PremintExecutorImpl(forkedPreminterProxy.zora1155Factory()); @@ -325,7 +313,7 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { // 2. create premint using upgraded impl premintConfig.uid = 101; - signature = _signPremint(ZoraCreator1155Attribution.hashPremint(premintConfig), ZoraCreator1155Attribution.HASHED_VERSION_2, deterministicAddress); + signature = _signPremint(ZoraCreator1155Attribution.hashPremint(premintConfig), PremintEncoding.HASHED_VERSION_2, deterministicAddress); // it should succeed ZoraCreator1155PremintExecutorImpl(address(forkedPreminterProxy)).premintV2{value: mintFeeAmount}( @@ -341,7 +329,7 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { signature = _signPremint( ZoraCreator1155Attribution.hashPremint(premintConfig), - ZoraCreator1155Attribution.HASHED_VERSION_2, + PremintEncoding.HASHED_VERSION_2, forkedPreminterProxy.getContractAddress(contractConfig) ); @@ -352,6 +340,7 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { signature, quantityToMint, defaultMintArguments, + makeAddr("firstMinter"), address(0) ); } diff --git a/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor.t.sol b/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor.t.sol index 0c8d5dbb8..636e10c37 100644 --- a/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor.t.sol +++ b/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor.t.sol @@ -17,7 +17,8 @@ import {Zora1155Factory} from "../../src/proxies/Zora1155Factory.sol"; import {ZoraCreator1155FactoryImpl} from "../../src/factory/ZoraCreator1155FactoryImpl.sol"; import {ZoraCreator1155PremintExecutorImpl} from "../../src/delegation/ZoraCreator1155PremintExecutorImpl.sol"; import {IZoraCreator1155PremintExecutor} from "../../src/interfaces/IZoraCreator1155PremintExecutor.sol"; -import {ZoraCreator1155Attribution, ContractCreationConfig, TokenCreationConfig, TokenCreationConfigV2, PremintConfigV2, PremintConfig} from "../../src/delegation/ZoraCreator1155Attribution.sol"; +import {ZoraCreator1155Attribution, PremintEncoding} from "../../src/delegation/ZoraCreator1155Attribution.sol"; +import {ContractCreationConfig, TokenCreationConfig, TokenCreationConfigV2, PremintConfigV2, PremintConfig, MintArguments} from "@zoralabs/shared-contracts/entities/Premint.sol"; import {UUPSUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import {ProxyShim} from "../../src/utils/ProxyShim.sol"; import {IMinterErrors} from "../../src/interfaces/IMinterErrors.sol"; @@ -43,7 +44,7 @@ contract ZoraCreator1155PreminterTest is Test { address internal premintExecutor; address internal collector; - IZoraCreator1155PremintExecutor.MintArguments defaultMintArguments; + MintArguments defaultMintArguments; ProtocolRewards rewards; event PremintedV2( @@ -69,11 +70,7 @@ contract ZoraCreator1155PreminterTest is Test { preminter = new ZoraCreator1155PremintExecutorImpl(factory); - defaultMintArguments = IZoraCreator1155PremintExecutor.MintArguments({ - mintRecipient: premintExecutor, - mintComment: "blah", - mintRewardsRecipients: new address[](0) - }); + defaultMintArguments = MintArguments({mintRecipient: premintExecutor, mintComment: "blah", mintRewardsRecipients: new address[](0)}); } function makeDefaultContractCreationConfig() internal view returns (ContractCreationConfig memory) { @@ -128,7 +125,7 @@ contract ZoraCreator1155PreminterTest is Test { // 2. Call smart contract to get digest to sign for creation params. bytes32 structHash = ZoraCreator1155Attribution.hashPremint(premintConfig); - bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, ZoraCreator1155Attribution.HASHED_VERSION_1, chainId); + bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, PremintEncoding.HASHED_VERSION_1, chainId); // 3. Sign the digest // create a signature with the digest for the params @@ -174,7 +171,7 @@ contract ZoraCreator1155PreminterTest is Test { // 2. Call smart contract to get digest to sign for creation params. bytes32 structHash = ZoraCreator1155Attribution.hashPremint(premintConfig); - bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, ZoraCreator1155Attribution.HASHED_VERSION_2, chainId); + bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, PremintEncoding.HASHED_VERSION_2, chainId); // 3. Sign the digest // create a signature with the digest for the params @@ -200,7 +197,7 @@ contract ZoraCreator1155PreminterTest is Test { premintConfig.uid++; structHash = ZoraCreator1155Attribution.hashPremint(premintConfig); - digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, ZoraCreator1155Attribution.HASHED_VERSION_2, chainId); + digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, PremintEncoding.HASHED_VERSION_2, chainId); signature = _sign(creatorPrivateKey, digest); vm.deal(premintExecutor, mintCost); @@ -230,7 +227,7 @@ contract ZoraCreator1155PreminterTest is Test { // 2. Call smart contract to get digest to sign for creation params. bytes32 structHash = ZoraCreator1155Attribution.hashPremint(premintConfig); - bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, ZoraCreator1155Attribution.HASHED_VERSION_2, chainId); + bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, PremintEncoding.HASHED_VERSION_2, chainId); // 3. Sign the digest // create a signature with the digest for the params @@ -263,12 +260,7 @@ contract ZoraCreator1155PreminterTest is Test { address deterministicAddress = preminter.getContractAddress(contractConfig); bytes32 structHash = ZoraCreator1155Attribution.hashPremint(premintConfig); - bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4( - structHash, - deterministicAddress, - ZoraCreator1155Attribution.HASHED_VERSION_1, - chainId - ); + bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, deterministicAddress, PremintEncoding.HASHED_VERSION_1, chainId); bytes memory signature = _sign(creatorPrivateKey, digest); uint256 quantityToMint = 4; @@ -280,7 +272,7 @@ contract ZoraCreator1155PreminterTest is Test { // verify CreatorAttribution was emitted from the erc1155 contract vm.expectEmit(true, true, true, true, deterministicAddress); - emit CreatorAttribution(structHash, ZoraCreator1155Attribution.NAME, ZoraCreator1155Attribution.VERSION_1, creator, signature); + emit CreatorAttribution(structHash, ZoraCreator1155Attribution.NAME, PremintEncoding.VERSION_1, creator, signature); // create contract and token via premint preminter.premintV1{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); @@ -296,12 +288,7 @@ contract ZoraCreator1155PreminterTest is Test { address deterministicAddress = preminter.getContractAddress(contractConfig); bytes32 structHash = ZoraCreator1155Attribution.hashPremint(premintConfig); - bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4( - structHash, - deterministicAddress, - ZoraCreator1155Attribution.HASHED_VERSION_2, - chainId - ); + bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, deterministicAddress, PremintEncoding.HASHED_VERSION_2, chainId); bytes memory signature = _sign(creatorPrivateKey, digest); uint256 quantityToMint = 4; @@ -313,7 +300,7 @@ contract ZoraCreator1155PreminterTest is Test { // verify CreatorAttribution was emitted from the erc1155 contract vm.expectEmit(true, true, true, true, deterministicAddress); - emit CreatorAttribution(structHash, ZoraCreator1155Attribution.NAME, ZoraCreator1155Attribution.VERSION_2, creator, signature); + emit CreatorAttribution(structHash, ZoraCreator1155Attribution.NAME, PremintEncoding.VERSION_2, creator, signature); // create contract and token via premint preminter.premintV2{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); @@ -336,7 +323,7 @@ contract ZoraCreator1155PreminterTest is Test { // 2. Call smart contract to get digest to sign for creation params. bytes32 structHash = ZoraCreator1155Attribution.hashPremint(premintConfig); - bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, ZoraCreator1155Attribution.HASHED_VERSION_2, chainId); + bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, PremintEncoding.HASHED_VERSION_2, chainId); // 3. Sign the digest // create a signature with the digest for the params @@ -450,11 +437,7 @@ contract ZoraCreator1155PreminterTest is Test { address[] memory mintRewardsRecipients = new address[](1); mintRewardsRecipients[0] = mintReferral; - IZoraCreator1155PremintExecutor.MintArguments memory mintArguments = IZoraCreator1155PremintExecutor.MintArguments({ - mintRecipient: minter, - mintComment: "", - mintRewardsRecipients: mintRewardsRecipients - }); + MintArguments memory mintArguments = MintArguments({mintRecipient: minter, mintComment: "", mintRewardsRecipients: mintRewardsRecipients}); uint256 mintCost = (mintFeeAmount + premintConfig.tokenConfig.pricePerToken) * quantityToMint; @@ -904,11 +887,7 @@ contract ZoraCreator1155PreminterTest is Test { // sign and execute premint bytes memory signature = _signPremint(contractAddress, premintConfig, creatorPrivateKey, block.chainid); - IZoraCreator1155PremintExecutor.MintArguments memory mintArguments = IZoraCreator1155PremintExecutor.MintArguments({ - mintRecipient: address(0), - mintComment: "", - mintRewardsRecipients: new address[](0) - }); + MintArguments memory mintArguments = MintArguments({mintRecipient: address(0), mintComment: "", mintRewardsRecipients: new address[](0)}); uint256 quantityToMint = 3; uint256 mintCost = mintFeeAmount * quantityToMint; @@ -958,11 +937,7 @@ contract ZoraCreator1155PreminterTest is Test { ) private returns (uint256 newTokenId) { bytes memory signature = _signPremint(preminter.getContractAddress(contractConfig), premintConfig, privateKey, chainId); - IZoraCreator1155PremintExecutor.MintArguments memory mintArguments = IZoraCreator1155PremintExecutor.MintArguments({ - mintRecipient: executor, - mintComment: comment, - mintRewardsRecipients: new address[](0) - }); + MintArguments memory mintArguments = MintArguments({mintRecipient: executor, mintComment: comment, mintRewardsRecipients: new address[](0)}); uint256 mintCost = (mintFeeAmount + premintConfig.tokenConfig.pricePerToken) * quantityToMint; vm.deal(executor, mintCost); @@ -979,7 +954,7 @@ contract ZoraCreator1155PreminterTest is Test { uint256 chainId ) private pure returns (bytes memory signature) { bytes32 structHash = ZoraCreator1155Attribution.hashPremint(premintConfig); - bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, ZoraCreator1155Attribution.HASHED_VERSION_2, chainId); + bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, PremintEncoding.HASHED_VERSION_2, chainId); // create a signature with the digest for the params signature = _sign(privateKey, digest); diff --git a/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor_aa.t.sol b/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor_aa.t.sol index 4f2b4c945..10ebd7225 100644 --- a/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor_aa.t.sol +++ b/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor_aa.t.sol @@ -17,7 +17,8 @@ import {Zora1155Factory} from "../../src/proxies/Zora1155Factory.sol"; import {ZoraCreator1155FactoryImpl} from "../../src/factory/ZoraCreator1155FactoryImpl.sol"; import {ZoraCreator1155PremintExecutorImpl} from "../../src/delegation/ZoraCreator1155PremintExecutorImpl.sol"; import {IZoraCreator1155PremintExecutor} from "../../src/interfaces/IZoraCreator1155PremintExecutor.sol"; -import {ZoraCreator1155Attribution, ContractCreationConfig, TokenCreationConfig, TokenCreationConfigV2, PremintConfigV2, PremintConfig} from "../../src/delegation/ZoraCreator1155Attribution.sol"; +import {ZoraCreator1155Attribution, PremintEncoding} from "../../src/delegation/ZoraCreator1155Attribution.sol"; +import {ContractCreationConfig, TokenCreationConfigV2, PremintConfigV2, MintArguments, PremintResult} from "@zoralabs/shared-contracts/entities/Premint.sol"; import {UUPSUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import {ProxyShim} from "../../src/utils/ProxyShim.sol"; import {IMinterErrors} from "../../src/interfaces/IMinterErrors.sol"; @@ -62,8 +63,9 @@ contract ZoraCreator1155PreminterTest is Test { address internal zora; address internal premintExecutor; address internal collector; + address internal firstMinter; - IZoraCreator1155PremintExecutor.MintArguments defaultMintArguments; + MintArguments defaultMintArguments; ProtocolRewards rewards; function setUp() external { @@ -71,6 +73,7 @@ contract ZoraCreator1155PreminterTest is Test { zora = makeAddr("zora"); premintExecutor = makeAddr("premintExecutor"); collector = makeAddr("collector"); + firstMinter = collector; vm.startPrank(zora); (rewards, , , factoryProxy, ) = Zora1155FactoryFixtures.setup1155AndFactoryProxy(zora, zora); @@ -80,11 +83,7 @@ contract ZoraCreator1155PreminterTest is Test { preminter = new ZoraCreator1155PremintExecutorImpl(factory); - defaultMintArguments = IZoraCreator1155PremintExecutor.MintArguments({ - mintRecipient: premintExecutor, - mintComment: "blah", - mintRewardsRecipients: new address[](0) - }); + defaultMintArguments = MintArguments({mintRecipient: premintExecutor, mintComment: "blah", mintRewardsRecipients: new address[](0)}); } function makeDefaultContractCreationConfig() internal view returns (ContractCreationConfig memory) { @@ -120,12 +119,13 @@ contract ZoraCreator1155PreminterTest is Test { uint256 mintCost = (mintFeeAmount + premintConfig.tokenConfig.pricePerToken) * quantityToMint; // when - IZoraCreator1155PremintExecutor.PremintResult memory premintResult = preminter.premintV2WithSignerContract{value: mintCost}( + PremintResult memory premintResult = preminter.premintV2WithSignerContract{value: mintCost}( contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments, + firstMinter, address(mockAA) ); @@ -148,7 +148,15 @@ contract ZoraCreator1155PreminterTest is Test { // this should revert - because the smart wallet param is not a contract. vm.expectRevert(IZoraCreator1155Errors.premintSignerContractNotAContract.selector); - preminter.premintV2WithSignerContract{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments, creator); + preminter.premintV2WithSignerContract{value: mintCost}( + contractConfig, + premintConfig, + signature, + quantityToMint, + defaultMintArguments, + firstMinter, + creator + ); } function test_premintV2_whenpremintSignerContract_revertsWhen_premintSignerContractRejectsSigner() external { @@ -169,7 +177,15 @@ contract ZoraCreator1155PreminterTest is Test { uint256 mintCost = (mintFeeAmount + premintConfig.tokenConfig.pricePerToken) * quantityToMint; vm.expectRevert(abi.encodeWithSelector(IZoraCreator1155Errors.InvalidSigner.selector, bytes4(0))); - preminter.premintV2WithSignerContract{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments, address(mockAA)); + preminter.premintV2WithSignerContract{value: mintCost}( + contractConfig, + premintConfig, + signature, + quantityToMint, + defaultMintArguments, + firstMinter, + address(mockAA) + ); } function test_premintV2_whenpremintSignerContract_revertsWhen_invalidSignature() external { @@ -188,7 +204,15 @@ contract ZoraCreator1155PreminterTest is Test { bytes memory signature = abi.encodePacked("bad"); vm.expectRevert(IZoraCreator1155Errors.premintSignerContractFailedToRecoverSigner.selector); - preminter.premintV2WithSignerContract{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments, address(mockAA)); + preminter.premintV2WithSignerContract{value: mintCost}( + contractConfig, + premintConfig, + signature, + quantityToMint, + defaultMintArguments, + firstMinter, + address(mockAA) + ); } function test_premintV2_whenpremintSignerContract_revertsWhen_premintSignerContractNotAContract() external { @@ -207,6 +231,7 @@ contract ZoraCreator1155PreminterTest is Test { bytes(""), 1, defaultMintArguments, + firstMinter, // here we pass an account thats not a contract - it should revert makeAddr("randomAccount") ); @@ -219,7 +244,7 @@ contract ZoraCreator1155PreminterTest is Test { uint256 chainId ) private pure returns (bytes memory signature) { bytes32 structHash = ZoraCreator1155Attribution.hashPremint(premintConfig); - bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, ZoraCreator1155Attribution.HASHED_VERSION_2, chainId); + bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, contractAddress, PremintEncoding.HASHED_VERSION_2, chainId); // create a signature with the digest for the params signature = _sign(privateKey, digest); diff --git a/packages/1155-deployments/package.json b/packages/1155-deployments/package.json index 35bac375d..0ef9b774d 100644 --- a/packages/1155-deployments/package.json +++ b/packages/1155-deployments/package.json @@ -9,16 +9,18 @@ "dev": "FOUNDRY_PROFILE=dev forge test --watch -vvv", "test": "FORK_TEST_CHAINS=mainnet,optimism,zora,sepolia,base,zora_sepolia,arbitrum_one,arbitrum_sepolia,blast,blast_sepolia forge test -vvv", "copy-deployed-contracts": "yarn tsx script/copy-deployed-contracts.ts", + "unlink-common": "rm -rf ./node_modules/@zoralabs/shared-contracts && cp -r ../shared-contracts ./node_modules/@zoralabs/shared-contracts", "unlink-protocol-rewards": "rm -rf ./node_modules/@zoralabs/protocol-rewards && cp -r ../protocol-rewards ./node_modules/@zoralabs/protocol-rewards", "unlink-1155": "rm -rf ./node_modules/@zoralabs/zora-1155-contracts && cp -r ../1155-contracts ./node_modules/@zoralabs/zora-1155-contracts", - "unlink-contracts": "yarn unlink-protocol-rewards && yarn unlink-1155", + "unlink-contracts": "yarn unlink-common && yarn unlink-protocol-rewards && yarn unlink-1155", "link-contracts": "rm -rf ./node_modules && cd .. && yarn" }, "dependencies": { "solmate": "6.1.0", "forge-std": "https://github.com/foundry-rs/forge-std#705263c95892a906d7af65f0f73ce8a4a0c80b80", "ds-test": "https://github.com/dapphub/ds-test#cd98eff28324bfac652e63a239a60632a761790b", - "@zoralabs/zora-1155-contracts": "*" + "@zoralabs/zora-1155-contracts": "*", + "@zoralabs/shared-contracts": "*" }, "devDependencies": { "zoralabs-tsconfig": "*", diff --git a/packages/1155-deployments/remappings.txt b/packages/1155-deployments/remappings.txt index 9e89d8c48..6b52e1410 100644 --- a/packages/1155-deployments/remappings.txt +++ b/packages/1155-deployments/remappings.txt @@ -3,6 +3,8 @@ forge-std/=node_modules/forge-std/src/ @zoralabs/openzeppelin-contracts-upgradeable/=node_modules/@zoralabs/openzeppelin-contracts-upgradeable/ @zoralabs/protocol-rewards/src/=node_modules/@zoralabs/protocol-rewards/src/ @zoralabs/zora-1155-contracts/src/=node_modules/@zoralabs/zora-1155-contracts/src/ +@zoralabs/mints-contracts/src/=node_modules/@zoralabs/mints-contracts/src/ +@zoralabs/shared-contracts/=node_modules/@zoralabs/shared-contracts/src/ @openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ _imagine=node_modules/@zoralabs/zora-1155-contracts/_imagine solemate/=/node_modules/solemate/src/ diff --git a/packages/1155-deployments/script/DeployProxiesToNewChain.s.sol b/packages/1155-deployments/script/DeployProxiesToNewChain.s.sol index f41a2c800..5293394b6 100644 --- a/packages/1155-deployments/script/DeployProxiesToNewChain.s.sol +++ b/packages/1155-deployments/script/DeployProxiesToNewChain.s.sol @@ -8,6 +8,7 @@ import {ZoraDeployerBase} from "../src/ZoraDeployerBase.sol"; import {Deployment} from "../src/DeploymentConfig.sol"; import {ZoraDeployerUtils} from "../src/ZoraDeployerUtils.sol"; import {DeploymentTestingUtils} from "../src/DeploymentTestingUtils.sol"; +import {MintArguments} from "@zoralabs/shared-contracts/entities/Premint.sol"; import {IZoraCreator1155PremintExecutor} from "@zoralabs/zora-1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol"; contract DeployProxiesToNewChain is ZoraDeployerBase { @@ -33,11 +34,7 @@ contract DeployProxiesToNewChain is ZoraDeployerBase { console2.log("testing premint"); address fundsRecipient = vm.envAddress("TEST_PREMINT_FUNDS_RECIPIENT"); - IZoraCreator1155PremintExecutor.MintArguments memory mintArguments = IZoraCreator1155PremintExecutor.MintArguments({ - mintRecipient: fundsRecipient, - mintComment: "", - mintRewardsRecipients: new address[](0) - }); + MintArguments memory mintArguments = MintArguments({mintRecipient: fundsRecipient, mintComment: "", mintRewardsRecipients: new address[](0)}); signAndExecutePremintV2(deployment.preminterProxy, vm.envAddress("TEST_PREMINT_FUNDS_RECIPIENT"), mintArguments); diff --git a/packages/1155-deployments/script/DeployTestContracts.s.sol b/packages/1155-deployments/script/DeployTestContracts.s.sol index 2d1e15e95..06537525e 100644 --- a/packages/1155-deployments/script/DeployTestContracts.s.sol +++ b/packages/1155-deployments/script/DeployTestContracts.s.sol @@ -7,6 +7,7 @@ import "forge-std/console2.sol"; import {ZoraDeployerBase} from "../src/ZoraDeployerBase.sol"; import {Deployment} from "../src/DeploymentConfig.sol"; import {ZoraDeployerUtils} from "../src/ZoraDeployerUtils.sol"; +import {MintArguments} from "@zoralabs/shared-contracts/entities/Premint.sol"; import {IZoraCreator1155PremintExecutor} from "@zoralabs/zora-1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol"; contract DeployTestContracts is ZoraDeployerBase { @@ -18,11 +19,7 @@ contract DeployTestContracts is ZoraDeployerBase { ZoraDeployerUtils.deployTestContractForVerification(deployment.factoryProxy, makeAddr("admin")); address fundsRecipient = vm.envAddress("DEPLOYER"); - IZoraCreator1155PremintExecutor.MintArguments memory mintArguments = IZoraCreator1155PremintExecutor.MintArguments({ - mintRecipient: fundsRecipient, - mintComment: "", - mintRewardsRecipients: new address[](0) - }); + MintArguments memory mintArguments = MintArguments({mintRecipient: fundsRecipient, mintComment: "", mintRewardsRecipients: new address[](0)}); signAndExecutePremintV2(deployment.preminterProxy, fundsRecipient, mintArguments); diff --git a/packages/1155-deployments/src/DeploymentTestingUtils.sol b/packages/1155-deployments/src/DeploymentTestingUtils.sol index 6744cc1ed..75faa8182 100644 --- a/packages/1155-deployments/src/DeploymentTestingUtils.sol +++ b/packages/1155-deployments/src/DeploymentTestingUtils.sol @@ -6,7 +6,9 @@ import {IMinter1155} from "@zoralabs/zora-1155-contracts/src/interfaces/IMinter1 import {IZoraCreator1155PremintExecutor} from "@zoralabs/zora-1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol"; import {ZoraCreator1155PremintExecutorImpl} from "@zoralabs/zora-1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol"; import {ZoraCreator1155FactoryImpl} from "@zoralabs/zora-1155-contracts/src/factory/ZoraCreator1155FactoryImpl.sol"; -import {ZoraCreator1155Attribution, ContractCreationConfig, PremintConfigV2, TokenCreationConfigV2, PremintConfig, TokenCreationConfig} from "@zoralabs/zora-1155-contracts/src/delegation/ZoraCreator1155Attribution.sol"; +import {ZoraCreator1155Attribution} from "@zoralabs/zora-1155-contracts/src/delegation/ZoraCreator1155Attribution.sol"; +import {ContractCreationConfig, PremintConfigV2, TokenCreationConfigV2, PremintConfig, TokenCreationConfig, MintArguments, PremintResult} from "@zoralabs/shared-contracts/entities/Premint.sol"; +import {PremintEncoding} from "@zoralabs/shared-contracts/premint/PremintEncoding.sol"; import {ScriptDeploymentConfig} from "./DeploymentConfig.sol"; import {ZoraCreator1155Impl} from "@zoralabs/zora-1155-contracts/src/nft/ZoraCreator1155Impl.sol"; @@ -51,11 +53,7 @@ contract DeploymentTestingUtils is Script { signature = signPremint(premintConfig, deterministicAddress, creatorPrivateKey); } - function signAndExecutePremintV1( - address premintExecutorProxyAddress, - address payoutRecipient, - IZoraCreator1155PremintExecutor.MintArguments memory mintArguments - ) internal { + function signAndExecutePremintV1(address premintExecutorProxyAddress, address payoutRecipient, MintArguments memory mintArguments) internal { ( ContractCreationConfig memory contractConfig, IZoraCreator1155PremintExecutor preminterAtProxy, @@ -66,7 +64,7 @@ contract DeploymentTestingUtils is Script { uint256 quantityToMint = 1; // execute the premint - IZoraCreator1155PremintExecutor.PremintResult memory premintResult = preminterAtProxy.premintV1{value: mintFee(quantityToMint)}( + PremintResult memory premintResult = preminterAtProxy.premintV1{value: mintFee(quantityToMint)}( contractConfig, premintConfig, signature, @@ -117,11 +115,7 @@ contract DeploymentTestingUtils is Script { signature = signPremint(premintConfig, deterministicAddress, creatorPrivateKey); } - function signAndExecutePremintV2( - address premintExecutorProxyAddress, - address payoutRecipient, - IZoraCreator1155PremintExecutor.MintArguments memory mintArguments - ) internal { + function signAndExecutePremintV2(address premintExecutorProxyAddress, address payoutRecipient, MintArguments memory mintArguments) internal { ( ContractCreationConfig memory contractConfig, IZoraCreator1155PremintExecutor preminterAtProxy, @@ -141,7 +135,7 @@ contract DeploymentTestingUtils is Script { } function signPremint(PremintConfigV2 memory premintConfig, address deterministicAddress, uint256 privateKey) private view returns (bytes memory signature) { - bytes32 signatureVersion = ZoraCreator1155Attribution.HASHED_VERSION_2; + bytes32 signatureVersion = PremintEncoding.HASHED_VERSION_2; bytes32 structHash = ZoraCreator1155Attribution.hashPremint(premintConfig); // sign the premint bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, deterministicAddress, signatureVersion, block.chainid); @@ -155,7 +149,7 @@ contract DeploymentTestingUtils is Script { } function signPremint(PremintConfig memory premintConfig, address deterministicAddress, uint256 privateKey) private view returns (bytes memory signature) { - bytes32 signatureVersion = ZoraCreator1155Attribution.HASHED_VERSION_1; + bytes32 signatureVersion = PremintEncoding.HASHED_VERSION_1; bytes32 structHash = ZoraCreator1155Attribution.hashPremint(premintConfig); // sign the premint bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4(structHash, deterministicAddress, signatureVersion, block.chainid); diff --git a/packages/1155-deployments/test/UpgradesTest.t.sol b/packages/1155-deployments/test/UpgradesTest.t.sol index 788d81f0a..2f050ac21 100644 --- a/packages/1155-deployments/test/UpgradesTest.t.sol +++ b/packages/1155-deployments/test/UpgradesTest.t.sol @@ -7,6 +7,7 @@ import {ZoraCreator1155PremintExecutorImpl} from "@zoralabs/zora-1155-contracts/ import {ForkDeploymentConfig, Deployment, ChainConfig} from "../src/DeploymentConfig.sol"; import {ZoraDeployerUtils} from "../src/ZoraDeployerUtils.sol"; import {DeploymentTestingUtils} from "../src/DeploymentTestingUtils.sol"; +import {MintArguments} from "@zoralabs/shared-contracts/entities/Premint.sol"; import {IZoraCreator1155PremintExecutor} from "@zoralabs/zora-1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol"; contract UpgradesTest is ForkDeploymentConfig, DeploymentTestingUtils, Test { @@ -173,11 +174,7 @@ contract UpgradesTest is ForkDeploymentConfig, DeploymentTestingUtils, Test { address[] memory mintRewardsRecipients = new address[](1); mintRewardsRecipients[0] = mintReferral; - IZoraCreator1155PremintExecutor.MintArguments memory mintArguments = IZoraCreator1155PremintExecutor.MintArguments({ - mintRecipient: collector, - mintComment: "", - mintRewardsRecipients: mintRewardsRecipients - }); + MintArguments memory mintArguments = MintArguments({mintRecipient: collector, mintComment: "", mintRewardsRecipients: mintRewardsRecipients}); vm.startPrank(collector); signAndExecutePremintV1(targetPreminterProxy, makeAddr("payoutRecipientA"), mintArguments); diff --git a/packages/1155-deployments/test/ZoraCreator1155PremintExecutorForkTest.t.sol b/packages/1155-deployments/test/ZoraCreator1155PremintExecutorForkTest.t.sol index f65d0b1cd..0177fc024 100644 --- a/packages/1155-deployments/test/ZoraCreator1155PremintExecutorForkTest.t.sol +++ b/packages/1155-deployments/test/ZoraCreator1155PremintExecutorForkTest.t.sol @@ -3,7 +3,9 @@ pragma solidity 0.8.17; import "forge-std/Test.sol"; import {ForkDeploymentConfig} from "../src/DeploymentConfig.sol"; -import {ZoraCreator1155Attribution, ContractCreationConfig, PremintConfig, PremintConfigV2, TokenCreationConfig} from "@zoralabs/zora-1155-contracts/src/delegation/ZoraCreator1155Attribution.sol"; +import {ZoraCreator1155Attribution} from "@zoralabs/zora-1155-contracts/src/delegation/ZoraCreator1155Attribution.sol"; +import {ContractCreationConfig, PremintConfig, PremintConfigV2, TokenCreationConfig, MintArguments} from "@zoralabs/shared-contracts/entities/Premint.sol"; +import {PremintEncoding} from "@zoralabs/shared-contracts/premint/PremintEncoding.sol"; import {ZoraCreator1155PremintExecutorImpl} from "@zoralabs/zora-1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol"; import {ZoraCreator1155FactoryImpl} from "@zoralabs/zora-1155-contracts/src/factory/ZoraCreator1155FactoryImpl.sol"; import {IZoraCreator1155PremintExecutor} from "@zoralabs/zora-1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol"; @@ -132,7 +134,7 @@ contract ZoraCreator1155PreminterForkTest is ForkDeploymentConfig, Test { // now call the premint function, using the same config that was used to generate the digest, and the signature vm.prank(executor); - IZoraCreator1155PremintExecutor.MintArguments memory mintArguments; + MintArguments memory mintArguments; mintArguments.mintComment = comment; mintArguments.mintRecipient = executor; newTokenId = preminter.premintV1{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, mintArguments).tokenId; @@ -152,7 +154,7 @@ contract ZoraCreator1155PreminterForkTest is ForkDeploymentConfig, Test { premintConfig, signature, quantityToMint, - IZoraCreator1155PremintExecutor.MintArguments({mintRecipient: executor, mintComment: comment, mintRewardsRecipients: new address[](0)}) + MintArguments({mintRecipient: executor, mintComment: comment, mintRewardsRecipients: new address[](0)}) ); } @@ -160,7 +162,7 @@ contract ZoraCreator1155PreminterForkTest is ForkDeploymentConfig, Test { bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4( ZoraCreator1155Attribution.hashPremint(premintConfig), contractAddress, - ZoraCreator1155Attribution.HASHED_VERSION_1, + PremintEncoding.HASHED_VERSION_1, chainId ); @@ -183,7 +185,7 @@ contract ZoraCreator1155PreminterForkTest is ForkDeploymentConfig, Test { premintConfigV2, signature, quantityToMint, - IZoraCreator1155PremintExecutor.MintArguments({mintRecipient: executor, mintComment: comment, mintRewardsRecipients: new address[](0)}) + MintArguments({mintRecipient: executor, mintComment: comment, mintRewardsRecipients: new address[](0)}) ); } @@ -191,7 +193,7 @@ contract ZoraCreator1155PreminterForkTest is ForkDeploymentConfig, Test { bytes32 digest = ZoraCreator1155Attribution.premintHashedTypeDataV4( ZoraCreator1155Attribution.hashPremint(premintConfigV2), contractAddress, - ZoraCreator1155Attribution.HASHED_VERSION_2, + PremintEncoding.HASHED_VERSION_2, chainId ); diff --git a/packages/shared-contracts/package.json b/packages/shared-contracts/package.json new file mode 100644 index 000000000..01d764955 --- /dev/null +++ b/packages/shared-contracts/package.json @@ -0,0 +1,22 @@ +{ + "name": "@zoralabs/shared-contracts", + "version": "0.0.0", + "license": "MIT", + "private": true, + "files": [ + "src/" + ], + "scripts": { + "prettier:check": "prettier --check 'src/**/*.sol'", + "prettier": "prettier --write 'src/**/*.sol'" + }, + "dependencies": { + "@openzeppelin/contracts": "^5.0.1", + "ds-test": "https://github.com/dapphub/ds-test#cd98eff28324bfac652e63a239a60632a761790b", + "forge-std": "https://github.com/foundry-rs/forge-std#705263c95892a906d7af65f0f73ce8a4a0c80b80", + "solady": "^0.0.168" + }, + "devDependencies": { + "prettier-plugin-solidity": "^1.3.1" + } +} diff --git a/packages/shared-contracts/remappings.txt b/packages/shared-contracts/remappings.txt new file mode 100644 index 000000000..27618b21f --- /dev/null +++ b/packages/shared-contracts/remappings.txt @@ -0,0 +1,4 @@ +ds-test/=node_modules/ds-test/src/ +forge-std/=node_modules/forge-std/src/ +solady/=node_modules/solady/src/ +@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ \ No newline at end of file diff --git a/packages/shared-contracts/src/entities/Premint.sol b/packages/shared-contracts/src/entities/Premint.sol new file mode 100644 index 000000000..695b8a821 --- /dev/null +++ b/packages/shared-contracts/src/entities/Premint.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +struct ContractCreationConfig { + // Creator/admin of the created contract. Must match the account that signed the message + address contractAdmin; + // Metadata URI for the created contract + string contractURI; + // Name of the created contract + string contractName; +} + +struct PremintConfig { + // The config for the token to be created + TokenCreationConfig tokenConfig; + // Unique id of the token, used to ensure that multiple signatures can't be used to create the same intended token. + // only one signature per token id, scoped to the contract hash can be executed. + uint32 uid; + // Version of this premint, scoped to the uid and contract. Not used for logic in the contract, but used externally to track the newest version + uint32 version; + // If executing this signature results in preventing any signature with this uid from being minted. + bool deleted; +} + +struct TokenCreationConfig { + // Metadata URI for the created token + string tokenURI; + // Max supply of the created token + uint256 maxSupply; + // Max tokens that can be minted for an address, 0 if unlimited + uint64 maxTokensPerAddress; + // Price per token in eth wei. 0 for a free mint. + uint96 pricePerToken; + // The start time of the mint, 0 for immediate. Prevents signatures from being used until the start time. + uint64 mintStart; + // The duration of the mint, starting from the first mint of this token. 0 for infinite + uint64 mintDuration; + // deperecated field; will be ignored. + uint32 royaltyMintSchedule; + // RoyaltyBPS for created tokens. The royalty amount in basis points for secondary sales. + uint32 royaltyBPS; + // This is the address that will be set on the `royaltyRecipient` for the created token on the 1155 contract, + // which is the address that receives creator rewards and secondary royalties for the token, + // and on the `fundsRecipient` on the ZoraCreatorFixedPriceSaleStrategy contract for the token, + // which is the address that receives paid mint funds for the token. + address royaltyRecipient; + // Fixed price minter address + address fixedPriceMinter; +} + +struct PremintConfigV2 { + // The config for the token to be created + TokenCreationConfigV2 tokenConfig; + // Unique id of the token, used to ensure that multiple signatures can't be used to create the same intended token. + // only one signature per token id, scoped to the contract hash can be executed. + uint32 uid; + // Version of this premint, scoped to the uid and contract. Not used for logic in the contract, but used externally to track the newest version + uint32 version; + // If executing this signature results in preventing any signature with this uid from being minted. + bool deleted; +} + +struct TokenCreationConfigV2 { + // Metadata URI for the created token + string tokenURI; + // Max supply of the created token + uint256 maxSupply; + // Max tokens that can be minted for an address, 0 if unlimited + uint64 maxTokensPerAddress; + // Price per token in eth wei. 0 for a free mint. + uint96 pricePerToken; + // The start time of the mint, 0 for immediate. Prevents signatures from being used until the start time. + uint64 mintStart; + // The duration of the mint, starting from the first mint of this token. 0 for infinite + uint64 mintDuration; + // RoyaltyBPS for created tokens. The royalty amount in basis points for secondary sales. + uint32 royaltyBPS; + // This is the address that will be set on the `royaltyRecipient` for the created token on the 1155 contract, + // which is the address that receives creator rewards and secondary royalties for the token, + // and on the `fundsRecipient` on the ZoraCreatorFixedPriceSaleStrategy contract for the token, + // which is the address that receives paid mint funds for the token. + address payoutRecipient; + // Fixed price minter address + address fixedPriceMinter; + // create referral + address createReferral; +} + +struct MintArguments { + address mintRecipient; + string mintComment; + /// array of accounts to receive rewards - mintReferral is first argument, and platformReferral is second. platformReferral isn't supported as of now but will be in a future release. + address[] mintRewardsRecipients; +} + +struct PremintResult { + address contractAddress; + uint256 tokenId; + bool createdNewContract; +} diff --git a/packages/shared-contracts/src/interfaces/ICreatorCommands.sol b/packages/shared-contracts/src/interfaces/ICreatorCommands.sol new file mode 100644 index 000000000..b2ee709a3 --- /dev/null +++ b/packages/shared-contracts/src/interfaces/ICreatorCommands.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +/// @notice Creator Commands used by minter modules passed back to the main modules +interface ICreatorCommands { + /// @notice This enum is used to define supported creator action types. + /// This can change in the future + enum CreatorActions { + // No operation - also the default for mintings that may not return a command + NO_OP, + // Send ether + SEND_ETH, + // Mint operation + MINT + } + + /// @notice This command is for + struct Command { + // Method for operation + CreatorActions method; + // Arguments used for this operation + bytes args; + } + + /// @notice This command set is returned from the minter back to the user + struct CommandSet { + Command[] commands; + uint256 at; + } +} diff --git a/packages/shared-contracts/src/interfaces/IERC165Upgradeable.sol b/packages/shared-contracts/src/interfaces/IERC165Upgradeable.sol new file mode 100644 index 000000000..73f352902 --- /dev/null +++ b/packages/shared-contracts/src/interfaces/IERC165Upgradeable.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +/** + * @dev Interface of the ERC165 standard, as defined in the + * https://eips.ethereum.org/EIPS/eip-165[EIP]. + * + * Implementers can declare support of contract interfaces, which can then be + * queried by others ({ERC165Checker}). + * + * For an implementation, see {ERC165}. + */ +interface IERC165Upgradeable { + /** + * @dev Returns true if this contract implements the interface defined by + * `interfaceId`. See the corresponding + * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] + * to learn more about how these ids are created. + * + * This function call must use less than 30 000 gas. + */ + function supportsInterface(bytes4 interfaceId) external view returns (bool); +} diff --git a/packages/shared-contracts/src/interfaces/IGetContractAddress.sol b/packages/shared-contracts/src/interfaces/IGetContractAddress.sol new file mode 100644 index 000000000..6c4fb6259 --- /dev/null +++ b/packages/shared-contracts/src/interfaces/IGetContractAddress.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +import {ContractCreationConfig} from "../entities/Premint.sol"; + +interface IGetContractAddress { + function getContractAddress(ContractCreationConfig calldata contractConfig) external view returns (address); +} diff --git a/packages/shared-contracts/src/interfaces/IImmutableCreate2Factory.sol b/packages/shared-contracts/src/interfaces/IImmutableCreate2Factory.sol new file mode 100644 index 000000000..4e67f4a78 --- /dev/null +++ b/packages/shared-contracts/src/interfaces/IImmutableCreate2Factory.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +// Extracted interface of ImmutableCreate2Factory.sol, located at https://raw.githubusercontent.com/0age/metamorphic/master/contracts/ImmutableCreate2Factory.sol + +interface IImmutableCreate2Factory { + /** + * @dev Create a contract using CREATE2 by submitting a given salt or nonce + * along with the initialization code for the contract. Note that the first 20 + * bytes of the salt must match those of the calling address, which prevents + * contract creation events from being submitted by unintended parties. + * @param salt bytes32 The nonce that will be passed into the CREATE2 call. + * @param initializationCode bytes The initialization code that will be passed + * into the CREATE2 call. + * @return deploymentAddress Address of the contract that will be created, or the null address + * if a contract already exists at that address. + */ + function safeCreate2(bytes32 salt, bytes calldata initializationCode) external payable returns (address deploymentAddress); + + /** + * @dev Compute the address of the contract that will be created when + * submitting a given salt or nonce to the contract along with the contract's + * initialization code. The CREATE2 address is computed in accordance with + * EIP-1014, and adheres to the formula therein of + * `keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)))[12:]` when + * performing the computation. The computed address is then checked for any + * existing contract code - if so, the null address will be returned instead. + * @param salt bytes32 The nonce passed into the CREATE2 address calculation. + * @param initCode bytes The contract initialization code to be used. + * that will be passed into the CREATE2 address calculation. + * @return deploymentAddress Address of the contract that will be created, or the null address + * if a contract has already been deployed to that address. + */ + function findCreate2Address(bytes32 salt, bytes calldata initCode) external view returns (address deploymentAddress); + + /** + * @dev Compute the address of the contract that will be created when + * submitting a given salt or nonce to the contract along with the keccak256 + * hash of the contract's initialization code. The CREATE2 address is computed + * in accordance with EIP-1014, and adheres to the formula therein of + * `keccak256( 0xff ++ address ++ salt ++ keccak256(init_code)))[12:]` when + * performing the computation. The computed address is then checked for any + * existing contract code - if so, the null address will be returned instead. + * @param salt bytes32 The nonce passed into the CREATE2 address calculation. + * @param initCodeHash bytes32 The keccak256 hash of the initialization code + * that will be passed into the CREATE2 address calculation. + * @return deploymentAddress Address of the contract that will be created, or the null address + * if a contract has already been deployed to that address. + */ + function findCreate2AddressViaHash(bytes32 salt, bytes32 initCodeHash) external view returns (address deploymentAddress); + + /** + * @dev Determine if a contract has already been deployed by the factory to a + * given address. + * @param deploymentAddress address The contract address to check. + * @return True if the contract has been deployed, false otherwise. + */ + function hasBeenDeployed(address deploymentAddress) external view returns (bool); +} diff --git a/packages/shared-contracts/src/interfaces/ILegacyNaming.sol b/packages/shared-contracts/src/interfaces/ILegacyNaming.sol new file mode 100644 index 000000000..a8f7d740d --- /dev/null +++ b/packages/shared-contracts/src/interfaces/ILegacyNaming.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +interface ILegacyNaming { + function name() external returns (string memory); + + function symbol() external returns (string memory); +} diff --git a/packages/shared-contracts/src/interfaces/IMinter1155.sol b/packages/shared-contracts/src/interfaces/IMinter1155.sol new file mode 100644 index 000000000..5ccfcc1f8 --- /dev/null +++ b/packages/shared-contracts/src/interfaces/IMinter1155.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +import {ICreatorCommands} from "./ICreatorCommands.sol"; +import {IERC165Upgradeable} from "./IERC165Upgradeable.sol"; + +/// @notice Minter standard interface +/// @dev Minters need to confirm to the ERC165 selector of type(IMinter1155).interfaceId +interface IMinter1155 is IERC165Upgradeable { + function requestMint( + address sender, + uint256 tokenId, + uint256 quantity, + uint256 ethValueSent, + bytes calldata minterArguments + ) external returns (ICreatorCommands.CommandSet memory commands); +} diff --git a/packages/shared-contracts/src/interfaces/IVersionedContract.sol b/packages/shared-contracts/src/interfaces/IVersionedContract.sol new file mode 100644 index 000000000..c4569c9ee --- /dev/null +++ b/packages/shared-contracts/src/interfaces/IVersionedContract.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +interface IVersionedContract { + function contractVersion() external returns (string memory); +} diff --git a/packages/shared-contracts/src/interfaces/IZoraCreator1155PremintExecutorV2.sol b/packages/shared-contracts/src/interfaces/IZoraCreator1155PremintExecutorV2.sol new file mode 100644 index 000000000..df58e88b6 --- /dev/null +++ b/packages/shared-contracts/src/interfaces/IZoraCreator1155PremintExecutorV2.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +import {ContractCreationConfig, PremintConfigV2, PremintResult, MintArguments} from "../entities/Premint.sol"; +import {IGetContractAddress} from "./IGetContractAddress.sol"; + +interface IZoraCreator1155PremintExecutorV2 is IGetContractAddress { + function premintV2( + ContractCreationConfig calldata contractConfig, + PremintConfigV2 calldata premintConfig, + bytes calldata signature, + uint256 quantityToMint, + MintArguments calldata mintArguments + ) external payable returns (PremintResult memory); + + function premintV2WithSignerContract( + ContractCreationConfig calldata contractConfig, + PremintConfigV2 calldata premintConfig, + bytes calldata signature, + uint256 quantityToMint, + MintArguments calldata mintArguments, + address firstMinter, + address signerContract + ) external payable returns (PremintResult memory result); +} diff --git a/packages/shared-contracts/src/interfaces/errors/IMinterErrors.sol b/packages/shared-contracts/src/interfaces/errors/IMinterErrors.sol new file mode 100644 index 000000000..ff474ec0a --- /dev/null +++ b/packages/shared-contracts/src/interfaces/errors/IMinterErrors.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +interface IMinterErrors { + error CallerNotZoraCreator1155(); + error MinterContractAlreadyExists(); + error MinterContractDoesNotExist(); + + error SaleEnded(); + error SaleHasNotStarted(); + error WrongValueSent(); + error InvalidMerkleProof(address mintTo, bytes32[] merkleProof, bytes32 merkleRoot); +} diff --git a/packages/shared-contracts/src/interfaces/errors/IZoraCreator1155Errors.sol b/packages/shared-contracts/src/interfaces/errors/IZoraCreator1155Errors.sol new file mode 100644 index 000000000..3b0227244 --- /dev/null +++ b/packages/shared-contracts/src/interfaces/errors/IZoraCreator1155Errors.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +import {IMinterErrors} from "./IMinterErrors.sol"; + +interface ILimitedMintPerAddressErrors { + error UserExceedsMintLimit(address user, uint256 limit, uint256 requestedAmount); +} + +interface ICreatorRoyaltyErrors { + /// @notice Thrown when a user tries to have 100% supply royalties + error InvalidMintSchedule(); +} + +interface IZoraCreator1155Errors is ICreatorRoyaltyErrors, ILimitedMintPerAddressErrors, IMinterErrors { + error Call_TokenIdMismatch(); + error TokenIdMismatch(uint256 expected, uint256 actual); + error UserMissingRoleForToken(address user, uint256 tokenId, uint256 role); + + error Config_TransferHookNotSupported(address proposedAddress); + + error Mint_InsolventSaleTransfer(); + error Mint_ValueTransferFail(); + error Mint_TokenIDMintNotAllowed(); + error Mint_UnknownCommand(); + error Mint_InvalidMintArrayLength(); + + error Burn_NotOwnerOrApproved(address operator, address user); + + error NewOwnerNeedsToBeAdmin(); + + error Sale_CannotCallNonSalesContract(address targetContract); + + error CallFailed(bytes reason); + error Renderer_NotValidRendererContract(); + + error ETHWithdrawFailed(address recipient, uint256 amount); + error FundsWithdrawInsolvent(uint256 amount, uint256 contractValue); + error ProtocolRewardsWithdrawFailed(address caller, address recipient, uint256 amount); + + error CannotMintMoreTokens(uint256 tokenId, uint256 quantity, uint256 totalMinted, uint256 maxSupply); + + error MintNotYetStarted(); + error PremintDeleted(); + + // DelegatedMinting related errors + error InvalidSignatureVersion(); + error premintSignerContractNotAContract(); + error InvalidSignature(); + error InvalidSigner(bytes4 magicValue); + error premintSignerContractFailedToRecoverSigner(); + error FirstMinterAddressZero(); + + error ERC1155_MINT_TO_ZERO_ADDRESS(); +} diff --git a/packages/shared-contracts/src/mocks/ReceiveRejector.sol b/packages/shared-contracts/src/mocks/ReceiveRejector.sol new file mode 100644 index 000000000..8d2015e43 --- /dev/null +++ b/packages/shared-contracts/src/mocks/ReceiveRejector.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +contract ReceiveRejector { + receive() external payable { + revert("Transfer rejected"); + } +} diff --git a/packages/shared-contracts/src/premint/PremintEncoding.sol b/packages/shared-contracts/src/premint/PremintEncoding.sol new file mode 100644 index 000000000..76e7e2e78 --- /dev/null +++ b/packages/shared-contracts/src/premint/PremintEncoding.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.17; + +import {PremintConfig, PremintConfigV2} from "../entities/Premint.sol"; +import {IMinter1155} from "../interfaces/IMinter1155.sol"; + +struct EncodedPremintConfig { + bytes premintConfig; + bytes32 premintConfigVersion; + uint32 uid; + address fixedPriceMinter; +} + +library PremintEncoding { + string internal constant VERSION_1 = "1"; + bytes32 internal constant HASHED_VERSION_1 = keccak256(bytes(VERSION_1)); + string internal constant VERSION_2 = "2"; + bytes32 internal constant HASHED_VERSION_2 = keccak256(bytes(VERSION_2)); + + function encodePremintV1(PremintConfig memory premintConfig) internal pure returns (EncodedPremintConfig memory) { + return EncodedPremintConfig(abi.encode(premintConfig), HASHED_VERSION_1, premintConfig.uid, premintConfig.tokenConfig.fixedPriceMinter); + } + + function encodePremintV2(PremintConfigV2 memory premintConfig) internal pure returns (EncodedPremintConfig memory) { + return EncodedPremintConfig(abi.encode(premintConfig), HASHED_VERSION_2, premintConfig.uid, premintConfig.tokenConfig.fixedPriceMinter); + } +} diff --git a/packages/shared-contracts/src/utils/ImmutableCreate2FactoryUtils.sol b/packages/shared-contracts/src/utils/ImmutableCreate2FactoryUtils.sol new file mode 100644 index 000000000..051c814ef --- /dev/null +++ b/packages/shared-contracts/src/utils/ImmutableCreate2FactoryUtils.sol @@ -0,0 +1,57 @@ +// spdx-license-identifier: MIT +pragma solidity ^0.8.17; + +import {IImmutableCreate2Factory} from "../interfaces/IImmutableCreate2Factory.sol"; +import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; +import {LibString} from "solady/utils/LibString.sol"; + +library ImmutableCreate2FactoryUtils { + IImmutableCreate2Factory public constant IMMUTABLE_CREATE2_FACTORY = IImmutableCreate2Factory(0x0000000000FFe8B47B3e2130213B802212439497); + + bytes32 constant IMMUTABLE_CREATE_2_FRIENDLY_SALT = bytes32(0x0000000000000000000000000000000000000000000000000000000000000000); + + function saltWithAddressInFirst20Bytes(address addressToMakeSaltWith, uint256 suffix) internal pure returns (bytes32) { + uint256 shifted = uint256(uint160(address(addressToMakeSaltWith))) << 96; + + // shifted on the left, suffix on the right: + + return bytes32(shifted | suffix); + } + + /// Checks if a contract has been deployed at a determinstic address based on the sale using safe create 2, and if it hasnt been, deploys it + /// @param salt The salt to use for the create 2 address + /// @param creationCode The creation code to create with + function safeCreate2OrGetExisting(bytes32 salt, bytes memory creationCode) internal returns (address) { + address computedAddress = Create2.computeAddress(salt, keccak256(creationCode), address(IMMUTABLE_CREATE2_FACTORY)); + + // if hasn't been created, create it + if (computedAddress.code.length == 0) { + IMMUTABLE_CREATE2_FACTORY.safeCreate2(salt, creationCode); + } + + return computedAddress; + } + + function safeCreate2OrGetExistingWithFriendlySalt(bytes memory creationCode) internal returns (address) { + return safeCreate2OrGetExisting(IMMUTABLE_CREATE_2_FRIENDLY_SALT, creationCode); + } + + function immutableCreate2Address(bytes memory creationCode) internal pure returns (address) { + return immutableCreate2Address(IMMUTABLE_CREATE_2_FRIENDLY_SALT, creationCode); + } + + function immutableCreate2Address(bytes32 salt, bytes memory creationCode) internal pure returns (address) { + return Create2.computeAddress(salt, keccak256(creationCode), address(IMMUTABLE_CREATE2_FACTORY)); + } + + function generateMineSaltCommand(address deployer, address signer, bytes32 initCodeHash) internal pure returns (string memory) { + string memory targetCommand = "cargo run --release "; + targetCommand = string.concat(targetCommand, LibString.toHexString(deployer)); + targetCommand = string.concat(targetCommand, " "); + targetCommand = string.concat(targetCommand, LibString.toHexString(signer)); + targetCommand = string.concat(targetCommand, " "); + targetCommand = string.concat(targetCommand, LibString.toHexStringNoPrefix(uint256(initCodeHash), 32)); + targetCommand = string.concat(targetCommand, " 0"); + return targetCommand; + } +} diff --git a/yarn.lock b/yarn.lock index 4b26cef55..fe8c59c0b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1910,7 +1910,7 @@ fast-url-parser "^1.1.3" tslib "^2.3.1" -"@zoralabs/mints-contracts@^0.0.3": +"@zoralabs/mints-contracts@*", "@zoralabs/mints-contracts@^0.0.3": version "0.0.3" resolved "https://registry.yarnpkg.com/@zoralabs/mints-contracts/-/mints-contracts-0.0.3.tgz#26974e2e0d7d1d565e4d7589f646c0f2c5d0cf6b" integrity sha512-kmvSzzgGiBUr+d/aeWsdsz6MFKKp+4gElcivcZWigv45KNVAOz3mOEeKcMnAFcyN0j+XNrZCOi9R4AIu/Ckpcg== @@ -6966,6 +6966,11 @@ solady@0.0.132: resolved "https://registry.yarnpkg.com/solady/-/solady-0.0.132.tgz#5e81ec342990f334055db8e8f319786fcedb6b1a" integrity sha512-qMdj/Y5fgPmxcis3eTs1Z03Qt/DVt1VJmlugRNjw7DySkrMOW/rHNyUVqqvevsYaGXgbPT54z68chDNesFnH+Q== +solady@^0.0.168: + version "0.0.168" + resolved "https://registry.yarnpkg.com/solady/-/solady-0.0.168.tgz#b466f907455632241f459a623f285a30990ef645" + integrity sha512-7tgy21selT6Tg+8aAxkLUyjjCx9iQ3m3KE+5D4x/tIXr4wAfoVe6EK0lmmZjyIv8MRqQSx/vB6NfIC1LME3oZA== + solidity-comments-extractor@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19"