¡El código fuente de este contrato está verificado!
Metadatos del Contrato
Compilador
0.8.9+commit.e5eed63a
Idioma
Solidity
Código Fuente del Contrato
Archivo 1 de 11: CreatorExtension.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/// @author: manifold.xyzimport"@openzeppelin/contracts/utils/introspection/ERC165.sol";
/**
* @dev Base creator extension variables
*/abstractcontractCreatorExtensionisERC165{
/**
* @dev Legacy extension interface identifiers
*
* {IERC165-supportsInterface} needs to return 'true' for this interface
* in order backwards compatible with older creator contracts
*/bytes4constantinternal LEGACY_EXTENSION_INTERFACE =0x7005caad;
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(ERC165) returns (bool) {
return interfaceId == LEGACY_EXTENSION_INTERFACE
||super.supportsInterface(interfaceId);
}
}
Código Fuente del Contrato
Archivo 2 de 11: 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;
}
}
Código Fuente del Contrato
Archivo 3 de 11: 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);
}
Código Fuente del Contrato
Archivo 4 de 11: 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);
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);
}
Código Fuente del Contrato
Archivo 5 de 11: 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);
}
Código Fuente del Contrato
Archivo 6 de 11: 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);
}
Código Fuente del Contrato
Archivo 7 de 11: 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 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 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;
}
Código Fuente del Contrato
Archivo 8 de 11: IManifoldERC721Edition.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/// @author: manifold.xyz/**
* Manifold ERC721 Edition Controller interface
*/interfaceIManifoldERC721Edition{
eventSeriesCreated(address caller, address creator, uint256 series, uint256 maxSupply);
/**
* @dev Create a new series. Returns the series id.
*/functioncreateSeries(address creator, uint256 maxSupply, stringcalldata prefix) externalreturns(uint256);
/**
* @dev Get the latest series created.
*/functionlatestSeries(address creator) externalviewreturns(uint256);
/**
* @dev Set the token uri prefix
*/functionsetTokenURIPrefix(address creator, uint256 series, stringcalldata prefix) external;
/**
* @dev Mint NFTs to a single recipient
*/functionmint(address creator, uint256 series, address recipient, uint16 count) external;
/**
* @dev Mint NFTS to the recipients
*/functionmint(address creator, uint256 series, address[] calldata recipients) external;
/**
* @dev Total supply of editions
*/functiontotalSupply(address creator, uint256 series) externalviewreturns(uint256);
/**
* @dev Max supply of editions
*/functionmaxSupply(address creator, uint256 series) externalviewreturns(uint256);
}
Código Fuente del Contrato
Archivo 9 de 11: ManifoldERC721Edition.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/// @author: manifold.xyzimport"@manifoldxyz/libraries-solidity/contracts/access/IAdminControl.sol";
import"@manifoldxyz/creator-core-solidity/contracts/core/IERC721CreatorCore.sol";
import"@manifoldxyz/creator-core-solidity/contracts/extensions/CreatorExtension.sol";
import"@manifoldxyz/creator-core-solidity/contracts/extensions/ICreatorExtensionTokenURI.sol";
import"@openzeppelin/contracts/security/ReentrancyGuard.sol";
import"@openzeppelin/contracts/security/ReentrancyGuard.sol";
import"@openzeppelin/contracts/utils/Strings.sol";
import"./IManifoldERC721Edition.sol";
/**
* Manifold ERC721 Edition Controller Implementation
*/contractManifoldERC721EditionisCreatorExtension, ICreatorExtensionTokenURI, IManifoldERC721Edition, ReentrancyGuard{
usingStringsforuint256;
structIndexRange {
uint256 startIndex;
uint256 count;
}
mapping(address=>mapping(uint256=>string)) _tokenPrefix;
mapping(address=>mapping(uint256=>uint256)) _maxSupply;
mapping(address=>mapping(uint256=>uint256)) _totalSupply;
mapping(address=>mapping(uint256=> IndexRange[])) _indexRanges;
mapping(address=>uint256) _currentSeries;
/**
* @dev Only allows approved admins to call the specified function
*/modifiercreatorAdminRequired(address creator) {
require(IAdminControl(creator).isAdmin(msg.sender), "Must be owner or admin of creator contract");
_;
}
functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(CreatorExtension, IERC165) returns (bool) {
return interfaceId ==type(ICreatorExtensionTokenURI).interfaceId|| interfaceId ==type(IManifoldERC721Edition).interfaceId||
CreatorExtension.supportsInterface(interfaceId);
}
/**
* @dev See {IManifoldERC721Edition-totalSupply}.
*/functiontotalSupply(address creator, uint256 series) externalviewoverridereturns(uint256) {
return _totalSupply[creator][series];
}
/**
* @dev See {IManifoldERC721Edition-maxSupply}.
*/functionmaxSupply(address creator, uint256 series) externalviewoverridereturns(uint256) {
return _maxSupply[creator][series];
}
/**
* @dev See {IManifoldERC721Edition-createSeries}.
*/functioncreateSeries(address creator, uint256 maxSupply_, stringcalldata prefix) externaloverridecreatorAdminRequired(creator) returns(uint256) {
_currentSeries[creator] +=1;
uint256 series = _currentSeries[creator];
_maxSupply[creator][series] = maxSupply_;
_tokenPrefix[creator][series] = prefix;
emit SeriesCreated(msg.sender, creator, series, maxSupply_);
return series;
}
/**
* @dev See {IManifoldERC721Edition-latestSeries}.
*/functionlatestSeries(address creator) externalviewoverridereturns(uint256) {
return _currentSeries[creator];
}
/**
* See {IManifoldERC721Edition-setTokenURIPrefix}.
*/functionsetTokenURIPrefix(address creator, uint256 series, stringcalldata prefix) externaloverridecreatorAdminRequired(creator) {
require(series >0&& series <= _currentSeries[creator], "Invalid series");
_tokenPrefix[creator][series] = prefix;
}
/**
* @dev See {ICreatorExtensionTokenURI-tokenURI}.
*/functiontokenURI(address creator, uint256 tokenId) externalviewoverridereturns (stringmemory) {
(uint256 series, uint256 index) = _tokenSeriesAndIndex(creator, tokenId);
returnstring(abi.encodePacked(_tokenPrefix[creator][series], (index+1).toString()));
}
/**
* @dev See {IManifoldERC721Edition-mint}.
*/functionmint(address creator, uint256 series, address recipient, uint16 count) externaloverridenonReentrantcreatorAdminRequired(creator) {
require(count >0, "Invalid amount requested");
require(_totalSupply[creator][series]+count <= _maxSupply[creator][series], "Too many requested");
uint256[] memory tokenIds = IERC721CreatorCore(creator).mintExtensionBatch(recipient, count);
_updateIndexRanges(creator, series, tokenIds[0], count);
}
/**
* @dev See {IManifoldERC721Edition-mint}.
*/functionmint(address creator, uint256 series, address[] calldata recipients) externaloverridenonReentrantcreatorAdminRequired(creator) {
require(recipients.length>0, "Invalid amount requested");
require(_totalSupply[creator][series]+recipients.length<= _maxSupply[creator][series], "Too many requested");
uint256 startIndex = IERC721CreatorCore(creator).mintExtension(recipients[0]);
for (uint256 i =1; i < recipients.length; i++) {
IERC721CreatorCore(creator).mintExtension(recipients[i]);
}
_updateIndexRanges(creator, series, startIndex, recipients.length);
}
/**
* @dev Update the index ranges, which is used to figure out the index from a tokenId
*/function_updateIndexRanges(address creator, uint256 series, uint256 startIndex, uint256 count) internal{
IndexRange[] storage indexRanges = _indexRanges[creator][series];
if (indexRanges.length==0) {
indexRanges.push(IndexRange(startIndex, count));
} else {
IndexRange storage lastIndexRange = indexRanges[indexRanges.length-1];
if ((lastIndexRange.startIndex + lastIndexRange.count) == startIndex) {
lastIndexRange.count += count;
} else {
indexRanges.push(IndexRange(startIndex, count));
}
}
_totalSupply[creator][series] += count;
}
/**
* @dev Index from tokenId
*/function_tokenSeriesAndIndex(address creator, uint256 tokenId) internalviewreturns(uint256, uint256) {
require(_currentSeries[creator] >0, "Invalid token");
for (uint series=1; series <= _currentSeries[creator]; series++) {
IndexRange[] memory indexRanges = _indexRanges[creator][series];
uint256 offset;
for (uint i =0; i < indexRanges.length; i++) {
IndexRange memory currentIndex = indexRanges[i];
if (tokenId < currentIndex.startIndex) break;
if (tokenId >= currentIndex.startIndex && tokenId < currentIndex.startIndex + currentIndex.count) {
return (series, tokenId - currentIndex.startIndex + offset);
}
offset += currentIndex.count;
}
}
revert("Invalid token");
}
}
Código Fuente del Contrato
Archivo 10 de 11: ReentrancyGuard.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)pragmasolidity ^0.8.0;/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/abstractcontractReentrancyGuard{
// Booleans are more expensive than uint256 or any type that takes up a full// word because each write operation emits an extra SLOAD to first read the// slot's contents, replace the bits taken up by the boolean, and then write// back. This is the compiler's defense against contract upgrades and// pointer aliasing, and it cannot be disabled.// The values being non-zero value makes deployment a bit more expensive,// but in exchange the refund on every call to nonReentrant will be lower in// amount. Since refunds are capped to a percentage of the total// transaction's gas, it is best to keep them low in cases like this one, to// increase the likelihood of the full refund coming into effect.uint256privateconstant _NOT_ENTERED =1;
uint256privateconstant _ENTERED =2;
uint256private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/modifiernonReentrant() {
// On the first call to nonReentrant, _notEntered will be truerequire(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
Código Fuente del Contrato
Archivo 11 de 11: Strings.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)pragmasolidity ^0.8.0;/**
* @dev String operations.
*/libraryStrings{
bytes16privateconstant _HEX_SYMBOLS ="0123456789abcdef";
/**
* @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);
}
}