(完整版)編寫智能合約_第1頁
(完整版)編寫智能合約_第2頁
(完整版)編寫智能合約_第3頁
(完整版)編寫智能合約_第4頁
(完整版)編寫智能合約_第5頁
已閱讀5頁,還剩12頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

編寫智能合約Solidity源文件Solidity源文件使用的擴展名為.sol。在源文件中,可以使用pragmaSolidity說明編寫代碼時用的編譯器版本。例如:pragmaSolidity八0.4.2;現(xiàn)在,源文件不會低于0.4.2的編譯器版本,也不會用高于0.5.0的編譯器版本進行編譯(第二個條件使用人添加)。智能合約的結構合約就像一^個類(class),其中包含狀態(tài)變量(statevariable)、函數(shù)(function)、函數(shù)修改器(functionmodifier)、事件(event)、結構(structure)和枚舉(enum)。合約還支持繼承,通過在編譯時備份代碼來實現(xiàn)。最后,合約還支持多態(tài)。下面來看一個智能合約的例子:contractSample{//statevariableuint256data;addressowner;eventlogData(uint256dataToLog);modifieronlyOwner(){if(msg.sender!=owner)throw;_;}functionSample(uint256initData,addressinitOwner){data=initData;owner=initOwner;}functiongetData()returns(uint256returnedData){returndata;}functionsetData(uint256newData)onlyOwner{logData(newData);data=newData;上述代碼的工作原理如下:1)使用contract關鍵字聲明一個合約。2)聲明兩個狀態(tài)變量data和owner。data包含一些數(shù)據(jù),owner包含所有者的以太坊錢包地址,即部署合約者的以太坊地址。3)定義一個事件(event)。事件用于通知客戶端。一旦data發(fā)生變化,將觸發(fā)這個事件。所有事件都保存在區(qū)塊鏈中。4)定義一個函數(shù)修改器functionmodifier)。修改器用于在執(zhí)行一個函數(shù)之前自動檢測條件。這里,修改器檢測合約所有者是否在調用函數(shù)。如果不是,就拋出異常。5)得到合約構造函數(shù)(constructor)。在部署合約時,調用構造函數(shù)。構造函數(shù)用于初始化狀態(tài)變量。6)定義兩個方法。第一個方法用于得到data狀態(tài)變量的值,第二個方法用于改變data的值。在更深入地學習智能合約的函數(shù)之前,我們先來學習一些與Solidity有關的其他知識,然后再回答合約。3數(shù)據(jù)位置截止目前,我們學過的所有編程語言可能都把變量存儲在內存中。但是在Solidity中,根據(jù)情況的不同,變量可能不存儲在內存和文件系統(tǒng)中。根據(jù)情況的不同,數(shù)據(jù)總有一個默認位置。但是對于復雜數(shù)據(jù)類型,例如字符串(string)、數(shù)組(array)和結構類型(struct),可以用向類型添加storage或者memory進行重寫。函數(shù)參數(shù)(包括返回參數(shù))默認用memory,本地變量默認用storage.顯然,對于狀態(tài)變量來說,位置強制用storage。數(shù)據(jù)位置很重要,因為它們會改變分配的行為:storage變量和memory變量之間的分配總是創(chuàng)建一個獨立的備份。但如果分配是從memory存儲的一種復雜類型到另一種復雜類型,則不創(chuàng)建備份。到一個狀態(tài)變量的分配(即使是來自其他狀態(tài)變量)總是創(chuàng)建一個獨立的備份。不能把memory中國存儲的復雜類型分配給本地存儲變量。在分配狀態(tài)變量和本地存儲變量的情況下,本地存儲變量指向狀態(tài)變量,也就是說,本地存儲變量變?yōu)橹羔槨?什么是不同的數(shù)據(jù)類型Solidity是一種靜態(tài)類型語言,變量存儲的數(shù)據(jù)類型需要預先定義。所有變量默認都是0。在Solidity中,變量是有函數(shù)作用范圍的,在函數(shù)中任何地方聲明的變量將對整個函數(shù)存在適用范圍,無論它是在哪里聲明的?,F(xiàn)在讓我們看看Solidity提供的不同數(shù)據(jù)類型:最簡單的數(shù)據(jù)類型是布爾值,可以是true或者false。uint8,uint16,uint24,...,uint256分別用于存儲無符號的8位,16位,24位,...246位整數(shù)。同理,int8,int16,...,int256分別用于存儲8位,16位,24位..,256位整數(shù)。uint和int是uint256和int256的別名。類似于uint和int,ufixed和fixed代碼分數(shù)。ufixed0x8,ufixed0x16,...,ufixed0x256分別用于存儲未簽名的8位,16位,24位,...,256位分數(shù)。同理,fixed0x8,fixed0x16,...,fixed0x256分別用于存儲8位,16位,24位,...,256位分數(shù)。如果一個數(shù)字超過256位,則使用256位數(shù)據(jù)類型存儲該數(shù)字的近似值。?address可以用于存儲最大20字節(jié)的值(十六進制表示)。它用于存儲以太坊地址。address類型有兩個屬性:balance和send。balance用于檢測地址余額,send用于向地址發(fā)送以太幣。send方法拿出需要轉賬的那些數(shù)量的wei,并根據(jù)轉賬是否成功返回ture或者false。wei從調用send方法的合約中扣除。用戶可以在Solidity中使用0x前綴給變量分配一個十六進制的數(shù)值。數(shù)組類型Solidity支持generic和byte兩種數(shù)組類型。它們支持固定長度和動態(tài)長度兩種數(shù)組,也支持多維數(shù)組。bytesLbytes2,bytes3,…,bytes32是字節(jié)數(shù)組的類型。byte是bytes1的別名。下面給出了generic數(shù)組語法的一個示例:constractsample{int[]myArray=[0,0];functionsample(uintindex,intvalue){myArray[index]=value;int[]myArray2=myArray;uint24[3]memorymyArray3=[1,3,9999];uint8[2]myArray4=[1,2];}}關于數(shù)組的重要內容如下:數(shù)組還有l(wèi)ength屬性,用于發(fā)現(xiàn)數(shù)組的長度。用戶還可以給length屬性分配一個值,以改變數(shù)組的大小,但不可以在內存中改變數(shù)組的大小,也不同可以改變非動態(tài)數(shù)組的大小。如果想訪問動態(tài)數(shù)組的微設置索引(unsetindex),會拋出異常。array、structs和map都不可以作為函數(shù)參數(shù),也不可以用作函數(shù)返回值。字符串類型在Solidity中,有兩種方法創(chuàng)建字符串:使用bytes和string。bytes用于創(chuàng)建原始字符串,而string用于創(chuàng)建UTF-8字符串。字符串長度總是動態(tài)的。下面給出了字符串語法的一個示例:constractsample{stringmyString=“”;bytesmyRawString;functionsample(stringinitString,bytesrawStringInit){myString=initString;stringmyString2=myString;stringmemorymyString3=“ABCDE”;myString3=“XYZ”;myRawString=rawStringInit;myRawString.length++;stringmyString4=“Example”;//throwsexceptionwhilecompilingstringmyString5=initString;//throwsexceptionwhilecompiling}}結構類型Solidity還支持結構類型(struct)。下面給出了struct語法的一^個示例:contractsample{structmyStruct{boolmyBool;stringmyString;}myStructs1;myStructs2=myStruct(true,””);functionsample(boolinitBool,stringinitString){s1=myStruct(initBool,initString);myStructmemorys3=myStruct(initBool,initString);}}函數(shù)參數(shù)不可以是結構類型,且函數(shù)不可以返回結構類型。枚舉類型Solidity還支持枚舉類型(enum)。下面給出了enum語法的一^個示例:contractsample{enumOS{Windows,Linux,OSX,UNIX}OSchoice;functionsample(OSchosen){choice=chosen;}functionsetLinuxOS(){choice=OS.Linux;}functiongetChoice()returns(OSchosenOS){returnchoice;mapping類型mapping數(shù)據(jù)類型是一^個哈希表。mapping類型只可以存在與storage中,不存在與memory中,因此它們是作為狀態(tài)變量聲明的??梢哉J為mapping類型包含key/value對,不是時間存儲key,而是存儲key和keccak256哈希,用于查詢value。mapping類型沒有長度。mapping不可以被分配給另一^個mapping。下面給出一^個創(chuàng)建和使用mapping的示例:contractsample{mapping(int=>string)myMap;functionsample(intkey,stringvalue){myMap[key]=value;mapping(int=>string)myMap2=myMap;}}如果想訪問mapping中不存在的key,返回的value均為0。delete操作符delete操作符可以用于任何變量,將其設置成默認值。默認值均為0.如果對動態(tài)數(shù)組使用delete操作符,則刪除所有元素,其長度變?yōu)?。如果對靜態(tài)數(shù)組使用delete操作符,則重置所有索引。還可以通過對特定索位置使用delete來重置索引。如果讀map類型使用delete操作符,什么都不會發(fā)生。但是如果對map類型的一個鍵使用delete操作符,則會刪除與該鍵相關的值。下面給出了delete操作符的一^個示例:contractsample{structStruct{mapping(int=>int)myMap;intmyNumber;}int[]myArray;StructmyStruct;functionsample(intkey,intvalue,intnumber,int[]array){myStruct=Struct(number);myStruct.myMap[key]=value;myArray=array;}functionreset(){deletemyArray;deletemyStruct;}functiondeleteKey(intkey){deletemyStruct.myMap[key];}}基本類型之間的轉換除了數(shù)組類型、字符串類型、結構類型、枚舉類型和map類型外,其他類型均稱為基本類型。如果把一個操作符應用與不同的類型,編譯器將嘗試把一個操作數(shù)隱式轉換微另一種類型。通常來說,如果沒有語義信息丟失,值和類型之間可以進行隱式轉換:uint8可轉換微uint16,uint128可轉換微int256,但int8不可轉換微uint256(因為uint256不能存儲,例如-1)。此外,無符號整數(shù)可以轉換成同等大小或更大的字節(jié),但是反之則不然。任何可以轉換成uint160的類型都可以轉換成地址。Solidity也支持顯示轉換,所以如果編譯器不允許在兩種兩種數(shù)據(jù)類型之間隱式轉換,則可以進行顯示轉換。建議盡量避免顯式轉換,因為可能返回難以預料的結果。來看一個例子:uint32a=0x12345678;uint16b=uint16(a);//bwillbe0x5678now這里是將uint32類型顯示轉換微uint16,也就是說,把較大類型轉換為較小類型,因此高位被砍掉了。使用varSolidity提供了用于聲明變量的var關鍵字。變量類型根據(jù)分配給它的第一個值來動態(tài)確定。一旦分配了值,類型劇固定了,所以如果給它知道另一類型,將引起類型轉換。示例如下:int256x=12;vary=x;uint256z=9;y=z;在定義數(shù)組array和map時不能使用var。var也不能用于定義函數(shù)參數(shù)和狀態(tài)變量。5控制結構solidity支持if/else/while/for/break/continue/return?:等控制結構。下面給出了控制結構的一個示例:constractsample{inta=12;int[]b;functionsample(){if(a==12){}esleif(a==34){}else{}vartemp=10;while(temp<20){if(temp==17){break;}else{continue;}temp++;}for(variii=0;iii<b.length;iii++){}}}6用new操作符創(chuàng)建合約一個合約可以使用new關鍵字來創(chuàng)建一個新合約,但前提示必須知道新創(chuàng)建的合約的完整代碼。示例如下:contractsample1{inta;functionassign(intb){a=b;}}contractsample2{functionsample2(){sample1s=newsample1();s.assign(12);7異常在一些情況下,異常會被自動拋出。也可以使用throw手動拋出異常。拋出異常會停止回滾目前執(zhí)行的調用(也就是說,撤銷對狀態(tài)和余額的所有改變)。捕獲異常是不可能的:constractsample{functionmyFunction(){throw;}}8外部函數(shù)調用在Solidity中,有兩種函數(shù)調用:內部函數(shù)調用和外部函數(shù)調用。內部函數(shù)調用是指一個函數(shù)在同一個合約中調用另一個函數(shù)。示例如下:contractsample1{inta;functionsample1(intb)payable{a=b;}functionassign(intc){a=c;}functionmakePayment(intd)payable{a=d;}}contractsample2{sample1s=(newsample1).value(12)(23);s.makePayment(22);s.makePayment.value(45)(12);s.makePayment.value(4).gas(900)(12);this.hello();sample1s2=sample1(addressOfContract);s2.makePayment(112);}使用this關鍵字進行的調用稱為外部調用。在函數(shù)中,this關鍵字代表當前合約實例。9合約功能現(xiàn)在是時候深入學習合約了。我們將看看一些新的功能,還將深入學習已經見過的一些功能。可見性函數(shù)或者狀態(tài)變量的可見性定義了誰可以看到它。函數(shù)和狀態(tài)變量的四種可見性:external/public/internal和private函數(shù)可見性默認為public,狀態(tài)變量可見性默認為internal。各可見性函數(shù)的含義如下:external。外部函數(shù)只能有其他合約調用,或者通過交易調用。外部函數(shù)f不能被內部函數(shù)調用,也就是說,f()沒有用,但this.f()有用。不能把external可見性應用到狀態(tài)變量。public。公共函數(shù)和狀態(tài)變量可以用所有可行辦法訪問。編譯器生成的存取器(accessor)函數(shù)都是公共狀態(tài)變量。用戶不能創(chuàng)建自己的存取器。事實上,它只生成getters,而不生成settersointernal。內部函數(shù)和狀態(tài)變量只可以內部訪問,也就是說,從當前合約內核繼承它的合約訪問。不可以使用this訪問它。private。私有函數(shù)和狀態(tài)變量類似于內部函數(shù),但是繼承合約部可以訪問它們。下面給出了可見性和存取器(accessor)的一個示例:contractsample1{intpublicb=78;intinternalc=90;functionsample1(){this.a();a();b=21;this.b;this.b();this.b(8);this.c();c=9;}functiona()external{}}contractsample2{intinternald=9;intprivatee=90;}contractsample3issample2{sample1s;functionsample3(){s=newsample1();s.a();varf=s.b;s.b=18;s.c();d=8;e=7;}}函數(shù)修改器我們之前看到了函數(shù)修改器(functionmodifier)的概念,還編寫了一個基本的函數(shù)修改器,現(xiàn)在來深入學習修改器。修改器由子合約(childcontract)繼承,且子合約可以對其重寫??梢酝ㄟ^用空格分隔的列表指定修改器將多個修改器應用到一個函數(shù),并將多個修改器按順序估值;還可以像修改器傳送實參。在修改器中,無論下一個修改器或者函數(shù)體二者哪個先到達,會白插入到”_”;出現(xiàn)的地方。讓我們來看一個函數(shù)修改器的復雜代碼例子:contractsample{inta=90;modifiermyModifier1(intb){intc=b;_;c=a;a=8;}modifiermyModifier2{intc=a;_;}modifiermyModifier3{a=96;return;_;a=99;modifiermyModifier4{intc=a;_;}functionmyFunction()myModifier1(a)myModifier2myModifier3return(intd){a=1;returna;}}myFunction()的執(zhí)行代碼如下:intc=b;intc=a;a=96;return;intc=a;a=1;returna;a=99;c=a;a=8;在上述代碼中調用myFunction()方法時,將返回。.但是之后返回狀態(tài)變量a時,將得到8.修改器或者函數(shù)體中的return(返回)立即離開整個函數(shù),返回值被分配成它需要成為的任何變量。就函數(shù)來說,return之后的代碼在調用者的代碼完成運行后再執(zhí)行,就修改器來說,上述修改器中的_;之后的代碼在調用者的代碼完成運行后在執(zhí)行。在上面的例子中,第5、6和7行從未執(zhí)行過。在第4行之后,執(zhí)行從第8-10行開始。修改器中的return不可以有相關值,它總是返回全0?;赝撕瘮?shù)一個合約可以有唯一的未命名函數(shù),稱為回退函數(shù)(fallbackfunction)。該函數(shù)不能有實參,不能返回任何值。如果其他函數(shù)都不能匹配給定的函數(shù)標識符,就在合約上執(zhí)行回退函數(shù)。當合約不用任何函數(shù)調用及接受以太幣(即交易發(fā)生以太幣給合約卻不調用任何方法)時,也執(zhí)行該函數(shù)。在此情況下,用于函數(shù)調用的gas通常很少(準確地說是2300gas),所以使回退函數(shù)盡可能便宜很重要。接收以太幣但是卻不定義回退函數(shù)的合約會拋出異常,把以太幣發(fā)送回去,所以如果你想讓你的合約接收以太幣,就必須要實現(xiàn)回退函數(shù)。下面給出了回退函數(shù)的一個示例:constructsample{function()payable{//keepanoteofhowmuchEtherhasbeensentbywhom繼承Slidity通過代碼備份(包括多態(tài))支持多重繼承(multipleinheritance)。即使一^個合約繼承自其它多個合約,在區(qū)塊鏈上值創(chuàng)建一個合約,來自父合約(parentcontract)的代碼總是被復制到最終合約里。示例如下:contractsample1{functiona(){}functionb(){}}contractsample2issample1{functionb(){}}contractsample3{functionsample3(intb){}}contractsample4issample1,sample2{functiona(){}functionc(){a();sample1.a();b();}}contractsample5issample3(122){}super關鍵字super關鍵字用于引用最終繼承鏈中的下一個合約,示例如下:constractsample1{}constractsample2{}constractsample3issample2{}constractsample4issample2{}contractsample5issample4{functionmyFunc(){}}contractsample6issample1,sample2,sample3,sample5{functionmyFunc(){super.myFunc();}}其中,弓I用sample6合約的最終繼承鏈式sample6,sample5,sample4,sample2,sample3和samplel。繼承鏈始于衍生最充分的合約,終于衍生最不充分的合約。抽象合約僅包含函數(shù)原型而不包含函數(shù)實現(xiàn)的合約稱為抽象合約(abstractcontract)。這些合約不能被編譯(即使包含實現(xiàn)函數(shù)和非實現(xiàn)函數(shù))。如果一個合約繼承自抽象合約且不重寫并實現(xiàn)所有非實現(xiàn)函數(shù),那么它自己也是抽象的。抽象合約僅在創(chuàng)建編譯器已知的接口時提供。這在弓用已部署的合約和調用器函數(shù)時很有用的。示例如下:contractsample1{functiona()returns(intb);}constractsample2{functionmyFunc(){sample1s=sample1(0x...);s.a();}}10庫庫類似于合約,但其目的是在一個特定地址只部署一次,且器代碼有不同合約反復使用。這意味著如果調用庫函數(shù),其代碼在調用合約(callingcontract)中執(zhí)行,也就是說,1川5指向調用合約,特別是來自調用合約的storage可以被訪問。由于庫是源代碼中獨立的一部分,它只能訪問調用合約的狀態(tài)變量,因此這些變量是顯示的(否則無法命名這些變量)。庫沒有狀態(tài)變量一它們不支持繼承,也不能接收以太幣。庫可以包含結構類型(struct)和枚舉類型(enum)。一旦在區(qū)塊鏈中部署Solidity庫,任何知道器地址和源代碼(紙質的原型或者知道完整實現(xiàn))的人都可以使用它。Solidity編譯器需要有源代碼,這能確保所訪問的方法在庫中真實存在。示例如下:librarymath{functionaddInt(inta,intb)returns(intc){returna+b;}}contractsample{functiondata()returns(intd){returnmath.addInt(1,2);}}不能在合約源代碼中添加庫地址,而是需要在編譯時想編譯器提供庫地址。庫有許多使用示例。兩個主要的示例如下:如果有許多合約,它們有一些共同代碼,則可以把共同代碼部署成一個庫。這樣節(jié)省gas,因為gas也依賴于合約的規(guī)模。因此,可以把庫想象成使用其合約的基礎合約。使用基礎合約(而非庫)切分共同代碼不會節(jié)省gas,因為在solidity中,繼承通過復制代碼工作。由于庫被當做基礎合約,庫里面帶有內部可視化的函數(shù)被復制給使用它的合約;否則,庫里面帶有內部可視性的函數(shù)不能被使用這個庫的合約調用,因為這需要外部調用,而帶有內部可是性的函數(shù)不能通過外部調用被調用。此外,庫里的structs和enums被復制給使用這個庫的合約。庫可擁有被數(shù)據(jù)類型添加成員函數(shù)。如果一個庫只包含內部函數(shù)和/或structs/enums則不需要部署庫,因為庫里面的所有內容都被復制給使用它的合約。usingforusingAforB這條指令可用于連接庫函數(shù)(從庫A到任意類型B)。這些函數(shù)將被調用的對象作為它們的第一個參數(shù)接收。usingAfor*的結果表示來自庫A的函數(shù)被連接到所有類型。示例如下:librarymath{structmyStruct1{inta;}structmyStruct2{inta;}functionaddInt(myStruct1storages,intb)returns(intc){returns.a+b;}functionsubInt(myStruct2storages,intb)returns(intc{returns.a+b;

}contractsample{usingmathfor*;math.myStruct1s1;math.myStruct2s2;functionsample(){=math.myStruct1(9);=math.myStruct2(9);s1.addInt(2);s2.addInt(1);}}11返回多值11返回多值Solidity允許函數(shù)返回多值(multiplevalues),示例如下:contractsample{functiona()returns(inta,stringc){return(1,”ss”);}functionb(){intA;stringmemoryB;(A,B)=a();(A,)=a();(,B)=a();}}12導入其他Solidity源文件Solidi

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論