// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
import {LibClone} from "solady/src/utils/LibClone.sol";
import {Ownable} from "solady/src/auth/Ownable.sol";
import {Pausable} from "openzeppelin-contracts/contracts/security/Pausable.sol";
import {IAccessControl} from "openzeppelin/contracts/access/IAccessControl.sol";
import {IFxGenArt721, InitInfo, MetadataInfo, MintInfo, ProjectInfo} from "src/interfaces/IFxGenArt721.sol";
import {IFxIssuerFactory} from "src/interfaces/IFxIssuerFactory.sol";
import {IFxTicketFactory} from "src/interfaces/IFxTicketFactory.sol";
/**
* @title FxIssuerFactory
* @author fx(hash)
* @dev See the documentation in {IFxIssuerFactory}
*/
contract FxIssuerFactory is IFxIssuerFactory, Ownable, Pausable {
/*//////////////////////////////////////////////////////////////////////////
STORAGE
//////////////////////////////////////////////////////////////////////////*/
/**
* @inheritdoc IFxIssuerFactory
*/
address public immutable roleRegistry;
/**
* @inheritdoc IFxIssuerFactory
*/
address public implementation;
/**
* @inheritdoc IFxIssuerFactory
*/
uint96 public projectId;
/**
* @inheritdoc IFxIssuerFactory
*/
mapping(address => uint256) public nonces;
/**
* @inheritdoc IFxIssuerFactory
*/
mapping(uint96 => address) public projects;
/*//////////////////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////////////////*/
/**
* @dev Initializes factory owner, FxRoleRegistry and FxGenArt721 implementation
*/
constructor(address _admin, address _roleRegistry, address _implementation) {
_pause();
roleRegistry = _roleRegistry;
_initializeOwner(_admin);
_setImplementation(_implementation);
}
/*//////////////////////////////////////////////////////////////////////////
EXTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/**
* @inheritdoc IFxIssuerFactory
*/
function createProjectWithTicket(
bytes calldata _projectCreationInfo,
bytes calldata _ticketCreationInfo,
address _ticketFactory
) external whenNotPaused returns (address genArtToken, address mintTicket) {
genArtToken = createProject(_projectCreationInfo);
mintTicket = IFxTicketFactory(_ticketFactory).createTicket(_ticketCreationInfo);
}
/**
* @inheritdoc IFxIssuerFactory
*/
function unpause() external onlyOwner {
_unpause();
}
/**
* @inheritdoc IFxIssuerFactory
*/
function pause() external onlyOwner {
_pause();
}
/**
* @inheritdoc IFxIssuerFactory
*/
function setImplementation(address _implementation) external onlyOwner {
_setImplementation(_implementation);
}
/*//////////////////////////////////////////////////////////////////////////
PUBLIC FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/**
* @inheritdoc IFxIssuerFactory
*/
function createProject(bytes memory _creationInfo) public returns (address genArt721) {
(
address _owner,
InitInfo memory _initInfo,
ProjectInfo memory _projectInfo,
MetadataInfo memory _metadataInfo,
MintInfo[] memory _mintInfo,
address[] memory _royaltyReceivers,
uint32[] memory _allocations,
uint96 _basisPoints
) = abi.decode(
_creationInfo,
(address, InitInfo, ProjectInfo, MetadataInfo, MintInfo[], address[], uint32[], uint96)
);
genArt721 = createProjectWithParams(
_owner,
_initInfo,
_projectInfo,
_metadataInfo,
_mintInfo,
_royaltyReceivers,
_allocations,
_basisPoints
);
}
/**
* @inheritdoc IFxIssuerFactory
*/
function createProjectWithParams(
address _owner,
InitInfo memory _initInfo,
ProjectInfo memory _projectInfo,
MetadataInfo memory _metadataInfo,
MintInfo[] memory _mintInfo,
address[] memory _royaltyReceivers,
uint32[] memory _allocations,
uint96 _basisPoints
) public whenNotPaused returns (address genArtToken) {
if (_owner == address(0)) revert InvalidOwner();
bytes32 salt = keccak256(abi.encode(msg.sender, nonces[msg.sender]));
genArtToken = LibClone.cloneDeterministic(implementation, salt);
nonces[msg.sender]++;
projects[++projectId] = genArtToken;
emit ProjectCreated(projectId, genArtToken, _owner);
IFxGenArt721(genArtToken).initialize(
_owner,
_initInfo,
_projectInfo,
_metadataInfo,
_mintInfo,
_royaltyReceivers,
_allocations,
_basisPoints
);
}
/*//////////////////////////////////////////////////////////////////////////
VIEW FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/**
* @inheritdoc IFxIssuerFactory
*/
function getTokenAddress(address _sender) external view returns (address) {
bytes32 salt = keccak256(abi.encode(_sender, nonces[_sender]));
return LibClone.predictDeterministicAddress(implementation, salt, address(this));
}
/*//////////////////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/**
* @dev Sets the FxGenArt721 implementation contract
*/
function _setImplementation(address _implementation) internal {
implementation = _implementation;
emit ImplementationUpdated(msg.sender, _implementation);
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
import {GenArtInfo, InitInfo, IssuerInfo, MetadataInfo, MintInfo, ProjectInfo, ReserveInfo} from "src/lib/Structs.sol";
import {ISeedConsumer} from "src/interfaces/ISeedConsumer.sol";
import {IToken} from "src/interfaces/IToken.sol";
/**
* @title IFxGenArt721
* @author fx(hash)
* @notice ERC-721 token for generative art projects created on fxhash
*/
interface IFxGenArt721 is ISeedConsumer, IToken {
/*//////////////////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////////////////*/
/**
* @notice Event emitted when the base URI is updated
* @param _uri Decoded content identifier of metadata pointer
*/
event BaseURIUpdated(bytes _uri);
/**
* @notice Event emitted when public burn is enabled or disabled
* @param _flag Status of burn
*/
event BurnEnabled(bool indexed _flag);
/**
* @notice Event emitted when public mint is enabled or disabled
* @param _flag Status of mint
*/
event MintEnabled(bool indexed _flag);
/**
* @notice Event emitted when project is deleted only once supply is set to zero
*/
event ProjectDeleted();
/**
* @notice Event emitted when new project is initialized
* @param _primaryReceiver Address of splitter contract receiving primary sales
* @param _projectInfo Project information
* @param _metadataInfo Metadata information of token
* @param _mintInfo Array of authorized minter contracts and their reserves
*/
event ProjectInitialized(
address indexed _primaryReceiver,
ProjectInfo _projectInfo,
MetadataInfo _metadataInfo,
MintInfo[] _mintInfo
);
/**
* @notice Event emitted when the primary receiver address is updated
* @param _receiver The split address receiving funds on behalf of the users
* @param _receivers Array of addresses receiving a portion of the funds in a split
* @param _allocations Array of allocation shares for the split
*/
event PrimaryReceiverUpdated(address indexed _receiver, address[] _receivers, uint32[] _allocations);
/**
* @notice Event emitted when project tags are set
* @param _tagIds Array of tag IDs describing the project
*/
event ProjectTags(uint256[] _tagIds);
/**
* @notice Event emitted when Randomizer contract is updated
* @param _randomizer Address of new Randomizer contract
*/
event RandomizerUpdated(address indexed _randomizer);
/**
* @notice Event emitted when Renderer contract is updated
* @param _renderer Address of new Renderer contract
*/
event RendererUpdated(address indexed _renderer);
/**
* @notice Event emitted when onchain data of project is updated
* @param _pointer SSTORE2 pointer to the onchain data
*/
event OnchainPointerUpdated(address _pointer);
/**
* @notice Event emitted when maximum supply is reduced
* @param _prevSupply Amount of previous supply
* @param _newSupply Amount of new supply
*/
event SupplyReduced(uint120 indexed _prevSupply, uint120 indexed _newSupply);
/*//////////////////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////////////////*/
/**
* @notice Error thrown when total minter allocation exceeds maximum supply
*/
error AllocationExceeded();
/**
* @notice Error thrown when burning is inactive
*/
error BurnInactive();
/**
* @notice Error thrown when the fee receiver address is not included in the receiver allocations
*/
error FeeReceiverMissing();
/**
* @notice Error thrown when remaining supply is zero
*/
error InsufficientSupply();
/**
* @notice Error thrown when max supply amount is invalid
*/
error InvalidAmount();
/**
* @notice Error thrown when input size does not match actual byte size of params data
*/
error InvalidInputSize();
/**
* @notice Error thrown when reserve start time is invalid
*/
error InvalidStartTime();
/**
* @notice Error thrown when reserve end time is invalid
*/
error InvalidEndTime();
/**
* @notice Error thrown when the configured fee receiver is not valid
*/
error InvalidFeeReceiver();
/**
* @notice Error thrown when minting is active
*/
error MintActive();
/**
* @notice Error thrown when minting is inactive
*/
error MintInactive();
/**
* @notice Error thrown when caller is not authorized to execute transaction
*/
error NotAuthorized();
/**
* @notice Error thrown when signer is not the owner
*/
error NotOwner();
/**
* @notice Error thrown when supply is remaining
*/
error SupplyRemaining();
/**
* @notice Error thrown when caller does not have the specified role
*/
error UnauthorizedAccount();
/**
* @notice Error thrown when caller does not have minter role
*/
error UnauthorizedMinter();
/**
* @notice Error thrown when minter is not registered on token contract
*/
error UnregisteredMinter();
/*//////////////////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/*
* @notice Returns the list of minter contracts currently active on the token
*/
function activeMinters() external view returns (address[] memory);
/**
* @notice Burns token ID from the circulating supply
* @param _tokenId ID of the token
*/
function burn(uint256 _tokenId) external;
/**
* @notice Returns address of the FxContractRegistry contract
*/
function contractRegistry() external view returns (address);
/**
* @notice Returns contract-level metadata for storefront marketplaces
*/
function contractURI() external view returns (string memory);
/**
* @inheritdoc ISeedConsumer
*/
function fulfillSeedRequest(uint256 _tokenId, bytes32 _seed) external;
/**
* @notice Mapping of token ID to GenArtInfo struct (minter, seed, fxParams)
*/
function genArtInfo(uint256 _tokenId) external view returns (address, bytes32, bytes memory);
/**
* @notice Generates typed data hash for setting project metadata onchain
* @param _data Bytes-encoded onchain data
* @return Typed data hash
*/
function generateOnchainPointerHash(bytes calldata _data) external view returns (bytes32);
/**
* @notice Generates typed data hash for setting the primary receiver address
* @param _renderer Address of the new renderer contract
* @return Typed data hash
*/
function generateRendererHash(address _renderer) external view returns (bytes32);
/**
* @notice Initializes new generative art project
* @param _owner Address of token proxy owner
* @param _initInfo Initialization information set on project creation
* @param _projectInfo Project information
* @param _metadataInfo Metadata information
* @param _mintInfo Array of authorized minter contracts and their reserves
* @param _royaltyReceivers Array of addresses receiving royalties
* @param _allocations Array of allocation amounts for calculating royalty shares
* @param _basisPoints Total allocation scalar for calculating royalty shares
*/
function initialize(
address _owner,
InitInfo calldata _initInfo,
ProjectInfo calldata _projectInfo,
MetadataInfo calldata _metadataInfo,
MintInfo[] calldata _mintInfo,
address[] calldata _royaltyReceivers,
uint32[] calldata _allocations,
uint96 _basisPoints
) external;
/**
* @notice Gets the authorization status for the given minter contract
* @param _minter Address of the minter contract
* @return Authorization status
*/
function isMinter(address _minter) external view returns (bool);
/**
* @notice Returns the issuer information of the project (primaryReceiver, ProjectInfo)
*/
function issuerInfo() external view returns (address, ProjectInfo memory);
/**
* @notice Returns the metadata information of the project (baseURI, onchainPointer)
*/
function metadataInfo() external view returns (bytes memory, address);
/**
* @inheritdoc IToken
*/
function mint(address _to, uint256 _amount, uint256 _payment) external;
/**
* @notice Mints single fxParams token
* @dev Only callable by registered minter contracts
* @param _to Address receiving minted token
* @param _fxParams Random sequence of fixed-length bytes used as input
*/
function mintParams(address _to, bytes calldata _fxParams) external;
/**
* @notice Current nonce for admin signatures
*/
function nonce() external returns (uint96);
/**
* @notice Mints single token with randomly generated seed
* @dev Only callable by contract owner
* @param _to Address receiving token
*/
function ownerMint(address _to) external;
/**
* @notice Mints single fxParams token
* @dev Only callable by contract owner
* @param _to Address receiving minted token
* @param _fxParams Random sequence of fixed-length bytes used as input
*/
function ownerMintParams(address _to, bytes calldata _fxParams) external;
/**
* @notice Pauses all function executions where modifier is applied
*/
function pause() external;
/**
* @inheritdoc IToken
*/
function primaryReceiver() external view returns (address);
/**
* @notice Returns the address of the randomizer contract
*/
function randomizer() external view returns (address);
/**
* @notice Reduces maximum supply of collection
* @param _supply Maximum supply amount
*/
function reduceSupply(uint120 _supply) external;
/**
* @notice Registers minter contracts with resereve info
* @param _mintInfo Mint information of token reserves
*/
function registerMinters(MintInfo[] memory _mintInfo) external;
/**
* @notice Returns the remaining supply of tokens left to mint
*/
function remainingSupply() external view returns (uint256);
/**
* @notice Returns the address of the Renderer contract
*/
function renderer() external view returns (address);
/**
* @notice Returns the address of the FxRoleRegistry contract
*/
function roleRegistry() external view returns (address);
/**
* @notice Sets the base royalties for all secondary token sales
* @param _receivers Array of addresses receiving royalties
* @param _allocations Array of allocations used to calculate royalty payments
* @param _basisPoints basis points used to calculate royalty payments
*/
function setBaseRoyalties(
address[] calldata _receivers,
uint32[] calldata _allocations,
uint96 _basisPoints
) external;
/**
* @notice Sets the new URI of the token metadata
* @param _uri Decoded content identifier of metadata pointer
*/
function setBaseURI(bytes calldata _uri) external;
/**
* @notice Sets flag status of public burn to enabled or disabled
* @param _flag Status of burn
*/
function setBurnEnabled(bool _flag) external;
/**
* @notice Sets flag status of public mint to enabled or disabled
* @param _flag Status of mint
*/
function setMintEnabled(bool _flag) external;
/**
* @notice Sets the onchain pointer for reconstructing project metadata onchain
* @param _onchainData Bytes-encoded metadata
* @param _signature Signature of creator used to verify metadata update
*/
function setOnchainPointer(bytes calldata _onchainData, bytes calldata _signature) external;
/**
* @notice Sets the primary receiver address for primary sale proceeds
* @param _receivers Array of addresses receiving shares from primary sales
* @param _allocations Array of allocation amounts for calculating primary sales shares
*/
function setPrimaryReceivers(address[] calldata _receivers, uint32[] calldata _allocations) external;
/**
* @notice Sets the new randomizer contract
* @param _randomizer Address of the randomizer contract
*/
function setRandomizer(address _randomizer) external;
/**
* @notice Sets the new renderer contract
* @param _renderer Address of the renderer contract
* @param _signature Signature of creator used to verify renderer update
*/
function setRenderer(address _renderer, bytes calldata _signature) external;
/**
* @notice Emits an event for setting tag descriptions for the project
* @param _tagIds Array of tag IDs describing the project
*/
function setTags(uint256[] calldata _tagIds) external;
/**
* @notice Returns the current circulating supply of tokens
*/
function totalSupply() external view returns (uint96);
/**
* @notice Unpauses all function executions where modifier is applied
*/
function unpause() external;
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
import {InitInfo, MetadataInfo, MintInfo, ProjectInfo} from "src/lib/Structs.sol";
/**
* @title IFxIssuerFactory
* @author fx(hash)
* @notice Factory for managing newly deployed FxGenArt721 tokens
*/
interface IFxIssuerFactory {
/*//////////////////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////////////////*/
/**
* @notice Event emitted when the FxGenArt721 implementation contract is updated
* @param _owner Address of the factory owner
* @param _implementation Address of the new FxGenArt721 implementation contract
*/
event ImplementationUpdated(address indexed _owner, address indexed _implementation);
/**
* @notice Event emitted when a new generative art project is created
* @param _projectId ID of the project
* @param _genArtToken Address of newly deployed FxGenArt721 token contract
* @param _owner Address of project owner
*/
event ProjectCreated(uint96 indexed _projectId, address indexed _genArtToken, address indexed _owner);
/*//////////////////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////////////////*/
/**
* @notice Error thrown when owner is zero address
*/
error InvalidOwner();
/**
* @notice Error thrown when primary receiver is zero address
*/
error InvalidPrimaryReceiver();
/**
* @notice Error thrown when caller is not authorized to execute transaction
*/
error NotAuthorized();
/*//////////////////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/**
* @notice Creates new generative art project
* @param _owner Address of project owner
* @param _initInfo Initialization information
* @param _projectInfo Project information
* @param _metadataInfo Metadata information
* @param _mintInfo Array of authorized minter contracts and their reserves
* @param _royaltyReceivers Array of addresses receiving royalties
* @param _allocations Array of allocation amounts for calculating royalty shares
* @param _basisPoints Total allocation scalar for calculating royalty shares
* @return genArtToken Address of newly created FxGenArt721 proxy
*/
function createProjectWithParams(
address _owner,
InitInfo memory _initInfo,
ProjectInfo memory _projectInfo,
MetadataInfo memory _metadataInfo,
MintInfo[] memory _mintInfo,
address[] memory _royaltyReceivers,
uint32[] memory _allocations,
uint96 _basisPoints
) external returns (address);
/**
* @notice Creates new generative art project with single parameter
* @param _creationInfo Bytes-encoded data for project creation
* @return genArtToken Address of newly created FxGenArt721 proxy
*/
function createProject(bytes memory _creationInfo) external returns (address);
/**
* @notice Creates new generative art project with new mint ticket in single transaction
* @param _projectCreationInfo Bytes-encoded data for project creation
* @param _ticketCreationInfo Bytes-encoded data for ticket creation
* @param _tickeFactory Address of FxTicketFactory contract
* @return genArtToken Address of newly created FxGenArt721 proxy
* @return mintTicket Address of newly created FxMintTicket721 proxy
*/
function createProjectWithTicket(
bytes calldata _projectCreationInfo,
bytes calldata _ticketCreationInfo,
address _tickeFactory
) external returns (address, address);
/**
* @notice Calculates the CREATE2 address of a new FxGenArt721 proxy
*/
function getTokenAddress(address _sender) external view returns (address);
/**
* @notice Returns address of current FxGenArt721 implementation contract
*/
function implementation() external view returns (address);
/**
* @notice Mapping of deployer address to nonce value for precomputing token address
*/
function nonces(address _deployer) external view returns (uint256);
/**
* @notice Stops new FxGenArt721 tokens from being created
*/
function pause() external;
/**
* @notice Returns counter of latest project ID
*/
function projectId() external view returns (uint96);
/**
* @notice Mapping of project ID to address of FxGenArt721 token contract
*/
function projects(uint96) external view returns (address);
/**
* @notice Returns the address of the FxRoleRegistry contract
*/
function roleRegistry() external view returns (address);
/**
* @notice Sets new FxGenArt721 implementation contract
* @param _implementation Address of the implementation contract
*/
function setImplementation(address _implementation) external;
/**
* @notice Enables new FxGenArt721 tokens from being created
*/
function unpause() external;
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
import {MintInfo} from "src/lib/Structs.sol";
/**
* @title IFxTicketFactory
* @author fx(hash)
* @notice Factory for managing newly deployed FxMintTicket721 tokens
*/
interface IFxTicketFactory {
/*//////////////////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////////////////*/
/**
* @notice Event emitted when the minimum grace period is updated
* @param _owner Address of the factory owner
* @param _gracePeriod Time duration of the new grace period
*/
event GracePeriodUpdated(address indexed _owner, uint48 indexed _gracePeriod);
/**
* @notice Event emitted when the FxMintTicket721 implementation contract is updated
* @param _owner Address of the factory owner
* @param _implementation Address of the new FxMintTicket721 implementation contract
*/
event ImplementationUpdated(address indexed _owner, address indexed _implementation);
/**
* @notice Event emitted when new FxMintTicket721 is created
* @param _ticketId ID of the ticket contract
* @param _mintTicket Address of newly deployed FxMintTicket721 token contract
* @param _owner Address of ticket owner
*/
event TicketCreated(uint96 indexed _ticketId, address indexed _mintTicket, address indexed _owner);
/*//////////////////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////////////////*/
/**
* @notice Error thrown when grace period is less than minimum requirement of one day
*/
error InvalidGracePeriod();
/**
* @notice Error thrown when owner is zero address
*/
error InvalidOwner();
/**
* @notice Error thrown when redeemer contract is zero address
*/
error InvalidRedeemer();
/**
* @notice Error thrown when renderer contract is zero address
*/
error InvalidRenderer();
/**
* @notice Error thrown when token contract is zero address
*/
error InvalidToken();
/*//////////////////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/**
* @notice Creates new mint ticket
* @param _owner Address of project owner
* @param _genArt721 Address of GenArt721 token contract
* @param _redeemer Address of TicketRedeemer minter contract
* @param _redeemer Address of renderer contract
* @param _gracePeriod Duration of time before token enters harberger taxation
* @param _mintInfo Array of authorized minter contracts and their reserves
*/
function createTicket(
address _owner,
address _genArt721,
address _redeemer,
address _renderer,
uint48 _gracePeriod,
MintInfo[] memory _mintInfo
) external returns (address);
/**
* @notice Creates new mint ticket for new generative art project in single transaction
* @param _creationInfo Bytes-encoded data for ticket creation
* @return mintTicket Address of newly created FxMintTicket721 proxy
*/
function createTicket(bytes calldata _creationInfo) external returns (address);
/**
* @notice Calculates the CREATE2 address of a new FxMintTicket721 proxy
*/
function getTicketAddress(address _sender) external view returns (address);
/**
* @notice Returns address of current FxMintTicket721 implementation contract
*/
function implementation() external view returns (address);
/**
* @notice Returns the minimum duration of time before a ticket enters harberger taxation
*/
function minGracePeriod() external view returns (uint48);
/**
* @notice Mapping of deployer address to nonce value for precomputing ticket address
*/
function nonces(address _deployer) external view returns (uint256);
/**
* @notice Sets the new minimum grace period
* @param _gracePeriod Minimum time duration before a ticket enters harberger taxation
*/
function setMinGracePeriod(uint48 _gracePeriod) external;
/**
* @notice Sets new FxMintTicket721 implementation contract
* @param _implementation Address of the implementation contract
*/
function setImplementation(address _implementation) external;
/**
* @notice Returns counter of latest token ID
*/
function ticketId() external view returns (uint48);
/**
* @notice Mapping of token ID to address of FxMintTicket721 token contract
*/
function tickets(uint48 _ticketId) external view returns (address);
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
/**
* @title ISeedConsumer
* @author fx(hash)
* @notice Interface for randomizers to interact with FxGenArt721 tokens
*/
interface ISeedConsumer {
/*//////////////////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////////////////*/
/**
* @notice Event emitted when a seed request is fulfilled for a specific token
* @param _randomizer Address of the randomizer contract
* @param _tokenId ID of the token
* @param _seed Hash of the random seed
*/
event SeedFulfilled(address indexed _randomizer, uint256 indexed _tokenId, bytes32 _seed);
/*//////////////////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/**
* @notice Fullfills the random seed request on the FxGenArt721 token contract
* @param _tokenId ID of the token
* @param _seed Hash of the random seed
*/
function fulfillSeedRequest(uint256 _tokenId, bytes32 _seed) external;
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
/**
* @title IToken
* @author fx(hash)
* @notice Interface for minters to interact with tokens
*/
interface IToken {
/*//////////////////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/
/**
* @notice Mints arbitrary number of tokens
* @dev Only callable by registered minter contracts
* @param _to Address receiving tokens
* @param _amount Number of tokens being minted
* @param _payment Total payment amount of the transaction
*/
function mint(address _to, uint256 _amount, uint256 _payment) external;
/**
* @notice Returns address of primary receiver for token sales
*/
function primaryReceiver() external view returns (address);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Minimal proxy library.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)
/// @author Minimal proxy by 0age (https://github.com/0age)
/// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie
/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)
///
/// @dev Minimal proxy:
/// Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime,
/// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,
/// which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode.
///
/// @dev Minimal proxy (PUSH0 variant):
/// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.
/// It is optimized first for minimal runtime gas, then for minimal bytecode.
/// The PUSH0 clone functions are intentionally postfixed with a jarring "_PUSH0" as
/// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.
/// Please use with caution.
///
/// @dev Clones with immutable args (CWIA):
/// The implementation of CWIA here implements a `receive()` method that emits the
/// `ReceiveETH(uint256)` event. This skips the `DELEGATECALL` when there is no calldata,
/// enabling us to accept hard gas-capped `sends` & `transfers` for maximum backwards
/// composability. The minimal proxy implementation does not offer this feature.
library LibClone {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Unable to deploy the clone.
error DeploymentFailed();
/// @dev The salt must start with either the zero address or the caller.
error SaltDoesNotStartWithCaller();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MINIMAL PROXY OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Deploys a clone of `implementation`.
function clone(address implementation) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
/**
* --------------------------------------------------------------------------+
* CREATION (9 bytes) |
* --------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* --------------------------------------------------------------------------|
* 60 runSize | PUSH1 runSize | r | |
* 3d | RETURNDATASIZE | 0 r | |
* 81 | DUP2 | r 0 r | |
* 60 offset | PUSH1 offset | o r 0 r | |
* 3d | RETURNDATASIZE | 0 o r 0 r | |
* 39 | CODECOPY | 0 r | [0..runSize): runtime code |
* f3 | RETURN | | [0..runSize): runtime code |
* --------------------------------------------------------------------------|
* RUNTIME (44 bytes) |
* --------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* --------------------------------------------------------------------------|
* |
* ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | 0 | |
* 3d | RETURNDATASIZE | 0 0 | |
* 3d | RETURNDATASIZE | 0 0 0 | |
* 3d | RETURNDATASIZE | 0 0 0 0 | |
* |
* ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds 0 0 0 0 | |
* 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | |
* 3d | RETURNDATASIZE | 0 0 cds 0 0 0 0 | |
* 37 | CALLDATACOPY | 0 0 0 0 | [0..cds): calldata |
* |
* ::: delegate call to the implementation contract :::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds 0 0 0 0 | [0..cds): calldata |
* 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0..cds): calldata |
* 73 addr | PUSH20 addr | addr 0 cds 0 0 0 0 | [0..cds): calldata |
* 5a | GAS | gas addr 0 cds 0 0 0 0 | [0..cds): calldata |
* f4 | DELEGATECALL | success 0 0 | [0..cds): calldata |
* |
* ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata |
* 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata |
* 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata |
* 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata |
* 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |
* |
* 60 0x2a | PUSH1 0x2a | 0x2a success 0 rds | [0..rds): returndata |
* 57 | JUMPI | 0 rds | [0..rds): returndata |
* |
* ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* fd | REVERT | | [0..rds): returndata |
* |
* ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 5b | JUMPDEST | 0 rds | [0..rds): returndata |
* f3 | RETURN | | [0..rds): returndata |
* --------------------------------------------------------------------------+
*/
mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
mstore(0x14, implementation)
mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
instance := create(0, 0x0c, 0x35)
// Restore the part of the free memory pointer that has been overwritten.
mstore(0x21, 0)
// If `instance` is zero, revert.
if iszero(instance) {
// Store the function selector of `DeploymentFailed()`.
mstore(0x00, 0x30116425)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
}
}
/// @dev Deploys a deterministic clone of `implementation` with `salt`.
function cloneDeterministic(address implementation, bytes32 salt)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
mstore(0x14, implementation)
mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
instance := create2(0, 0x0c, 0x35, salt)
// Restore the part of the free memory pointer that has been overwritten.
mstore(0x21, 0)
// If `instance` is zero, revert.
if iszero(instance) {
// Store the function selector of `DeploymentFailed()`.
mstore(0x00, 0x30116425)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
}
}
/// @dev Returns the initialization code hash of the clone of `implementation`.
/// Used for mining vanity addresses with create2crunch.
function initCodeHash(address implementation) internal pure returns (bytes32 hash) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
mstore(0x14, implementation)
mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
hash := keccak256(0x0c, 0x35)
// Restore the part of the free memory pointer that has been overwritten.
mstore(0x21, 0)
}
}
/// @dev Returns the address of the deterministic clone of `implementation`,
/// with `salt` by `deployer`.
function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)
internal
pure
returns (address predicted)
{
bytes32 hash = initCodeHash(implementation);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MINIMAL PROXY OPERATIONS (PUSH0 VARIANT) */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Deploys a PUSH0 clone of `implementation`.
function clone_PUSH0(address implementation) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
/**
* --------------------------------------------------------------------------+
* CREATION (9 bytes) |
* --------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* --------------------------------------------------------------------------|
* 60 runSize | PUSH1 runSize | r | |
* 5f | PUSH0 | 0 r | |
* 81 | DUP2 | r 0 r | |
* 60 offset | PUSH1 offset | o r 0 r | |
* 5f | PUSH0 | 0 o r 0 r | |
* 39 | CODECOPY | 0 r | [0..runSize): runtime code |
* f3 | RETURN | | [0..runSize): runtime code |
* --------------------------------------------------------------------------|
* RUNTIME (45 bytes) |
* --------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* --------------------------------------------------------------------------|
* |
* ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |
* 5f | PUSH0 | 0 | |
* 5f | PUSH0 | 0 0 | |
* |
* ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds 0 0 | |
* 5f | PUSH0 | 0 cds 0 0 | |
* 5f | PUSH0 | 0 0 cds 0 0 | |
* 37 | CALLDATACOPY | 0 0 | [0..cds): calldata |
* |
* ::: delegate call to the implementation contract :::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds 0 0 | [0..cds): calldata |
* 5f | PUSH0 | 0 cds 0 0 | [0..cds): calldata |
* 73 addr | PUSH20 addr | addr 0 cds 0 0 | [0..cds): calldata |
* 5a | GAS | gas addr 0 cds 0 0 | [0..cds): calldata |
* f4 | DELEGATECALL | success | [0..cds): calldata |
* |
* ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds success | [0..cds): calldata |
* 5f | PUSH0 | 0 rds success | [0..cds): calldata |
* 5f | PUSH0 | 0 0 rds success | [0..cds): calldata |
* 3e | RETURNDATACOPY | success | [0..rds): returndata |
* |
* 60 0x29 | PUSH1 0x29 | 0x29 success | [0..rds): returndata |
* 57 | JUMPI | | [0..rds): returndata |
* |
* ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds | [0..rds): returndata |
* 5f | PUSH0 | 0 rds | [0..rds): returndata |
* fd | REVERT | | [0..rds): returndata |
* |
* ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 5b | JUMPDEST | | [0..rds): returndata |
* 3d | RETURNDATASIZE | rds | [0..rds): returndata |
* 5f | PUSH0 | 0 rds | [0..rds): returndata |
* f3 | RETURN | | [0..rds): returndata |
* --------------------------------------------------------------------------+
*/
mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
mstore(0x14, implementation) // 20
mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
instance := create(0, 0x0e, 0x36)
// Restore the part of the free memory pointer that has been overwritten.
mstore(0x24, 0)
// If `instance` is zero, revert.
if iszero(instance) {
// Store the function selector of `DeploymentFailed()`.
mstore(0x00, 0x30116425)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
}
}
/// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.
function cloneDeterministic_PUSH0(address implementation, bytes32 salt)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
mstore(0x14, implementation) // 20
mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
instance := create2(0, 0x0e, 0x36, salt)
// Restore the part of the free memory pointer that has been overwritten.
mstore(0x24, 0)
// If `instance` is zero, revert.
if iszero(instance) {
// Store the function selector of `DeploymentFailed()`.
mstore(0x00, 0x30116425)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
}
}
/// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.
/// Used for mining vanity addresses with create2crunch.
function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
mstore(0x14, implementation) // 20
mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
hash := keccak256(0x0e, 0x36)
// Restore the part of the free memory pointer that has been overwritten.
mstore(0x24, 0)
}
}
/// @dev Returns the address of the deterministic PUSH0 clone of `implementation`,
/// with `salt` by `deployer`.
function predictDeterministicAddress_PUSH0(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes32 hash = initCodeHash_PUSH0(implementation);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CLONES WITH IMMUTABLE ARGS OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Deploys a minimal proxy with `implementation`,
/// using immutable arguments encoded in `data`.
function clone(address implementation, bytes memory data) internal returns (address instance) {
assembly {
// Compute the boundaries of the data and cache the memory slots around it.
let mBefore3 := mload(sub(data, 0x60))
let mBefore2 := mload(sub(data, 0x40))
let mBefore1 := mload(sub(data, 0x20))
let dataLength := mload(data)
let dataEnd := add(add(data, 0x20), dataLength)
let mAfter1 := mload(dataEnd)
// +2 bytes for telling how much data there is appended to the call.
let extraLength := add(dataLength, 2)
// The `creationSize` is `extraLength + 108`
// The `runSize` is `creationSize - 10`.
/**
* ---------------------------------------------------------------------------------------------------+
* CREATION (10 bytes) |
* ---------------------------------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* ---------------------------------------------------------------------------------------------------|
* 61 runSize | PUSH2 runSize | r | |
* 3d | RETURNDATASIZE | 0 r | |
* 81 | DUP2 | r 0 r | |
* 60 offset | PUSH1 offset | o r 0 r | |
* 3d | RETURNDATASIZE | 0 o r 0 r | |
* 39 | CODECOPY | 0 r | [0..runSize): runtime code |
* f3 | RETURN | | [0..runSize): runtime code |
* ---------------------------------------------------------------------------------------------------|
* RUNTIME (98 bytes + extraLength) |
* ---------------------------------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* ---------------------------------------------------------------------------------------------------|
* |
* ::: if no calldata, emit event & return w/o `DELEGATECALL` ::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds | |
* 60 0x2c | PUSH1 0x2c | 0x2c cds | |
* 57 | JUMPI | | |
* 34 | CALLVALUE | cv | |
* 3d | RETURNDATASIZE | 0 cv | |
* 52 | MSTORE | | [0..0x20): callvalue |
* 7f sig | PUSH32 0x9e.. | sig | [0..0x20): callvalue |
* 59 | MSIZE | 0x20 sig | [0..0x20): callvalue |
* 3d | RETURNDATASIZE | 0 0x20 sig | [0..0x20): callvalue |
* a1 | LOG1 | | [0..0x20): callvalue |
* 00 | STOP | | [0..0x20): callvalue |
* 5b | JUMPDEST | | |
* |
* ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds | |
* 3d | RETURNDATASIZE | 0 cds | |
* 3d | RETURNDATASIZE | 0 0 cds | |
* 37 | CALLDATACOPY | | [0..cds): calldata |
* |
* ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | 0 | [0..cds): calldata |
* 3d | RETURNDATASIZE | 0 0 | [0..cds): calldata |
* 3d | RETURNDATASIZE | 0 0 0 | [0..cds): calldata |
* 3d | RETURNDATASIZE | 0 0 0 0 | [0..cds): calldata |
* 61 extra | PUSH2 extra | e 0 0 0 0 | [0..cds): calldata |
* |
* ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 80 | DUP1 | e e 0 0 0 0 | [0..cds): calldata |
* 60 0x62 | PUSH1 0x62 | 0x62 e e 0 0 0 0 | [0..cds): calldata |
* 36 | CALLDATASIZE | cds 0x62 e e 0 0 0 0 | [0..cds): calldata |
* 39 | CODECOPY | e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |
* |
* ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |
* 01 | ADD | cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |
* 3d | RETURNDATASIZE | 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |
* 73 addr | PUSH20 addr | addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |
* 5a | GAS | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData |
* f4 | DELEGATECALL | success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |
* |
* ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |
* 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData |
* 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |
* 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData |
* 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |
* |
* 60 0x60 | PUSH1 0x60 | 0x60 success 0 rds | [0..rds): returndata |
* 57 | JUMPI | 0 rds | [0..rds): returndata |
* |
* ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* fd | REVERT | | [0..rds): returndata |
* |
* ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 5b | JUMPDEST | 0 rds | [0..rds): returndata |
* f3 | RETURN | | [0..rds): returndata |
* ---------------------------------------------------------------------------------------------------+
*/
// Write the bytecode before the data.
mstore(data, 0x5af43d3d93803e606057fd5bf3)
// Write the address of the implementation.
mstore(sub(data, 0x0d), implementation)
// Write the rest of the bytecode.
mstore(
sub(data, 0x21),
or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)
)
// `keccak256("ReceiveETH(uint256)")`
mstore(
sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff
)
mstore(
sub(data, 0x5a),
or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)
)
mstore(dataEnd, shl(0xf0, extraLength))
// Create the instance.
instance := create(0, sub(data, 0x4c), add(extraLength, 0x6c))
// If `instance` is zero, revert.
if iszero(instance) {
// Store the function selector of `DeploymentFailed()`.
mstore(0x00, 0x30116425)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
// Restore the overwritten memory surrounding `data`.
mstore(dataEnd, mAfter1)
mstore(data, dataLength)
mstore(sub(data, 0x20), mBefore1)
mstore(sub(data, 0x40), mBefore2)
mstore(sub(data, 0x60), mBefore3)
}
}
/// @dev Deploys a deterministic clone of `implementation`,
/// using immutable arguments encoded in `data`, with `salt`.
function cloneDeterministic(address implementation, bytes memory data, bytes32 salt)
internal
returns (address instance)
{
assembly {
// Compute the boundaries of the data and cache the memory slots around it.
let mBefore3 := mload(sub(data, 0x60))
let mBefore2 := mload(sub(data, 0x40))
let mBefore1 := mload(sub(data, 0x20))
let dataLength := mload(data)
let dataEnd := add(add(data, 0x20), dataLength)
let mAfter1 := mload(dataEnd)
// +2 bytes for telling how much data there is appended to the call.
let extraLength := add(dataLength, 2)
// Write the bytecode before the data.
mstore(data, 0x5af43d3d93803e606057fd5bf3)
// Write the address of the implementation.
mstore(sub(data, 0x0d), implementation)
// Write the rest of the bytecode.
mstore(
sub(data, 0x21),
or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)
)
// `keccak256("ReceiveETH(uint256)")`
mstore(
sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff
)
mstore(
sub(data, 0x5a),
or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)
)
mstore(dataEnd, shl(0xf0, extraLength))
// Create the instance.
instance := create2(0, sub(data, 0x4c), add(extraLength, 0x6c), salt)
// If `instance` is zero, revert.
if iszero(instance) {
// Store the function selector of `DeploymentFailed()`.
mstore(0x00, 0x30116425)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
// Restore the overwritten memory surrounding `data`.
mstore(dataEnd, mAfter1)
mstore(data, dataLength)
mstore(sub(data, 0x20), mBefore1)
mstore(sub(data, 0x40), mBefore2)
mstore(sub(data, 0x60), mBefore3)
}
}
/// @dev Returns the initialization code hash of the clone of `implementation`
/// using immutable arguments encoded in `data`.
/// Used for mining vanity addresses with create2crunch.
function initCodeHash(address implementation, bytes memory data)
internal
pure
returns (bytes32 hash)
{
assembly {
// Compute the boundaries of the data and cache the memory slots around it.
let mBefore3 := mload(sub(data, 0x60))
let mBefore2 := mload(sub(data, 0x40))
let mBefore1 := mload(sub(data, 0x20))
let dataLength := mload(data)
let dataEnd := add(add(data, 0x20), dataLength)
let mAfter1 := mload(dataEnd)
// +2 bytes for telling how much data there is appended to the call.
let extraLength := add(dataLength, 2)
// Write the bytecode before the data.
mstore(data, 0x5af43d3d93803e606057fd5bf3)
// Write the address of the implementation.
mstore(sub(data, 0x0d), implementation)
// Write the rest of the bytecode.
mstore(
sub(data, 0x21),
or(shl(0x48, extraLength), 0x593da1005b363d3d373d3d3d3d610000806062363936013d73)
)
// `keccak256("ReceiveETH(uint256)")`
mstore(
sub(data, 0x3a), 0x9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff
)
mstore(
sub(data, 0x5a),
or(shl(0x78, add(extraLength, 0x62)), 0x6100003d81600a3d39f336602c57343d527f)
)
mstore(dataEnd, shl(0xf0, extraLength))
// Compute and store the bytecode hash.
hash := keccak256(sub(data, 0x4c), add(extraLength, 0x6c))
// Restore the overwritten memory surrounding `data`.
mstore(dataEnd, mAfter1)
mstore(data, dataLength)
mstore(sub(data, 0x20), mBefore1)
mstore(sub(data, 0x40), mBefore2)
mstore(sub(data, 0x60), mBefore3)
}
}
/// @dev Returns the address of the deterministic clone of
/// `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`.
function predictDeterministicAddress(
address implementation,
bytes memory data,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes32 hash = initCodeHash(implementation, data);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* OTHER OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the address when a contract with initialization code hash,
/// `hash`, is deployed with `salt`, by `deployer`.
function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)
internal
pure
returns (address predicted)
{
/// @solidity memory-safe-assembly
assembly {
// Compute and store the bytecode hash.
mstore8(0x00, 0xff) // Write the prefix.
mstore(0x35, hash)
mstore(0x01, shl(96, deployer))
mstore(0x15, salt)
predicted := keccak256(0x00, 0x55)
// Restore the part of the free memory pointer that has been overwritten.
mstore(0x35, 0)
}
}
/// @dev Reverts if `salt` does not start with either the zero address or the caller.
function checkStartsWithCaller(bytes32 salt) internal view {
/// @solidity memory-safe-assembly
assembly {
// If the salt does not start with the zero address or the caller.
if iszero(or(iszero(shr(96, salt)), eq(caller(), shr(96, salt)))) {
// Store the function selector of `SaltDoesNotStartWithCaller()`.
mstore(0x00, 0x2f634836)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The caller is not authorized to call the function.
error Unauthorized();
/// @dev The `newOwner` cannot be the zero address.
error NewOwnerIsZeroAddress();
/// @dev The `pendingOwner` does not have a valid handover request.
error NoHandoverRequest();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ownership is transferred from `oldOwner` to `newOwner`.
/// This event is intentionally kept the same as OpenZeppelin's Ownable to be
/// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
/// despite it not being as lightweight as a single argument event.
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
/// @dev An ownership handover to `pendingOwner` has been requested.
event OwnershipHandoverRequested(address indexed pendingOwner);
/// @dev The ownership handover to `pendingOwner` has been canceled.
event OwnershipHandoverCanceled(address indexed pendingOwner);
/// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
/// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
/// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The owner slot is given by: `not(_OWNER_SLOT_NOT)`.
/// It is intentionally chosen to be a high value
/// to avoid collision with lower slots.
/// The choice of manual storage layout is to enable compatibility
/// with both regular and upgradeable contracts.
uint256 private constant _OWNER_SLOT_NOT = 0x8b78c6d8;
/// The ownership handover slot of `newOwner` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
/// let handoverSlot := keccak256(0x00, 0x20)
/// ```
/// It stores the expiry timestamp of the two-step ownership handover.
uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Initializes the owner directly without authorization guard.
/// This function must be called upon initialization,
/// regardless of whether the contract is upgradeable or not.
/// This is to enable generalization to both regular and upgradeable contracts,
/// and to save gas in case the initial owner is not the caller.
/// For performance reasons, this function will not check if there
/// is an existing owner.
function _initializeOwner(address newOwner) internal virtual {
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(not(_OWNER_SLOT_NOT), newOwner)
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
}
/// @dev Sets the owner directly without authorization guard.
function _setOwner(address newOwner) internal virtual {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := not(_OWNER_SLOT_NOT)
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, newOwner)
}
}
/// @dev Throws if the sender is not the owner.
function _checkOwner() internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner, revert.
if iszero(eq(caller(), sload(not(_OWNER_SLOT_NOT)))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Returns how long a two-step ownership handover is valid for in seconds.
/// Override to return a different value if needed.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
return 48 * 3600;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to transfer the ownership to `newOwner`.
function transferOwnership(address newOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
if iszero(shl(96, newOwner)) {
mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
revert(0x1c, 0x04)
}
}
_setOwner(newOwner);
}
/// @dev Allows the owner to renounce their ownership.
function renounceOwnership() public payable virtual onlyOwner {
_setOwner(address(0));
}
/// @dev Request a two-step ownership handover to the caller.
/// The request will automatically expire in 48 hours (172800 seconds) by default.
function requestOwnershipHandover() public payable virtual {
unchecked {
uint256 expires = block.timestamp + _ownershipHandoverValidFor();
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to `expires`.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), expires)
// Emit the {OwnershipHandoverRequested} event.
log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
}
}
}
/// @dev Cancels the two-step ownership handover to the caller, if any.
function cancelOwnershipHandover() public payable virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), 0)
// Emit the {OwnershipHandoverCanceled} event.
log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
}
}
/// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
/// Reverts if there is no existing ownership handover requested by `pendingOwner`.
function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
let handoverSlot := keccak256(0x0c, 0x20)
// If the handover does not exist, or has expired.
if gt(timestamp(), sload(handoverSlot)) {
mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
revert(0x1c, 0x04)
}
// Set the handover slot to 0.
sstore(handoverSlot, 0)
}
_setOwner(pendingOwner);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the owner of the contract.
function owner() public view virtual returns (address result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(not(_OWNER_SLOT_NOT))
}
}
/// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
function ownershipHandoverExpiresAt(address pendingOwner)
public
view
virtual
returns (uint256 result)
{
/// @solidity memory-safe-assembly
assembly {
// Compute the handover slot.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
// Load the handover slot.
result := sload(keccak256(0x0c, 0x20))
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by the owner.
modifier onlyOwner() virtual {
_checkOwner();
_;
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
/*//////////////////////////////////////////////////////////////////////////
STRUCTS
//////////////////////////////////////////////////////////////////////////*/
/**
* @notice Struct of dutch auction information
* - `refunded` Flag indicating if refunds are enabled
* - `stepLength` Duration (in seconds) of each auction step
* - `prices` Array of prices for each step of the auction
*/
struct AuctionInfo {
bool refunded;
uint248 stepLength;
uint256[] prices;
}
/**
* @notice Struct of system config information
* - `feeReceiver` Address receiving platform fees
* - `primaryFeeAllocation` Amount of basis points allocated to calculate platform fees on primary sale proceeds
* - `secondaryFeeAllocation` Amount of basis points allocated to calculate platform fees on royalty payments
* - `lockTime` Locked time duration added to mint start time for unverified creators
* - `referrerShare` Share amount distributed to accounts referring tokens
* - `defaultMetadataURI` Default base URI of token metadata
* - `externalURI` External URI for displaying tokens
*/
struct ConfigInfo {
address feeReceiver;
uint32 primaryFeeAllocation;
uint32 secondaryFeeAllocation;
uint32 lockTime;
uint64 referrerShare;
string defaultMetadataURI;
string externalURI;
}
/**
* @notice Struct of generative art information
* - `minter` Address of initial token owner
* - `seed` Hash of randomly generated seed
* - `fxParams` Random sequence of fixed-length bytes used as token input
*/
struct GenArtInfo {
address minter;
bytes32 seed;
bytes fxParams;
}
/**
* @notice Struct of initialization information used on project creation
* - `name` Name of project
* - `symbol` Symbol of project
* - `primaryReceiver` Address of splitter contract receiving primary sales
* - `randomizer` Address of Randomizer contract
* - `renderer` Address of Renderer contract
* - `tagIds` Array of tag IDs describing the project
* - 'onchainData' Onchain data to be stored using SSTORE2 and available to renderers
*/
struct InitInfo {
string name;
string symbol;
address[] primaryReceivers;
uint32[] allocations;
address randomizer;
address renderer;
uint256[] tagIds;
bytes onchainData;
}
/**
* @notice Struct of issuer information
* - `primaryReceiver` Address of splitter contract receiving primary sales
* - `projectInfo` Project information
* - `activeMinters` Array of authorized minter contracts used for enumeration
* - `minters` Mapping of minter contract to authorization status
*/
struct IssuerInfo {
address primaryReceiver;
ProjectInfo projectInfo;
address[] activeMinters;
mapping(address => uint8) minters;
}
/**
* @notice Struct of metadata information
* - `baseURI` Decoded URI of content identifier
* - `onchainPointer` Address of bytes-encoded data rendered onchain
*/
struct MetadataInfo {
bytes baseURI;
address onchainPointer;
}
/**
* @notice Struct of mint information
* - `minter` Address of the minter contract
* - `reserveInfo` Reserve information
* - `params` Optional bytes data decoded inside minter
*/
struct MintInfo {
address minter;
ReserveInfo reserveInfo;
bytes params;
}
/**
* @notice Struct of minter information
* - `totalMints` Total number of mints executed by the minter
* - `totalPaid` Total amount paid by the minter
*/
struct MinterInfo {
uint128 totalMints;
uint128 totalPaid;
}
/**
* @notice Struct of project information
* - `mintEnabled` Flag inidicating if minting is enabled
* - `burnEnabled` Flag inidicating if burning is enabled
* - `maxSupply` Maximum supply of tokens
* - `inputSize` Maximum input size of fxParams bytes data
* - `earliestStartTime` Earliest possible start time for registering minters
*/
struct ProjectInfo {
bool mintEnabled;
bool burnEnabled;
uint120 maxSupply;
uint88 inputSize;
uint32 earliestStartTime;
}
/**
* @notice Struct of refund information
* - `lastPrice` Price of last sale before selling out
* - `minterInfo` Mapping of minter address to struct of minter information
*/
struct RefundInfo {
uint256 lastPrice;
mapping(address minter => MinterInfo) minterInfo;
}
/**
* @notice Struct of reserve information
* - `startTime` Start timestamp of minter
* - `endTime` End timestamp of minter
* - `allocation` Allocation amount for minter
*/
struct ReserveInfo {
uint64 startTime;
uint64 endTime;
uint128 allocation;
}
/**
* @notice Struct of royalty information
* - `receiver` Address receiving royalties
* - `basisPoints` Points used to calculate the royalty payment (0.01%)
*/
struct RoyaltyInfo {
address receiver;
uint96 basisPoints;
}
/**
* @notice Struct of tax information
* - `startTime` Timestamp of when harberger taxation begins
* - `foreclosureTime` Timestamp of token foreclosure
* - `currentPrice` Current listing price of token
* - `depositAmount` Total amount of taxes deposited
*/
struct TaxInfo {
uint48 startTime;
uint48 foreclosureTime;
uint80 currentPrice;
uint80 depositAmount;
}
{
"compilationTarget": {
"src/factories/FxIssuerFactory.sol": "FxIssuerFactory"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 2
},
"remappings": [
":ds-test/=lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
":openzeppelin/=lib/openzeppelin-contracts/",
":scripty.sol/=lib/scripty.sol/",
":solady/=lib/solady/",
":solmate/=lib/solmate/",
":sstore2/=lib/sstore2/"
]
}
[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_roleRegistry","type":"address"},{"internalType":"address","name":"_implementation","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidOwner","type":"error"},{"inputs":[],"name":"InvalidPrimaryReceiver","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_implementation","type":"address"}],"name":"ImplementationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint96","name":"_projectId","type":"uint96"},{"indexed":true,"internalType":"address","name":"_genArtToken","type":"address"},{"indexed":true,"internalType":"address","name":"_owner","type":"address"}],"name":"ProjectCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_creationInfo","type":"bytes"}],"name":"createProject","outputs":[{"internalType":"address","name":"genArt721","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address[]","name":"primaryReceivers","type":"address[]"},{"internalType":"uint32[]","name":"allocations","type":"uint32[]"},{"internalType":"address","name":"randomizer","type":"address"},{"internalType":"address","name":"renderer","type":"address"},{"internalType":"uint256[]","name":"tagIds","type":"uint256[]"},{"internalType":"bytes","name":"onchainData","type":"bytes"}],"internalType":"struct InitInfo","name":"_initInfo","type":"tuple"},{"components":[{"internalType":"bool","name":"mintEnabled","type":"bool"},{"internalType":"bool","name":"burnEnabled","type":"bool"},{"internalType":"uint120","name":"maxSupply","type":"uint120"},{"internalType":"uint88","name":"inputSize","type":"uint88"},{"internalType":"uint32","name":"earliestStartTime","type":"uint32"}],"internalType":"struct ProjectInfo","name":"_projectInfo","type":"tuple"},{"components":[{"internalType":"bytes","name":"baseURI","type":"bytes"},{"internalType":"address","name":"onchainPointer","type":"address"}],"internalType":"struct MetadataInfo","name":"_metadataInfo","type":"tuple"},{"components":[{"internalType":"address","name":"minter","type":"address"},{"components":[{"internalType":"uint64","name":"startTime","type":"uint64"},{"internalType":"uint64","name":"endTime","type":"uint64"},{"internalType":"uint128","name":"allocation","type":"uint128"}],"internalType":"struct ReserveInfo","name":"reserveInfo","type":"tuple"},{"internalType":"bytes","name":"params","type":"bytes"}],"internalType":"struct MintInfo[]","name":"_mintInfo","type":"tuple[]"},{"internalType":"address[]","name":"_royaltyReceivers","type":"address[]"},{"internalType":"uint32[]","name":"_allocations","type":"uint32[]"},{"internalType":"uint96","name":"_basisPoints","type":"uint96"}],"name":"createProjectWithParams","outputs":[{"internalType":"address","name":"genArtToken","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_projectCreationInfo","type":"bytes"},{"internalType":"bytes","name":"_ticketCreationInfo","type":"bytes"},{"internalType":"address","name":"_ticketFactory","type":"address"}],"name":"createProjectWithTicket","outputs":[{"internalType":"address","name":"genArtToken","type":"address"},{"internalType":"address","name":"mintTicket","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"}],"name":"getTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"projectId","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint96","name":"","type":"uint96"}],"name":"projects","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"roleRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_implementation","type":"address"}],"name":"setImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]