{"author":{"address":null,"user":"https://learnblockchain.cn/people/18158"},"content":{"body":"# 前言\r\n\u003e 本文主要依托于openzeppelin库实现一个ERC1155标准的代币，包含了合约的开发，测试，部署以及和ERC20标准,ERC721标准的区别和使用场景分析。\r\n# ERC20、ERC721、ERC1155标准\r\n#### 特点\r\n* **ERC20标准**：同质化、可分割性、标准化、兼容性、流通性;\r\n* **ERC721标准**：非同质化、不可分割性、所有权验证、元数据、稀缺性;\r\n* **ERC1155标准**：多功能性、效率、灵活性、批量操作、兼容性、安全性;\r\n#### 使用场景\r\n* **ERC20标准**：ERC-20代币广泛应用于ICO、代币化资产、DApp的实用代币、去中心化自治组织(DAO)的治理代币，以及作为在以太坊生态系统内转移价值的手段\r\n\r\n* **ERC721标准**：ERC-721代币被广泛应用于各类NFT项目中，包括数字艺术、游戏内资产、数字收藏品、虚拟地产等\r\n\r\n* **ERC1155标准**：ERC-1155代币标准提供了更为高效的代币管理方式，适用于需要在同一合约中管理多种资产的场景；\r\n\r\n#### 标准区别\r\n* **ERC20标准**：同质化代币，具有可分割性以及可替代性，类似于货币；\r\n* **ERC721标准**：非同质化代币，具有不可分割性以及不可替代性，类似于艺术品；\r\n* **ERC1155标准**：在一个合约中包装多个同质化与非同质化代币，提供了更灵活高效的搭配；\r\n#### ERC1155合约\r\n**合约功能**：铸造，销毁，批量销毁和铸造，转账、查看、验证等相关的功能；\r\n```\r\n// SPDX-License-Identifier: MIT\r\n// Compatible with OpenZeppelin Contracts ^5.0.0\r\npragma solidity ^0.8.22;\r\n\r\nimport {ERC1155} from \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\r\nimport {ERC1155Burnable} from \"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Burnable.sol\";\r\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\r\n\r\ncontract GameToken is ERC1155, Ownable, ERC1155Burnable {\r\n    constructor(address initialOwner)\r\n        ERC1155(\"ipfs://QmcN49MKt4MbSXSGckAcpvFqtea43uuPD2tvmuER1mG67s\")\r\n        Ownable(initialOwner)\r\n    {}\r\n\r\n    function setURI(string memory newuri) public onlyOwner {\r\n        _setURI(newuri);\r\n    }\r\n\r\n    function mint(address account, uint256 id, uint256 amount, bytes memory data)\r\n        public\r\n        onlyOwner\r\n    {\r\n        _mint(account, id, amount, data);\r\n    }\r\n\r\n    function mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data)\r\n        public\r\n        onlyOwner\r\n    {\r\n        _mintBatch(to, ids, amounts, data);\r\n    }\r\n}\r\n\r\n```\r\n#### ERC1155合约测试\r\n```\r\nconst {ethers,getNamedAccounts,deployments} = require(\"hardhat\");\r\nconst { assert,expect } = require(\"chai\");\r\ndescribe(\"GameToken\",async()=\u003e{\r\n    let GameToken;//合约\r\n    let addr1;//第一个账户\r\n    let addr2;//第二个账户\r\n    let firstAccount//第一个账户\r\n    let secondAccount//第二个账户;\r\n    let mekadata=\"ipfs://QmcN49MKt4MbSXSGckAcpvFqtea43uuPD2tvmuER1mG67s\"\r\n    let mekadata1=\"ipfs://QmTL5CJsEUGGPxBi3VNYnFebGScrs8ANa5aeK98QGb5Prn\"\r\n    let tokenId=0;\r\n    beforeEach(async()=\u003e{\r\n        await deployments.fixture([\"gametoken\"]);\r\n        [addr1,addr2]=await ethers.getSigners();\r\n        firstAccount=(await getNamedAccounts()).firstAccount;\r\n        secondAccount=(await getNamedAccounts()).secondAccount;\r\n        const GameTokenDeployment = await deployments.get(\"GameToken\");\r\n        GameToken = await ethers.getContractAt(\"GameToken\",GameTokenDeployment.address);//已经部署的合约交互\r\n    })\r\n    describe(\"GameToken测试用例\",async()=\u003e{\r\n        it(\"测试用例\",async()=\u003e{\r\n            const owner = await GameToken.owner();\r\n            console.log(\"owner\",owner)\r\n            //修改URI\r\n            await GameToken.setURI(mekadata1);\r\n            console.log(await GameToken.uri(0))\r\n            //铸造说明如果数量是1是非同质化代币，数量大于1是同质化代币\r\n            //铸造单个 参数说明：地址，tokenid，数量，唯一标识或其他参说\r\n            await GameToken.mint(firstAccount,0,100,'0x11');\r\n            console.log(\"tokenid 为0\",await GameToken.balanceOf(firstAccount,0))\r\n            //销毁单个 销毁tokenid为0的10个\r\n            await GameToken.burn(firstAccount,0,10);\r\n            //查看余额为90\r\n            console.log('销毁后firstAccount查看余额',await GameToken.balanceOf(firstAccount,0))\r\n            await GameToken.mint(firstAccount,1,1,'0x11');\r\n            console.log(\"tokenid 为1\",await GameToken.balanceOf(firstAccount,1))\r\n            //返回的value为0说明不存在\r\n            console.log(\"tokenid 为3不存在\",await GameToken.balanceOf(firstAccount,3))\r\n            //批量铸造\r\n            await GameToken.mintBatch(firstAccount,[2,3,4],[200,300,400],'0x22');\r\n            console.log(firstAccount)\r\n            //addr数字和id的数组长度必须一致 返回余额的数组\r\n            console.log(\"tokenid 为数组\",await GameToken.balanceOfBatch([firstAccount,firstAccount,firstAccount],[2,3,4]))\r\n            //批量销毁 tokenid为2,3,4的100个\r\n            await GameToken.burnBatch(firstAccount,[2,3,4],[100,100,100]);\r\n            //查看firstAccount余额为 100,200,300\r\n            console.log('销毁后firstAccount查看余额',await GameToken.balanceOfBatch([firstAccount,firstAccount,firstAccount],[2,3,4]))\r\n            //单个转账 \r\n            //把tokenid为1的转给secondAccount\r\n            await GameToken.safeTransferFrom(firstAccount,secondAccount,1,1,'0x');\r\n            console.log(\"firstAccount的余额\",await GameToken.balanceOf(firstAccount,1))\r\n            console.log(\"secondAccount的余额\",await GameToken.balanceOf(secondAccount,1))\r\n            //批量转账\r\n            //把tokenid为2,3的转给secondAccount\r\n            await GameToken.safeBatchTransferFrom(firstAccount,secondAccount,[2,3],[100,200],'0x');\r\n            console.log(\"firstAccount的余额\",await GameToken.balanceOfBatch([firstAccount],[4]))\r\n            console.log(\"secondAccount的余额\",await GameToken.balanceOfBatch([secondAccount,secondAccount,secondAccount],[1,2,3]))\r\n            console.log(await GameToken.uri(4))\r\n        })\r\n    })\r\n})\r\n```\r\n#### ERC1155合约部署\r\n```\r\nmodule.exports = async function ({getNamedAccounts,deployments}) {\r\n    const  firstAccount= (await getNamedAccounts()).firstAccount;\r\n    const {deploy,log} = deployments;\r\n    const GameToken=await deploy(\"GameToken\",{\r\n        from:firstAccount,\r\n        args: [firstAccount],//参数\r\n        log: true,\r\n    })\r\n    console.log(\"gametoken合约\",GameToken.address)\r\n\r\n}\r\nmodule.exports.tags = [\"all\",\"gametoken\"];\r\n# 部署指令\r\n# npx hardhat deploy\r\n```\r\n#### 总结\r\n以上就是基于ERC1155标准实现的综合代币合约，包含了开发、测试、部署流程，在测试文件中对合约单个或批量铸造、销毁、转移代币等相关功能进行相关测试。简单一句话：ERC1155代币就是ERC20和ERC721标准的综合使用。","title":"基于ERC1155标准实现一个代币合约"},"history":null,"timestamp":1740634332,"version":1}