待字閨中開發(fā)了一門區(qū)塊鏈方面的課程:《深入淺出ETH原理與智能合約開發(fā)》,馬良老師講授惫企。此簡書文集記錄我的學(xué)習(xí)筆記撕瞧。
課程共8節(jié)課。其中狞尔,前四課講ETH原理丛版,后四課講智能合約。
第五課分為三部分:
- Dapp用例
- 合約結(jié)構(gòu)
- Solidity語法
這篇文章是第五課第二部分的學(xué)習(xí)筆記:合約結(jié)構(gòu) 偏序。
這節(jié)課主要講解了智能合約結(jié)構(gòu)页畦、ERC20、ERC721規(guī)范研儒。
1豫缨、智能合約結(jié)構(gòu)
1.1 智能合約的結(jié)構(gòu)
智能合約的源代碼由以下7個(gè)部分組成。
版本聲明
在以太坊的solidity編程語言中端朵,各個(gè)大版本之間不具有兼容性好芭,所以需要在開頭聲明版本號。不能在之前或之后的版本中運(yùn)行冲呢,如pragma solidity ^0.4.x舍败,不能在0.3或0.5的系統(tǒng)中運(yùn)行。包含其它代碼文件:import
可以引入其它文件或者庫。合約的定義
使用關(guān)鍵字contract邻薯,后面跟上合約的名字裙戏。contract 合約名存儲(chǔ)狀態(tài)變量
這部分內(nèi)容需要存儲(chǔ)在Storage Root中。(第3課)構(gòu)造函數(shù)
它是一類很特殊的函數(shù)弛说,它在合約被創(chuàng)建的交易中被執(zhí)行一次挽懦,函數(shù)名需要與合約名相同。(與C++的構(gòu)造函數(shù)類似)調(diào)用接口函數(shù)
提供給其它賬戶調(diào)用木人。事件
用于記錄關(guān)鍵這個(gè)步驟與信息信柿。
1.2 智能合約的ABI
開發(fā) DApp 時(shí)要調(diào)用在區(qū)塊鏈上的 Ethereum 智能合約,就需要智能合約的 ABI醒第。ABI(Application Binary Interface)主要是規(guī)范外部賬戶與合約之間二進(jìn)制數(shù)據(jù)的編碼規(guī)范渔嚷。
要調(diào)用一個(gè)合約特定的接口,首先要有合約的地址稠曼。在這個(gè)合約眾多的接口中形病,怎么找到需要調(diào)用的那一個(gè),這就要用到函數(shù)簽名霞幅。函數(shù)的簽名由函數(shù)名與所有參數(shù)類型組成(返回值類型不算在內(nèi))漠吻,編碼的前四個(gè)字節(jié)是函數(shù)簽名的Keccak256 單向散列值的前四字節(jié)。如:function baz(uint32 x, bool y)這個(gè)函數(shù)司恳,其編碼的前四個(gè)字節(jié)是baz(uint32,bool)經(jīng)過Keccak256計(jì)算后途乃,再取前四個(gè)字節(jié)0xcdcd77c0。從第五字節(jié)開始對輸入的實(shí)際調(diào)用參數(shù)進(jìn)行編碼扔傅,并補(bǔ)齊32字節(jié)耍共。比如例子中的x, y分別取值0x88,0x1猎塞,補(bǔ)齊32字節(jié)试读。
1.3 通過 remix 介紹合約結(jié)構(gòu)
1.3.1 一個(gè)小例子
打開remix網(wǎng)站,自帶一個(gè)例子程序荠耽」澈В→Remix
此外,老師的例子開頭處铝量,比我的多了兩行伊履,導(dǎo)入其它文件。分別是導(dǎo)入github上的文件款违,和導(dǎo)入本地的文件唐瀑。
import "github.com/ethereum/dapp-bin/library/iterable-mapping.sol";
import "./test.sol";
1.3.2 solidity中的注釋
有三種。
/*注釋*/
插爹,類似于C語言中的注釋哄辣;
//注釋
请梢,類似于C++中的注釋;
///注釋
力穗,也可以三個(gè)斜杠毅弧,主要用于函數(shù)前,說明函數(shù)作用当窗。
1.3.3 remix的使用
remix是一個(gè)強(qiáng)大的IDE(Integrated Development Environment 够坐,集成開發(fā)環(huán)境)。
中間是代碼區(qū)崖面,右邊有六個(gè)表單元咙。
- Compile
編譯,可以設(shè)置為自動(dòng)編譯巫员,修改后自動(dòng)執(zhí)行庶香。
Detail按鈕可以查看該程序的詳細(xì)信息。點(diǎn)開彈出简识。其中赶掖,METADATA是該程序的元數(shù)據(jù),含有編譯器的版本七扰,和其它的一些數(shù)據(jù)等奢赂。這里關(guān)注一下ABI數(shù)據(jù)。它是關(guān)于接口的颈走,點(diǎn)開具體的接口膳灶,可以看到接口的名字,輸入和輸出等疫鹊。
- Run
運(yùn)行代碼袖瞻。
它提供了三種運(yùn)行環(huán)境司致,自己練習(xí)可以選用JavaScript VM拆吆,在本地運(yùn)行,速度快脂矫。它自動(dòng)提供了5個(gè)賬號枣耀,每個(gè)都含有100ETH。Gas limit是發(fā)起合約的Gas上限庭再;Value是發(fā)送以太幣到一個(gè)合約時(shí)發(fā)送的數(shù)量捞奕。
Deploy布署一個(gè)合約。代碼區(qū)的下面拄轻,有控制臺(tái)可以看到合約執(zhí)行情況颅围。
Settings
設(shè)置。主要是設(shè)置編譯器的版本恨搓。Analysis
分析院促。主要是一些安全性的分析筏养,比如Gas的數(shù)量,使用情況常拓;還有一些雜項(xiàng)渐溶。Debugger
調(diào)試。后面在具體的例子中再介紹弄抬。Support
2茎辐、ERC 20 規(guī)范
前面介紹的DApp例子中,大部分使用了ERC 20 規(guī)范掂恕。
官方文檔:ERC20規(guī)范
這個(gè)規(guī)范有六個(gè)接口是強(qiáng)制必須實(shí)施的拖陆。
- totalSupply()總的供給量
- balanceOf(address tokenOwner)查詢某一地址的余額
- approve(address spender, uint tokens) 代幣擁有者授權(quán)某地址,可以在未來多次從擁有者的賬戶使用代幣竹海。它有一點(diǎn)安全問題慕蔚,即授權(quán)數(shù)量要改變時(shí),需要先改為零斋配,再改為更改的值孔飒。
- allowance(address tokenOwner,address spender)查詢操作,查詢一個(gè)代幣的擁有者艰争,還可以允許支出者花費(fèi)多少代幣坏瞄。這個(gè)跟前面的approve有關(guān)。
- transferFrom(address from, address to,uint tokens) 授權(quán)的地址從擁有者那里花費(fèi)代幣甩卓,也和approve結(jié)合使用鸠匀。花費(fèi)的數(shù)量要小于授權(quán)的數(shù)量逾柿,如果大于則失斪汗鳌;地址輸入錯(cuò)誤机错,也會(huì)失敗爬范。
- transfer(address to, uint tokens) 轉(zhuǎn)移代幣,把自己的代幣移給目標(biāo)地址弱匪。
還有三個(gè)可選操作青瀑。name() , symbol(), decimals(),分別是名稱萧诫,符號斥难,可以分割的程度,如18帘饶,1ETH可以分割為10^18份哑诊。
還有兩個(gè)事件。event Transfer(address from, address to, uint256 value)及刻,event Approval(address owner, address spender, uint256 value)镀裤,分別是記錄Transfer和Approval的操作穷当。
說明一下ERC20規(guī)范的本質(zhì)。它其實(shí)是維護(hù)了兩張表淹禾。
一張是每個(gè)地址對應(yīng)了多少代幣馁菜,如左圖。所有余額加起來就是總的供給量铃岔。轉(zhuǎn)移代幣是把一個(gè)地址的余額減少一定的數(shù)值汪疮,另一個(gè)地址增加相應(yīng)的數(shù)值。查詢余額就是從這張表中查詢毁习。
另一張表是如右圖的樣子智嚷,包含了許可的賬戶及許可額。再說明一下許可(Approval)的意義纺且。假如合約A調(diào)用合約B盏道,如果在調(diào)用前直接把代幣打到B,B收到幣后會(huì)有不執(zhí)行合約的風(fēng)險(xiǎn)载碌,因此不能先直接給B轉(zhuǎn)移代幣猜嘱。ERC20的做法是分為兩步,先授權(quán)B一定額度的代幣嫁艇,B執(zhí)行時(shí)朗伶,從A那里支取代幣。因?yàn)轭~度預(yù)先分配了步咪,所以轉(zhuǎn)移會(huì)成功论皆。
3、ERC 721 規(guī)范
官方文檔:ERC721規(guī)范
ERC 20 和ERC 721 的不同猾漫,可以做一個(gè)類比点晴。ERC 20 可以類比為現(xiàn)實(shí)中的錢幣,你的5塊錢和我的5塊錢是等價(jià)的悯周,沒有什么不同粒督。我們的錢還都可以再細(xì)分。而ERC 721队橙,主要是用在游戲中的道具坠陈,比如以太坊中的加密貓游戲萨惑,你的貓和我的貓是不一樣的捐康。我們的貓也不能分割為半只貓。每只貓都有不同的特性庸蔼,是非同質(zhì)的解总。
在數(shù)據(jù)結(jié)構(gòu)上,其本質(zhì)與ERC 20 沒有太大的區(qū)別姐仅,也是維護(hù)兩張表花枫。具體內(nèi)容如下刻盐。
- balanceOf(address tokenOwner) 一個(gè)地址下的余額;
- ownerOf(uint256 tokenId) 從一個(gè)ID查詢其主人是誰劳翰;
- safeTransferFrom(address from, address to, uint256 tokenId, bytes data) 轉(zhuǎn)換操作敦锌,把代幣轉(zhuǎn)移到合約;
- safeTransferFrom(address from, address to, uint256 tokenId) 轉(zhuǎn)換操作佳簸,把代幣轉(zhuǎn)移到地址乙墙;
- transferFrom(address from, address to, uint256 tokenId) 傳統(tǒng)的轉(zhuǎn)移方式;
3生均、4和5兩種方式的區(qū)別听想,5不檢查接收者是否為一個(gè)合約地址,而3和4會(huì)檢查接收者是否為合約地址马胧,還會(huì)校驗(yàn)地址汉买。
approve(address approved, uint256 tokenId) 授權(quán)某一地址一定的代幣;
METADATA (Name, SYM, URI) 元數(shù)據(jù):名稱佩脊,符號蛙粘,超鏈接。鏈接可以指向一張圖片威彰,如加密貓的外觀圖组题。
setApprovalForAll(address operator, bool approved) external; 允許一個(gè)地址完全控制自己的代幣;
getApproved(uint256 tokenId) 查詢哪個(gè)賬戶有一個(gè)ID的許可權(quán)抱冷;
isApprovedForAll(address owner, address operator) 查詢一個(gè)地址是否擁有一個(gè)地址所有的操作權(quán)崔列。
還有三個(gè)事件,對應(yīng)操作發(fā)生時(shí)負(fù)責(zé)記錄下日志旺遮。
- event Transfer(address indexed from, address indexed to, uint256 tokenId)
- event Approval(address owner, address _approved, uint256 _tokenId)
- evnet ApprovalForAll(address owner, address operator, bool approved)
總結(jié)一下赵讯,這節(jié)課主要介紹了智能合約結(jié)構(gòu)、ERC20耿眉、ERC721規(guī)范边翼,還簡要介紹了Remix的使用。
不足之處鸣剪,請批評指正组底,感謝。