Solidity Ver. 0.5.0の変更点をまとめた(互換性なし)
SolidityがVersion 0.5.0にアップデートされたため、互換性のない変更部分に関してまとめてみました。
セマンティクスとシンタックスの変更
このセクションはシンタックスとセマンティクスに影響を与える変更を強調します。
以下の関数はシングルバイトの引数のみ許容します。さらに、引数はパッドされません。
この変更により引数の連結方法がより明確になります。
call()
delegatecall()
staticcall()
keccak256()
sha256()
ripemd160()
.call()
を.call("")
、.call(signature, a, b, c)
を.call(abi.encodeWithSignature(signature, a, b, c))
(最後の一つの引数はvalue型でのみ動きます。)
keccak256(a, b, c)
をkeccak256(abi.encodePacked(a, b, c))
に変更してください。
互換性を破る変更ではありませんが、開発者にはx.call(bytes4(keccak256("f(uint256)"), a, b)
をx.call(abi.encodeWithSignature("f(uint256)", a, b))
に変更することをおすすめします。
関数.call()
、.delegatecall()
、.staticcall()
は(bool, bytes memory)
を返し、返されたデータにアクセスすることができます。
bool success = otherContract.call("f")
から(bool success, bytes memory data) = otherContract.call("f")
に変更してください。
SolidityはC99スタイルのスコープルールを関数内ローカル変数に適応しています。これは、変数は宣言後に使用可能であり、同じあるいはネストされたスコープ内でのみ使えます。for文の初期化ブロック内で宣言された変数はループ内のどこでも有効です。
Explicitness Requirements
このセクションはコードをより明確に記述する必要がある部分を説明します。ほとんどのトピックでは、コンパイラーがおすすめの記述方法を提供します。
- 関数の可視性
- 関数の可視性の明確化は現在は強制です。全ての関数とコンストラクターにはpublic修飾子をつけてください。fallback関数とインターフェース関数にはexternalをつけて下さい。
- 変数の保存領域
- 構造体、配列、マッピング型の全ての変数の保存領域の明確化は強制です。これは関数のパラメーターと返り値にも適応されます。
- 例:
uint[] x = m_x
からuint[] storage x = m_x
に変更して下さい。 - 例:
function f(uint[][] x)
からfunction f(uint[][] memory x)
に変更して下さい。 -
memory
がデータ領域です、状況に応じてstorage
やcalldata
に変更して下さい。 -
external
関数はcalldata
データ領域と共にパラメーターが必要です。
- コントラクトのアドレス
- 名前空間を分けるために、コントラクト型は
address
メンバーを持ちません。 - コントラクト型からアドレス型への変更は明示的に行う必要があります。
- 例:cがコントラクトの場合、
c.transfer(...)
をaddress(c).transfer(...)
に、c.balance
をaddress(c).balance
に変更する必要があります。
- 名前空間を分けるために、コントラクト型は
- コントラクト間の変換
- 無関係なコントラクト型間の明示的な変換は現在禁止されています。
- コントラクト型は、基本型または祖先型のいずれかにのみ変換できます。
- コントラクトが変換したいコントラクトタイプと互換性があることが確かな場合はそれを継承しませんが、最初にaddress型に変換することで対応できます。
- 例:A及びBがコントラクト型で、BはAを継承していない、bはB型のコントラクトであるとする。
-
A(address(b))
を用いれば、bからaに変換することが可能です。以下で説明するように、依然としてpayableなフォールバック関数を考慮する必要があることに注意してください。
-
-
address
型-
address
型はaddress
型とaddress payable
型に別れました。address payable
型のみtransfer(...)
関数を提供します。 -
address payable
型からaddress
型への直接変換は可能ですが、逆はできません。 -
address
型からaddress payable
型への変換は、uint160を経由することで可能です。- cがコントラクトで、かつcがpayableなフォールバック関数を持つ場合のみ、
address(c)
よりaddress payable
型に変換できる
- cがコントラクトで、かつcがpayableなフォールバック関数を持つ場合のみ、
- もしwithdrawパターンを用いていた場合、コードを変更する必要はほとんどの場合必要ありません。
- なぜなら、transferには
msg.sender
のみ用いており、msg.sender
はaddress payable
型であるためです。
- なぜなら、transferには
-