编译器
0.8.17+commit.8df45f5f
文件 1 的 11:CreatorExtension.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
abstract contract CreatorExtension is ERC165 {
bytes4 constant internal LEGACY_EXTENSION_INTERFACE = 0x7005caad;
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165) returns (bool) {
return interfaceId == LEGACY_EXTENSION_INTERFACE
|| super.supportsInterface(interfaceId);
}
}
文件 2 的 11:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 3 的 11:IAdminControl.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
interface IAdminControl is IERC165 {
event AdminApproved(address indexed account, address indexed sender);
event AdminRevoked(address indexed account, address indexed sender);
function getAdmins() external view returns (address[] memory);
function approveAdmin(address admin) external;
function revokeAdmin(address admin) external;
function isAdmin(address admin) external view returns (bool);
}
文件 4 的 11:ICreatorCore.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
interface ICreatorCore is IERC165 {
event ExtensionRegistered(address indexed extension, address indexed sender);
event ExtensionUnregistered(address indexed extension, address indexed sender);
event ExtensionBlacklisted(address indexed extension, address indexed sender);
event MintPermissionsUpdated(address indexed extension, address indexed permissions, address indexed sender);
event RoyaltiesUpdated(uint256 indexed tokenId, address payable[] receivers, uint256[] basisPoints);
event DefaultRoyaltiesUpdated(address payable[] receivers, uint256[] basisPoints);
event ApproveTransferUpdated(address extension);
event ExtensionRoyaltiesUpdated(address indexed extension, address payable[] receivers, uint256[] basisPoints);
event ExtensionApproveTransferUpdated(address indexed extension, bool enabled);
function getExtensions() external view returns (address[] memory);
function registerExtension(address extension, string calldata baseURI) external;
function registerExtension(address extension, string calldata baseURI, bool baseURIIdentical) external;
function unregisterExtension(address extension) external;
function blacklistExtension(address extension) external;
function setBaseTokenURIExtension(string calldata uri) external;
function setBaseTokenURIExtension(string calldata uri, bool identical) external;
function setTokenURIPrefixExtension(string calldata prefix) external;
function setTokenURIExtension(uint256 tokenId, string calldata uri) external;
function setTokenURIExtension(uint256[] memory tokenId, string[] calldata uri) external;
function setBaseTokenURI(string calldata uri) external;
function setTokenURIPrefix(string calldata prefix) external;
function setTokenURI(uint256 tokenId, string calldata uri) external;
function setTokenURI(uint256[] memory tokenIds, string[] calldata uris) external;
function setMintPermissions(address extension, address permissions) external;
function setApproveTransferExtension(bool enabled) external;
function tokenExtension(uint256 tokenId) external view returns (address);
function setRoyalties(address payable[] calldata receivers, uint256[] calldata basisPoints) external;
function setRoyalties(uint256 tokenId, address payable[] calldata receivers, uint256[] calldata basisPoints) external;
function setRoyaltiesExtension(address extension, address payable[] calldata receivers, uint256[] calldata basisPoints) external;
function getRoyalties(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory);
function getFeeRecipients(uint256 tokenId) external view returns (address payable[] memory);
function getFeeBps(uint256 tokenId) external view returns (uint[] memory);
function getFees(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory);
function royaltyInfo(uint256 tokenId, uint256 value) external view returns (address, uint256);
function setApproveTransfer(address extension) external;
function getApproveTransfer() external view returns (address);
}
文件 5 的 11:ICreatorExtensionTokenURI.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
interface ICreatorExtensionTokenURI is IERC165 {
function tokenURI(address creator, uint256 tokenId) external view returns (string memory);
}
文件 6 的 11:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 7 的 11:IERC721CreatorCore.sol
pragma solidity ^0.8.0;
import "./ICreatorCore.sol";
interface IERC721CreatorCore is ICreatorCore {
function mintBase(address to) external returns (uint256);
function mintBase(address to, string calldata uri) external returns (uint256);
function mintBaseBatch(address to, uint16 count) external returns (uint256[] memory);
function mintBaseBatch(address to, string[] calldata uris) external returns (uint256[] memory);
function mintExtension(address to) external returns (uint256);
function mintExtension(address to, string calldata uri) external returns (uint256);
function mintExtension(address to, uint80 data) external returns (uint256);
function mintExtensionBatch(address to, uint16 count) external returns (uint256[] memory);
function mintExtensionBatch(address to, string[] calldata uris) external returns (uint256[] memory);
function mintExtensionBatch(address to, uint80[] calldata data) external returns (uint256[] memory);
function burn(uint256 tokenId) external;
function tokenData(uint256 tokenId) external view returns (uint80);
}
文件 8 的 11:IManifoldERC721Edition.sol
pragma solidity ^0.8.0;
interface IManifoldERC721Edition {
event SeriesCreated(address caller, address creator, uint256 series, uint256 maxSupply);
function createSeries(address creator, uint256 maxSupply, string calldata prefix) external returns(uint256);
function latestSeries(address creator) external view returns(uint256);
function setTokenURIPrefix(address creator, uint256 series, string calldata prefix) external;
function mint(address creator, uint256 series, address recipient, uint16 count) external;
function mint(address creator, uint256 series, address[] calldata recipients) external;
function totalSupply(address creator, uint256 series) external view returns(uint256);
function maxSupply(address creator, uint256 series) external view returns(uint256);
}
文件 9 的 11:ManifoldERC721Edition.sol
pragma solidity ^0.8.0;
import "@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";
contract ManifoldERC721Edition is CreatorExtension, ICreatorExtensionTokenURI, IManifoldERC721Edition, ReentrancyGuard {
using Strings for uint256;
struct IndexRange {
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;
modifier creatorAdminRequired(address creator) {
require(IAdminControl(creator).isAdmin(msg.sender), "Must be owner or admin of creator contract");
_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override(CreatorExtension, IERC165) returns (bool) {
return interfaceId == type(ICreatorExtensionTokenURI).interfaceId || interfaceId == type(IManifoldERC721Edition).interfaceId ||
CreatorExtension.supportsInterface(interfaceId);
}
function totalSupply(address creator, uint256 series) external view override returns(uint256) {
return _totalSupply[creator][series];
}
function maxSupply(address creator, uint256 series) external view override returns(uint256) {
return _maxSupply[creator][series];
}
function createSeries(address creator, uint256 maxSupply_, string calldata prefix) external override creatorAdminRequired(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;
}
function latestSeries(address creator) external view override returns(uint256) {
return _currentSeries[creator];
}
function setTokenURIPrefix(address creator, uint256 series, string calldata prefix) external override creatorAdminRequired(creator) {
require(series > 0 && series <= _currentSeries[creator], "Invalid series");
_tokenPrefix[creator][series] = prefix;
}
function tokenURI(address creator, uint256 tokenId) external view override returns (string memory) {
(uint256 series, uint256 index) = _tokenSeriesAndIndex(creator, tokenId);
return string(abi.encodePacked(_tokenPrefix[creator][series], (index+1).toString()));
}
function mint(address creator, uint256 series, address recipient, uint16 count) external override nonReentrant creatorAdminRequired(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);
}
function mint(address creator, uint256 series, address[] calldata recipients) external override nonReentrant creatorAdminRequired(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;) {
IERC721CreatorCore(creator).mintExtension(recipients[i]);
unchecked{i++;}
}
_updateIndexRanges(creator, series, startIndex, recipients.length);
}
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;
}
function _tokenSeriesAndIndex(address creator, uint256 tokenId) internal view returns(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");
}
}
文件 10 的 11:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 11 的 11:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(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");
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
{
"compilationTarget": {
"contracts/manifold/edition/ManifoldERC721Edition.sol": "ManifoldERC721Edition"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 500
},
"remappings": [
":@ensdomains/=node_modules/@ensdomains/",
":@manifoldxyz/=node_modules/@manifoldxyz/",
":@openzeppelin/=node_modules/@openzeppelin/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":eth-gas-reporter/=node_modules/eth-gas-reporter/",
":forge-std/=lib/forge-std/src/",
":hardhat/=node_modules/hardhat/",
":operator-filter-registry/=node_modules/operator-filter-registry/",
":truffle/=node_modules/truffle/",
"lib/forge-std:ds-test/=lib/forge-std/lib/ds-test/src/"
]
}
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"uint256","name":"series","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxSupply","type":"uint256"}],"name":"SeriesCreated","type":"event"},{"inputs":[{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"maxSupply_","type":"uint256"},{"internalType":"string","name":"prefix","type":"string"}],"name":"createSeries","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creator","type":"address"}],"name":"latestSeries","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"series","type":"uint256"}],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"series","type":"uint256"},{"internalType":"address[]","name":"recipients","type":"address[]"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"series","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint16","name":"count","type":"uint16"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"series","type":"uint256"},{"internalType":"string","name":"prefix","type":"string"}],"name":"setTokenURIPrefix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"series","type":"uint256"}],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]