Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Premint - can execute premint on legacy version of contracts #299

Merged
merged 1 commit into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/dirty-dodos-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@zoralabs/zora-1155-contracts": patch
---

Premint executor can still execute premint mints on 1155 contracts that were created with the old signature for `delegateSetupNewToken`
2 changes: 1 addition & 1 deletion .changeset/violet-starfishes-visit.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,4 @@ struct TokenCreationConfig {
* deprecated function `premint` - call `premintV1` instead
* new function `isValidSignatureV1` - takes an 1155 address, contract admin, premint v1 config and signature, and validates the signature. Can be used for 1155 contracts that were not created via the premint executor contract.
* new function `isValidSignatureV2` - takes an 1155 address, contract admin, premint v2 config and signature, and validates the signature. Can be used for 1155 contracts that were not created via the premint executor contract.
* deprecated function `isValidSignature` - call `isValidSignatureV1` instead
* deprecated function `isValidSignature` - call `isValidSignatureV1` instead
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ 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";
import {IZoraCreator1155PremintExecutor} from "../interfaces/IZoraCreator1155PremintExecutor.sol";

struct MintArguments {
// which account should receive the tokens minted. If set to address(0), then defaults to the msg.sender
Expand All @@ -30,7 +30,6 @@ struct MintArguments {
/// Mints the first x tokens to the executor of the transaction.
/// @author @oveddan
contract ZoraCreator1155PremintExecutorImpl is
ILegacyZoraCreator1155PremintExecutor,
IZoraCreator1155PremintExecutor,
Ownable2StepUpgradeable,
UUPSUpgradeable,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import {ContractCreationConfig} from "./ZoraCreator1155Attribution.sol";
import {ContractCreationConfig, PremintConfig} from "./ZoraCreator1155Attribution.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} from "../interfaces/IZoraCreator1155DelegatedCreation.sol";

interface ILegacyZoraCreator1155DelegatedMinter {
function delegateSetupNewToken(PremintConfig calldata premintConfig, bytes calldata signature, address sender) external returns (uint256 newTokenId);
}

library ZoraCreator1155PremintExecutorImplLib {
function getOrCreateContract(
Expand Down Expand Up @@ -60,6 +65,21 @@ library ZoraCreator1155PremintExecutorImplLib {
return abi.decode(mintArguments, (address, string));
}

function legacySetupNewToken(address contractAddress, bytes memory encodedPremintConfig, bytes calldata signature) private returns (uint256) {
// for use when the erc1155 contract does not support the new delegateSetupNewToken interface, where it expects
// a PremintConfig as an argument.

// decode the PremintConfig from the encoded bytes.
PremintConfig memory premintConfig = abi.decode(encodedPremintConfig, (PremintConfig));

// call the legacy version of the delegateSetupNewToken function.
return ILegacyZoraCreator1155DelegatedMinter(contractAddress).delegateSetupNewToken(premintConfig, signature, msg.sender);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens for contracts deployed pre-premint? does this just revert?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes they'd revert

}

function supportsNewPremintInterface(address contractAddress) internal view returns (bool) {
return IZoraCreator1155(contractAddress).supportsInterface(type(IZoraCreator1155DelegatedCreation).interfaceId);
}

function premint(
IZoraCreator1155Factory zora1155Factory,
ContractCreationConfig calldata contractConfig,
Expand All @@ -74,10 +94,19 @@ library ZoraCreator1155PremintExecutorImplLib {
// contract address is deterministic.
(IZoraCreator1155 tokenContract, bool isNewContract) = 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);
uint256 newTokenId;

if (supportsNewPremintInterface(address(tokenContract))) {
// if the contract supports the new interface, we can use it to create the token.

// 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);
} else {
// otherwise, we need to use the legacy interface.
newTokenId = legacySetupNewToken(address(tokenContract), encodedPremintConfig, signature);
}

_performMint(tokenContract, fixedPriceMinter, newTokenId, quantityToMint, mintArguments);

Expand Down
20 changes: 9 additions & 11 deletions packages/1155-contracts/src/interfaces/IZoraCreator1155.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {IMinter1155} from "../interfaces/IMinter1155.sol";
import {IOwnable} from "../interfaces/IOwnable.sol";
import {IVersionedContract} from "./IVersionedContract.sol";
import {ICreatorRoyaltiesControl} from "../interfaces/ICreatorRoyaltiesControl.sol";
import {PremintConfigV2} from "../delegation/ZoraCreator1155Attribution.sol";
import {IZoraCreator1155DelegatedCreation} from "./IZoraCreator1155DelegatedCreation.sol";

/*
Expand All @@ -36,8 +36,14 @@ import {PremintConfigV2} from "../delegation/ZoraCreator1155Attribution.sol";

/// @notice Main interface for the ZoraCreator1155 contract
/// @author @iainnash / @tbtstl
interface IZoraCreator1155 is IZoraCreator1155TypesV1, IZoraCreator1155Errors, IVersionedContract, IOwnable, IERC1155MetadataURIUpgradeable {
/// @notice This user role allows for any action to be performed
interface IZoraCreator1155 is
IZoraCreator1155TypesV1,
IZoraCreator1155Errors,
IVersionedContract,
IOwnable,
IERC1155MetadataURIUpgradeable,
IZoraCreator1155DelegatedCreation
{
function PERMISSION_BIT_ADMIN() external returns (uint256);

/// @notice This user role allows for only mint actions to be performed
Expand Down Expand Up @@ -70,7 +76,6 @@ interface IZoraCreator1155 is IZoraCreator1155TypesV1, IZoraCreator1155Errors, I
event ContractRendererUpdated(IRenderer1155 renderer);
event ContractMetadataUpdated(address indexed updater, string uri, string name);
event Purchased(address indexed sender, address indexed minter, uint256 indexed tokenId, uint256 quantity, uint256 value);
event CreatorAttribution(bytes32 structHash, string domainName, string version, address creator, bytes signature);

/// @notice Only allow minting one token id at time
/// @dev Mint contract function that calls the underlying sales function for commands
Expand Down Expand Up @@ -103,13 +108,6 @@ interface IZoraCreator1155 is IZoraCreator1155TypesV1, IZoraCreator1155Errors, I

function getCreatorRewardRecipient(uint256 tokenId) external view returns (address);

function delegateSetupNewToken(
bytes memory premintConfigEncoded,
bytes32 premintVersion,
bytes calldata signature,
address sender
) external returns (uint256 newTokenId);

function updateTokenURI(uint256 tokenId, string memory _newURI) external;

function updateContractMetadata(string memory _newURI, string memory _newName) external;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

interface IZoraCreator1155DelegatedCreation {
event CreatorAttribution(bytes32 structHash, string domainName, string version, address creator, bytes signature);

function delegateSetupNewToken(
bytes memory premintConfigEncoded,
bytes32 premintVersion,
bytes calldata signature,
address sender
) external returns (uint256 newTokenId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ interface IZoraCreator1155Errors is ICreatorRoyaltyErrors, ILimitedMintPerAddres

error MintNotYetStarted();
error PremintDeleted();

error InvalidSignatureVersion();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
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";

// interface for legacy v1 of premint executor methods
Expand Down Expand Up @@ -62,7 +63,12 @@ interface IZoraCreator1155PremintExecutorV2 {
) external view returns (bool isValid, address recoveredSigner);
}

interface IZoraCreator1155PremintExecutor is IZoraCreator1155PremintExecutorV1, IZoraCreator1155PremintExecutorV2 {
interface IZoraCreator1155PremintExecutor is
ILegacyZoraCreator1155PremintExecutor,
IZoraCreator1155PremintExecutorV1,
IZoraCreator1155PremintExecutorV2,
IOwnable2StepUpgradeable
{
struct MintArguments {
address mintRecipient;
string mintComment;
Expand Down
7 changes: 6 additions & 1 deletion packages/1155-contracts/src/nft/ZoraCreator1155Impl.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {TransferHelperUtils} from "../utils/TransferHelperUtils.sol";
import {ZoraCreator1155StorageV1} from "./ZoraCreator1155StorageV1.sol";
import {IZoraCreator1155Errors} from "../interfaces/IZoraCreator1155Errors.sol";
import {ERC1155DelegationStorageV1} from "../delegation/ERC1155DelegationStorageV1.sol";
import {IZoraCreator1155DelegatedCreation} from "../interfaces/IZoraCreator1155DelegatedCreation.sol";
import {ZoraCreator1155Attribution, DecodedCreatorAttribution, PremintTokenSetup, PremintConfig, PremintConfigV2, DelegatedTokenCreation, DelegatedTokenSetup} from "../delegation/ZoraCreator1155Attribution.sol";

/// Imagine. Mint. Enjoy.
Expand Down Expand Up @@ -564,7 +565,11 @@ contract ZoraCreator1155Impl is
function supportsInterface(
bytes4 interfaceId
) public view virtual override(CreatorRoyaltiesControl, ERC1155Upgradeable, IERC165Upgradeable) returns (bool) {
return super.supportsInterface(interfaceId) || interfaceId == type(IZoraCreator1155).interfaceId || ERC1155Upgradeable.supportsInterface(interfaceId);
return
super.supportsInterface(interfaceId) ||
interfaceId == type(IZoraCreator1155).interfaceId ||
ERC1155Upgradeable.supportsInterface(interfaceId) ||
interfaceId == type(IZoraCreator1155DelegatedCreation).interfaceId;
}

/// Generic 1155 function overrides ///
Expand Down
20 changes: 16 additions & 4 deletions packages/1155-contracts/test/fixtures/Zora1155FactoryFixtures.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import {Zora1155Factory} from "../../src/proxies/Zora1155Factory.sol";
import {ZoraCreator1155FactoryImpl} from "../../src/factory/ZoraCreator1155FactoryImpl.sol";
import {ProtocolRewards} from "@zoralabs/protocol-rewards/src/ProtocolRewards.sol";
import {ProxyShim} from "../../src/utils/ProxyShim.sol";
import {IUpgradeGate} from "../../src/interfaces/IUpgradeGate.sol";
import {UpgradeGate} from "../../src/upgrades/UpgradeGate.sol";

library Zora1155FactoryFixtures {
function setupZora1155Impl(address zora, Zora1155Factory factoryProxy) internal returns (ZoraCreator1155Impl) {
function setupZora1155Impl(address zora, IUpgradeGate upgradeGate) internal returns (ZoraCreator1155Impl) {
ProtocolRewards rewards = new ProtocolRewards();
return new ZoraCreator1155Impl(zora, address(factoryProxy), address(rewards));
return new ZoraCreator1155Impl(zora, address(upgradeGate), address(rewards));
}

function upgradeFactoryProxyToUse1155(
Expand All @@ -36,13 +38,23 @@ library Zora1155FactoryFixtures {
factoryProxy = new Zora1155Factory(factoryShimAddress, "");
}

function setupNew1155AndFactory(
address zora,
IUpgradeGate upgradeGate,
IMinter1155 fixedPriceMinter
) internal returns (ZoraCreator1155Impl zoraCreator1155Impl, ZoraCreator1155FactoryImpl factoryImpl) {
zoraCreator1155Impl = setupZora1155Impl(zora, upgradeGate);
factoryImpl = new ZoraCreator1155FactoryImpl(zoraCreator1155Impl, IMinter1155(address(1)), fixedPriceMinter, IMinter1155(address(3)));
}

function setup1155AndFactoryProxy(
address zora,
address deployer
) internal returns (ZoraCreator1155Impl zoraCreator1155Impl, IMinter1155 fixedPriceMinter, Zora1155Factory factoryProxy) {
) internal returns (ZoraCreator1155Impl zoraCreator1155Impl, IMinter1155 fixedPriceMinter, Zora1155Factory factoryProxy, IUpgradeGate upgradeGate) {
factoryProxy = setupFactoryProxy(deployer);
fixedPriceMinter = new ZoraCreatorFixedPriceSaleStrategy();
zoraCreator1155Impl = setupZora1155Impl(zora, factoryProxy);
upgradeGate = new UpgradeGate();
zoraCreator1155Impl = setupZora1155Impl(zora, upgradeGate);
upgradeFactoryProxyToUse1155(factoryProxy, zoraCreator1155Impl, fixedPriceMinter, deployer);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {Zora1155Factory} from "../../src/proxies/Zora1155Factory.sol";
import {ZoraCreator1155FactoryImpl} from "../../src/factory/ZoraCreator1155FactoryImpl.sol";
import {ProtocolRewards} from "@zoralabs/protocol-rewards/src/ProtocolRewards.sol";
import {ProxyShim} from "../../src/utils/ProxyShim.sol";
import {ContractCreationConfig, TokenCreationConfigV2} from "../../src/delegation/ZoraCreator1155Attribution.sol";
import {PremintConfig, ContractCreationConfig, TokenCreationConfigV2, TokenCreationConfig} from "../../src/delegation/ZoraCreator1155Attribution.sol";

library Zora1155PremintFixtures {
function makeDefaultContractCreationConfig(address contractAdmin) internal pure returns (ContractCreationConfig memory) {
Expand Down Expand Up @@ -51,4 +51,26 @@ library Zora1155PremintFixtures {
createReferral: createReferral
});
}

function makeDefaultV1PremintConfig(IMinter1155 fixedPriceMinter, address royaltyRecipient) internal pure returns (PremintConfig memory) {
// make a v1 premint config
return
PremintConfig({
tokenConfig: TokenCreationConfig({
tokenURI: "blah.token",
maxSupply: 10,
maxTokensPerAddress: 5,
pricePerToken: 0,
mintStart: 0,
mintDuration: 0,
fixedPriceMinter: address(fixedPriceMinter),
royaltyRecipient: royaltyRecipient,
royaltyBPS: 10,
royaltyMintSchedule: 0
}),
uid: 100,
version: 0,
deleted: false
});
}
}
Loading
Loading