一個簡單的以太坊ERC721通證例子
ERC-721 token(通證)是當今的一個熱門話題,隨著 crypto kitties 的出現以及其成功的產生許多其他數字收藏品。 ERC-721標準 已經經歷了幾次迭代,現在或多或少已經到位,所以期待越來越多的玩家進入這個領域。這些不可替代的token(通證)的基本前提是每個token(通證)都是唯一的,因此不能像ERC20通證那樣以1:1的方式進行交換。有許多用例,這些ERC-721代幣可以代表獨特的有形或數字資產,例如房地產,藝術品,寶石等。實際上,數字可收集用例可能是它們的所有最低市場價值用例。
本文的目的
本文將嘗試使用ERC-721標準的 OpenZeppelin 實現以最簡單有用的形式建立ERC-721。我建議檢視上面連結的標準,以便熟悉這些要求,因為它們有時可能隱藏在優秀的OpenZeppelin實現中。這裡還有一篇精彩的 文章 ,深入介紹了ERC-721規範。
專案設定
確保安裝了node,npm和truffle
mkdir erc721 && cd erc721 && truffle init
用以下內容替換truffle.js內容:
// Allows us to use ES6 in our migrations and tests. require('babel-register') require('babel-polyfill') module.exports = { networks: { development: { host: '127.0.0.1', port: 8545, network_id: '*', // Match any network id } }, };
安裝 Ganache 並確保它在8545埠上執行。
然後編譯和遷移:
truffle compile truffle migrate
將資料夾初始化為npm專案:
npm init
安裝zeppelin依賴項:
npm install zeppelin-solidity
token 通證
將以下內容新增到 /contract
作為 MyERC721.sol
:
pragma solidity ^0.4.23; import "../node_modules/zeppelin-solidity/contracts/token/ERC721/ERC721Token.sol"; contract MyERC721 is ERC721Token { constructor (string _name, string _symbol) public ERC721Token(_name, _symbol) { } /** * Custom accessor to create a unique token */ function mintUniqueTokenTo( address _to, uint256 _tokenId, string_tokenURI ) public { super._mint(_to, _tokenId); super._setTokenURI(_tokenId, _tokenURI); } }
將以下內容新增到 /migration
作為 2_erc721_migration.js
:
const MyERC721 = artifacts.require("./MyERC721.sol"); module.exports = async function(deployer) { await deployer.deploy(MyERC721, "MyERC721", "MyERC721") const erc721 = await MyERC721.deployed() };
執行遷移指令碼並驗證它是否正確部署:
Marks-MacBook-Pro:erc721 markmathis$ truffle migrate Using network 'development'. Running migration: 2_erc721_migration.js Deploying MyERC721... ... 0x25c26fd5b79b6328bee75bd34d78b37ff9389aad2d487600d46595adf0ee398d MyERC721: 0x6d9b92dfaf3cc3ae2e45b37b584f52f23bc03085 Saving successful migration to network... ... 0x5c147afb3f4c2d225ef3b4cabcd7b9d3b5e4cbab88617fa150b061b85eb4cc0a Saving artifacts...
測試一下
安裝測試庫:
npm install chai --save-dev npm install chai-as-promised --save-dev npm install babel-preset-es2015 --save-dev npm install babel-register --save-dev npm install babel-polyfill --save-dev
將 .babelrc
新增到專案根目錄:
{ "presets": ["babel-preset-es2015"] }
將 erc721.spec.js
新增到 /test
:
import chai from 'chai' import chaiAsPromised from 'chai-as-promised' chai.use(chaiAsPromised) const { expect, assert } = chai var MyERC721 = artifacts.require("MyERC721"); contract('Testing ERC721 contract', function(accounts) { let token; const name = "BlueCat"; const symbol = "BCat" const account1 = accounts[1] const tokenId1 = 1111; const tokenUri1 = "This is data for the token 1"; // Does not have to be unique const account2 = accounts[2] const tokenId2 = 2222; const tokenUri2 = "This is data for the token 2"; // Does not have to be unique const account3 = accounts[3] it(' should be able to deploy and mint ERC721 token', async () => { token = await MyERC721.new(name, symbol) await token.mintUniqueTokenTo(account1, tokenId1, tokenUri1, {from: accounts[0]}) expect(await token.symbol()).to.equal(symbol) expect(await token.name()).to.equal(name) }) it(' should be unique', async () => { const duplicateTokenID = token.mintUniqueTokenTo(account2, tokenId1, tokenUri2, {from: accounts[0]}) //tokenId expect(duplicateTokenID).to.be.rejectedWith(/VM Exception while processing transaction: revert/) }) it(' should allow creation of multiple unique tokens and manage ownership', async () => { const additionalToken = await token.mintUniqueTokenTo(account2, tokenId2, tokenUri2, {from: accounts[0]}) expect(Number(await token.totalSupply())).to.equal(2) expect(await token.exists(tokenId1)).to.be.true expect(await token.exists(tokenId2)).to.be.true expect(await token.exists(9999)).to.be.false // Dummy tokenId expect(await token.ownerOf(tokenId1)).to.equal(account1) expect(await token.ownerOf(tokenId2)).to.equal(account2) }) it(' should allow safe transfers', async () => { const unownedTokenId = token.safeTransferFrom(account2, account3, tokenId1, {from: accounts[2]}) // tokenId expect(unownedTokenId).to.be.rejectedWith(/VM Exception while processing transaction: revert/) const wrongOwner = token.safeTransferFrom(account1, account3, tokenId2, {from: accounts[1]}) // wrong owner expect(wrongOwner).to.be.rejectedWith(/VM Exception while processing transaction: revert/) // Noticed that the from gas param needs to be the token owners or it fails const wrongFromGas = token.safeTransferFrom(account2, account3, tokenId2, {from: accounts[1]}) // wrong owner expect(wrongFromGas).to.be.rejectedWith(/VM Exception while processing transaction: revert/) await token.safeTransferFrom(account2, account3, tokenId2, {from: accounts[2]}) expect(await token.ownerOf(tokenId2)).to.equal(account3) }) })
從專案根目錄執行測試:
truffle test
附錄
幾乎所有常規的ERC20功能都可以在ERC721合約中找到。你可以批准第三方使用你的token(通證),燒錄token(通證)等。功能是相同的,但輸入和幕後發生的事情有點複雜。本文未討論的一些ERC721方法也值得獨立研究:
- safeTransferFrom
- isApprovedForAll
- setApprovedForAll
總結
讓我們回顧一下我們在本文中學到的內容。首先,我們使用truffle設定專案並匯入我們的依賴項,包括世界級智慧合約庫OpenZeppelin。接下來,我們使用OpenZeppelin——ERC721Token模板編寫了ERC721 token(通證)。我們進行了一些檢查以確保我們的合約有效,然後我們設定了一個mocha測試來測試我們的斷言。我們的solidity程式碼看似簡單,我建議更深入地瞭解ERC721標準和OpenZeppelin實現。我們通過建立一個簡單的ERC721 token(通證)來完成我們在本文中的目的,你應該在繼續學習這種新token型別的過程中保持良好的感覺。即使這個token不是很有趣的——我希望你還會繼續玩下去:)
完整的可用專案原始碼在 這裡 。
如果想更深入的瞭解和學習也可以試試我們的ERC721以太坊通證實戰,課程以一個數字藝術品創作與分享DApp的實戰開發為主線,深入講解以太坊非同質化通證的概念、標準與開發方案。內容包含ERC-721標準的自主實現,講解OpenZeppelin合約程式碼庫二次開發,實戰專案採用Truffle,IPFS,實現了通證以及去中心化的通證交易所。
======================================================================
分享一些以太坊、EOS、比特幣等區塊鏈相關的互動式線上程式設計實戰教程:
- java以太坊開發教程,主要是針對java和android程式設計師進行區塊鏈以太坊開發的web3j詳解。
- php以太坊,主要是介紹使用php進行智慧合約開發互動,進行賬號建立、交易、轉賬、代幣開發以及過濾器和交易等內容。
- python以太坊,主要是針對python工程師使用web3.py進行區塊鏈以太坊開發的詳解。
- 以太坊入門教程,主要介紹智慧合約與dapp應用開發,適合入門。
- 以太坊開發進階教程,主要是介紹使用node.js、mongodb、區塊鏈、ipfs實現去中心化電商DApp實戰,適合進階。
- C#以太坊,主要講解如何使用C#開發基於.Net的以太坊應用,包括賬戶管理、狀態與交易、智慧合約開發與互動、過濾器和交易等。
- EOS教程,本課程幫助你快速入門EOS區塊鏈去中心化應用的開發,內容涵蓋EOS工具鏈、賬戶與錢包、發行代幣、智慧合約開發與部署、使用程式碼與智慧合約互動等核心知識點,最後綜合運用各知識點完成一個便籤DApp的開發。
- java比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈儲存、去中心化共識機制、金鑰與指令碼、交易與UTXO等,同時也詳細講解如何在Java程式碼中整合比特幣支援功能,例如建立地址、管理錢包、構造裸交易等,是Java工程師不可多得的比特幣開發學習課程。
- php比特幣開發教程,本課程面向初學者,內容即涵蓋比特幣的核心概念,例如區塊鏈儲存、去中心化共識機制、金鑰與指令碼、交易與UTXO等,同時也詳細講解如何在Php程式碼中整合比特幣支援功能,例如建立地址、管理錢包、構造裸交易等,是Php工程師不可多得的比特幣開發學習課程。
- tendermint區塊鏈開發詳解 ,本課程適合希望使用tendermint進行區塊鏈開發的工程師,課程內容即包括tendermint應用開發模型中的核心概念,例如ABCI介面、默克爾樹、多版本狀態庫等,也包括代幣發行等豐富的實操程式碼,是go語言工程師快速入門區塊鏈開發的最佳選擇。
匯智網原創翻譯,轉載請標明出處。這裡是原文 一個簡單的以太坊ERC721通證例子