安装openZeppelin
npm install --save-dev @openzeppelin/contracts
创建一个truffle空项目
mkdir FishToken cd FishToken truffle init
在contracts目录下创建基于ERC1155的智能合约FishToken.sol
pragma solidity >=0.6.0 <0.9.0; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; contract FishToken is ERC1155, Ownable { using SafeMath for uint256; uint256 public immutable pricePerFish; uint256 public immutable maxFish; uint256 public totalSupply; bool public isSaleActive; address private immutable reserveAddress; constructor(address _reserveAddress) public ERC1155("Fish") { pricePerFish = 0.029 * 10 ** 18; maxFish = 1000; totalSupply = 1; reserveAddress = _reserveAddress; } function flipSaleState() public onlyOwner { isSaleActive = !isSaleActive; } function setURI(string memory URI) public onlyOwner { _setURI(URI); } function reserveFish(uint256 count) public onlyOwner { require(totalSupply < 100); uint256 mintIndex = totalSupply; if (mintIndex < maxFish) { _mint(msg.sender, mintIndex, count, ""); totalSupply ++; } } function mintFish(uint256 count) public payable { require(isSaleActive, "Sale is not active"); require(totalSupply+1 <= maxFish, "Purchase would exceed max supply of Fish"); require(pricePerFish == msg.value, "Ether value is not correct"); require(count > 0, "Fish count should > 0"); payable(owner()).transfer(msg.value); uint256 mintIndex = totalSupply; if (mintIndex < maxFish) { _mint(msg.sender, mintIndex, count, ""); totalSupply ++; } } }
在migrations目录下创建部署脚本2_deploy_contracts.js
const FishToken = artifacts.require("FishToken"); module.exports = function(deployer) { deployer.deploy(FishToken, "0x4451FbD16a256aEdEd217E4B413966c12B2e52B6"); };部署合约到本地网络
修改配置文件truffle-config.js
module.exports = { networks: { development: { host: "127.0.0.1", // Localhost (default: none) port: 7545, // Standard Ethereum port (default: none) network_id: "*", // Any network (default: none) }, }, };
部署合约
truffle migrate --reset
打开Truffle控制台
truffle console
执行测试
//获取测试账号列表 let accounts = await web3.eth.getAccounts() //获取实例 let instance = await FishToken.deployed() //创建 await instance.reserveFish(1) //查询余额 let balance = await instance.balanceOf(accounts[0],1) balance.toString() //转账 instance.safeTransferFrom(accounts[0], accounts[1], 1, 1, "0x0") //查询余额 balance = await instance.balanceOf(accounts[1],1) balance.toString()部署合约到rinkeby网络 1、在Infura创建项目
Infura是一个托管的以太坊节点集群,可以将你开发的以太坊智能合约部署到infura提供的节点上,而无需搭建自己的以太坊节点。
其实MetaMask背后就是使用了Infura作为以太坊供应商。访问infura网站(https://infura.io),先注册一个帐号。注册完成后登录网站。
- 登录成功后,创建一个Project。
- 点击Project的SETTINGS按钮,选择网络为Ropsten,然后复制服务商的地址,后面需要用到。
npm install @truffle/hdwallet-provider3、修改配置文件truffle-config.js
const HDWalletProvider = require('@truffle/hdwallet-provider'); const fs = require('fs'); const mnemonic = fs.readFileSync("./mnemonic.secret").toString().trim(); module.exports = { networks: { rinkeby: { provider: () => new HDWalletProvider(mnemonic, `https://rinkeby.infura.io/v3/{your infura project ID}`), network_id: 4, // Ropsten's id gas: 5500000, // Ropsten has a lower block limit than mainnet confirmations: 2, // # of confs to wait between deployments. (default: 0) timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) skipDryRun: true // Skip dry run before migrations? (default: false for public nets ) }, }, };4、部署合约
truffle migrate --reset --network rinkeby5、打开truffle控制台
truffle console --network rinkeby6、执行测试
let account1 = "0xdfcB3D55462e20CF6B4f03881234689Ac8234BCD" let account2 = "0xbe27d85f56558d4e01a7ae034567c7cf7e665555" //获取实例 let instance = await FishToken.deployed() //创建 await instance.reserveFish(1) //查询余额 let balance = await instance.balanceOf(account1,1) balance.toString() //转账 instance.safeTransferFrom(account1, account2, 1, 1, "0x0") //查询余额 balance = await instance.balanceOf(account2,1) balance.toString()
在以太坊测试网络查看合约
https://rinkeby.etherscan.io/address/0x854320944cd1a9259477e284979e4e94cec571ae
查看交易
https://rinkeby.etherscan.io/tx/0x1522e8abf91ca03a15c23dc12a3b43382cb6ace35c71a06511e4650fd8884ca8
添加元数据Metadata{ "name": "Herbie Starbelly", "description": "Friendly OpenSea Creature that enjoys long swims in the ocean.", "image": "https://storage.googleapis.com/opensea-prod.appspot.com/creature/50.png", "attributes": [...] }
ERC721和ERC1155合约中的每个token标识符都具有相应的元数据URI,该元数据URI返回有关该项目的其他重要信息,如该项目的名称、图像、描述等。
将元数据JSON保存为文件上传到服务器或者IPFS,将元数据URI配置到合约
//创建实例 let instance = await FishToken.deployed() //设置URI await instance.setURI("http://www.example.com/upload/{id}.json") //获取URI let uri = await instance.uri(1) uri.toString()在OpenSea上查看合约资产
Developer TutorialsThe largest peer-to-peer Non-Fungible Token marketplace. As the leading platform for Ethereum and Polygon NFT's, OpenSea prides itself in offering a first-in-class developer platform consisting of APIs, SDKs, and tutorials.https://docs.opensea.io/docsOpenSea有一个Rinkeby环境,允许开发人员测试他们与OpenSea的集成。
testnets.opensea.iohttps://testnets.opensea.io/导入合约资产
https://rinkeby.opensea.io/get-listed/step-twohttps://rinkeby.opensea.io/get-listed/step-two查看合约上创建的资产
https://testnets.opensea.io/assets//
校验合约项目的元数据
https://testnets-api.opensea.io/asset///validate