// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)pragmasolidity ^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.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
Contract Source Code
File 4 of 20: ECDSA.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol)pragmasolidity ^0.8.0;import"../Strings.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/libraryECDSA{
enumRecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function_throwError(RecoverError error) privatepure{
if (error == RecoverError.NoError) {
return; // no error: do nothing
} elseif (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} elseif (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} elseif (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} elseif (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/functiontryRecover(bytes32 hash, bytesmemory signature) internalpurereturns (address, RecoverError) {
if (signature.length==65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them// currently is to use assembly./// @solidity memory-safe-assemblyassembly {
r :=mload(add(signature, 0x20))
s :=mload(add(signature, 0x40))
v :=byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/functionrecover(bytes32 hash, bytesmemory signature) internalpurereturns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/functiontryRecover(bytes32 hash,
bytes32 r,
bytes32 vs
) internalpurereturns (address, RecoverError) {
bytes32 s = vs &bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v =uint8((uint256(vs) >>255) +27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/functionrecover(bytes32 hash,
bytes32 r,
bytes32 vs
) internalpurereturns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/functiontryRecover(bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internalpurereturns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most// signatures from current libraries generate a unique signature with an s-value in the lower half order.//// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept// these malleable signatures as well.if (uint256(s) >0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v !=27&& v !=28) {
return (address(0), RecoverError.InvalidSignatureV);
}
// If the signature is valid (and not malleable), return the signer addressaddress signer =ecrecover(hash, v, r, s);
if (signer ==address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/functionrecover(bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internalpurereturns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/functiontoEthSignedMessageHash(bytes32 hash) internalpurereturns (bytes32) {
// 32 is the length in bytes of hash,// enforced by the type signature abovereturnkeccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/functiontoEthSignedMessageHash(bytesmemory s) internalpurereturns (bytes32) {
returnkeccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/functiontoTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internalpurereturns (bytes32) {
returnkeccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
Contract Source Code
File 5 of 20: ERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)pragmasolidity ^0.8.0;import"./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/abstractcontractERC165isIERC165{
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverridereturns (bool) {
return interfaceId ==type(IERC165).interfaceId;
}
}
Contract Source Code
File 6 of 20: ERC165Checker.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.2) (utils/introspection/ERC165Checker.sol)pragmasolidity ^0.8.0;import"./IERC165.sol";
/**
* @dev Library used to query support of an interface declared via {IERC165}.
*
* Note that these functions return the actual result of the query: they do not
* `revert` if an interface is not supported. It is up to the caller to decide
* what to do in these cases.
*/libraryERC165Checker{
// As per the EIP-165 spec, no interface should ever match 0xffffffffbytes4privateconstant _INTERFACE_ID_INVALID =0xffffffff;
/**
* @dev Returns true if `account` supports the {IERC165} interface,
*/functionsupportsERC165(address account) internalviewreturns (bool) {
// Any contract that implements ERC165 must explicitly indicate support of// InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalidreturn
_supportsERC165Interface(account, type(IERC165).interfaceId) &&!_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
}
/**
* @dev Returns true if `account` supports the interface defined by
* `interfaceId`. Support for {IERC165} itself is queried automatically.
*
* See {IERC165-supportsInterface}.
*/functionsupportsInterface(address account, bytes4 interfaceId) internalviewreturns (bool) {
// query support of both ERC165 as per the spec and support of _interfaceIdreturn supportsERC165(account) && _supportsERC165Interface(account, interfaceId);
}
/**
* @dev Returns a boolean array where each value corresponds to the
* interfaces passed in and whether they're supported or not. This allows
* you to batch check interfaces for a contract where your expectation
* is that some interfaces may not be supported.
*
* See {IERC165-supportsInterface}.
*
* _Available since v3.4._
*/functiongetSupportedInterfaces(address account, bytes4[] memory interfaceIds)
internalviewreturns (bool[] memory)
{
// an array of booleans corresponding to interfaceIds and whether they're supported or notbool[] memory interfaceIdsSupported =newbool[](interfaceIds.length);
// query support of ERC165 itselfif (supportsERC165(account)) {
// query support of each interface in interfaceIdsfor (uint256 i =0; i < interfaceIds.length; i++) {
interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);
}
}
return interfaceIdsSupported;
}
/**
* @dev Returns true if `account` supports all the interfaces defined in
* `interfaceIds`. Support for {IERC165} itself is queried automatically.
*
* Batch-querying can lead to gas savings by skipping repeated checks for
* {IERC165} support.
*
* See {IERC165-supportsInterface}.
*/functionsupportsAllInterfaces(address account, bytes4[] memory interfaceIds) internalviewreturns (bool) {
// query support of ERC165 itselfif (!supportsERC165(account)) {
returnfalse;
}
// query support of each interface in _interfaceIdsfor (uint256 i =0; i < interfaceIds.length; i++) {
if (!_supportsERC165Interface(account, interfaceIds[i])) {
returnfalse;
}
}
// all interfaces supportedreturntrue;
}
/**
* @notice Query if a contract implements an interface, does not check ERC165 support
* @param account The address of the contract to query for support of an interface
* @param interfaceId The interface identifier, as specified in ERC-165
* @return true if the contract at account indicates support of the interface with
* identifier interfaceId, false otherwise
* @dev Assumes that account contains a contract that supports ERC165, otherwise
* the behavior of this method is undefined. This precondition can be checked
* with {supportsERC165}.
* Interface identification is specified in ERC-165.
*/function_supportsERC165Interface(address account, bytes4 interfaceId) privateviewreturns (bool) {
// prepare callbytesmemory encodedParams =abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);
// perform static callbool success;
uint256 returnSize;
uint256 returnValue;
assembly {
success :=staticcall(30000, account, add(encodedParams, 0x20), mload(encodedParams), 0x00, 0x20)
returnSize :=returndatasize()
returnValue :=mload(0x00)
}
return success && returnSize >=0x20&& returnValue >0;
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)pragmasolidity ^0.8.0;/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet.
* ====
*/libraryEnumerableSet{
// To implement this library for multiple types with as little code// repetition as possible, we write it in terms of a generic Set type with// bytes32 values.// The Set implementation uses private functions, and user-facing// implementations (such as AddressSet) are just wrappers around the// underlying Set.// This means that we can only create new EnumerableSets for types that fit// in bytes32.structSet {
// Storage of set valuesbytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0// means a value is not in the set.mapping(bytes32=>uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/function_add(Set storage set, bytes32 value) privatereturns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/function_remove(Set storage set, bytes32 value) privatereturns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slotuint256 valueIndex = set._indexes[value];
if (valueIndex !=0) {
// Equivalent to contains(set, value)// To delete an element from the _values array in O(1), we swap the element to delete with the last one in// the array, and then remove the last element (sometimes called as 'swap and pop').// This modifies the order of the array, as noted in {at}.uint256 toDeleteIndex = valueIndex -1;
uint256 lastIndex = set._values.length-1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slotdelete set._indexes[value];
returntrue;
} else {
returnfalse;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/function_contains(Set storage set, bytes32 value) privateviewreturns (bool) {
return set._indexes[value] !=0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/function_length(Set storage set) privateviewreturns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/function_at(Set storage set, uint256 index) privateviewreturns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/function_values(Set storage set) privateviewreturns (bytes32[] memory) {
return set._values;
}
// Bytes32SetstructBytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(Bytes32Set storage set, bytes32 value) internalreturns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(Bytes32Set storage set, bytes32 value) internalreturns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(Bytes32Set storage set, bytes32 value) internalviewreturns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/functionlength(Bytes32Set storage set) internalviewreturns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(Bytes32Set storage set, uint256 index) internalviewreturns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(Bytes32Set storage set) internalviewreturns (bytes32[] memory) {
return _values(set._inner);
}
// AddressSetstructAddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(AddressSet storage set, address value) internalreturns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(AddressSet storage set, address value) internalreturns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(AddressSet storage set, address value) internalviewreturns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/functionlength(AddressSet storage set) internalviewreturns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(AddressSet storage set, uint256 index) internalviewreturns (address) {
returnaddress(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(AddressSet storage set) internalviewreturns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assemblyassembly {
result := store
}
return result;
}
// UintSetstructUintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/functionadd(UintSet storage set, uint256 value) internalreturns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/functionremove(UintSet storage set, uint256 value) internalreturns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/functioncontains(UintSet storage set, uint256 value) internalviewreturns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/functionlength(UintSet storage set) internalviewreturns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/functionat(UintSet storage set, uint256 index) internalviewreturns (uint256) {
returnuint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/functionvalues(UintSet storage set) internalviewreturns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assemblyassembly {
result := store
}
return result;
}
}
Contract Source Code
File 9 of 20: IAdminControl.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/// @author: manifold.xyzimport"@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @dev Interface for admin control
*/interfaceIAdminControlisIERC165{
eventAdminApproved(addressindexed account, addressindexed sender);
eventAdminRevoked(addressindexed account, addressindexed sender);
/**
* @dev gets address of all admins
*/functiongetAdmins() externalviewreturns (address[] memory);
/**
* @dev add an admin. Can only be called by contract owner.
*/functionapproveAdmin(address admin) external;
/**
* @dev remove an admin. Can only be called by contract owner.
*/functionrevokeAdmin(address admin) external;
/**
* @dev checks whether or not given address is an admin
* Returns True if they are
*/functionisAdmin(address admin) externalviewreturns (bool);
}
Contract Source Code
File 10 of 20: ICollectibleCore.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import"@openzeppelin/contracts/utils/introspection/IERC165.sol";
/// @author: manifold.xyz/**
* @dev CollectibleBase Interface
*/interfaceICollectibleCoreisIERC165{
structActivationParameters {
uint48 startTime;
uint48 duration;
uint48 presaleInterval;
uint48 claimStartTime;
uint48 claimEndTime;
}
structInitializationParameters {
bool useDynamicPresalePurchaseLimit;
uint16 transactionLimit;
uint16 purchaseMax;
uint16 purchaseLimit;
uint16 presalePurchaseLimit;
uint256 purchasePrice;
uint256 presalePurchasePrice;
address signingAddress;
addresspayable paymentReceiver;
}
structUpdateInitializationParameters {
bool useDynamicPresalePurchaseLimit;
uint16 transactionLimit;
uint16 purchaseMax;
uint16 purchaseLimit;
uint16 presalePurchaseLimit;
uint256 purchasePrice;
uint256 presalePurchasePrice;
}
structCollectibleInstance {
bool isActive;
bool useDynamicPresalePurchaseLimit;
bool isTransferLocked;
uint8 contractVersion;
uint16 transactionLimit;
uint16 purchaseMax;
uint16 purchaseLimit;
uint16 presalePurchaseLimit;
uint16 purchaseCount;
uint48 startTime;
uint48 endTime;
uint48 presaleInterval;
uint48 claimStartTime;
uint48 claimEndTime;
uint256 purchasePrice;
uint256 presalePurchasePrice;
string baseURI;
addresspayable paymentReceiver;
}
structCollectibleState {
bool isActive;
bool useDynamicPresalePurchaseLimit;
bool isTransferLocked;
uint16 transactionLimit;
uint16 purchaseMax;
uint16 purchaseLimit;
uint16 presalePurchaseLimit;
uint16 purchaseCount;
uint48 startTime;
uint48 endTime;
uint48 presaleInterval;
uint48 claimStartTime;
uint48 claimEndTime;
uint256 purchasePrice;
uint256 presalePurchasePrice;
uint256 purchaseRemaining;
addresspayable paymentReceiver;
}
eventCollectibleInitialized(address creatorContractAddress, uint256 instanceId, address initializer);
eventCollectibleActivated(address creatorContractAddress,
uint256 instanceId,
uint48 startTime,
uint48 endTime,
uint48 presaleInterval,
uint48 claimStartTime,
uint48 claimEndTime
);
eventCollectibleDeactivated(address creatorContractAddress, uint256 instanceId);
/**
* @notice get a burn redeem corresponding to a creator contract and index
* @param creatorContractAddress the address of the creator contract
* @param index the index of the burn redeem
* @return CollectibleInstsance the burn redeem object
*/functiongetCollectible(address creatorContractAddress,
uint256 index
) externalviewreturns (CollectibleInstance memory);
/**
* @dev Check if nonce has been used
* @param creatorContractAddress the creator contract address
* @param instanceId the index of the claim for which we will mint
*/functionnonceUsed(address creatorContractAddress, uint256 instanceId, bytes32 nonce) externalviewreturns (bool);
/**
* @dev Activate the contract
* @param creatorContractAddress the creator contract the claim will mint tokens for
* @param instanceId the index of the claim in the list of creatorContractAddress' _claims
* @param activationParameters the sale start time
*/functionactivate(address creatorContractAddress,
uint256 instanceId,
ActivationParameters calldata activationParameters
) external;
/**
* @dev Deactivate the contract
* @param creatorContractAddress the creator contract the claim will mint tokens for
* @param instanceId the index of the claim in the list of creatorContractAddress' _claims
*/functiondeactivate(address creatorContractAddress, uint256 instanceId) external;
/**
* @notice Set the Manifold Membership address
*/functionsetMembershipAddress(address membershipAddress) external;
/**
* @notice withdraw Manifold fee proceeds from the contract
* @param recipient recepient of the funds
* @param amount amount to withdraw in Wei
*/functionwithdraw(addresspayable recipient, uint256 amount) external;
/**
* @notice initialize a new burn redeem, emit initialize event, and return the newly created index
* @param creatorContractAddress the creator contract the burn will mint redeem tokens for
* @param instanceId the id of the multi-asssetclaim in the mapping of creatorContractAddress <-> instance id
* @param initializationParameters initial claim parameters
*/functioninitializeCollectible(address creatorContractAddress,
uint256 instanceId,
InitializationParameters calldata initializationParameters
) external;
/**
* Updates a handful of sale parameters
* @param creatorContractAddress the creator contract the burn will mint redeem tokens for
* @param instanceId the id of the multi-asssetclaim in the mapping of creatorContractAddress <-> instance id
* @param initializationParameters initial claim parameters
*/functionupdateInitializationParameters(address creatorContractAddress,
uint256 instanceId,
UpdateInitializationParameters calldata initializationParameters
) external;
/**
* Updates payment receiver
* @param creatorContractAddress the creator contract the burn will mint redeem tokens for
* @param instanceId the id of the multi-asssetclaim in the mapping of creatorContractAddress <-> instance id
* @param paymentReceiver the new address that will receive payments
*/functionupdatePaymentReceiver(address creatorContractAddress,
uint256 instanceId,
addresspayable paymentReceiver
) external;
}
Contract Source Code
File 11 of 20: ICreatorCore.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/// @author: manifold.xyzimport"@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @dev Core creator interface
*/interfaceICreatorCoreisIERC165{
eventExtensionRegistered(addressindexed extension, addressindexed sender);
eventExtensionUnregistered(addressindexed extension, addressindexed sender);
eventExtensionBlacklisted(addressindexed extension, addressindexed sender);
eventMintPermissionsUpdated(addressindexed extension, addressindexed permissions, addressindexed sender);
eventRoyaltiesUpdated(uint256indexed tokenId, addresspayable[] receivers, uint256[] basisPoints);
eventDefaultRoyaltiesUpdated(addresspayable[] receivers, uint256[] basisPoints);
eventApproveTransferUpdated(address extension);
eventExtensionRoyaltiesUpdated(addressindexed extension, addresspayable[] receivers, uint256[] basisPoints);
eventExtensionApproveTransferUpdated(addressindexed extension, bool enabled);
/**
* @dev gets address of all extensions
*/functiongetExtensions() externalviewreturns (address[] memory);
/**
* @dev add an extension. Can only be called by contract owner or admin.
* extension address must point to a contract implementing ICreatorExtension.
* Returns True if newly added, False if already added.
*/functionregisterExtension(address extension, stringcalldata baseURI) external;
/**
* @dev add an extension. Can only be called by contract owner or admin.
* extension address must point to a contract implementing ICreatorExtension.
* Returns True if newly added, False if already added.
*/functionregisterExtension(address extension, stringcalldata baseURI, bool baseURIIdentical) external;
/**
* @dev add an extension. Can only be called by contract owner or admin.
* Returns True if removed, False if already removed.
*/functionunregisterExtension(address extension) external;
/**
* @dev blacklist an extension. Can only be called by contract owner or admin.
* This function will destroy all ability to reference the metadata of any tokens created
* by the specified extension. It will also unregister the extension if needed.
* Returns True if removed, False if already removed.
*/functionblacklistExtension(address extension) external;
/**
* @dev set the baseTokenURI of an extension. Can only be called by extension.
*/functionsetBaseTokenURIExtension(stringcalldata uri) external;
/**
* @dev set the baseTokenURI of an extension. Can only be called by extension.
* For tokens with no uri configured, tokenURI will return "uri+tokenId"
*/functionsetBaseTokenURIExtension(stringcalldata uri, bool identical) external;
/**
* @dev set the common prefix of an extension. Can only be called by extension.
* If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI"
* Useful if you want to use ipfs/arweave
*/functionsetTokenURIPrefixExtension(stringcalldata prefix) external;
/**
* @dev set the tokenURI of a token extension. Can only be called by extension that minted token.
*/functionsetTokenURIExtension(uint256 tokenId, stringcalldata uri) external;
/**
* @dev set the tokenURI of a token extension for multiple tokens. Can only be called by extension that minted token.
*/functionsetTokenURIExtension(uint256[] memory tokenId, string[] calldata uri) external;
/**
* @dev set the baseTokenURI for tokens with no extension. Can only be called by owner/admin.
* For tokens with no uri configured, tokenURI will return "uri+tokenId"
*/functionsetBaseTokenURI(stringcalldata uri) external;
/**
* @dev set the common prefix for tokens with no extension. Can only be called by owner/admin.
* If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI"
* Useful if you want to use ipfs/arweave
*/functionsetTokenURIPrefix(stringcalldata prefix) external;
/**
* @dev set the tokenURI of a token with no extension. Can only be called by owner/admin.
*/functionsetTokenURI(uint256 tokenId, stringcalldata uri) external;
/**
* @dev set the tokenURI of multiple tokens with no extension. Can only be called by owner/admin.
*/functionsetTokenURI(uint256[] memory tokenIds, string[] calldata uris) external;
/**
* @dev set a permissions contract for an extension. Used to control minting.
*/functionsetMintPermissions(address extension, address permissions) external;
/**
* @dev Configure so transfers of tokens created by the caller (must be extension) gets approval
* from the extension before transferring
*/functionsetApproveTransferExtension(bool enabled) external;
/**
* @dev get the extension of a given token
*/functiontokenExtension(uint256 tokenId) externalviewreturns (address);
/**
* @dev Set default royalties
*/functionsetRoyalties(addresspayable[] calldata receivers, uint256[] calldata basisPoints) external;
/**
* @dev Set royalties of a token
*/functionsetRoyalties(uint256 tokenId, addresspayable[] calldata receivers, uint256[] calldata basisPoints) external;
/**
* @dev Set royalties of an extension
*/functionsetRoyaltiesExtension(address extension, addresspayable[] calldata receivers, uint256[] calldata basisPoints) external;
/**
* @dev Get royalites of a token. Returns list of receivers and basisPoints
*/functiongetRoyalties(uint256 tokenId) externalviewreturns (addresspayable[] memory, uint256[] memory);
// Royalty support for various other standardsfunctiongetFeeRecipients(uint256 tokenId) externalviewreturns (addresspayable[] memory);
functiongetFeeBps(uint256 tokenId) externalviewreturns (uint[] memory);
functiongetFees(uint256 tokenId) externalviewreturns (addresspayable[] memory, uint256[] memory);
functionroyaltyInfo(uint256 tokenId, uint256 value) externalviewreturns (address, uint256);
/**
* @dev Set the default approve transfer contract location.
*/functionsetApproveTransfer(address extension) external;
/**
* @dev Get the default approve transfer contract location.
*/functiongetApproveTransfer() externalviewreturns (address);
}
Contract Source Code
File 12 of 20: ICreatorExtensionTokenURI.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/// @author: manifold.xyzimport"@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* @dev Implement this if you want your extension to have overloadable URI's
*/interfaceICreatorExtensionTokenURIisIERC165{
/**
* Get the uri for a given creator/tokenId
*/functiontokenURI(address creator, uint256 tokenId) externalviewreturns (stringmemory);
}
Contract Source Code
File 13 of 20: IERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)pragmasolidity ^0.8.0;/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/interfaceIERC165{
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/functionsupportsInterface(bytes4 interfaceId) externalviewreturns (bool);
}
Contract Source Code
File 14 of 20: IERC721Collectible.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/// @author: manifold.xyzimport"@openzeppelin/contracts/utils/introspection/IERC165.sol";
import"@manifoldxyz/creator-core-solidity/contracts/core/IERC721CreatorCore.sol";
import"@manifoldxyz/creator-core-solidity/contracts/extensions/ERC721/IERC721CreatorExtensionApproveTransfer.sol";
import"@manifoldxyz/creator-core-solidity/contracts/extensions/ICreatorExtensionTokenURI.sol";
import"./ICollectibleCore.sol";
/**
* @dev ERC721 Collection Interface
*/interfaceIERC721CollectibleisICollectibleCore, IERC721CreatorExtensionApproveTransfer, ICreatorExtensionTokenURI{
eventUnveil(address creatorContractAddress, uint256 instanceId, uint256 tokenMintIndex, uint256 tokenId);
/**
* @dev Pre-mint given amount to caller
* @param creatorContractAddress the creator contract the claim will mint tokens for
* @param instanceId the id of the claim in the list of creatorContractAddress' _instances
* @param amount the number of tokens to mint
*/functionpremint(address creatorContractAddress, uint256 instanceId, uint16 amount) external;
/**
* @dev Pre-mint 1 token to designated addresses
* @param creatorContractAddress the creator contract the claim will mint tokens for
* @param instanceId the id of the claim in the list of creatorContractAddress' _instances
* @param addresses List of addresses to premint to
*/functionpremint(address creatorContractAddress, uint256 instanceId, address[] calldata addresses) external;
/**
* @dev set the tokenURI prefix
* @param creatorContractAddress the creator contract the claim will mint tokens for
* @param instanceId the id of the claim in the list of creatorContractAddress' _instances
* @param prefix the uri prefix to set
*/functionsetTokenURIPrefix(address creatorContractAddress, uint256 instanceId, stringcalldata prefix) external;
/**
* @dev Set whether or not token transfers are locked until end of sale.
* @param creatorContractAddress the creator contract the claim will mint tokens for
* @param instanceId the id of the claim in the list of creatorContractAddress' _instances
* @param locked Whether or not transfers are locked
*/functionsetTransferLocked(address creatorContractAddress, uint256 instanceId, bool locked) external;
/**
* @dev The `claim` function represents minting during a free claim period. A bit of an overloaded use of hte word "claim".
*/functionclaim(address creatorContractAddress,
uint256 instanceId,
uint16 amount,
bytes32 message,
bytescalldata signature,
bytes32 nonce
) externalpayable;
/**
* @dev purchase
*/functionpurchase(address creatorContractAddress,
uint256 instanceId,
uint16 amount,
bytes32 message,
bytescalldata signature,
bytes32 nonce
) externalpayable;
/**
* @dev returns the collection state
*/functionstate(address creatorContractAddress, uint256 instanceId) externalviewreturns (CollectibleState memory);
/**
* @dev Get number of tokens left
*/functionpurchaseRemaining(address creatorContractAddress, uint256 instanceId) externalviewreturns (uint16);
}
Contract Source Code
File 15 of 20: IERC721CreatorCore.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/// @author: manifold.xyzimport"./ICreatorCore.sol";
/**
* @dev Core ERC721 creator interface
*/interfaceIERC721CreatorCoreisICreatorCore{
/**
* @dev mint a token with no extension. Can only be called by an admin.
* Returns tokenId minted
*/functionmintBase(address to) externalreturns (uint256);
/**
* @dev mint a token with no extension. Can only be called by an admin.
* Returns tokenId minted
*/functionmintBase(address to, stringcalldata uri) externalreturns (uint256);
/**
* @dev batch mint a token with no extension. Can only be called by an admin.
* Returns tokenId minted
*/functionmintBaseBatch(address to, uint16 count) externalreturns (uint256[] memory);
/**
* @dev batch mint a token with no extension. Can only be called by an admin.
* Returns tokenId minted
*/functionmintBaseBatch(address to, string[] calldata uris) externalreturns (uint256[] memory);
/**
* @dev mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/functionmintExtension(address to) externalreturns (uint256);
/**
* @dev mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/functionmintExtension(address to, stringcalldata uri) externalreturns (uint256);
/**
* @dev mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/functionmintExtension(address to, uint80 data) externalreturns (uint256);
/**
* @dev batch mint a token. Can only be called by a registered extension.
* Returns tokenIds minted
*/functionmintExtensionBatch(address to, uint16 count) externalreturns (uint256[] memory);
/**
* @dev batch mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/functionmintExtensionBatch(address to, string[] calldata uris) externalreturns (uint256[] memory);
/**
* @dev batch mint a token. Can only be called by a registered extension.
* Returns tokenId minted
*/functionmintExtensionBatch(address to, uint80[] calldata data) externalreturns (uint256[] memory);
/**
* @dev burn a token. Can only be called by token owner or approved address.
* On burn, calls back to the registered extension's onBurn method
*/functionburn(uint256 tokenId) external;
/**
* @dev get token data
*/functiontokenData(uint256 tokenId) externalviewreturns (uint80);
}
File 17 of 20: IERC721CreatorExtensionApproveTransfer.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/// @author: manifold.xyzimport"@openzeppelin/contracts/utils/introspection/IERC165.sol";
/**
* Implement this if you want your extension to approve a transfer
*/interfaceIERC721CreatorExtensionApproveTransferisIERC165{
/**
* @dev Set whether or not the creator will check the extension for approval of token transfer
*/functionsetApproveTransfer(address creator, bool enabled) external;
/**
* @dev Called by creator contract to approve a transfer
*/functionapproveTransfer(address operator, addressfrom, address to, uint256 tokenId) externalreturns (bool);
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)pragmasolidity ^0.8.0;import"../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/abstractcontractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/function_checkOwner() internalviewvirtual{
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
require(newOwner !=address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Contract Source Code
File 20 of 20: Strings.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)pragmasolidity ^0.8.0;/**
* @dev String operations.
*/libraryStrings{
bytes16privateconstant _HEX_SYMBOLS ="0123456789abcdef";
uint8privateconstant _ADDRESS_LENGTH =20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/functiontoString(uint256 value) internalpurereturns (stringmemory) {
// Inspired by OraclizeAPI's implementation - MIT licence// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.solif (value ==0) {
return"0";
}
uint256 temp = value;
uint256 digits;
while (temp !=0) {
digits++;
temp /=10;
}
bytesmemory buffer =newbytes(digits);
while (value !=0) {
digits -=1;
buffer[digits] =bytes1(uint8(48+uint256(value %10)));
value /=10;
}
returnstring(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/functiontoHexString(uint256 value) internalpurereturns (stringmemory) {
if (value ==0) {
return"0x00";
}
uint256 temp = value;
uint256 length =0;
while (temp !=0) {
length++;
temp >>=8;
}
return toHexString(value, length);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/functiontoHexString(uint256 value, uint256 length) internalpurereturns (stringmemory) {
bytesmemory buffer =newbytes(2* length +2);
buffer[0] ="0";
buffer[1] ="x";
for (uint256 i =2* length +1; i >1; --i) {
buffer[i] = _HEX_SYMBOLS[value &0xf];
value >>=4;
}
require(value ==0, "Strings: hex length insufficient");
returnstring(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/functiontoHexString(address addr) internalpurereturns (stringmemory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}