単位とグローバルで利用可能な変数
Etherの単位
リテラルの数に wei
、 gwei
、 ether
の接尾辞を付けて、Etherの別の単位を指定できますが、接尾辞のないEtherの数はWeiとみなされます。
assert(1 wei == 1);
assert(1 gwei == 1e9);
assert(1 ether == 1e18);
単位の接尾辞は、10の累乗にだけ対応しています。
注釈
バージョン0.7.0では、単位 finney
と szabo
が削除されました。
時間の単位
リテラルの数の後に seconds
、 minutes
、 hours
、 days
、 weeks
などの接尾辞をつけると、時間の単位を指定できます。
秒を基本単位とし、単位は次のように単純なものです。
1 == 1 seconds
1 minutes == 60 seconds
1 hours == 60 minutes
1 days == 24 hours
1 weeks == 7 days
これらの単位を使ってカレンダーの計算を行う場合、 うるう秒 のために1年が365日ではなく、1日が24時間でもないので注意が必要です。 うるう秒が予測できないため、正確なカレンダーライブラリは外部のオラクルで更新する必要があります。
注釈
上記の理由により、バージョン0.5.0では接尾語の years
が削除されました。
これらの接尾辞は、変数には適用できません。 例えば、関数のパラメータを日単位で解釈したい場合は、以下のようになります。
function f(uint start, uint daysAfter) public {
if (block.timestamp >= start + daysAfter * 1 days) {
// ...
}
}
特別な変数と関数
グローバルな名前空間に常に存在し、主にブロックチェーンに関する情報を提供するために使用されたり、汎用的なユーティリティー関数である特別な変数や関数があります。
ブロックとトランザクションのプロパティ
blockhash(uint blockNumber) returns (bytes32)
:blocknumber
が直近256個のブロックの一つである場合は、与えられたブロックのハッシュ、そうでない場合はゼロを返すblock.basefee
(uint
): カレントブロックのベースフィー(base fee)( EIP-3198 と EIP-1559)block.chainid
(uint
): カレントブロックのチェーンIDblock.coinbase
(address payable
): カレントブロックのマイナーのアドレスblock.difficulty
(uint
): 現在のブロックの難易度(EVM < Paris
)。 EVMの他のバージョンでは、block.prevrandao
の非推奨のエイリアスとして動作ます( EIP-4399 )。block.gaslimit
(uint
): カレントブロックのガスリミットblock.number
(uint
): カレントブロックの番号block.prevrandao
(uint
): ビーコンチェーンが提供する乱数(EVM >= Paris
)block.timestamp
(uint
): カレントブロックのタイムスタンプ(Unixエポックからの秒数)gasleft() returns (uint256)
: 残りのガスmsg.data
(bytes calldata
): 完全なコールデータmsg.sender
(address
): メッセージの送信者(現在のコール)msg.sig
(bytes4
): コールデータの最初の4バイト(すなわち関数識別子)msg.value
(uint
): メッセージと一緒に送られたweiの数tx.gasprice
(uint
): トランザクションのガスプライスtx.origin
(address
): トランザクションの送信者(フルコールチェーン)
注釈
msg.sender
と msg.value
を含む msg
のすべてのメンバーの値は、 外部(external) 関数を呼び出すたびに変わる可能性があります。
これには、ライブラリ関数の呼び出しも含まれます。
注釈
コントラクトが、ブロックに含まれるトランザクションのコンテキストではなく、オフチェーンで評価される場合、 block.*
と tx.*
が特定のブロックやトランザクションの値を参照していると仮定すべきではありません。
これらの値は、コントラクトを実行するEVM実装によって提供され、任意のものとなり得ます。
注釈
自分が何をしているか分かっていない限り、ランダムネスのソースとして block.timestamp
や blockhash
に頼らないでください。
タイムスタンプもブロックハッシュも、ある程度はマイナーの影響を受ける可能性があります。 マイニングコミュニティの悪質なアクターは、例えば、選択したハッシュでカジノのペイアウト関数を実行し、対価(例えばEther)を受け取れなかった場合は別のハッシュで再試行できます。
現在のブロックのタイムスタンプは、最後のブロックのタイムスタンプよりも厳密に大きくなければなりませんが、唯一の保証は、正規のチェーンで連続する2つのブロックのタイムスタンプの間のどこかになるということです。
注釈
ブロックハッシュは、スケーラビリティの観点から、すべてのブロックで利用できるわけではありません。 アクセスできるのは最新の256ブロックのハッシュのみで、その他の値はすべてゼロになります。
注釈
関数 blockhash
は、以前は block.blockhash
と呼ばれていましたが、バージョン0.4.22で非推奨となり、バージョン0.5.0で削除されました。
注釈
gasleft
関数は、以前は msg.gas
と呼ばれていましたが、バージョン0.4.21で非推奨となり、バージョン0.5.0で削除されました。
注釈
バージョン0.7.0では、 now
(block.timestamp
)というエイリアスを削除しました。
ABIエンコーディングおよびデコーディングの関数
abi.decode(bytes memory encodedData, (...)) returns (...)
: ABIは与えられたデータをデコードしますが、型は第2引数として括弧内に与えます。 例:(uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))
。abi.encode(...) returns (bytes memory)
: 与えられた引数をABIエンコードします。abi.encodePacked(...) returns (bytes memory)
: 与えられた引数の packed encoding を実行します。 パックされたエンコーディングは曖昧になる可能性があることに注意してください。abi.encodeWithSelector(bytes4 selector, ...) returns (bytes memory)
: 与えられた引数を2番目から順にABIエンコードし、与えられた4バイトのセレクタを前に付加します。abi.encodeWithSignature(string memory signature, ...) returns (bytes memory)
:abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)
に相当。abi.encodeCall(function functionPointer, (...)) returns (bytes memory)
:functionPointer``の呼び出しを、タプルで見つかった引数でABIエンコードします。 完全な型チェックを行い、型が関数のシグネチャと一致することを確認します。 結果は ``abi.encodeWithSelector(functionPointer.selector, (...))
に等しいです。
注釈
これらのエンコーディング関数は、実際に外部関数を呼び出すことなく、外部関数呼び出しのためにデータを細工するために使用できます。
さらに、 keccak256(abi.encodePacked(a, b))
は構造化されたデータのハッシュを計算する方法でもあります(ただし、異なる関数パラメータタイプを使って「ハッシュの衝突」を工作することが可能なので注意が必要です)。
エンコーディングの詳細については、 ABI および タイトにパックするエンコーディング に関するドキュメントを参照してください。
bytesのメンバー
bytes.concat(...) returns (bytes memory)
: 可変個の bytes, bytes1, ..., bytes32 の引数を一つのバイト列に連結します 。
stringのメンバー
string.concat(...) returns (string memory)
: 可変個の文字列引数を1つの文字列に連結します 。
エラーハンドリング
エラー処理の詳細や、いつどの関数を使うかについては、 assertとrequire の専用セクションを参照してください。
assert(bool condition)
条件が満たされないとパニックエラーを引き起こし、状態変化が戻ります - 内部エラーに使用されます。
require(bool condition)
条件が満たされないとリバートします - 入力や外部コンポーネントのエラーに使用されます。
require(bool condition, string memory message)
条件が満たされないとリバートします - 入力や外部コンポーネントのエラーに使用します。 また、エラーメッセージも表示されます。
revert()
実行を中止し、状態変化をリバートします。
revert(string memory reason)
実行を中止し、状態変化をリバートするために、説明用の文字列を提供します。
数理的関数と暗号学的関数
addmod(uint x, uint y, uint k) returns (uint)
任意の精度で加算が実行され、
2**256
で切り捨てられない(x + y) % k
を計算します。 バージョン0.5.0からk != 0
であることをアサートします。mulmod(uint x, uint y, uint k) returns (uint)
任意の精度で乗算が実行され、
2**256
で切り捨てられない(x * y) % k
を計算します。 バージョン0.5.0からk != 0
であることをアサートします。keccak256(bytes memory) returns (bytes32)
入力のKeccak-256ハッシュを計算します。
注釈
以前は sha3
という keccak256
のエイリアスがありましたが、バージョン0.5.0で削除されました。
sha256(bytes memory) returns (bytes32)
入力のSHA-256ハッシュを計算します。
ripemd160(bytes memory) returns (bytes20)
入力のRIPEMD-160ハッシュを計算します。
ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)
楕円曲線の署名から公開鍵に紐づくアドレスを復元するか、エラーで0を返します。 この関数のパラメータは、署名のECDSA値に対応しています。
r
= 署名の最初の32バイトs
= 署名の2番目の32バイトv
= 署名の最後の1バイト
ecrecover
はaddress
を返し、address payable
を返しません。 復旧したアドレスに送金する必要がある場合は、 address payable を参照して変換してください。詳しくは 使用例 を参照してください。
警告
ecrecover
を使用している場合、対応する秘密鍵を知らなくても、有効な署名を別の有効な署名に変えることができることに注意してください。
Homesteadのハードフォークでは、この問題は _transaction_ signaturesで修正されましたが( EIP-2 参照)、ecrecover関数は変更されませんでした。
これは、署名を一意にする必要がある場合や、アイテムを識別するために使用する場合を除き、通常は問題になりません。
OpenZeppelinには、この問題なしに ecrecover
のラッパーとして使用できる ECDSAヘルパーライブラリ があります。
注釈
sha256
、 ripemd160
、 ecrecover
を プライベートブロックチェーン で実行すると、Out-of-Gasに遭遇することがあります。
これは、これらの関数が「プリコンパイル済みコントラクト」として実装されており、最初のメッセージを受信して初めて実際に存在するからです(ただし、コントラクトコードはハードコードされています)。
存在しないコントラクトへのメッセージはより高価であるため、実行時にOut-of-Gasエラーが発生する可能性があります。
この問題を回避するには、実際のコントラクトで使用する前に、まず各コントラクトにWei(例: 1)を送信することです。
これは、メインネットやテストネットでは問題になりません。
コントラクト関連
this
(現在のコントラクト型)現在のコントラクトで、 アドレス に明示的に変換可能なもの
super
継承階層の1つ上のレベルのコントラクト
selfdestruct(address payable recipient)
現在のコントラクトを破棄し、その資金を所定の アドレス に送り、実行を終了します。
selfdestruct
はEVMから引き継いだいくつかの特殊性を持っていることに注意してください。受信側コントラクトのレシーブ関数が実行されません。
コントラクトが実際に破壊されるのはトランザクション終了時であり、
revert
はその破壊を「リバートする」かもしれません。
さらに、現在のコントラクトのすべての関数は、現在の関数を含めて直接呼び出すことができます。
警告
バージョン0.8.18以降、SolidityとYulの両方で selfdestruct
を使用すると、非推奨の警告が発生します。
というのも、 SELFDESTRUCT
オペコードは、 EIP-6049 で述べられているように、いずれ動作が大きく変わることになるからです。
注釈
バージョン0.5.0以前では、 selfdestruct
と同じセマンティクスを持つ suicide
という関数がありました。
型情報
type(X)
という式を使って、 X
という型に関する情報を取り出すことができます。
現在のところ、この機能のサポートは限られていますが( X
はコントラクト型か整数型のどちらかです)、将来は拡張されるかもしれません。
コントラクト型 C
には以下のプロパティがあります。
type(C).name
コントラクトの名称です。
type(C).creationCode
コントラクトの作成バイトコードを含むメモリバイト列。 これはインラインアセンブリで使用でき、特に
create2
オペコードを使用してカスタム作成ルーチンを構築できます。 このプロパティは、コントラクト自体または派生コントラクトでアクセスできま せん。 これにより、バイトコードはコールサイトのバイトコードに含まれることになり、そのような循環参照はできません。
type(C).runtimeCode
コントラクトのランタイムバイトコードを含むメモリバイト列。 これは、通常、
C
のコンストラクタによってデプロイされるコードです。C
のコンストラクタがインラインアセンブリを使用している場合、これは実際にデプロイされるバイトコードとは異なる可能性があります。 また、ライブラリはデプロイ時にランタイムのバイトコードを変更し、正規の呼び出しを防ぐことにも注意してください。 このプロパティにも、.creationCode
と同様の制限が適用されます。
上記のプロパティに加えて、インターフェース型 I
では以下のプロパティが利用可能です。
type(I).interfaceId
:bytes4
値で、与えられたインターフェースI
の EIP-165 インターフェース識別子を含む。 この識別子は、インターフェース自身の中で定義されたすべての関数セレクタのXOR
として定義され、すべての継承された関数は除外されます。
整数型の T
には以下のプロパティがあります。
type(T).min
型
T
で表現可能な最小の値です。type(T).max
型
T
で表現可能な最大の値です。
予約語
これらのキーワードはSolidityで予約されています。 将来は構文の一部になるかもしれません。
after
, alias
, apply
, auto
, byte
, case
, copyof
, default
,
define
, final
, implements
, in
, inline
, let
, macro
, match
,
mutable
, null
, of
, partial
, promise
, reference
, relocatable
,
sealed
, sizeof
, static
, supports
, switch
, typedef
, typeof
,
var
。