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