Solidity--5.0重大更新

前言

隨著solidity 0.5.0 nightly build版本的穩(wěn)步推進(jìn),正式版也將在不久的將來與開發(fā)者見面.作為一個大版本更新,新版引入了很多特性,也廢棄了很多關(guān)鍵字,比如

.call()不僅可以獲知遠(yuǎn)程調(diào)用執(zhí)行成功與否,還將獲得遠(yuǎn)程調(diào)用執(zhí)行的返回值

ABI解碼做了新的處理規(guī)范,有效防御了”短地址攻擊”

address地址類型細(xì)分成 address和 address payable

uintY和 bytesX不能直接轉(zhuǎn)換

回退函數(shù)必須顯式聲明為 external可見性

構(gòu)造函數(shù)必須用 constructor關(guān)鍵字定義

用于拋出異常的 throw關(guān)鍵字棄用, 函數(shù)狀態(tài)可變性修飾符必須用 view,不能混用 constant和 view

下面我們將對這些改變一一予以介紹,最后給出一個示例代碼,對比展示新舊版solidity代碼寫法的區(qū)別,供大家參考.

顯式聲明

函數(shù)可見性

函數(shù)可見性必須顯式聲明. 之前, 函數(shù)如果不顯式聲明,將默認(rèn) public可見性.

public: constructor構(gòu)造函數(shù)必須聲明為 public可見性,否則編譯報錯.

external: 回退函數(shù)(fallback function), 接口(interface)的函數(shù)必須聲明為 external可見性,否則編譯報錯.

存儲位置

結(jié)構(gòu)體(struct),數(shù)組(array),映射(mapping)類型的變量必須顯式聲明存儲位置( storage, memeory, calldata),包括函數(shù)參數(shù)和返回值變量都必須顯式聲明.

external 的函數(shù)參數(shù)需顯式聲明為 calldata.

合約與地址

contract合約類型不再包括 address類型的成員函數(shù),必須顯式轉(zhuǎn)換成 address地址類型才能使用 send(), transfer(), balance等與之相關(guān)的成員函數(shù)/變量成員.

address地址類型細(xì)分為 address和 address payable,只有 address payable可以使用 transfer(), send()函數(shù).

address payable類型可以直接轉(zhuǎn)換為 address類型, 反之不能.

但是 address x可以通過 address(uint160(x)),強(qiáng)制轉(zhuǎn)換成 address payable類型.

如果 contract A不具有 payable的回退函數(shù), 那么 address(A)是 address類型.

如果 contract A具有 payable的回退函數(shù), 那么 address(A)是 address payable類型.

msg.sender屬于 address payable類型.

轉(zhuǎn)換與填充(padding)

uintY與 bytesX

因?yàn)樘畛?padding)的時候, bytesX是右填充(低比特位補(bǔ)0),而 uintY是左填充(高比特位補(bǔ)0),二者直接轉(zhuǎn)換可能會導(dǎo)致不符合預(yù)期的結(jié)果,所以現(xiàn)在當(dāng) bytesX和 uintY長度大小不一致(即X*8 != Y)時,不能直接轉(zhuǎn)換,必須先轉(zhuǎn)換到相同長度,再轉(zhuǎn)換到相同類型.

10進(jìn)制數(shù)值不能直接轉(zhuǎn)換成 bytesX類型, 必須先轉(zhuǎn)換到與 bytesX相同長度的 uintY,再轉(zhuǎn)換到 bytesX類型

16進(jìn)制數(shù)值如果長度與 bytesX不相等,也不能直接轉(zhuǎn)換成 byteX類型

ABI

字面值必須顯式轉(zhuǎn)換成類型才能使用 abi.encodePacked()

ABI編碼器在構(gòu)造外部函數(shù)入?yún)⒑?abi.encode()會恰當(dāng)?shù)靥幚?bytes和 string類型的填充(padding),若不需要進(jìn)行填充,請使用 abi.encodePacked()

ABI解碼器在解析函數(shù)入?yún)⒑?abi.decode()時,如果發(fā)現(xiàn) calldata太短或超長,將直接拋出異常,而不是像之前自動填充(補(bǔ)0)和截斷處理,從而有效地遏制了短地址攻擊.

.call()族函數(shù)( .call(), .delegatecall(), .staticcall())和 哈希函數(shù)( keccak256(), sha256(), ripemd160())只接受一個參數(shù) bytes,且不進(jìn)行填充(padding)處理.

