本文介绍如何升级Truffle到v5.0.0的方法便于编译使用Solidity v0.5.0,同时也介绍了一下Solidity v0.5.0新特性。node
以前一直在用TRUFFLE 4.0版本,最近使用REMIX编译时发现Solidity 已升级到v0.5.0了。为了使用Solidity v0.5.0新特性,TRUFFLE的版本也要配套升级了。
先查看版本,而后卸载truffleV4.1.11旧版本。git
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
在npm中安装固定的版本号package,只须要在其后加 ‘@版本号’。npm
npm install -g truffle@5.0.0编程
安装时存在错误提示,暂时不用管,不影响使用。ubuntu
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
查看版本,发现已经切换为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
关键字:promise
pragma solidity ^0.5.0;安全
Solidity 0.5.0 于11月13日正式发布, 此版本中包含了许多重要更新。app
增长新的关键字calldata, constructor编程语言
新的保留关键字alias, apply, auto, copyof, define, immutable,
implements, macro, mutable, override, partial, promise, reference,
sealed, sizeof, supports, typedef and unchecked
函数call/ delegatecall/ staticcall/ keccak256/ sha256/ ripemd160只接受一
个类型为bytes的参数,而且不会对此参数进行pad。
call/delegatecall/staticcall如今返回(bool, bytes memory),这样既能检
查操做是否成功,也能操做返回的数据。因此须要将以前的写法
改成
如今Solidity对函数内局部变量采用C99类型的做用域解析规则,也就是变量只能在被声明后使用而且只在同一个做用域或者其下嵌套的(更深层次)做用域可见。在for循环的初始化部分定义的变量在整个循环内可见。
函数类型中不容许包含返回值的名字,好比
当遇到循环体中的continue时,0.5.0中下一步会检查while中的条件,而以前则跳回执行循环体。0.5.0的行为与其余编程语言的处理保持一致。
solidity 0.5.0中返回3,0.4.x 版本返回4
以前Solidity中的算术右移是用除法实现,因此对负数作右移时,效果为向0靠拢,但在其余编程语言中表现为向负无穷靠拢。在0.5.0中,此操做的行为与其余语言保持一致。
上述代码,0.5.0返回-1,而0.4.x返回0
这三个函数若是只给定一个bytes类型的参数,不进行任何pad操做。
声明为view的函数不修改状态。修改状态的行为包括
写状态变量
emit event
建立新的合约
调用selfdestruct
发送Ether
调用其余未被标记为pure、view的函数
使用了底层调用
使用了包含某些操做码的内联汇编代码
声明为pure的函数既不读取状态也不修改状态。读取状态的行为包括:
读取状态变量
访问某个地址的balance变量, address(this).balance , .balance.
访问block、tx、msg的成员(不包括msg.sig msg.data)
调用任何未标记为pure的函数
使用了包含某些操做码的内联汇编代码
在 0.5.0 以前,pure/view函数中可使用非法的类型转换绕过对pure/view的语义限制,而在新版本中,使用STATICCALL在EVM层面保证了语义安全。
从Tangerine Whistle起,调用外部函数时,该外部函数共享全部可用gas。
函数的可见性(pure/external/view)强制显式定义。
全部struct/array/mapping类型变量的数据存储类型强制显式定义。
好比原有写法
已经不合法,须要显式指明x的存储类型,好比
image
再好比
image
也不合法,须要指明参数x的存储类型
注意external类型的函数须要参数的数据存储类型为calldata
Contract类型再也不包含address成员。因此要显式将其转为address, 好比c为一个合约
要修改成
禁止无关合约类型变量之间的转换,一般状况下只能在合约有直接或间接继承关系时,才能够进行类型转换。若是你肯定他们不存在这种关系,可是接口上是相符的,仍是想进行转换,好比A与B是两个合约类型,他们之间不存在继承关系,b是一个类型为B的合约,那么能够用A(address(b))将b转为A类型。
address类型分解为address与address payable两种,只有address payable提 供transfer函数。一个address payable能够直接转换为address,反之则不行。 能够用以下方法将address转换为address payable
若是c是一个合约,address(c)仅当c有一个payable的fallback函数时返回 address payable。
若是合约实现时,使用了withdraw模式,是不须要修改现有代码,由于合约中 并不须要直接往存储的地址进行转帐操做,全部转帐操做是由msg.sender发起 的,而msg.sender是address payable。
禁止不一样大小的bytesX与uintY的转换,由于bytesX在右端补齐,而uintY在左 端,这可能会致使异常转换。如今必须先将大小调制为一致,再进行转换。比 如,要将bytes4 (4 bytes)转换为uint64(8 bytes),须要先将byte4转换为bytes8。
禁止在non-payble的函数中使用msg.value。要么将该函数修改成payable,要么专门定义一个新的内部函数来使用msg.value