[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M7144C6JS18Y5ZSCMHVJYPTE":3,"skill-same:01M7144C6JS18Y5ZSCMHVJYPTE":56},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":30,"linkOnly":31,"markdownContent":32,"markdownBody":33,"frontMatter":34,"refName":36,"commitSha":37,"skillDirectory":38,"forksCount":14,"repositoryHtmlUrl":39,"repositoryHomepageUrl":6,"ownerHtmlUrl":40,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":41,"install":42,"resources":55},"01M7144C6JS18Y5ZSCMHVJYPTE","nft-standards",null,"Master ERC-721 and ERC-1155 NFT standards, metadata best practices, and advanced NFT features.","sapsapshen\u002Fai-memory-router","sapsapshen","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F20347959?v=4","01M6XDQEF1DP50DKF37H81J3J5","shenmian","01M6XDQEJPE41Y3DT2763X8ZJN",0,"MIT","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fcopilot\u002Fnft-standards\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29],"standards","nft standards","nft","best practices","metadata","master","community","advanced","unknown","features","2026","2026-11-10 10:12:30",false,"---\nname: nft-standards\ndescription: \"Master ERC-721 and ERC-1155 NFT standards, metadata best practices, and advanced NFT features.\"\nrisk: unknown\nsource: community\ndate_added: \"2026-02-27\"\n---\n\n# NFT Standards\n\nMaster ERC-721 and ERC-1155 NFT standards, metadata best practices, and advanced NFT features.\n\n## Do not use this skill when\n\n- The task is unrelated to nft standards\n- You need a different domain or tool outside this scope\n\n## Instructions\n\n- Clarify goals, constraints, and required inputs.\n- Apply relevant best practices and validate outcomes.\n- Provide actionable steps and verification.\n- If detailed examples are required, open `resources\u002Fimplementation-playbook.md`.\n\n## Use this skill when\n\n- Creating NFT collections (art, gaming, collectibles)\n- Implementing marketplace functionality\n- Building on-chain or off-chain metadata\n- Creating soulbound tokens (non-transferable)\n- Implementing royalties and revenue sharing\n- Developing dynamic\u002Fevolving NFTs\n\n## ERC-721 (Non-Fungible Token Standard)\n\n```solidity\n\u002F\u002F SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin\u002Fcontracts\u002Ftoken\u002FERC721\u002Fextensions\u002FERC721URIStorage.sol\";\nimport \"@openzeppelin\u002Fcontracts\u002Ftoken\u002FERC721\u002Fextensions\u002FERC721Enumerable.sol\";\nimport \"@openzeppelin\u002Fcontracts\u002Faccess\u002FOwnable.sol\";\nimport \"@openzeppelin\u002Fcontracts\u002Futils\u002FCounters.sol\";\n\ncontract MyNFT is ERC721URIStorage, ERC721Enumerable, Ownable {\n    using Counters for Counters.Counter;\n    Counters.Counter private _tokenIds;\n\n    uint256 public constant MAX_SUPPLY = 10000;\n    uint256 public constant MINT_PRICE = 0.08 ether;\n    uint256 public constant MAX_PER_MINT = 20;\n\n    constructor() ERC721(\"MyNFT\", \"MNFT\") {}\n\n    function mint(uint256 quantity) external payable {\n        require(quantity > 0 && quantity \u003C= MAX_PER_MINT, \"Invalid quantity\");\n        require(_tokenIds.current() + quantity \u003C= MAX_SUPPLY, \"Exceeds max supply\");\n        require(msg.value >= MINT_PRICE * quantity, \"Insufficient payment\");\n\n        for (uint256 i = 0; i \u003C quantity; i++) {\n            _tokenIds.increment();\n            uint256 newTokenId = _tokenIds.current();\n            _safeMint(msg.sender, newTokenId);\n            _setTokenURI(newTokenId, generateTokenURI(newTokenId));\n        }\n    }\n\n    function generateTokenURI(uint256 tokenId) internal pure returns (string memory) {\n        \u002F\u002F Return IPFS URI or on-chain metadata\n        return string(abi.encodePacked(\"ipfs:\u002F\u002FQmHash\u002F\", Strings.toString(tokenId), \".json\"));\n    }\n\n    \u002F\u002F Required overrides\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId,\n        uint256 batchSize\n    ) internal override(ERC721, ERC721Enumerable) {\n        super._beforeTokenTransfer(from, to, tokenId, batchSize);\n    }\n\n    function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {\n        super._burn(tokenId);\n    }\n\n    function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) {\n        return super.tokenURI(tokenId);\n    }\n\n    function supportsInterface(bytes4 interfaceId)\n        public\n        view\n        override(ERC721, ERC721Enumerable)\n        returns (bool)\n    {\n        return super.supportsInterface(interfaceId);\n    }\n\n    function withdraw() external onlyOwner {\n        payable(owner()).transfer(address(this).balance);\n    }\n}\n```\n\n## ERC-1155 (Multi-Token Standard)\n\n```solidity\n\u002F\u002F SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin\u002Fcontracts\u002Ftoken\u002FERC1155\u002FERC1155.sol\";\nimport \"@openzeppelin\u002Fcontracts\u002Faccess\u002FOwnable.sol\";\n\ncontract GameItems is ERC1155, Ownable {\n    uint256 public constant SWORD = 1;\n    uint256 public constant SHIELD = 2;\n    uint256 public constant POTION = 3;\n\n    mapping(uint256 => uint256) public tokenSupply;\n    mapping(uint256 => uint256) public maxSupply;\n\n    constructor() ERC1155(\"ipfs:\u002F\u002FQmBaseHash\u002F{id}.json\") {\n        maxSupply[SWORD] = 1000;\n        maxSupply[SHIELD] = 500;\n        maxSupply[POTION] = 10000;\n    }\n\n    function mint(\n        address to,\n        uint256 id,\n        uint256 amount\n    ) external onlyOwner {\n        require(tokenSupply[id] + amount \u003C= maxSupply[id], \"Exceeds max supply\");\n\n        _mint(to, id, amount, \"\");\n        tokenSupply[id] += amount;\n    }\n\n    function mintBatch(\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts\n    ) external onlyOwner {\n        for (uint256 i = 0; i \u003C ids.length; i++) {\n            require(tokenSupply[ids[i]] + amounts[i] \u003C= maxSupply[ids[i]], \"Exceeds max supply\");\n            tokenSupply[ids[i]] += amounts[i];\n        }\n\n        _mintBatch(to, ids, amounts, \"\");\n    }\n\n    function burn(\n        address from,\n        uint256 id,\n        uint256 amount\n    ) external {\n        require(from == msg.sender || isApprovedForAll(from, msg.sender), \"Not authorized\");\n        _burn(from, id, amount);\n        tokenSupply[id] -= amount;\n    }\n}\n```\n\n## Metadata Standards\n\n### Off-Chain Metadata (IPFS)\n\n```json\n{\n  \"name\": \"NFT #1\",\n  \"description\": \"Description of the NFT\",\n  \"image\": \"ipfs:\u002F\u002FQmImageHash\",\n  \"attributes\": [\n    {\n      \"trait_type\": \"Background\",\n      \"value\": \"Blue\"\n    },\n    {\n      \"trait_type\": \"Rarity\",\n      \"value\": \"Legendary\"\n    },\n    {\n      \"trait_type\": \"Power\",\n      \"value\": 95,\n      \"display_type\": \"number\",\n      \"max_value\": 100\n    }\n  ]\n}\n```\n\n### On-Chain Metadata\n\n```solidity\ncontract OnChainNFT is ERC721 {\n    struct Traits {\n        uint8 background;\n        uint8 body;\n        uint8 head;\n        uint8 rarity;\n    }\n\n    mapping(uint256 => Traits) public tokenTraits;\n\n    function tokenURI(uint256 tokenId) public view override returns (string memory) {\n        Traits memory traits = tokenTraits[tokenId];\n\n        string memory json = Base64.encode(\n            bytes(\n                string(\n                    abi.encodePacked(\n                        '{\"name\": \"NFT #', Strings.toString(tokenId), '\",',\n                        '\"description\": \"On-chain NFT\",',\n                        '\"image\": \"data:image\u002Fsvg+xml;base64,', generateSVG(traits), '\",',\n                        '\"attributes\": [',\n                        '{\"trait_type\": \"Background\", \"value\": \"', Strings.toString(traits.background), '\"},',\n                        '{\"trait_type\": \"Rarity\", \"value\": \"', getRarityName(traits.rarity), '\"}',\n                        ']}'\n                    )\n                )\n            )\n        );\n\n        return string(abi.encodePacked(\"data:application\u002Fjson;base64,\", json));\n    }\n\n    function generateSVG(Traits memory traits) internal pure returns (string memory) {\n        \u002F\u002F Generate SVG based on traits\n        return \"...\";\n    }\n}\n```\n\n## Royalties (EIP-2981)\n\n```solidity\nimport \"@openzeppelin\u002Fcontracts\u002Finterfaces\u002FIERC2981.sol\";\n\ncontract NFTWithRoyalties is ERC721, IERC2981 {\n    address public royaltyRecipient;\n    uint96 public royaltyFee = 500; \u002F\u002F 5%\n\n    constructor() ERC721(\"Royalty NFT\", \"RNFT\") {\n        royaltyRecipient = msg.sender;\n    }\n\n    function royaltyInfo(uint256 tokenId, uint256 salePrice)\n        external\n        view\n        override\n        returns (address receiver, uint256 royaltyAmount)\n    {\n        return (royaltyRecipient, (salePrice * royaltyFee) \u002F 10000);\n    }\n\n    function setRoyalty(address recipient, uint96 fee) external onlyOwner {\n        require(fee \u003C= 1000, \"Royalty fee too high\"); \u002F\u002F Max 10%\n        royaltyRecipient = recipient;\n        royaltyFee = fee;\n    }\n\n    function supportsInterface(bytes4 interfaceId)\n        public\n        view\n        override(ERC721, IERC165)\n        returns (bool)\n    {\n        return interfaceId == type(IERC2981).interfaceId ||\n               super.supportsInterface(interfaceId);\n    }\n}\n```\n\n## Soulbound Tokens (Non-Transferable)\n\n```solidity\ncontract SoulboundToken is ERC721 {\n    constructor() ERC721(\"Soulbound\", \"SBT\") {}\n\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId,\n        uint256 batchSize\n    ) internal virtual override {\n        require(from == address(0) || to == address(0), \"Token is soulbound\");\n        super._beforeTokenTransfer(from, to, tokenId, batchSize);\n    }\n\n    function mint(address to) external {\n        uint256 tokenId = totalSupply() + 1;\n        _safeMint(to, tokenId);\n    }\n\n    \u002F\u002F Burn is allowed (user can destroy their SBT)\n    function burn(uint256 tokenId) external {\n        require(ownerOf(tokenId) == msg.sender, \"Not token owner\");\n        _burn(tokenId);\n    }\n}\n```\n\n## Dynamic NFTs\n\n```solidity\ncontract DynamicNFT is ERC721 {\n    struct TokenState {\n        uint256 level;\n        uint256 experience;\n        uint256 lastUpdated;\n    }\n\n    mapping(uint256 => TokenState) public tokenStates;\n\n    function gainExperience(uint256 tokenId, uint256 exp) external {\n        require(ownerOf(tokenId) == msg.sender, \"Not token owner\");\n\n        TokenState storage state = tokenStates[tokenId];\n        state.experience += exp;\n\n        \u002F\u002F Level up logic\n        if (state.experience >= state.level * 100) {\n            state.level++;\n        }\n\n        state.lastUpdated = block.timestamp;\n    }\n\n    function tokenURI(uint256 tokenId) public view override returns (string memory) {\n        TokenState memory state = tokenStates[tokenId];\n\n        \u002F\u002F Generate metadata based on current state\n        return generateMetadata(tokenId, state);\n    }\n\n    function generateMetadata(uint256 tokenId, TokenState memory state)\n        internal\n        pure\n        returns (string memory)\n    {\n        \u002F\u002F Dynamic metadata generation\n        return \"\";\n    }\n}\n```\n\n## Gas-Optimized Minting (ERC721A)\n\n```solidity\nimport \"erc721a\u002Fcontracts\u002FERC721A.sol\";\n\ncontract OptimizedNFT is ERC721A {\n    uint256 public constant MAX_SUPPLY = 10000;\n    uint256 public constant MINT_PRICE = 0.05 ether;\n\n    constructor() ERC721A(\"Optimized NFT\", \"ONFT\") {}\n\n    function mint(uint256 quantity) external payable {\n        require(_totalMinted() + quantity \u003C= MAX_SUPPLY, \"Exceeds max supply\");\n        require(msg.value >= MINT_PRICE * quantity, \"Insufficient payment\");\n\n        _mint(msg.sender, quantity);\n    }\n\n    function _baseURI() internal pure override returns (string memory) {\n        return \"ipfs:\u002F\u002FQmBaseHash\u002F\";\n    }\n}\n```\n\n## Resources\n\n- **references\u002Ferc721.md**: ERC-721 specification details\n- **references\u002Ferc1155.md**: ERC-1155 multi-token standard\n- **references\u002Fmetadata-standards.md**: Metadata best practices\n- **references\u002Fenumeration.md**: Token enumeration patterns\n- **assets\u002Ferc721-contract.sol**: Production ERC-721 template\n- **assets\u002Ferc1155-contract.sol**: Production ERC-1155 template\n- **assets\u002Fmetadata-schema.json**: Standard metadata format\n- **assets\u002Fmetadata-uploader.py**: IPFS upload utility\n\n## Best Practices\n\n1. **Use OpenZeppelin**: Battle-tested implementations\n2. **Pin Metadata**: Use IPFS with pinning service\n3. **Implement Royalties**: EIP-2981 for marketplace compatibility\n4. **Gas Optimization**: Use ERC721A for batch minting\n5. **Reveal Mechanism**: Placeholder → reveal pattern\n6. **Enumeration**: Support walletOfOwner for marketplaces\n7. **Whitelist**: Merkle trees for efficient whitelisting\n\n## Marketplace Integration\n\n- OpenSea: ERC-721\u002F1155, metadata standards\n- LooksRare: Royalty enforcement\n- Rarible: Protocol fees, lazy minting\n- Blur: Gas-optimized trading\n","# NFT Standards\n\nMaster ERC-721 and ERC-1155 NFT standards, metadata best practices, and advanced NFT features.\n\n## Do not use this skill when\n\n- The task is unrelated to nft standards\n- You need a different domain or tool outside this scope\n\n## Instructions\n\n- Clarify goals, constraints, and required inputs.\n- Apply relevant best practices and validate outcomes.\n- Provide actionable steps and verification.\n- If detailed examples are required, open `resources\u002Fimplementation-playbook.md`.\n\n## Use this skill when\n\n- Creating NFT collections (art, gaming, collectibles)\n- Implementing marketplace functionality\n- Building on-chain or off-chain metadata\n- Creating soulbound tokens (non-transferable)\n- Implementing royalties and revenue sharing\n- Developing dynamic\u002Fevolving NFTs\n\n## ERC-721 (Non-Fungible Token Standard)\n\n```solidity\n\u002F\u002F SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin\u002Fcontracts\u002Ftoken\u002FERC721\u002Fextensions\u002FERC721URIStorage.sol\";\nimport \"@openzeppelin\u002Fcontracts\u002Ftoken\u002FERC721\u002Fextensions\u002FERC721Enumerable.sol\";\nimport \"@openzeppelin\u002Fcontracts\u002Faccess\u002FOwnable.sol\";\nimport \"@openzeppelin\u002Fcontracts\u002Futils\u002FCounters.sol\";\n\ncontract MyNFT is ERC721URIStorage, ERC721Enumerable, Ownable {\n    using Counters for Counters.Counter;\n    Counters.Counter private _tokenIds;\n\n    uint256 public constant MAX_SUPPLY = 10000;\n    uint256 public constant MINT_PRICE = 0.08 ether;\n    uint256 public constant MAX_PER_MINT = 20;\n\n    constructor() ERC721(\"MyNFT\", \"MNFT\") {}\n\n    function mint(uint256 quantity) external payable {\n        require(quantity > 0 && quantity \u003C= MAX_PER_MINT, \"Invalid quantity\");\n        require(_tokenIds.current() + quantity \u003C= MAX_SUPPLY, \"Exceeds max supply\");\n        require(msg.value >= MINT_PRICE * quantity, \"Insufficient payment\");\n\n        for (uint256 i = 0; i \u003C quantity; i++) {\n            _tokenIds.increment();\n            uint256 newTokenId = _tokenIds.current();\n            _safeMint(msg.sender, newTokenId);\n            _setTokenURI(newTokenId, generateTokenURI(newTokenId));\n        }\n    }\n\n    function generateTokenURI(uint256 tokenId) internal pure returns (string memory) {\n        \u002F\u002F Return IPFS URI or on-chain metadata\n        return string(abi.encodePacked(\"ipfs:\u002F\u002FQmHash\u002F\", Strings.toString(tokenId), \".json\"));\n    }\n\n    \u002F\u002F Required overrides\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId,\n        uint256 batchSize\n    ) internal override(ERC721, ERC721Enumerable) {\n        super._beforeTokenTransfer(from, to, tokenId, batchSize);\n    }\n\n    function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {\n        super._burn(tokenId);\n    }\n\n    function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) {\n        return super.tokenURI(tokenId);\n    }\n\n    function supportsInterface(bytes4 interfaceId)\n        public\n        view\n        override(ERC721, ERC721Enumerable)\n        returns (bool)\n    {\n        return super.supportsInterface(interfaceId);\n    }\n\n    function withdraw() external onlyOwner {\n        payable(owner()).transfer(address(this).balance);\n    }\n}\n```\n\n## ERC-1155 (Multi-Token Standard)\n\n```solidity\n\u002F\u002F SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin\u002Fcontracts\u002Ftoken\u002FERC1155\u002FERC1155.sol\";\nimport \"@openzeppelin\u002Fcontracts\u002Faccess\u002FOwnable.sol\";\n\ncontract GameItems is ERC1155, Ownable {\n    uint256 public constant SWORD = 1;\n    uint256 public constant SHIELD = 2;\n    uint256 public constant POTION = 3;\n\n    mapping(uint256 => uint256) public tokenSupply;\n    mapping(uint256 => uint256) public maxSupply;\n\n    constructor() ERC1155(\"ipfs:\u002F\u002FQmBaseHash\u002F{id}.json\") {\n        maxSupply[SWORD] = 1000;\n        maxSupply[SHIELD] = 500;\n        maxSupply[POTION] = 10000;\n    }\n\n    function mint(\n        address to,\n        uint256 id,\n        uint256 amount\n    ) external onlyOwner {\n        require(tokenSupply[id] + amount \u003C= maxSupply[id], \"Exceeds max supply\");\n\n        _mint(to, id, amount, \"\");\n        tokenSupply[id] += amount;\n    }\n\n    function mintBatch(\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts\n    ) external onlyOwner {\n        for (uint256 i = 0; i \u003C ids.length; i++) {\n            require(tokenSupply[ids[i]] + amounts[i] \u003C= maxSupply[ids[i]], \"Exceeds max supply\");\n            tokenSupply[ids[i]] += amounts[i];\n        }\n\n        _mintBatch(to, ids, amounts, \"\");\n    }\n\n    function burn(\n        address from,\n        uint256 id,\n        uint256 amount\n    ) external {\n        require(from == msg.sender || isApprovedForAll(from, msg.sender), \"Not authorized\");\n        _burn(from, id, amount);\n        tokenSupply[id] -= amount;\n    }\n}\n```\n\n## Metadata Standards\n\n### Off-Chain Metadata (IPFS)\n\n```json\n{\n  \"name\": \"NFT #1\",\n  \"description\": \"Description of the NFT\",\n  \"image\": \"ipfs:\u002F\u002FQmImageHash\",\n  \"attributes\": [\n    {\n      \"trait_type\": \"Background\",\n      \"value\": \"Blue\"\n    },\n    {\n      \"trait_type\": \"Rarity\",\n      \"value\": \"Legendary\"\n    },\n    {\n      \"trait_type\": \"Power\",\n      \"value\": 95,\n      \"display_type\": \"number\",\n      \"max_value\": 100\n    }\n  ]\n}\n```\n\n### On-Chain Metadata\n\n```solidity\ncontract OnChainNFT is ERC721 {\n    struct Traits {\n        uint8 background;\n        uint8 body;\n        uint8 head;\n        uint8 rarity;\n    }\n\n    mapping(uint256 => Traits) public tokenTraits;\n\n    function tokenURI(uint256 tokenId) public view override returns (string memory) {\n        Traits memory traits = tokenTraits[tokenId];\n\n        string memory json = Base64.encode(\n            bytes(\n                string(\n                    abi.encodePacked(\n                        '{\"name\": \"NFT #', Strings.toString(tokenId), '\",',\n                        '\"description\": \"On-chain NFT\",',\n                        '\"image\": \"data:image\u002Fsvg+xml;base64,', generateSVG(traits), '\",',\n                        '\"attributes\": [',\n                        '{\"trait_type\": \"Background\", \"value\": \"', Strings.toString(traits.background), '\"},',\n                        '{\"trait_type\": \"Rarity\", \"value\": \"', getRarityName(traits.rarity), '\"}',\n                        ']}'\n                    )\n                )\n            )\n        );\n\n        return string(abi.encodePacked(\"data:application\u002Fjson;base64,\", json));\n    }\n\n    function generateSVG(Traits memory traits) internal pure returns (string memory) {\n        \u002F\u002F Generate SVG based on traits\n        return \"...\";\n    }\n}\n```\n\n## Royalties (EIP-2981)\n\n```solidity\nimport \"@openzeppelin\u002Fcontracts\u002Finterfaces\u002FIERC2981.sol\";\n\ncontract NFTWithRoyalties is ERC721, IERC2981 {\n    address public royaltyRecipient;\n    uint96 public royaltyFee = 500; \u002F\u002F 5%\n\n    constructor() ERC721(\"Royalty NFT\", \"RNFT\") {\n        royaltyRecipient = msg.sender;\n    }\n\n    function royaltyInfo(uint256 tokenId, uint256 salePrice)\n        external\n        view\n        override\n        returns (address receiver, uint256 royaltyAmount)\n    {\n        return (royaltyRecipient, (salePrice * royaltyFee) \u002F 10000);\n    }\n\n    function setRoyalty(address recipient, uint96 fee) external onlyOwner {\n        require(fee \u003C= 1000, \"Royalty fee too high\"); \u002F\u002F Max 10%\n        royaltyRecipient = recipient;\n        royaltyFee = fee;\n    }\n\n    function supportsInterface(bytes4 interfaceId)\n        public\n        view\n        override(ERC721, IERC165)\n        returns (bool)\n    {\n        return interfaceId == type(IERC2981).interfaceId ||\n               super.supportsInterface(interfaceId);\n    }\n}\n```\n\n## Soulbound Tokens (Non-Transferable)\n\n```solidity\ncontract SoulboundToken is ERC721 {\n    constructor() ERC721(\"Soulbound\", \"SBT\") {}\n\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 tokenId,\n        uint256 batchSize\n    ) internal virtual override {\n        require(from == address(0) || to == address(0), \"Token is soulbound\");\n        super._beforeTokenTransfer(from, to, tokenId, batchSize);\n    }\n\n    function mint(address to) external {\n        uint256 tokenId = totalSupply() + 1;\n        _safeMint(to, tokenId);\n    }\n\n    \u002F\u002F Burn is allowed (user can destroy their SBT)\n    function burn(uint256 tokenId) external {\n        require(ownerOf(tokenId) == msg.sender, \"Not token owner\");\n        _burn(tokenId);\n    }\n}\n```\n\n## Dynamic NFTs\n\n```solidity\ncontract DynamicNFT is ERC721 {\n    struct TokenState {\n        uint256 level;\n        uint256 experience;\n        uint256 lastUpdated;\n    }\n\n    mapping(uint256 => TokenState) public tokenStates;\n\n    function gainExperience(uint256 tokenId, uint256 exp) external {\n        require(ownerOf(tokenId) == msg.sender, \"Not token owner\");\n\n        TokenState storage state = tokenStates[tokenId];\n        state.experience += exp;\n\n        \u002F\u002F Level up logic\n        if (state.experience >= state.level * 100) {\n            state.level++;\n        }\n\n        state.lastUpdated = block.timestamp;\n    }\n\n    function tokenURI(uint256 tokenId) public view override returns (string memory) {\n        TokenState memory state = tokenStates[tokenId];\n\n        \u002F\u002F Generate metadata based on current state\n        return generateMetadata(tokenId, state);\n    }\n\n    function generateMetadata(uint256 tokenId, TokenState memory state)\n        internal\n        pure\n        returns (string memory)\n    {\n        \u002F\u002F Dynamic metadata generation\n        return \"\";\n    }\n}\n```\n\n## Gas-Optimized Minting (ERC721A)\n\n```solidity\nimport \"erc721a\u002Fcontracts\u002FERC721A.sol\";\n\ncontract OptimizedNFT is ERC721A {\n    uint256 public constant MAX_SUPPLY = 10000;\n    uint256 public constant MINT_PRICE = 0.05 ether;\n\n    constructor() ERC721A(\"Optimized NFT\", \"ONFT\") {}\n\n    function mint(uint256 quantity) external payable {\n        require(_totalMinted() + quantity \u003C= MAX_SUPPLY, \"Exceeds max supply\");\n        require(msg.value >= MINT_PRICE * quantity, \"Insufficient payment\");\n\n        _mint(msg.sender, quantity);\n    }\n\n    function _baseURI() internal pure override returns (string memory) {\n        return \"ipfs:\u002F\u002FQmBaseHash\u002F\";\n    }\n}\n```\n\n## Resources\n\n- **references\u002Ferc721.md**: ERC-721 specification details\n- **references\u002Ferc1155.md**: ERC-1155 multi-token standard\n- **references\u002Fmetadata-standards.md**: Metadata best practices\n- **references\u002Fenumeration.md**: Token enumeration patterns\n- **assets\u002Ferc721-contract.sol**: Production ERC-721 template\n- **assets\u002Ferc1155-contract.sol**: Production ERC-1155 template\n- **assets\u002Fmetadata-schema.json**: Standard metadata format\n- **assets\u002Fmetadata-uploader.py**: IPFS upload utility\n\n## Best Practices\n\n1. **Use OpenZeppelin**: Battle-tested implementations\n2. **Pin Metadata**: Use IPFS with pinning service\n3. **Implement Royalties**: EIP-2981 for marketplace compatibility\n4. **Gas Optimization**: Use ERC721A for batch minting\n5. **Reveal Mechanism**: Placeholder → reveal pattern\n6. **Enumeration**: Support walletOfOwner for marketplaces\n7. **Whitelist**: Merkle trees for efficient whitelisting\n\n## Marketplace Integration\n\n- OpenSea: ERC-721\u002F1155, metadata standards\n- LooksRare: Royalty enforcement\n- Rarible: Protocol fees, lazy minting\n- Blur: Gas-optimized trading\n",{"name":5,"risk":27,"source":25,"date_added":35,"description":7},"2026-02-27","main","7a38d8e7073e61c16eda85681cb32fb68a8657a5","skills-store\u002Fcopilot\u002Fnft-standards","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router","https:\u002F\u002Fgithub.com\u002Fsapsapshen","2026-04-14 21:12:12",{"source":8,"skillName":5,"commands":43,"prompt":53,"zipAvailable":54},[44,47,50],{"tool":45,"command":46},"npx","npx skills add sapsapshen\u002Fai-memory-router --skill nft-standards",{"tool":48,"command":49},"bunx","bunx skills add sapsapshen\u002Fai-memory-router --skill nft-standards",{"tool":51,"command":52},"pnpm","pnpm dlx skills add sapsapshen\u002Fai-memory-router --skill nft-standards","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fcopilot\u002Fnft-standards\u002FSKILL.md",true,[],[57,81,107,117,130,149],{"skillNo":58,"name":59,"nameZh":6,"description":60,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":61,"categories":62,"keywords":68,"publishedAt":30},"01M71ATQRKG48SH06FQ697T5G9","wechat-search","Search WeChat Official Account articles using OpenClaw's web search and fetch capabilities with compliance-focused design.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fwechat-search-release\u002FSKILL.md",[63],{"categoryNo":64,"categoryName":65,"taxonomyType":66,"taxonomyTypeDesc":67},"01JBSEEDCAT000000000000037","律师与法务","PROFESSION","适用职业",[69,70,71,72,73,74,75,76,77,78,79,80],"wechat search","wechat","search","capabilities","openclaw","design","web search","compliance","web","official","fetch","with",{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":30},"01M71ATNAVGZB35PFYM2GC5N00","trend-tap","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend tap', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-tap\u002FSKILL.md",[],[88,89,90,91,92,93,71,94,95,96,97,98,99,100,101,102,103,104,105,106],"trend","trend tap","tap","api keys","Bash","time","trending","hacker","aggregator","do","when","brew","live","data","google","install","read","across","api",{"skillNo":108,"name":109,"nameZh":6,"description":110,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":111,"categories":112,"keywords":113,"publishedAt":30},"01M71ATJ9AM5KM15AA8PS302EB","trend-radar","Real-time trending topics aggregator across 7 platforms (X\u002FTwitter, Reddit, Google Trends, Hacker News, Zhihu, Bilibili, Weibo). Trigger: when user says 'trend', 'trends', 'trend pulse', '热点', '热搜', or asks what is trending\u002Fhot. Do NOT use web_search — this skill already fetches live data from all platforms with zero API keys.","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftrend-radar\u002FSKILL.md",[],[114,115,88,99,100,101,102,92,71,104,116,105,106,98,96,95,94,103,93,91],"trend radar","radar","pulse",{"skillNo":118,"name":119,"nameZh":6,"description":120,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":123,"publishedAt":30},"01M71ATGF095N3EJM9G8SD0BB5","tech-news-daily","每日科技新闻汇——从全球多个 RSS 源抓取最新科技新闻，翻译（英→中）、去重、排版成每日简报。当用户询问科技新闻、科技新鲜事、每日科技、技术动态、Daily Tech News 或类似表达时触发此技能。","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Ftech-news-daily\u002FSKILL.md",[],[124,125,126,127,128,129],"news","tech","tech news daily","daily","rss","翻译",{"skillNo":131,"name":132,"nameZh":6,"description":133,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":134,"categories":135,"keywords":141,"publishedAt":30},"01M71ATFAEAMQ17M70NQNY7SR8","summarize","Summarize URLs or files with the summarize CLI (web, PDFs, images, audio, YouTube).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsummarize\u002FSKILL.md",[136],{"categoryNo":137,"categoryName":138,"taxonomyType":139,"taxonomyTypeDesc":140},"01JBSEEDCAT000000000000021","资料检索与研究","SCENARIO","使用场景",[132,77,142,143,144,80,99,145,146,147,90,148,103],"Audio","cli","youtube","images","https","files","pdfs",{"skillNo":150,"name":151,"nameZh":6,"description":152,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":153,"categories":154,"keywords":155,"publishedAt":30},"01M71ATDNS3R0M4H936PACQAWZ","sonoscli","Control Sonos speakers (discover\u002Fstatus\u002Fplay\u002Fvolume\u002Fgroup).","https:\u002F\u002Fgithub.com\u002Fsapsapshen\u002Fai-memory-router\u002Fblob\u002Fmain\u002Fskills-store\u002Fopenclaw\u002Fsonoscli\u002FSKILL.md",[],[151,156,157,158,103,159,146,160,161,162,163,164],"status","play","go","latest","github","discover","control","cmd","volume"]