脆弱性の原則
Ethereum スマート コントラクトの機能の 1 つは、他の外部コントラクトのコードを呼び出して使用できることです。これらのコントラクトは通常、イーサ上で動作し、さまざまな外部ユーザー アドレスにイーサを送信することがよくあります。外部コントラクトを呼び出す、または外部アドレスに Ether を送信するこの操作では、コントラクトが外部呼び出しを送信する必要があります。これらの外部呼び出しは、フォールバック関数などを介して攻撃者によってハイジャックされ、コントラクトにそれ自体への呼び出しを含むさらなるコードの実行を強制する可能性があります。このようにして、コードは繰り返し契約に入ることができ、これが「リエントランシー」の起源です。このタイプの脆弱性は、有名な DAO ハッキング事件で悪用されました。
次の Solidity ナレッジ ポイントは、再入攻撃の根本的な原因をより深く理解するのに役立ちます。
フォールバック機能
コントラクトには名前のない関数を含めることができます。この関数にはパラメータや戻り値を含めることはできません。コントラクトへの呼び出しで、指定された関数識別子に一致する関数が他にない場合 (または呼び出しデータが提供されていない場合)、この関数 (フォールバック関数) が実行されます。
これに加えて、コントラクトがイーサ (データなし) を受信するたびに、この関数が実行されます。さらに、イーサを受信するには、フォールバック関数を としてマークする必要がありますpayable
。このような機能が存在しない場合、コントラクトは通常のトランザクションでイーサを受け取ることができません。
フォールバック関数を定義せず、Ether を直接 (関数呼び出しなしで、つまりsend
または を使用せtransfer
ずに) 受け取るコントラクトは、例外をスローして Ether を返します。したがって、コントラクトでイーサを受信したい場合は、フォールバック関数を実装する必要があります。
さらに、コントラクトはそのようなイーサ転送に反応できないため、それらを拒否することはできません。これは EVM の設計時に決定されたものであり、Solidity はこの問題を回避できません。
関数呼び出しを呼び出す
Solidity の呼び出し関数ファミリー