diff --git a/.changeset/serious-goats-exist.md b/.changeset/serious-goats-exist.md new file mode 100644 index 000000000..59c9550b9 --- /dev/null +++ b/.changeset/serious-goats-exist.md @@ -0,0 +1,5 @@ +--- +"@zoralabs/zora-1155-contracts": patch +--- + +Premint - added method getSupportedPremintSignatureVersions(contractAddress) that returns an array of the premint signature versions an 1155 contract supports. If the contract hasn't been created yet, assumes that when it will be created it will support the latest versions of the signatures, so the function returns all versions. diff --git a/.changeset/thirty-dragons-pretend.md b/.changeset/thirty-dragons-pretend.md new file mode 100644 index 000000000..38b73d97b --- /dev/null +++ b/.changeset/thirty-dragons-pretend.md @@ -0,0 +1,5 @@ +--- +"@zoralabs/zora-1155-contracts": patch +--- + +Added method `IZoraCreator1155PremintExecutor.supportedPremintSignatureVersions(contractAddress)` that tells what version of the premint signature the contract supports, and added corresponding method `ZoraCreator1155Impl.supportedPremintSignatureVersions()` to fetch supported version. If premint not supported, returns an empty array. \ No newline at end of file diff --git a/packages/1155-contracts/src/delegation/ZoraCreator1155Attribution.sol b/packages/1155-contracts/src/delegation/ZoraCreator1155Attribution.sol index e2c6ee414..6f24664b7 100644 --- a/packages/1155-contracts/src/delegation/ZoraCreator1155Attribution.sol +++ b/packages/1155-contracts/src/delegation/ZoraCreator1155Attribution.sol @@ -420,6 +420,16 @@ library DelegatedTokenCreation { } } + function supportedPremintSignatureVersions() external pure returns (string[] memory versions) { + return _supportedPremintSignatureVersions(); + } + + function _supportedPremintSignatureVersions() internal pure returns (string[] memory versions) { + versions = new string[](2); + versions[0] = ZoraCreator1155Attribution.VERSION_1; + versions[1] = ZoraCreator1155Attribution.VERSION_2; + } + function _recoverCreatorAttribution( string memory version, bytes32 structHash, diff --git a/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol b/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol index f7dd19b3d..6f8332340 100644 --- a/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol +++ b/packages/1155-contracts/src/delegation/ZoraCreator1155PremintExecutorImpl.sol @@ -13,8 +13,9 @@ 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, ContractCreationConfig, PremintConfig, PremintConfigV2, TokenCreationConfig, TokenCreationConfigV2} from "./ZoraCreator1155Attribution.sol"; +import {PremintEncoding, ZoraCreator1155Attribution, DelegatedTokenCreation, ContractCreationConfig, PremintConfig, PremintConfigV2, TokenCreationConfig, TokenCreationConfigV2} from "./ZoraCreator1155Attribution.sol"; import {IZoraCreator1155PremintExecutor} from "../interfaces/IZoraCreator1155PremintExecutor.sol"; +import {IZoraCreator1155DelegatedCreation} from "../interfaces/IZoraCreator1155DelegatedCreation.sol"; struct MintArguments { // which account should receive the tokens minted. @@ -213,6 +214,31 @@ contract ZoraCreator1155PremintExecutorImpl is ); } + /// @notice Returns the versions of the premint signature that the contract supports + /// @param contractAddress The address of the contract to check + /// @return versions The versions of the premint signature that the contract supports. If contract hasn't been created yet, + /// assumes that when it will be created it will support the latest versions of the signatures, so the function returns all versions. + function supportedPremintSignatureVersions(address contractAddress) external view returns (string[] memory versions) { + // if contract hasn't been created yet, assume it will be created with the latest version + // and thus supports all versions of the signature + if (contractAddress.code.length == 0) { + return DelegatedTokenCreation._supportedPremintSignatureVersions(); + } + + IZoraCreator1155 creatorContract = IZoraCreator1155(contractAddress); + if (creatorContract.supportsInterface(type(IZoraCreator1155DelegatedCreation).interfaceId)) { + return IZoraCreator1155DelegatedCreation(contractAddress).supportedPremintSignatureVersions(); + } + + // 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; + } catch { + versions = new string[](0); + } + } + // upgrade related functionality /// @notice The name of the contract for upgrade purposes diff --git a/packages/1155-contracts/src/interfaces/IZoraCreator1155DelegatedCreation.sol b/packages/1155-contracts/src/interfaces/IZoraCreator1155DelegatedCreation.sol index 85c49eaba..f33602a39 100644 --- a/packages/1155-contracts/src/interfaces/IZoraCreator1155DelegatedCreation.sol +++ b/packages/1155-contracts/src/interfaces/IZoraCreator1155DelegatedCreation.sol @@ -4,6 +4,8 @@ pragma solidity 0.8.17; interface IZoraCreator1155DelegatedCreation { event CreatorAttribution(bytes32 structHash, string domainName, string version, address creator, bytes signature); + function supportedPremintSignatureVersions() external pure returns (string[] memory); + function delegateSetupNewToken( bytes memory premintConfigEncoded, bytes32 premintVersion, diff --git a/packages/1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol b/packages/1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol index fbc449ed0..8c4c92ef8 100644 --- a/packages/1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol +++ b/packages/1155-contracts/src/interfaces/IZoraCreator1155PremintExecutor.sol @@ -93,4 +93,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); } diff --git a/packages/1155-contracts/src/nft/ZoraCreator1155Impl.sol b/packages/1155-contracts/src/nft/ZoraCreator1155Impl.sol index 7ee7c4d3c..a1a4c4cc9 100644 --- a/packages/1155-contracts/src/nft/ZoraCreator1155Impl.sol +++ b/packages/1155-contracts/src/nft/ZoraCreator1155Impl.sol @@ -752,6 +752,10 @@ contract ZoraCreator1155Impl is return _getImplementation(); } + function supportedPremintSignatureVersions() external pure returns (string[] memory) { + return DelegatedTokenCreation.supportedPremintSignatureVersions(); + } + /// Sets up a new token using a token configuration and a signature created for the token creation parameters. /// The signature must be created by an account with the PERMISSION_BIT_MINTER role on the contract. /// @param premintConfig abi encoded configuration of token to be created diff --git a/packages/1155-contracts/test/premint/Zora1155PremintExecutorProxy.t.sol b/packages/1155-contracts/test/premint/Zora1155PremintExecutorProxy.t.sol index b20fb10a2..69b23ba4d 100644 --- a/packages/1155-contracts/test/premint/Zora1155PremintExecutorProxy.t.sol +++ b/packages/1155-contracts/test/premint/Zora1155PremintExecutorProxy.t.sol @@ -169,6 +169,11 @@ contract Zora1155PremintExecutorProxyTest is Test, IHasContractName { forkedPreminterProxy.upgradeTo(address(newImplementation)); // 3. create premint on old version of contract using new version of preminter + // verify the 1155 supports up to version 1 + string[] memory supportedVersions = forkedPreminterProxy.supportedPremintSignatureVersions(deterministicAddress); + assertEq(supportedVersions.length, 1); + assertEq(supportedVersions[0], "1"); + uint32 existingUid = premintConfig.uid; premintConfig = Zora1155PremintFixtures.makeDefaultV1PremintConfig(fixedPriceMinter, creator); premintConfig.uid = existingUid + 1; diff --git a/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor.t.sol b/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor.t.sol index 898116654..11e15b0fa 100644 --- a/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor.t.sol +++ b/packages/1155-contracts/test/premint/ZoraCreator1155PremintExecutor.t.sol @@ -722,6 +722,54 @@ contract ZoraCreator1155PreminterTest is Test { preminter.premintV2{value: mintCost}(contractConfig, premintConfig2, newCreatorSignature, quantityToMint, defaultMintArguments); } + function test_premintVersion_whenCreatedBeforePremint_returnsZero() external { + vm.createSelectFork("zora", 5_789_193); + + // create preminter on fork + vm.startPrank(zora); + (, , factoryProxy, ) = Zora1155FactoryFixtures.setup1155AndFactoryProxy(zora, zora); + vm.stopPrank(); + + factory = ZoraCreator1155FactoryImpl(address(factoryProxy)); + + preminter = new ZoraCreator1155PremintExecutorImpl(factory); + + // this is a known contract deployed from the legacy factory proxy on zora mainnet + // that does not support getting the uid or premint sig version (it is prior to version 2) + address erc1155BeforePremint = 0xcACBbee9C2C703274BE026B62860cF56361410f3; + assertFalse(erc1155BeforePremint.code.length == 0); + + // if contract is not a known 1155 contract that supports getting uid or premint sig version, + // this should return 0 + assertEq(preminter.supportedPremintSignatureVersions(erc1155BeforePremint).length, 0); + } + + function test_premintVersion_beforeCreated_returnsAllVersion() external { + // build a premint + string[] memory supportedVersions = preminter.supportedPremintSignatureVersions(makeAddr("randomContract")); + + assertEq(supportedVersions.length, 2); + assertEq(supportedVersions[0], "1"); + assertEq(supportedVersions[1], "2"); + } + + function test_premintVersion_whenCreated_returnsAllVersion() external { + // build a premint + ContractCreationConfig memory contractConfig = makeDefaultContractCreationConfig(); + PremintConfigV2 memory premintConfig = makeDefaultPremintConfig(); + + // sign and execute premint + address deterministicAddress = preminter.getContractAddress(contractConfig); + + _signAndExecutePremint(contractConfig, premintConfig, creatorPrivateKey, block.chainid, premintExecutor, 1, "hi"); + + string[] memory supportedVersions = preminter.supportedPremintSignatureVersions(deterministicAddress); + + assertEq(supportedVersions.length, 2); + assertEq(supportedVersions[0], "1"); + assertEq(supportedVersions[1], "2"); + } + function testPremintWithCreateReferral() public { address createReferral = makeAddr("createReferral");