ethereum
在Dora上
0x30...9396
TOOMUCHLAG EDITIONS

TOOMUCHLAG EDITIONS

TML721

收藏品
收藏品
收藏品互动
此合同的源代码已经过验证!
合同元数据
编译器
0.8.19+commit.7dd6d404
语言
Solidity
公司
贡献
社交
© 2025在Dora上搜索

Network

All
Ethereum
Ethereum
Arbitrum One
Arbitrum One
Base
Base
Zora
Zora
Celo
Celo
Gnosis
Gnosis
Scroll
Scroll
Scroll Sepolia
Scroll Sepolia
Xai
Xai
Palm
Palm
Palm Testnet
Palm Testnet
Xai Testnet
Xai Testnet
Mode
Mode
Forma
Forma
Rari
Rari
World Chain
World Chain
Solana
Solana
coming soon
Celestia
Celestia
coming soon
Mantle
Mantle
coming soon
Movement
Movement
coming soon
Scroll Goerli
Scroll Goerli
coming soon
Polygon
Polygon
coming soon
Binance Smart Chain
Binance Smart Chain
coming soon
zkSync Era
zkSync Era
coming soon
Optimism
Optimism
coming soon
Polygon ZKEVM
Polygon ZKEVM
coming soon
Astria
Astria
coming soon
Arbitrum Nova
Arbitrum Nova
coming soon
Metal L2
Metal L2
coming soon
Align Testnet
Align Testnet
coming soon
Zora Testnet
Zora Testnet
coming soon
Avalanche
Avalanche
coming soon
LUKSO
LUKSO
coming soon
Kroma Testnet
Kroma Testnet
coming soon
Modular Games Testnet
Modular Games Testnet
coming soon
Astria Devnet
Astria Devnet
coming soon
Eclipse
Eclipse
coming soon
Cosmos
Cosmos
coming soon
Apechain Testnet
Apechain Testnet
coming soon
Axelar
Axelar
coming soon
Degen
Degen
coming soon
Ethereum
Ethereum
EthereumEthereum
关于
条款
隐私政策
提交标签
报告诈骗
推特
底价
0.69 ETH
$2,345.34
大小
32
收藏品
所有者
26
81% 独特的所有者
3.2 gwei
收藏品互动
合约
此合同的源代码已经过验证!
合同元数据
编译器
0.8.25+commit.b61c2a91
语言
Solidity
合同源代码
文件 1 的 1:ERC721_Editions.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

//            _____            _____                     _____          
//           /\    \          /\    \                   /\    \         
//          /::\____\        /::\    \                 /::\    \        
//         /:::/    /       /::::\    \               /::::\    \       
//        /:::/    /       /::::::\    \             /::::::\    \      
//       /:::/    /       /:::/\:::\    \           /:::/\:::\    \     
//      /:::/    /       /:::/__\:::\    \         /:::/  \:::\    \    
//     /:::/    /       /::::\   \:::\    \       /:::/    \:::\    \   
//    /:::/    /       /::::::\   \:::\    \     /:::/    / \:::\    \  
//   /:::/    /       /:::/\:::\   \:::\    \   /:::/    /   \:::\ ___\ 
//  /:::/____/       /:::/  \:::\   \:::\____\ /:::/____/  ___\:::|    |
//  \:::\    \       \::/    \:::\  /:::/    / \:::\    \ /\  /:::|____|
//   \:::\    \       \/____/ \:::\/:::/    /   \:::\    /::\ \::/    / 
//    \:::\    \               \::::::/    /     \:::\   \:::\ \/____/  
//     \:::\    \               \::::/    /       \:::\   \:::\____\    
//      \:::\    \              /:::/    /         \:::\  /:::/    /    
//       \:::\    \            /:::/    /           \:::\/:::/    /     
//        \:::\    \          /:::/    /             \::::::/    /      
//         \:::\____\        /:::/    /               \::::/    /       
//          \::/    /        \::/    /                 \::/    /        
//           \/____/          \/____/                   \/____/



interface IERC721Receiver {
    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns(bytes4);
}

// Implementation of a custom tokenURI
interface ITokenURICustom {
    function constructTokenURI(uint256 tokenId) external view returns (string memory);
}

