Skip to content

Commit

Permalink
fix formatting.
Browse files Browse the repository at this point in the history
  • Loading branch information
oveddan committed Oct 17, 2023
1 parent 1e821af commit 25cbf64
Show file tree
Hide file tree
Showing 12 changed files with 257 additions and 75 deletions.
40 changes: 22 additions & 18 deletions packages/1155-contracts/package/preminter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ import {

import {
ContractCreationConfig,
PremintConfig,
TokenCreationConfig,
preminterTypedDataDefinition,
PremintConfigV2,
TokenCreationConfigV2,
encodeMintArguments,
preminterTypedDataDefinitionV2,
} from "./preminter";

const walletClient = createWalletClient({
Expand All @@ -51,8 +52,13 @@ const publicClient = createPublicClient({
type Address = `0x${string}`;

// JSON-RPC Account
const [deployerAccount, creatorAccount, collectorAccount] =
(await walletClient.getAddresses()) as [Address, Address, Address, Address];
const [
deployerAccount,
creatorAccount,
collectorAccount,
createReferralAccount,
mintReferral,
] = (await walletClient.getAddresses()) as [Address, Address, Address, Address];

type TestContext = {
preminterAddress: `0x${string}`;
Expand All @@ -75,20 +81,18 @@ const defaultContractConfig = ({

const defaultTokenConfig = (
fixedPriceMinterAddress: Address
): TokenCreationConfig => ({
): TokenCreationConfigV2 => ({
tokenURI: "ipfs://tokenIpfsId0",
maxSupply: 100n,
maxTokensPerAddress: 10n,
pricePerToken: 0n,
mintStart: 0n,
mintDuration: 100n,
royaltyMintSchedule: 30,
royaltyBPS: 200,
royaltyRecipient: creatorAccount,
fixedPriceMinter: fixedPriceMinterAddress,
createReferral: createReferralAccount,
});

const defaultPremintConfig = (fixedPriceMinter: Address): PremintConfig => ({
const defaultPremintConfig = (fixedPriceMinter: Address): PremintConfigV2 => ({
tokenConfig: defaultTokenConfig(fixedPriceMinter),
deleted: false,
uid: 105,
Expand Down Expand Up @@ -138,7 +142,7 @@ describe("ZoraCreator1155Preminter", () => {
});

const signedMessage = await walletClient.signTypedData({
...preminterTypedDataDefinition({
...preminterTypedDataDefinitionV2({
verifyingContract: contractAddress,
chainId: 999,
premintConfig,
Expand Down Expand Up @@ -177,7 +181,7 @@ describe("ZoraCreator1155Preminter", () => {

// sign message containing contract and token creation config and uid
const signedMessage = await walletClient.signTypedData({
...preminterTypedDataDefinition({
...preminterTypedDataDefinitionV2({
verifyingContract: contractAddress,
// we need to sign here for the anvil chain, cause thats where it is run on
chainId: anvilChainId,
Expand Down Expand Up @@ -226,7 +230,7 @@ describe("ZoraCreator1155Preminter", () => {
// have creator sign the message to create the contract
// and the token
const signedMessage = await walletClient.signTypedData({
...preminterTypedDataDefinition({
...preminterTypedDataDefinitionV2({
verifyingContract: contractAddress,
// we need to sign here for the anvil chain, cause thats where it is run on
chainId: anvilChainId,
Expand Down Expand Up @@ -274,7 +278,7 @@ describe("ZoraCreator1155Preminter", () => {
premintConfig,
signedMessage,
quantityToMint,
comment,
encodeMintArguments({ mintComment: comment }),
],
value: valueToSend,
});
Expand Down Expand Up @@ -319,7 +323,7 @@ describe("ZoraCreator1155Preminter", () => {

// sign the message to create the second token
const signedMessage2 = await walletClient.signTypedData({
...preminterTypedDataDefinition({
...preminterTypedDataDefinitionV2({
verifyingContract: contractAddress,
chainId: foundry.id,
premintConfig: premintConfig2,
Expand All @@ -345,7 +349,7 @@ describe("ZoraCreator1155Preminter", () => {
premintConfig2,
signedMessage2,
quantityToMint2,
comment,
encodeMintArguments({ mintComment: comment }),
],
value: valueToSend2,
});
Expand Down Expand Up @@ -403,7 +407,7 @@ describe("ZoraCreator1155Preminter", () => {
// have creator sign the message to create the contract
// and the token
const signedMessage = await walletClient.signTypedData({
...preminterTypedDataDefinition({
...preminterTypedDataDefinitionV2({
verifyingContract: contractAddress,
// we need to sign here for the anvil chain, cause thats where it is run on
chainId: anvilChainId,
Expand Down Expand Up @@ -439,7 +443,7 @@ describe("ZoraCreator1155Preminter", () => {
premintConfig,
signedMessage,
quantityToMint,
comment,
encodeMintArguments({ mintComment: comment }),
],
value: valueToSend,
});
Expand Down
105 changes: 98 additions & 7 deletions packages/1155-contracts/package/preminter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { Address } from "abitype";
import { ExtractAbiFunction, AbiParametersToPrimitiveTypes } from "abitype";
import { zoraCreator1155PremintExecutorImplABI as preminterAbi } from "./wagmiGenerated";
import { TypedDataDefinition } from "viem";
import {
TypedDataDefinition,
encodeAbiParameters,
hashDomain,
hashTypedData,
} from "viem";

type PremintInputs = ExtractAbiFunction<
typeof preminterAbi,
Expand All @@ -11,18 +16,88 @@ type PremintInputs = ExtractAbiFunction<
type PreminterHashDataTypes = AbiParametersToPrimitiveTypes<PremintInputs>;

export type ContractCreationConfig = PreminterHashDataTypes[0];
export type PremintConfig = PreminterHashDataTypes[1];
export type TokenCreationConfig = PremintConfig["tokenConfig"];
export type PremintConfigs = PreminterHashDataTypes[1];

export type TokenCreationConfigV1 = PremintConfigV2["tokenConfig"];
export type PremintConfigV2 = Extract<
PremintConfigs,
{
tokenConfig: {
createReferral: string;
};
}
>;
export type PremintConfigV1 = Exclude<PremintConfigs, PremintConfigV2>;
export type TokenCreationConfigV2 = PremintConfigV2["tokenConfig"];

const premintV2Types = {
CreatorAttribution: [
{ name: "tokenConfig", type: "TokenCreationConfig" },
// unique id scoped to the contract and token to create.
// ensure that a signature can be replaced, as long as the replacement
// has the same uid, and a newer version.
{ name: "uid", type: "uint32" },
{ name: "version", type: "uint32" },
// if this update should result in the signature being deleted.
{ name: "deleted", type: "bool" },
],
TokenCreationConfig: [
{ name: "tokenURI", type: "string" },
{ name: "maxSupply", type: "uint256" },
{ name: "maxTokensPerAddress", type: "uint64" },
{ name: "pricePerToken", type: "uint96" },
{ name: "mintStart", type: "uint64" },
{ name: "mintDuration", type: "uint64" },
{ name: "fixedPriceMinter", type: "address" },
{ name: "createReferral", type: "address" },
],
};

// Convenience method to create the structured typed data
// needed to sign for a premint contract and token
export const preminterTypedDataDefinitionV2 = ({
verifyingContract,
premintConfig,
chainId,
}: {
verifyingContract: Address;
premintConfig: PremintConfigV2;
chainId: number;
}) => {
const { tokenConfig, uid, version, deleted } = premintConfig;

const result: TypedDataDefinition<
typeof premintV2Types,
"CreatorAttribution"
> = {
domain: {
chainId,
name: "Preminter",
version: "2",
verifyingContract: verifyingContract,
},
types: premintV2Types,
message: {
tokenConfig,
uid,
version,
deleted,
},
primaryType: "CreatorAttribution",
};

return result;
};

// Convenience method to create the structured typed data
// needed to sign for a premint contract and token
export const preminterTypedDataDefinition = ({
export const preminterTypedDataDefinitionV1 = ({
verifyingContract,
premintConfig,
chainId,
}: {
verifyingContract: Address;
premintConfig: PremintConfig;
premintConfig: PremintConfigV1;
chainId: number;
}) => {
const { tokenConfig, uid, version, deleted } = premintConfig;
Expand Down Expand Up @@ -68,7 +143,23 @@ export const preminterTypedDataDefinition = ({
primaryType: "CreatorAttribution",
};

// console.log({ result, deleted });

return result;
};

const zeroAddress: Address = "0x0000000000000000000000000000000000000000";

export const encodeMintArguments = ({
mintComment = "",
mintReferral = zeroAddress,
}: {
mintComment?: string;
mintReferral?: Address;
}) => {
return encodeAbiParameters(
[
{ name: "mintReferral", type: "address" },
{ name: "mintComment", type: "string" },
],
[mintReferral, mintComment]
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ struct TokenCreationConfig {
address fixedPriceMinter;
}


struct PremintConfigV2 {
// The config for the token to be created
TokenCreationConfigV2 tokenConfig;
Expand Down Expand Up @@ -91,7 +90,6 @@ library ZoraCreator1155Attribution {
string internal constant VERSION_2 = "2";
bytes32 internal constant HASHED_VERSION_2 = keccak256(bytes(VERSION_2));


bytes32 constant ATTRIBUTION_DOMAIN_V1 =
keccak256(
"CreatorAttribution(TokenCreationConfig tokenConfig,uint32 uid,uint32 version,bool deleted)TokenCreationConfig(string tokenURI,uint256 maxSupply,uint64 maxTokensPerAddress,uint96 pricePerToken,uint64 mintStart,uint64 mintDuration,uint32 royaltyMintSchedule,uint32 royaltyBPS,address royaltyRecipient,address fixedPriceMinter)"
Expand All @@ -102,14 +100,18 @@ library ZoraCreator1155Attribution {
"CreatorAttribution(TokenCreationConfig tokenConfig,uint32 uid,uint32 version,bool deleted)TokenCreationConfig(string tokenURI,uint256 maxSupply,uint64 maxTokensPerAddress,uint96 pricePerToken,uint64 mintStart,uint64 mintDuration,address fixedPriceMinter,address createReferral)"
);

function hashPremintV1(PremintConfig calldata premintConfig) public pure returns (bytes32) {
function hashPremint(PremintConfig calldata premintConfig) public pure returns (bytes32) {
return
keccak256(abi.encode(ATTRIBUTION_DOMAIN_V1, _hashToken(premintConfig.tokenConfig), premintConfig.uid, premintConfig.version, premintConfig.deleted));
keccak256(
abi.encode(ATTRIBUTION_DOMAIN_V1, _hashToken(premintConfig.tokenConfig), premintConfig.uid, premintConfig.version, premintConfig.deleted)
);
}

function hashPremint(PremintConfigV2 calldata premintConfig) public pure returns (bytes32) {
return
keccak256(abi.encode(ATTRIBUTION_DOMAIN_V2, _hashToken(premintConfig.tokenConfig), premintConfig.uid, premintConfig.version, premintConfig.deleted));
keccak256(
abi.encode(ATTRIBUTION_DOMAIN_V2, _hashToken(premintConfig.tokenConfig), premintConfig.uid, premintConfig.version, premintConfig.deleted)
);
}

bytes32 constant TOKEN_DOMAIN_V1 =
Expand Down Expand Up @@ -171,7 +173,13 @@ library ZoraCreator1155Attribution {
return _buildDomainSeparator(hashedName, hashedVersion, verifyingContract, chainId);
}

function hashTypedDataV4(bytes32 structHash, bytes32 hashedName, bytes32 hashedVersion, address verifyingContract, uint256 chainId) internal pure returns (bytes32) {
function hashTypedDataV4(
bytes32 structHash,
bytes32 hashedName,
bytes32 hashedVersion,
address verifyingContract,
uint256 chainId
) internal pure returns (bytes32) {
return ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(chainId, verifyingContract, hashedName, hashedVersion), structHash);
}

Expand Down Expand Up @@ -202,7 +210,7 @@ library ZoraCreator1155Attribution {
chainId
);

(signatory,) = ECDSAUpgradeable.tryRecover(digest, signature);
(signatory, ) = ECDSAUpgradeable.tryRecover(digest, signature);
}

function _stringHash(string calldata value) private pure returns (bytes32) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,11 @@ import {SharedBaseConstants} from "../shared/SharedBaseConstants.sol";
import {ZoraCreatorFixedPriceSaleStrategy} from "../minters/fixed-price/ZoraCreatorFixedPriceSaleStrategy.sol";
import {IMinter1155} from "../interfaces/IMinter1155.sol";
import {ERC1155DelegationStorageV1} from "../delegation/ERC1155DelegationStorageV1.sol";
import {ZoraCreator1155PremintExecutorImplLib } from './ZoraCreator1155PremintExecutorImplLib.sol';
import {ZoraCreator1155PremintExecutorImplLib} from "./ZoraCreator1155PremintExecutorImplLib.sol";
import {ZoraCreator1155Attribution, ContractCreationConfig, PremintConfig, PremintConfigV2, TokenCreationConfig, TokenCreationConfigV2} from "./ZoraCreator1155Attribution.sol";

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

// interface for legacy v1 of premint executor methods
Expand Down Expand Up @@ -58,7 +54,13 @@ interface ILegacyZoraCreator1155PremintExecutor {
/// 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, Ownable2StepUpgradeable, UUPSUpgradeable, IHasContractName, IZoraCreator1155Errors {
contract ZoraCreator1155PremintExecutorImpl is
ILegacyZoraCreator1155PremintExecutor,
Ownable2StepUpgradeable,
UUPSUpgradeable,
IHasContractName,
IZoraCreator1155Errors
{
IZoraCreator1155Factory public immutable zora1155Factory;

constructor(IZoraCreator1155Factory _factory) {
Expand Down Expand Up @@ -170,15 +172,23 @@ contract ZoraCreator1155PremintExecutorImpl is ILegacyZoraCreator1155PremintExec
bytes32 signatureVersion,
bytes calldata signature
) public view returns (bool isValid, address recoveredSigner) {
return ZoraCreator1155Attribution.isValidSignature(originalPremintCreator, contractAddress, hashedPremint, signatureVersion, signature);
return ZoraCreator1155Attribution.isValidSignature(originalPremintCreator, contractAddress, hashedPremint, signatureVersion, signature);
}

function recoverSigner(
bytes32 hashedPremintConfig,
bytes calldata signature,
bytes32 signatureVersion,
address erc1155Contract
) public view returns (address recoveredSigner) {
return ZoraCreator1155Attribution.recoverSignerHashed(hashedPremintConfig, signature, erc1155Contract, signatureVersion, block.chainid);
}

/// 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) {
return
ZoraCreator1155PremintExecutorImplLib.getContractAddress(zora1155Factory, contractConfig);
return ZoraCreator1155PremintExecutorImplLib.getContractAddress(zora1155Factory, contractConfig);
}

/// @notice Utility function to determine if a premint contract has been created for a uid of a premint, and if so,
Expand Down Expand Up @@ -235,6 +245,16 @@ contract ZoraCreator1155PremintExecutorImpl is ILegacyZoraCreator1155PremintExec
PremintConfig calldata premintConfig,
bytes calldata signature
) public view returns (bool isValid, address contractAddress, address recoveredSigner) {

contractAddress = getContractAddress(contractConfig);

bytes32 hashedPremint = ZoraCreator1155Attribution.hashPremint(premintConfig);

(isValid, recoveredSigner) = isValidSignature(
contractConfig.contractAdmin,
contractAddress,
hashedPremint,
ZoraCreator1155Attribution.HASHED_VERSION_1,
signature
);
}
}
Loading

0 comments on commit 25cbf64

Please sign in to comment.