.call()空參數(shù)必須寫成 .call(“”)

.call(sig,a,b,c)必須寫成 .call(abi.encodeWithSignature(sig,a,b,c)),其他類推

keccak256(a,b,c)必須寫成 keccak256(abi.encodePacked(a,b,c)),其他類推

另外, .call()族函數(shù)之前只返回函數(shù)執(zhí)行成功是否的 bool, 現(xiàn)在還返回函數(shù)執(zhí)行的返回值,即 (bool,bytes memory). 所以之前 boolresult=<contract>.call(sig,a,b,c)現(xiàn)在必須寫成 (boolresult,bytes memory data)=<contract>.call(sig,a,b,c).

不允許的寫法

在之前版本的solidity編譯,以下不允許的寫法只會導(dǎo)致 warnings報警,現(xiàn)在將直接 errors報錯.

不允許聲明0長度的定長數(shù)組類型.

不允許聲明0結(jié)構(gòu)體成員的結(jié)構(gòu)體類型.

不允許聲明未初始化的 storage變量.

不允許定義具有命名返回值的函數(shù)類型.

不允許定義非編譯期常量的 constant常量. 如 uintconstant time=now;是不允許的.

不允許 0X(X大寫)做16進(jìn)制前綴,只能用 0x.

不允許16進(jìn)制數(shù)和單位名稱組合使用. 如 value=0xffether必須寫成 value=0xff*1ether.

不允許小數(shù)點(diǎn)后不跟數(shù)字的數(shù)值寫法. 如 value=255.0ether不能寫成 value=255.ether.

不允許使用一元運(yùn)算符 +. 例如 value=1ether不能寫成 value=+1ether.

不允許布爾表達(dá)式使用算術(shù)運(yùn)算.

不允許具有一個或多個返回值的函數(shù)使用空返回語句.

不允許未實(shí)現(xiàn)的函數(shù)使用修飾符(modifier).

不允許 msg.value用在非 payable函數(shù)里以及此函數(shù)的修飾符(modifier)里.

廢棄的關(guān)鍵字/函數(shù)

years時間單位已棄用,因?yàn)殚c年計算容易導(dǎo)致各種問題.

var已棄用,請用 uintY精確聲明變量長度.

constant函數(shù)修飾符已棄用,不能用作修飾函數(shù)狀態(tài)可變性, 請使用 view關(guān)鍵字.

throw關(guān)鍵字已棄用,請使用 revert(), require(), assert()拋出異常.

.callcode()已棄用,請使用 .delegatecall(). 但是注意,在內(nèi)聯(lián)匯編仍可使用.

suicide()已棄用, 請使用 selfdestruct().

sha3()已棄用,請使用 keccak256().

構(gòu)造函數(shù)

構(gòu)造函數(shù)必須用 constructor關(guān)鍵字定義. 之前,并未強(qiáng)制要求,既可以用合約同名函數(shù)定義構(gòu)造函數(shù),也可以用 constructor關(guān)鍵字定義.

不允許調(diào)用沒有括號的基類構(gòu)造函數(shù).

不允許在同一繼承層次結(jié)構(gòu)中多次指定基類構(gòu)造函數(shù)參數(shù).

不允許調(diào)用帶參數(shù)但具有錯誤參數(shù)計數(shù)的構(gòu)造函數(shù).如果只想在不提供參數(shù)的情況下指定繼承關(guān)系,請不要提供括號.

其他

do…while循環(huán)里的 continue不再跳轉(zhuǎn)到循環(huán)體內(nèi),而是跳轉(zhuǎn)到 while處判斷循環(huán)條件,若條件為假,就退出循環(huán).這一修改更符合一般編程語言的設(shè)計風(fēng)格.

實(shí)現(xiàn)了C99風(fēng)格的作用域:

變量必須先聲明,后使用.之前,是可以先使用,后聲明,現(xiàn)在會導(dǎo)致編譯報錯.

只能在相同或嵌套作用域使用.比如 if(){…}, do{…}while();, for{…}塊內(nèi)聲明的變量,不能用在塊外.

變量和結(jié)構(gòu)體的循環(huán)依賴遞歸限制在256層.

pure和 view函數(shù)在EVM內(nèi)部采用 staticcall操作碼實(shí)現(xiàn)(EVM版本>=拜占庭),而非之前的 call操作碼,這使得狀態(tài)不可更改(state changes disallowed)在虛擬機(jī)層面得到保證.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容