1糜芳, 摘要
本文介紹如何升級(jí)Truffle到v5.0.0的方法便于編譯使用Solidity v0.5.0飒货,同時(shí)也介紹了一下Solidity v0.5.0新特性。
2峭竣,操作步驟
2.1 查看TRUFFLE版本并卸載
之前一直在用TRUFFLE 4.0版本塘辅,最近使用REMIX編譯時(shí)發(fā)現(xiàn)Solidity 已升級(jí)到v0.5.0了。為了使用Solidity v0.5.0新特性皆撩,TRUFFLE的版本也要配套升級(jí)了莫辨。
先查看版本,然后卸載truffleV4.1.11舊版本毅访。
duncanwang@ubuntu:~/work/dapp-guide-pet-shop$ truffle version
Truffle v4.1.11 (core: 4.1.11)
Solidity v0.4.24 (solc-js)
duncanwang@ubuntu:~/work/dapp-guide-pet-shop$ sudo npm uninstall -g truffle
[sudo] password for duncanwang:
removed 81 packages in 1.852s
2.2 升級(jí)truffle到5.0版本
在npm中安裝固定的版本號(hào)package沮榜,只需要在其后加 ‘@版本號(hào)’。
npm install -g truffle@5.0.0
安裝時(shí)存在錯(cuò)誤提示喻粹,暫時(shí)不用管蟆融,不影響使用。
duncanwang@ubuntu:~/work/dapp-guide-pet-shop$ sudo npm install -g truffle@5.0.0
/usr/bin/truffle -> /usr/lib/node_modules/truffle/build/cli.bundled.js
> keccak@1.4.0 install /usr/lib/node_modules/truffle/node_modules/keccak
> npm run rebuild || echo "Keccak bindings compilation fail. Pure JS implementation will be used."
> keccak@1.4.0 rebuild /usr/lib/node_modules/truffle/node_modules/keccak
> node-gyp rebuild
gyp ERR! configure error
gyp ERR! stack Error: EACCES: permission denied, mkdir '/usr/lib/node_modules/truffle/node_modules/keccak/build'
gyp ERR! System Linux 4.13.0-46-generic
gyp ERR! command "/usr/bin/node" "/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /usr/lib/node_modules/truffle/node_modules/keccak
gyp ERR! node -v v9.11.1
gyp ERR! node-gyp -v v3.8.0
gyp ERR! not ok
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! keccak@1.4.0 rebuild: `node-gyp rebuild`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the keccak@1.4.0 rebuild script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /home/duncanwang/.npm/_logs/2018-12-20T05_33_47_253Z-debug.log
Keccak bindings compilation fail. Pure JS implementation will be used.
+ truffle@5.0.0
added 89 packages from 305 contributors in 22.714s
查看版本守呜,發(fā)現(xiàn)已經(jīng)切換為V5.0.0版本了型酥。
duncanwang@ubuntu:~/work/dapp-guide-pet-shop$ truffle version
{ mnemonic_ropsten: 'mosquito electric slim hybrid craft change shrimp digital car wonder term oven',
mnemonic_mainnet: '' }
Truffle v5.0.0 (core: 5.0.0)
Solidity v0.5.0 (solc-js)
Node v9.11.1
2.3 智能合約.sol文件可以使用新版本
關(guān)鍵字:
pragma solidity ^0.5.0;
3, Solidity 0.5.0新特性
Solidity 0.5.0 于11月13日正式發(fā)布, 此版本中包含了許多重要更新查乒。
3.1 Solidity 0.5.0 新增語法
增加新的關(guān)鍵字calldata, constructor
-
新的保留關(guān)鍵字alias, apply, auto, copyof, define, immutable,
implements, macro, mutable, override, partial, promise, reference,
sealed, sizeof, supports, typedef and unchecked
-
函數(shù)call/ delegatecall/ staticcall/ keccak256/ sha256/ ripemd160只接受一
個(gè)類型為bytes的參數(shù)弥喉,并且不會(huì)對(duì)此參數(shù)進(jìn)行pad。
-
call/delegatecall/staticcall現(xiàn)在返回(bool, bytes memory)玛迄,這樣既能檢
查操作是否成功由境,也能操作返回的數(shù)據(jù)。所以需要將之前的寫法
改為
現(xiàn)在Solidity對(duì)函數(shù)內(nèi)局部變量采用C99類型的作用域解析規(guī)則蓖议,也就是變量只能在被聲明后使用并且只在同一個(gè)作用域或者其下嵌套的(更深層次)作用域可見虏杰。在for循環(huán)的初始化部分定義的變量在整個(gè)循環(huán)內(nèi)可見。
3.2 Solidity 0.5.0 丟棄/禁止使用的特性
- 構(gòu)造函數(shù)必須用constructor關(guān)鍵字定義勒虾,而不是與合約同名的函數(shù)
- 不允許調(diào)用的函數(shù)
- callcode (推薦使用delegatecall)
- suicide (推薦使用selfdestruct)
- sha3 (推薦使用keccak256)
- throw (推薦使用revert, require, assert)
- 類型轉(zhuǎn)換
- 不允許十進(jìn)制數(shù)值往bytesXX的轉(zhuǎn)換(顯式或隱式)
- 不允許十六進(jìn)制數(shù)值往不同大小的bytesXX的轉(zhuǎn)換(顯式或隱式)
- 不允許使用years
- 十六進(jìn)制值后不允許加單位(比如0x1e wei)
- 十六進(jìn)制值不允許用0X,只能使用0x
- 變量相關(guān)
- 不允許聲明空的struct
- 不允許使用var纺阔,要顯式指定變量類型
- 不允許不同數(shù)目的tuple相互賦值
- 不允許編譯期不能確定的常量
- 存儲(chǔ)類型的變量必須初始化
- 不允許空的tuple
- 固定大小的數(shù)組長(zhǎng)度不能為0
- 語法相關(guān)
- 不允許使用constant作為函數(shù)的modifier (使用view腐缤,pure)
- 布爾表達(dá)式不能進(jìn)行算術(shù)操作
- 不允許使用一元的+
- 不允許將未轉(zhuǎn)化為具體類型的數(shù)值當(dāng)做abi.encodePacked的參數(shù)
- 匯編中不允許使用jump撞蚕,label以及非函數(shù)風(fēng)格的指令
- 沒實(shí)現(xiàn)的函數(shù)不允許使用modifier
-
函數(shù)類型中不允許包含返回值的名字,比如
3.3 continue在do-while中的行為
當(dāng)遇到循環(huán)體中的continue時(shí)聪富,0.5.0中下一步會(huì)檢查while中的條件,而之前則跳回執(zhí)行循環(huán)體玻靡。0.5.0的行為與其他編程語言的處理保持一致拯杠。
3.4 有符號(hào)數(shù)的算術(shù)右移
之前Solidity中的算術(shù)右移是用除法實(shí)現(xiàn)啃奴,所以對(duì)負(fù)數(shù)做右移時(shí),效果為向0靠攏雄妥,但在其他編程語言中表現(xiàn)為向負(fù)無窮靠攏最蕾。在0.5.0中,此操作的行為與其他語言保持一致老厌。
3.5 call/staticcall/delegatecall
這三個(gè)函數(shù)如果只給定一個(gè)bytes類型的參數(shù)枝秤,不進(jìn)行任何pad操作醋拧。
pure/view操作碼(opcode)改為STATICCALL
聲明為view的函數(shù)不修改狀態(tài)。修改狀態(tài)的行為包括
寫狀態(tài)變量
emit event
創(chuàng)建新的合約
調(diào)用selfdestruct
發(fā)送Ether
調(diào)用其他未被標(biāo)記為pure淀弹、view的函數(shù)
使用了底層調(diào)用
使用了包含某些操作碼的內(nèi)聯(lián)匯編代碼
聲明為pure的函數(shù)既不讀取狀態(tài)也不修改狀態(tài)丹壕。讀取狀態(tài)的行為包括:
讀取狀態(tài)變量
訪問某個(gè)地址的balance變量, address(this).balance , .balance.
訪問block、tx薇溃、msg的成員(不包括msg.sig msg.data)
調(diào)用任何未標(biāo)記為pure的函數(shù)
使用了包含某些操作碼的內(nèi)聯(lián)匯編代碼
在 0.5.0 之前菌赖,pure/view函數(shù)中可以使用非法的類型轉(zhuǎn)換繞過對(duì)pure/view的語義限制,而在新版本中沐序,使用STATICCALL在EVM層面保證了語義安全琉用。
3.6 外部函數(shù)調(diào)用
從Tangerine Whistle起,調(diào)用外部函數(shù)時(shí)策幼,該外部函數(shù)共享所有可用gas邑时。
3.7 顯式要求
函數(shù)的可見性(pure/external/view)強(qiáng)制顯式定義。
-
所有struct/array/mapping類型變量的數(shù)據(jù)存儲(chǔ)類型強(qiáng)制顯式定義特姐。
比如原有寫法
已經(jīng)不合法晶丘,需要顯式指明x的存儲(chǔ)類型,比如
再比如
也不合法唐含,需要指明參數(shù)x的存儲(chǔ)類型
注意external類型的函數(shù)需要參數(shù)的數(shù)據(jù)存儲(chǔ)類型為calldata
-
Contract類型不再包含address成員铣口。所以要顯式將其轉(zhuǎn)為address, 比如c為一個(gè)合約
要修改為
禁止無關(guān)合約類型變量之間的轉(zhuǎn)換,通常情況下只能在合約有直接或間接繼承關(guān)系時(shí)觉壶,才可以進(jìn)行類型轉(zhuǎn)換脑题。如果你確定他們不存在這種關(guān)系,但是接口上是相符的铜靶,還是想進(jìn)行轉(zhuǎn)換叔遂,比如A與B是兩個(gè)合約類型他炊,他們之間不存在繼承關(guān)系,b是一個(gè)類型為B的合約已艰,那么可以用A(address(b))將b轉(zhuǎn)為A類型痊末。
-
address類型分解為address與address payable兩種,只有address payable提 供transfer函數(shù)哩掺。一個(gè)address payable可以直接轉(zhuǎn)換為address凿叠,反之則不行。 可以用如下方法將address轉(zhuǎn)換為address payable
如果c是一個(gè)合約嚼吞,address(c)僅當(dāng)c有一個(gè)payable的fallback函數(shù)時(shí)返回 address payable盒件。
如果合約實(shí)現(xiàn)時(shí),使用了withdraw模式舱禽,是不需要修改現(xiàn)有代碼炒刁,因?yàn)楹霞s中 并不需要直接往存儲(chǔ)的地址進(jìn)行轉(zhuǎn)賬操作,所有轉(zhuǎn)賬操作是由msg.sender發(fā)起 的誊稚,而msg.sender是address payable翔始。
禁止不同大小的bytesX與uintY的轉(zhuǎn)換,因?yàn)閎ytesX在右端補(bǔ)齊里伯,而uintY在左 端城瞎,這可能會(huì)導(dǎo)致異常轉(zhuǎn)換。現(xiàn)在必須先將大小調(diào)制為一致疾瓮,再進(jìn)行轉(zhuǎn)換全谤。比 如,要將bytes4 (4 bytes)轉(zhuǎn)換為uint64(8 bytes)爷贫,需要先將byte4轉(zhuǎn)換為bytes8认然。
禁止在non-payble的函數(shù)中使用msg.value。要么將該函數(shù)修改為payable漫萄,要么專門定義一個(gè)新的內(nèi)部函數(shù)來使用msg.value