From 785787fcf1bfc5ef085529a9c58bafbfdf1470a2 Mon Sep 17 00:00:00 2001 From: Dan Oved Date: Mon, 23 Oct 2023 16:22:26 -0600 Subject: [PATCH] remove operator overloading --- .../1155-contracts/package/preminter.test.ts | 19 +- packages/1155-contracts/package/preminter.ts | 26 ++- .../ZoraCreator1155PremintExecutorImpl.sol | 171 ++++++------------ .../ZoraCreator1155PremintExecutorImplLib.sol | 38 ++++ .../src/deployment/DeploymentTestingUtils.sol | 13 +- .../IZoraCreator1155PremintExecutor.sol | 90 +++++++++ .../Zora1155PremintExecutorProxy.t.sol | 10 +- .../ZoraCreator1155PremintExecutor.t.sol | 74 ++++---- 8 files changed, 261 insertions(+), 180 deletions(-) create mode 100644 packages/1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol diff --git a/packages/1155-contracts/package/preminter.test.ts b/packages/1155-contracts/package/preminter.test.ts index cc705ea36..87409b587 100644 --- a/packages/1155-contracts/package/preminter.test.ts +++ b/packages/1155-contracts/package/preminter.test.ts @@ -198,14 +198,19 @@ describe("ZoraCreator1155Preminter", () => { }); // recover and verify address is correct - const [, , recoveredAddress] = await publicClient.readContract({ + const [isValidSignature] = await publicClient.readContract({ abi: preminterAbi, address: preminterAddress, - functionName: "isValidSignature", - args: [contractConfig, premintConfig, signedMessage], + functionName: "isValidSignatureV2", + args: [ + contractConfig.contractAdmin, + contractAddress, + premintConfig, + signedMessage, + ], }); - expect(recoveredAddress).to.equal(creatorAccount); + expect(isValidSignature).toBe(true); }, 20 * 1000 @@ -277,7 +282,7 @@ describe("ZoraCreator1155Preminter", () => { // parameters are required to call this function const mintHash = await walletClient.writeContract({ abi: preminterAbi, - functionName: "premint", + functionName: "premintV2", account: collectorAccount, address: preminterAddress, args: [ @@ -352,7 +357,7 @@ describe("ZoraCreator1155Preminter", () => { // it should create a new token against the existing contract const mintHash2 = await walletClient.writeContract({ abi: preminterAbi, - functionName: "premint", + functionName: "premintV2", account: collectorAccount, address: preminterAddress, args: [ @@ -450,7 +455,7 @@ describe("ZoraCreator1155Preminter", () => { // parameters are required to call this function const mintHash = await walletClient.writeContract({ abi: preminterAbi, - functionName: "premint", + functionName: "premintV2", account: collectorAccount, address: preminterAddress, args: [ diff --git a/packages/1155-contracts/package/preminter.ts b/packages/1155-contracts/package/preminter.ts index c54dc3045..ac5be5ee8 100644 --- a/packages/1155-contracts/package/preminter.ts +++ b/packages/1155-contracts/package/preminter.ts @@ -3,26 +3,24 @@ import { ExtractAbiFunction, AbiParametersToPrimitiveTypes } from "abitype"; import { zoraCreator1155PremintExecutorImplABI as preminterAbi } from "./wagmiGenerated"; import { TypedDataDefinition } from "viem"; -type PremintInputs = ExtractAbiFunction< +type PremintV1Inputs = ExtractAbiFunction< typeof preminterAbi, - "premint" + "premintV1" >["inputs"]; -type PreminterHashDataTypes = AbiParametersToPrimitiveTypes; +type PremintV2Inputs = ExtractAbiFunction< + typeof preminterAbi, + "premintV2" +>["inputs"]; + +type PreminterV1HashDataTypes = AbiParametersToPrimitiveTypes; +type PreminterV2HashDataTypes = AbiParametersToPrimitiveTypes; -export type ContractCreationConfig = PreminterHashDataTypes[0]; -export type PremintConfigs = PreminterHashDataTypes[1]; +export type ContractCreationConfig = PreminterV2HashDataTypes[0]; +export type PremintConfigV1 = PreminterV1HashDataTypes[1]; +export type PremintConfigV2 = PreminterV2HashDataTypes[1]; export type TokenCreationConfigV1 = PremintConfigV2["tokenConfig"]; -export type PremintConfigV2 = Extract< - PremintConfigs, - { - tokenConfig: { - createReferral: string; - }; - } ->; -export type PremintConfigV1 = Exclude; export type TokenCreationConfigV2 = PremintConfigV2["tokenConfig"]; const premintV2Types = { diff --git a/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol b/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol index 46c535cbb..7af16ba6c 100644 --- a/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol +++ b/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol @@ -14,47 +14,19 @@ import {IMinter1155} from "../interfaces/IMinter1155.sol"; import {ERC1155DelegationStorageV1} from "../delegation/ERC1155DelegationStorageV1.sol"; import {ZoraCreator1155PremintExecutorImplLib} from "./ZoraCreator1155PremintExecutorImplLib.sol"; import {PremintEncoding, ZoraCreator1155Attribution, ContractCreationConfig, PremintConfig, PremintConfigV2, TokenCreationConfig, TokenCreationConfigV2} from "./ZoraCreator1155Attribution.sol"; +import {IZoraCreator1155PremintExecutor, ILegacyZoraCreator1155PremintExecutor} from "../interfaces/IZoraCreator1155PremintExecutor.sol"; interface IZoraCreator1155PremintV1Signatures { function delegateSetupNewToken(PremintConfig calldata premintConfig, bytes calldata signature, address sender) external returns (uint256 newTokenId); } -// interface for legacy v1 of premint executor methods -// maintained in order to not break existing calls -// to legacy api when this api is upgraded -interface ILegacyZoraCreator1155PremintExecutor { - event Preminted( - address indexed contractAddress, - uint256 indexed tokenId, - bool indexed createdNewContract, - uint32 uid, - ContractCreationConfig contractConfig, - TokenCreationConfig tokenConfig, - address minter, - uint256 quantityMinted - ); - - function premint( - ContractCreationConfig calldata contractConfig, - PremintConfig calldata premintConfig, - bytes calldata signature, - uint256 quantityToMint, - string calldata mintComment - ) external payable returns (uint256 newTokenId); -} - -struct MintArguments { - address mintRecipient; - string mintComment; - address mintReferral; -} - /// @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. /// Mints the first x tokens to the executor of the transaction. /// @author @oveddan contract ZoraCreator1155PremintExecutorImpl is ILegacyZoraCreator1155PremintExecutor, + IZoraCreator1155PremintExecutor, Ownable2StepUpgradeable, UUPSUpgradeable, IHasContractName, @@ -71,15 +43,6 @@ contract ZoraCreator1155PremintExecutorImpl is __UUPSUpgradeable_init(); } - event PremintedV2( - address indexed contractAddress, - uint256 indexed tokenId, - bool indexed createdNewContract, - uint32 uid, - address minter, - uint256 quantityMinted - ); - /// Creates a new token on the given erc1155 contract on behalf of a creator, and mints x tokens to the executor of this transaction. /// If the erc1155 contract hasn't been created yet, it will be created with the given config within this same transaction. /// The creator must sign the intent to create the token, and must have mint new token permission on the erc1155 contract, @@ -90,30 +53,41 @@ contract ZoraCreator1155PremintExecutorImpl is /// @param signature Signature of the creator of the token, which must match the signer of the premint config, or have permission to create new tokens on the erc1155 contract if it's already been created /// @param quantityToMint How many tokens to mint to the executor of this transaction once the token is created /// @param mintArguments Abi encoded additional mint arguments: including mintComment and mintReferral - function premint( + function premintV2( ContractCreationConfig calldata contractConfig, PremintConfigV2 calldata premintConfig, bytes calldata signature, uint256 quantityToMint, MintArguments calldata mintArguments - ) external payable returns (uint256 newTokenId) { + ) external payable returns (PremintResult memory result) { (bytes memory encodedPremint, bytes32 premintVersion) = PremintEncoding.encodePremintV2(premintConfig); address fixedPriceMinter = premintConfig.tokenConfig.fixedPriceMinter; uint32 uid = premintConfig.uid; // we wrap this here to get around stack too deep issues { - newTokenId = _premint({ + result = ZoraCreator1155PremintExecutorImplLib.premint({ + zora1155Factory: zora1155Factory, contractConfig: contractConfig, encodedPremintConfig: encodedPremint, premintVersion: premintVersion, signature: signature, quantityToMint: quantityToMint, fixedPriceMinter: fixedPriceMinter, - uid: uid, mintArguments: mintArguments }); } + + { + emit PremintedV2({ + contractAddress: result.contractAddress, + tokenId: result.tokenId, + createdNewContract: result.createdNewContract, + uid: uid, + minter: msg.sender, + quantityMinted: quantityToMint + }); + } } /// Creates a new token on the given erc1155 contract on behalf of a creator, and mints x tokens to the executor of this transaction. @@ -126,74 +100,34 @@ contract ZoraCreator1155PremintExecutorImpl is /// @param signature Signature of the creator of the token, which must match the signer of the premint config, or have permission to create new tokens on the erc1155 contract if it's already been created /// @param quantityToMint How many tokens to mint to the executor of this transaction once the token is created /// @param mintArguments Abi encoded additional mint arguments: including mintComment and mintReferral - function premint( + function premintV1( ContractCreationConfig calldata contractConfig, PremintConfig calldata premintConfig, bytes calldata signature, uint256 quantityToMint, MintArguments memory mintArguments - ) public payable returns (uint256 newTokenId) { + ) public payable returns (PremintResult memory result) { (bytes memory encodedPremint, bytes32 premintVersion) = PremintEncoding.encodePremintV1(premintConfig); - return - _premint({ - contractConfig: contractConfig, - encodedPremintConfig: encodedPremint, - premintVersion: premintVersion, - signature: signature, - quantityToMint: quantityToMint, - fixedPriceMinter: premintConfig.tokenConfig.fixedPriceMinter, - uid: premintConfig.uid, - mintArguments: mintArguments - }); - } - - function _premint( - ContractCreationConfig calldata contractConfig, - bytes memory encodedPremintConfig, - bytes32 premintVersion, - bytes calldata signature, - uint256 quantityToMint, - address fixedPriceMinter, - uint32 uid, - MintArguments memory mintArguments - ) private returns (uint256 newTokenId) { - // get or create the contract with the given params - // contract address is deterministic. - (IZoraCreator1155 tokenContract, bool isNewContract) = ZoraCreator1155PremintExecutorImplLib.getOrCreateContract(zora1155Factory, contractConfig); - - // 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 = tokenContract.delegateSetupNewToken(encodedPremintConfig, premintVersion, signature, msg.sender); - - _performMint(tokenContract, fixedPriceMinter, newTokenId, quantityToMint, mintArguments); - - // emit Preminted event - emit PremintedV2(address(tokenContract), newTokenId, isNewContract, uid, msg.sender, quantityToMint); - } - - function _performMint( - IZoraCreator1155 tokenContract, - address fixedPriceMinter, - uint256 tokenId, - uint256 quantityToMint, - MintArguments memory mintArguments - ) internal { - bytes memory mintSettings = abi.encode(mintArguments.mintRecipient, mintArguments.mintComment); - if (quantityToMint != 0) - // mint the number of specified tokens to the executor - tokenContract.mintWithRewards{value: msg.value}(IMinter1155(fixedPriceMinter), tokenId, quantityToMint, mintSettings, mintArguments.mintReferral); - } - - function isValidSignature( - address originalPremintCreator, - address contractAddress, - bytes32 hashedPremint, - bytes32 signatureVersion, - bytes calldata signature - ) public view returns (bool isValid, address recoveredSigner) { - return ZoraCreator1155Attribution.isValidSignature(originalPremintCreator, contractAddress, hashedPremint, signatureVersion, signature); + result = ZoraCreator1155PremintExecutorImplLib.premint({ + zora1155Factory: zora1155Factory, + contractConfig: contractConfig, + encodedPremintConfig: encodedPremint, + premintVersion: premintVersion, + signature: signature, + quantityToMint: quantityToMint, + fixedPriceMinter: premintConfig.tokenConfig.fixedPriceMinter, + mintArguments: mintArguments + }); + + emit PremintedV2({ + contractAddress: result.contractAddress, + tokenId: result.tokenId, + createdNewContract: result.createdNewContract, + uid: premintConfig.uid, + minter: msg.sender, + quantityMinted: quantityToMint + }); } /// Gets the deterministic contract address for the given contract creation config. @@ -212,6 +146,7 @@ contract ZoraCreator1155PremintExecutorImpl is return (true, ERC1155DelegationStorageV1(contractAddress).delegatedTokenId(uid)); } + /// deprecated - use isValidSignatureV1 function isValidSignature( ContractCreationConfig calldata contractConfig, PremintConfig calldata premintConfig, @@ -219,10 +154,19 @@ contract ZoraCreator1155PremintExecutorImpl is ) public view returns (bool isValid, address contractAddress, address recoveredSigner) { contractAddress = getContractAddress(contractConfig); + (isValid, recoveredSigner) = isValidSignatureV1(contractConfig.contractAdmin, contractAddress, premintConfig, signature); + } + + function isValidSignatureV1( + address originalContractAdmin, + address contractAddress, + PremintConfig calldata premintConfig, + bytes calldata signature + ) public view returns (bool isValid, address recoveredSigner) { bytes32 hashedPremint = ZoraCreator1155Attribution.hashPremint(premintConfig); - (isValid, recoveredSigner) = isValidSignature( - contractConfig.contractAdmin, + (isValid, recoveredSigner) = ZoraCreator1155Attribution.isValidSignature( + originalContractAdmin, contractAddress, hashedPremint, ZoraCreator1155Attribution.HASHED_VERSION_1, @@ -230,17 +174,16 @@ contract ZoraCreator1155PremintExecutorImpl is ); } - function isValidSignature( - ContractCreationConfig calldata contractConfig, + function isValidSignatureV2( + address originalContractAdmin, + address contractAddress, PremintConfigV2 calldata premintConfig, bytes calldata signature - ) public view returns (bool isValid, address contractAddress, address recoveredSigner) { - contractAddress = getContractAddress(contractConfig); - + ) public view returns (bool isValid, address recoveredSigner) { bytes32 hashedPremint = ZoraCreator1155Attribution.hashPremint(premintConfig); - (isValid, recoveredSigner) = isValidSignature( - contractConfig.contractAdmin, + (isValid, recoveredSigner) = ZoraCreator1155Attribution.isValidSignature( + originalContractAdmin, contractAddress, hashedPremint, ZoraCreator1155Attribution.HASHED_VERSION_2, @@ -284,6 +227,6 @@ contract ZoraCreator1155PremintExecutorImpl is // encode legacy mint arguments to call current function: MintArguments memory mintArguments = MintArguments({mintRecipient: msg.sender, mintComment: mintComment, mintReferral: address(0)}); - return premint(contractConfig, premintConfig, signature, quantityToMint, mintArguments); + return premintV1(contractConfig, premintConfig, signature, quantityToMint, mintArguments).tokenId; } } diff --git a/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImplLib.sol b/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImplLib.sol index 873e20290..c39d485e0 100644 --- a/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImplLib.sol +++ b/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImplLib.sol @@ -6,6 +6,7 @@ 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"; library ZoraCreator1155PremintExecutorImplLib { function getOrCreateContract( @@ -58,4 +59,41 @@ library ZoraCreator1155PremintExecutorImplLib { function decodeMintArguments(bytes memory mintArguments) internal pure returns (address mintRecipient, string memory mintComment) { return abi.decode(mintArguments, (address, string)); } + + function premint( + IZoraCreator1155Factory zora1155Factory, + ContractCreationConfig calldata contractConfig, + bytes memory encodedPremintConfig, + bytes32 premintVersion, + bytes calldata signature, + uint256 quantityToMint, + address fixedPriceMinter, + IZoraCreator1155PremintExecutor.MintArguments memory mintArguments + ) internal returns (IZoraCreator1155PremintExecutor.PremintResult memory) { + // get or create the contract with the given params + // contract address is deterministic. + (IZoraCreator1155 tokenContract, bool isNewContract) = ZoraCreator1155PremintExecutorImplLib.getOrCreateContract(zora1155Factory, contractConfig); + + // 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. + uint256 newTokenId = tokenContract.delegateSetupNewToken(encodedPremintConfig, premintVersion, signature, msg.sender); + + _performMint(tokenContract, fixedPriceMinter, newTokenId, quantityToMint, mintArguments); + + return IZoraCreator1155PremintExecutor.PremintResult({contractAddress: address(tokenContract), tokenId: newTokenId, createdNewContract: isNewContract}); + } + + function _performMint( + IZoraCreator1155 tokenContract, + address fixedPriceMinter, + uint256 tokenId, + uint256 quantityToMint, + IZoraCreator1155PremintExecutor.MintArguments memory mintArguments + ) internal { + bytes memory mintSettings = abi.encode(mintArguments.mintRecipient, mintArguments.mintComment); + if (quantityToMint != 0) + // mint the number of specified tokens to the executor + tokenContract.mintWithRewards{value: msg.value}(IMinter1155(fixedPriceMinter), tokenId, quantityToMint, mintSettings, mintArguments.mintReferral); + } } diff --git a/packages/1155-contracts/src/deployment/DeploymentTestingUtils.sol b/packages/1155-contracts/src/deployment/DeploymentTestingUtils.sol index 3ed77c292..33bc6b2b0 100644 --- a/packages/1155-contracts/src/deployment/DeploymentTestingUtils.sol +++ b/packages/1155-contracts/src/deployment/DeploymentTestingUtils.sol @@ -5,7 +5,8 @@ import "forge-std/Script.sol"; import {IMinter1155} from "..//interfaces/IMinter1155.sol"; import {Zora1155FactoryFixtures} from "../../test/fixtures/Zora1155FactoryFixtures.sol"; import {Zora1155PremintFixtures} from "../../test/fixtures/Zora1155PremintFixtures.sol"; -import {ZoraCreator1155PremintExecutorImpl, MintArguments} from "../delegation/ZoraCreator1155PremintExecutorImpl.sol"; +import {ZoraCreator1155PremintExecutorImpl} from "../delegation/ZoraCreator1155PremintExecutorImpl.sol"; +import {IZoraCreator1155PremintExecutor} from "../interfaces/IZoraCreator1155PremintExecutor.sol"; import {ZoraCreator1155FactoryImpl} from "../factory/ZoraCreator1155FactoryImpl.sol"; import {ZoraCreator1155Attribution, ContractCreationConfig, PremintConfigV2} from "../delegation/ZoraCreator1155Attribution.sol"; import {ZoraCreator1155Impl} from "../nft/ZoraCreator1155Impl.sol"; @@ -16,7 +17,7 @@ contract DeploymentTestingUtils is Script { console2.log("preminter proxy", premintExecutorProxyAddress); (address creator, uint256 creatorPrivateKey) = makeAddrAndKey("creator"); - ZoraCreator1155PremintExecutorImpl preminterAtProxy = ZoraCreator1155PremintExecutorImpl(premintExecutorProxyAddress); + IZoraCreator1155PremintExecutor preminterAtProxy = IZoraCreator1155PremintExecutor(premintExecutorProxyAddress); IMinter1155 fixedPriceMinter = ZoraCreator1155FactoryImpl(address(preminterAtProxy.zora1155Factory())).fixedPriceMinter(); @@ -35,12 +36,16 @@ contract DeploymentTestingUtils is Script { address mintRecipient = creator; - MintArguments memory mintArguments = MintArguments({mintRecipient: mintRecipient, mintComment: "", mintReferral: address(0)}); + IZoraCreator1155PremintExecutor.MintArguments memory mintArguments = IZoraCreator1155PremintExecutor.MintArguments({ + mintRecipient: mintRecipient, + mintComment: "", + mintReferral: address(0) + }); bytes memory signature = signPremint(premintConfig, deterministicAddress, creatorPrivateKey); // execute the premint - uint256 tokenId = preminterAtProxy.premint{value: 0.000777 ether}(contractConfig, premintConfig, signature, quantityToMint, mintArguments); + uint256 tokenId = preminterAtProxy.premintV2{value: 0.000777 ether}(contractConfig, premintConfig, signature, quantityToMint, mintArguments).tokenId; require(ZoraCreator1155Impl(deterministicAddress).delegatedTokenId(premintConfig.uid) == tokenId, "token id not created for uid"); } diff --git a/packages/1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol b/packages/1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol new file mode 100644 index 000000000..b66df3af3 --- /dev/null +++ b/packages/1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.17; + +import {PremintEncoding, ZoraCreator1155Attribution, ContractCreationConfig, PremintConfig, PremintConfigV2, TokenCreationConfig, TokenCreationConfigV2} from "../delegation/ZoraCreator1155Attribution.sol"; +import {IZoraCreator1155Factory} from "./IZoraCreator1155Factory.sol"; + +// interface for legacy v1 of premint executor methods +// maintained in order to not break existing calls +// to legacy api when this api is upgraded +interface ILegacyZoraCreator1155PremintExecutor { + event Preminted( + address indexed contractAddress, + uint256 indexed tokenId, + bool indexed createdNewContract, + uint32 uid, + ContractCreationConfig contractConfig, + TokenCreationConfig tokenConfig, + address minter, + uint256 quantityMinted + ); + + function premint( + ContractCreationConfig calldata contractConfig, + PremintConfig calldata premintConfig, + bytes calldata signature, + uint256 quantityToMint, + string calldata mintComment + ) external payable returns (uint256 newTokenId); +} + +interface IZoraCreator1155PremintExecutorV1 { + function premintV1( + ContractCreationConfig calldata contractConfig, + PremintConfig calldata premintConfig, + bytes calldata signature, + uint256 quantityToMint, + IZoraCreator1155PremintExecutor.MintArguments calldata mintArguments + ) external payable returns (IZoraCreator1155PremintExecutor.PremintResult memory); + + function isValidSignatureV1( + address originalContractAdmin, + address contractAddress, + PremintConfig calldata premintConfig, + bytes calldata signature + ) external view returns (bool isValid, address recoveredSigner); +} + +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 isValidSignatureV2( + address originalContractAdmin, + address contractAddress, + PremintConfigV2 calldata premintConfig, + bytes calldata signature + ) external view returns (bool isValid, address recoveredSigner); +} + +interface IZoraCreator1155PremintExecutor is IZoraCreator1155PremintExecutorV1, IZoraCreator1155PremintExecutorV2 { + struct MintArguments { + address mintRecipient; + string mintComment; + address mintReferral; + } + + struct PremintResult { + address contractAddress; + uint256 tokenId; + bool createdNewContract; + } + + event PremintedV2( + address indexed contractAddress, + uint256 indexed tokenId, + bool indexed createdNewContract, + uint32 uid, + address minter, + uint256 quantityMinted + ); + + function zora1155Factory() external view returns (IZoraCreator1155Factory); + + function getContractAddress(ContractCreationConfig calldata contractConfig) external view returns (address); +} diff --git a/packages/1155-contracts/test/premint/Zora1155PremintExecutorProxy.t.sol b/packages/1155-contracts/test/premint/Zora1155PremintExecutorProxy.t.sol index aea0fe36b..2aac3c870 100644 --- a/packages/1155-contracts/test/premint/Zora1155PremintExecutorProxy.t.sol +++ b/packages/1155-contracts/test/premint/Zora1155PremintExecutorProxy.t.sol @@ -7,7 +7,7 @@ import {Zora1155PremintFixtures} from "../fixtures/Zora1155PremintFixtures.sol"; import {ZoraCreator1155FactoryImpl} from "../../src/factory/ZoraCreator1155FactoryImpl.sol"; import {Zora1155PremintExecutor} from "../../src/proxies/Zora1155PremintExecutor.sol"; import {ZoraCreator1155Impl} from "../../src/nft/ZoraCreator1155Impl.sol"; -import {ZoraCreator1155PremintExecutorImpl, MintArguments} from "../../src/delegation/ZoraCreator1155PremintExecutorImpl.sol"; +import {ZoraCreator1155PremintExecutorImpl} from "../../src/delegation/ZoraCreator1155PremintExecutorImpl.sol"; import {Zora1155Factory} from "../../src/proxies/Zora1155Factory.sol"; import {IMinter1155} from "../../src/interfaces/IMinter1155.sol"; import {ProxyShim} from "../../src/utils/ProxyShim.sol"; @@ -15,6 +15,7 @@ import {ZoraCreator1155Attribution, ContractCreationConfig, TokenCreationConfigV import {IOwnable2StepUpgradeable} from "../../src/utils/ownable/IOwnable2StepUpgradeable.sol"; import {IHasContractName} from "../../src/interfaces/IContractMetadata.sol"; import {ZoraCreator1155PremintExecutorImplLib} from "../../src/delegation/ZoraCreator1155PremintExecutorImplLib.sol"; +import {IZoraCreator1155PremintExecutor} from "../../src/interfaces/IZoraCreator1155PremintExecutor.sol"; contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { address internal owner; @@ -27,7 +28,7 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { uint256 internal mintFeeAmount = 0.000777 ether; ZoraCreator1155PremintExecutorImpl preminterAtProxy; - MintArguments defaultMintArguments; + IZoraCreator1155PremintExecutor.MintArguments defaultMintArguments; function setUp() external { zora = makeAddr("zora"); @@ -50,7 +51,7 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { preminterAtProxy = ZoraCreator1155PremintExecutorImpl(address(proxy)); preminterAtProxy.initialize(owner); - defaultMintArguments = MintArguments({mintRecipient: collector, mintComment: "blah", mintReferral: address(0)}); + defaultMintArguments = IZoraCreator1155PremintExecutor.MintArguments({mintRecipient: collector, mintComment: "blah", mintReferral: address(0)}); } function test_canInvokeImplementationMethods() external { @@ -86,7 +87,8 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { // execute the premint vm.deal(collector, mintFeeAmount); vm.prank(collector); - uint256 tokenId = preminterAtProxy.premint{value: mintFeeAmount}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + uint256 tokenId = preminterAtProxy + .premintV2{value: mintFeeAmount}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments).tokenId; assertEq(ZoraCreator1155Impl(deterministicAddress).balanceOf(collector, tokenId), 1); } diff --git a/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor.t.sol b/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor.t.sol index 11efc8bf8..ba4ebcb36 100644 --- a/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor.t.sol +++ b/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor.t.sol @@ -14,7 +14,8 @@ import {ICreatorRoyaltiesControl} from "../../src/interfaces/ICreatorRoyaltiesCo import {ZoraCreatorFixedPriceSaleStrategy} from "../../src/minters/fixed-price/ZoraCreatorFixedPriceSaleStrategy.sol"; import {Zora1155Factory} from "../../src/proxies/Zora1155Factory.sol"; import {ZoraCreator1155FactoryImpl} from "../../src/factory/ZoraCreator1155FactoryImpl.sol"; -import {ZoraCreator1155PremintExecutorImpl, MintArguments} from "../../src/delegation/ZoraCreator1155PremintExecutorImpl.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 {ForkDeploymentConfig, Deployment} from "../../src/deployment/DeploymentConfig.sol"; import {UUPSUpgradeable} from "@zoralabs/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; @@ -40,7 +41,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { address internal premintExecutor; address internal collector; - MintArguments defaultMintArguments; + IZoraCreator1155PremintExecutor.MintArguments defaultMintArguments; event PremintedV2( address indexed contractAddress, @@ -65,7 +66,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { preminter = new ZoraCreator1155PremintExecutorImpl(factory); - defaultMintArguments = MintArguments({mintRecipient: premintExecutor, mintComment: "blah", mintReferral: address(0)}); + defaultMintArguments = IZoraCreator1155PremintExecutor.MintArguments({mintRecipient: premintExecutor, mintComment: "blah", mintReferral: address(0)}); } function makeDefaultContractCreationConfig() internal view returns (ContractCreationConfig memory) { @@ -145,9 +146,17 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { // this account will be used to execute the premint, and should result in a contract being created vm.deal(premintExecutor, mintCost); + // make sure sig is still valid using legacy method + (bool isValid, , ) = preminter.isValidSignature(contractConfig, premintConfig, signature); + assertTrue(isValid); + + // now check using new method + (isValid, ) = preminter.isValidSignatureV1(contractConfig.contractAdmin, contractAddress, premintConfig, signature); + assertTrue(isValid); + // now call the premint function, using the same config that was used to generate the digest, and the signature vm.prank(premintExecutor); - uint256 tokenId = preminter.premint{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + uint256 tokenId = preminter.premintV1{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments).tokenId; // get the contract address from the preminter based on the contract hash id. IZoraCreator1155 created1155Contract = IZoraCreator1155(contractAddress); @@ -184,7 +193,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { // now call the premint function, using the same config that was used to generate the digest, and the signature vm.prank(premintExecutor); - uint256 tokenId = preminter.premint{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + uint256 tokenId = preminter.premintV2{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments).tokenId; // get the contract address from the preminter based on the contract hash id. IZoraCreator1155 created1155Contract = IZoraCreator1155(contractAddress); @@ -205,7 +214,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { // premint with new token config and signature vm.prank(premintExecutor); - tokenId = preminter.premint{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + tokenId = preminter.premintV2{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments).tokenId; // a new token shoudl have been created, with x tokens minted to the executor, on the same contract address // as before since the contract config didnt change @@ -238,7 +247,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { // now call the premint function, using the same config that was used to generate the digest, and the signature vm.prank(premintExecutor); - uint256 tokenId = preminter.premint(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + uint256 tokenId = preminter.premintV2(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments).tokenId; // get the contract address from the preminter based on the contract hash id. IZoraCreator1155 created1155Contract = IZoraCreator1155(contractAddress); @@ -281,7 +290,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { emit CreatorAttribution(structHash, ZoraCreator1155Attribution.NAME, ZoraCreator1155Attribution.VERSION_2, creator, signature); // create contract and token via premint - preminter.premint{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + preminter.premintV2{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); } /// @notice gets the chains to do fork tests on, by reading environment var FORK_TEST_CHAINS. @@ -324,7 +333,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { // now call the premint function, using the same config that was used to generate the digest, and the signature vm.deal(premintExecutor, mintCost); vm.prank(premintExecutor); - uint256 tokenId = preminter.premint{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + uint256 tokenId = preminter.premintV2{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments).tokenId; // get the contract address from the preminter based on the contract hash id. IZoraCreator1155 created1155Contract = IZoraCreator1155(contractAddress); @@ -394,7 +403,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { vm.startPrank(collector); // premint with new token config and signature, but same uid - it should mint tokens for the first token - nextTokenId = preminter.premint{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + nextTokenId = preminter.premintV2{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments).tokenId; assertEq(nextTokenId, firstTokenId); assertEq( @@ -410,7 +419,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { vm.deal(collector, mintCost); // premint with new token config and signature - it should mint tokens for the first token - nextTokenId = preminter.premint{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + nextTokenId = preminter.premintV2{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments).tokenId; vm.stopPrank(); assertEq(nextTokenId, firstTokenId); @@ -442,7 +451,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { vm.startPrank(collector); // premint with new token config and signature, but same uid - it should mint tokens for the first token - uint256 nextTokenId = preminter.premint{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + uint256 nextTokenId = preminter.premintV2{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments).tokenId; assertEq(firstTokenId, 1); assertEq(nextTokenId, 2); @@ -464,7 +473,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { // now call the premint function, using the same config that was used to generate the digest, and the signature vm.expectRevert(IZoraCreator1155Errors.PremintDeleted.selector); vm.prank(premintExecutor); - uint256 newTokenId = preminter.premint(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + uint256 newTokenId = preminter.premintV2(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments).tokenId; assertEq(newTokenId, 0, "tokenId"); @@ -495,7 +504,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { bool createdNewContract = true; vm.expectEmit(true, true, true, true); emit PremintedV2(contractAddress, expectedTokenId, createdNewContract, premintConfig.uid, premintExecutor, quantityToMint); - preminter.premint{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + preminter.premintV2{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); } function test_onlyOwner_hasAdminRights_onCreatedToken() public { @@ -629,7 +638,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { vm.deal(premintExecutor, mintCost); vm.prank(premintExecutor); - preminter.premint{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + preminter.premintV2{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); } function test_premintCanOnlyBeExecutedUpToDurationFromFirstMint(uint8 startDate, uint8 duration, uint8 timeOfFirstMint, uint8 timeOfSecondMint) external { @@ -666,7 +675,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { vm.startPrank(premintExecutor); vm.warp(timeOfFirstMint); - uint256 tokenId = preminter.premint{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments); + uint256 tokenId = preminter.premintV2{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, defaultMintArguments).tokenId; vm.warp(timeOfSecondMint); @@ -719,11 +728,10 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { // sign and execute premint bytes memory signature = _signPremint(contractAddress, premintConfig, creatorPrivateKey, block.chainid); - (bool isValidSignature, address recoveredSigner) = preminter.isValidSignature( + (bool isValidSignature, address recoveredSigner) = preminter.isValidSignatureV2( contractConfig.contractAdmin, contractAddress, - ZoraCreator1155Attribution.hashPremint(premintConfig), - ZoraCreator1155Attribution.HASHED_VERSION_2, + premintConfig, signature ); @@ -744,13 +752,7 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { bytes memory newCreatorSignature = _signPremint(contractAddress, premintConfig2, newCreatorPrivateKey, block.chainid); // it should not be considered a valid signature - (isValidSignature, ) = preminter.isValidSignature( - contractConfig.contractAdmin, - contractAddress, - ZoraCreator1155Attribution.hashPremint(premintConfig2), - ZoraCreator1155Attribution.HASHED_VERSION_2, - newCreatorSignature - ); + (isValidSignature, ) = preminter.isValidSignatureV2(contractConfig.contractAdmin, contractAddress, premintConfig2, newCreatorSignature); assertFalse(isValidSignature, "signature should not be valid"); @@ -761,27 +763,21 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { // try to mint, it should revert vm.expectRevert(abi.encodeWithSelector(IZoraCreator1155Errors.UserMissingRoleForToken.selector, newCreator, CONTRACT_BASE_ID, PERMISSION_BIT_MINTER)); vm.prank(premintExecutor); - preminter.premint{value: mintCost}(contractConfig, premintConfig2, newCreatorSignature, quantityToMint, defaultMintArguments); + preminter.premintV2{value: mintCost}(contractConfig, premintConfig2, newCreatorSignature, quantityToMint, defaultMintArguments); // now grant the new creator permission to mint vm.prank(creator); IZoraCreator1155(contractAddress).addPermission(CONTRACT_BASE_ID, newCreator, PERMISSION_BIT_MINTER); // should now be considered a valid signature - (isValidSignature, ) = preminter.isValidSignature( - contractConfig.contractAdmin, - contractAddress, - ZoraCreator1155Attribution.hashPremint(premintConfig2), - ZoraCreator1155Attribution.HASHED_VERSION_2, - newCreatorSignature - ); + (isValidSignature, ) = preminter.isValidSignatureV2(contractConfig.contractAdmin, contractAddress, premintConfig2, newCreatorSignature); assertTrue(isValidSignature, "valid signature after granted permission"); vm.deal(premintExecutor, mintCost); // try to mint again, should not revert vm.prank(premintExecutor); - preminter.premint{value: mintCost}(contractConfig, premintConfig2, newCreatorSignature, quantityToMint, defaultMintArguments); + preminter.premintV2{value: mintCost}(contractConfig, premintConfig2, newCreatorSignature, quantityToMint, defaultMintArguments); } function testPremintWithCreateReferral() public { @@ -810,14 +806,18 @@ contract ZoraCreator1155PreminterTest is ForkDeploymentConfig, Test { ) private returns (uint256 newTokenId) { bytes memory signature = _signPremint(preminter.getContractAddress(contractConfig), premintConfig, privateKey, chainId); - MintArguments memory mintArguments = MintArguments({mintRecipient: executor, mintComment: comment, mintReferral: address(0)}); + IZoraCreator1155PremintExecutor.MintArguments memory mintArguments = IZoraCreator1155PremintExecutor.MintArguments({ + mintRecipient: executor, + mintComment: comment, + mintReferral: address(0) + }); uint256 mintCost = mintFeeAmount * quantityToMint; vm.deal(executor, mintCost); // now call the premint function, using the same config that was used to generate the digest, and the signature vm.prank(executor); - newTokenId = preminter.premint{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, mintArguments); + newTokenId = preminter.premintV2{value: mintCost}(contractConfig, premintConfig, signature, quantityToMint, mintArguments).tokenId; } function _signPremint(