// Ownable From OpenZeppelin Contracts v4.4.1 (Ownable.sol)

abstract contract Ownable {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        _transferOwnership(msg.sender);
    }

    function owner() public view virtual returns (address) {
        return _owner;
    }

    modifier onlyOwner() {
        require(owner() == msg.sender, "Ownable: caller is not the owner");
        _;
    }

    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// ERC721 Contract with customisable URI

contract ERC721_Editions is Ownable {

    // Events ERC721
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    // NFT contract metadata
    string public name;

    string public symbol;

    // Mapping from token ID to owner address
    mapping(uint256 => address) private _owners;

    // Mapping owner address to token count
    mapping(address => uint256) private _balances;

    // Mapping from token ID to approved address
    mapping(uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals
    mapping(address => mapping(address => bool)) private _operatorApprovals;

    // Mapping for token URIs
    mapping(uint256 => string) private _tokenURIs;

    // Mapping from token ID to URIs custom contract
    mapping(uint256 => address) public customURI;

    // Mapping from token ID to token URIs locked
    mapping(uint256 => bool) public lockedURI;

    // Minter contract
    address public minterContract;

    // ERC-2981: NFT Royalty Standard
    address payable private _royaltyRecipient;
    uint256 private _royaltyBps;

    // Mapping from token ID to non-default royaltyBps
    mapping(uint256 => uint256) private _royaltyBpsTokenId;


    // CONSTRUCTOR
    constructor(string memory name_, string memory symbol_) {
        name = name_;
        symbol = symbol_;

        _royaltyRecipient = payable(msg.sender);
        _royaltyBps = 1000;

    }

    // ADMIN FUNCTIONS

    function setMinterContract (address minterContract_) public onlyOwner {
        minterContract = minterContract_;
    }

    // ERC165

    function supportsInterface(bytes4 interfaceId) public pure returns (bool) {
        return 
            interfaceId == 0x01ffc9a7 || // ERC165 = 0x01ffc9a7
            interfaceId == 0x80ac58cd || // ERC721 = 0x80ac58cd
            interfaceId == 0x5b5e139f || // ERC721 Metadata = 0x5b5e139f
            interfaceId == 0x2a55205a;  // ERC2981 = 0x2a55205a;

        // ERC721 = 0x80ac58cd
        // ERC721 Metadata = 0x5b5e139f
        // ERC721 Enumerable = 0x780e9d63
        // ERC721 Receiver = 0x150b7a02
        // ERC165 = 0x01ffc9a7
        // ERC2981 = 0x2a55205a;
    }

    // URI SECTION

    function tokenURI(uint256 tokenId) public view returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        if(customURI[tokenId] != address(0)) {
            return ITokenURICustom(customURI[tokenId]).constructTokenURI(tokenId);
        }
        else {
            return _tokenURIs[tokenId];
        }
 
    }

    function setTokenURI(uint256 tokenId, string calldata tokenURI_) public onlyOwner {
        require(!lockedURI[tokenId], "URI finalised");
        _tokenURIs[tokenId] = tokenURI_;

    }

    function setTokenURIBatch(uint256[] calldata tokenIDs, string[] calldata tokenURI_) public onlyOwner {
        for (uint256 i = 0; i < tokenIDs.length; ++i) {
            require(!lockedURI[tokenIDs[i]], "URI finalised");
            _tokenURIs[tokenIDs[i]] = tokenURI_[i];
        }
    }

    function setCustomURI(uint256 tokenId, address contractURI) public onlyOwner {
        require(!lockedURI[tokenId], "URI finalised");
        customURI[tokenId] = contractURI;
    }

    function lockURIs(uint256[] calldata tokenIDs) public onlyOwner {
        for (uint256 i = 0; i < tokenIDs.length; ++i) {
            require(!lockedURI[tokenIDs[i]], "URI finalised");
            lockedURI[tokenIDs[i]] = true;
        }
    }

    // ERC721 SECTION

    function balanceOf(address owner) public view returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _balances[owner];
    }

    function ownerOf(uint256 tokenId) public view returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

    function approve(address to, uint256 tokenId) public {
        address owner = ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(
            msg.sender == owner || isApprovedForAll(owner, msg.sender),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    function getApproved(uint256 tokenId) public view returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    function setApprovalForAll(address operator, bool approved) public {
        _setApprovalForAll(msg.sender, operator, approved);
    }

    function isApprovedForAll(address owner, address operator) public view returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public {
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public {
        safeTransferFrom(from, to, tokenId, "");
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) public {
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    function _safeTransfer(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) internal {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    function _exists(uint256 tokenId) internal view returns (bool) {
        return _owners[tokenId] != address(0);
    }

    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }

    function mintBatch(address to, uint256 startId, uint256 quantity, string[] calldata tokenURI_) public onlyOwner {
        for (uint256 i = 0; i < quantity; ++i) {
            _mint(to, startId + i);
            _tokenURIs[startId + i] = tokenURI_[i];
        }
        
    }

    function mintCustomUri(address to, uint256 tokenId, address contractURI) public onlyOwner {
        _mint(to, tokenId);
        customURI[tokenId] = contractURI;
    }

    function mintExternal(address to, uint256 tokenId, string calldata tokenURI_) public {
        require(msg.sender == minterContract, "Not Allowed");

        _mint(to, tokenId);
        _tokenURIs[tokenId] = tokenURI_;
    }

    function mintCustomExternal(address to, uint256 tokenId, address contractURI) public {
        require(msg.sender == minterContract, "Not Allowed");
        
        _mint(to, tokenId);
        customURI[tokenId] = contractURI;
    }

    function burn(uint256 tokenId) public {
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: caller is not owner nor approved");
        _burn(tokenId);
        delete _tokenURIs[tokenId];
        delete customURI[tokenId];
        delete lockedURI[tokenId];
    }

    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(address(0), to, tokenId);

    }

    function _burn(uint256 tokenId) internal {
        address owner = ownerOf(tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

        emit Transfer(owner, address(0), tokenId);

    }

    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal {
        require(ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
        require(to != address(0), "ERC721: transfer to the zero address");


        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);

    }

    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ownerOf(tokenId), to, tokenId);
    }

    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.code.length > 0) {
            try IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver.onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }


    // EIP-2981 ROYALTY STANDARD
    function setRoyaltyBps(uint256 royaltyPercentageBasisPoints) public onlyOwner {
        _royaltyBps = royaltyPercentageBasisPoints;
    }

    function setRoyaltyBpsForTokenId(uint256 tokenId, uint256 royaltyPercentageBasisPoints) public onlyOwner {
        _royaltyBpsTokenId[tokenId] = royaltyPercentageBasisPoints;
    }

    function setRoyaltyReceipientAddress(address payable royaltyReceipientAddress) public onlyOwner {
        _royaltyRecipient = royaltyReceipientAddress;
    }

    function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount) {
        uint256 bps;

        if(_royaltyBpsTokenId[tokenId] > 0) {
            bps = _royaltyBpsTokenId[tokenId];
        }
        else {
            bps = _royaltyBps;
        }

        uint256 royalty = (salePrice * bps) / 10000;
        return (_royaltyRecipient, royalty);
    }

}
设置
{
  "compilationTarget": {
    "ERC721_Editions.sol": "ERC721_Editions"
  },
  "evmVersion": "cancun",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 1000
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"customURI","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIDs","type":"uint256[]"}],"name":"lockURIs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lockedURI","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"startId","type":"uint256"},{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"string[]","name":"tokenURI_","type":"string[]"}],"name":"mintBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"contractURI","type":"address"}],"name":"mintCustomExternal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"contractURI","type":"address"}],"name":"mintCustomUri","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"tokenURI_","type":"string"}],"name":"mintExternal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"minterContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"contractURI","type":"address"}],"name":"setCustomURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minterContract_","type":"address"}],"name":"setMinterContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"royaltyPercentageBasisPoints","type":"uint256"}],"name":"setRoyaltyBps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"royaltyPercentageBasisPoints","type":"uint256"}],"name":"setRoyaltyBpsForTokenId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"royaltyReceipientAddress","type":"address"}],"name":"setRoyaltyReceipientAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"tokenURI_","type":"string"}],"name":"setTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIDs","type":"uint256[]"},{"internalType":"string[]","name":"tokenURI_","type":"string[]"}],"name":"setTokenURIBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]