808 文字
4 分
Solidity における call, delegatecall の違いは?
Solidityにおけるcallとdelegatecallは、どちらも別のスマートコントラクトの関数を呼び出すための関数ですが、いくつかの重要な違いがあります。
1. 呼び出しコンテキスト
call:呼び出し先コントラクトのコンテキストで関数を呼び出します。delegatecall:呼び出し元コントラクトのコンテキストで関数を呼び出します。
2. 状態変数
call:呼び出し先コントラクトの状態変数を参照・変更します。delegatecall:呼び出し元コントラクトの状態変数を参照・変更します。
3. メッセージ送信者
call:呼び出し元コントラクトのアドレスがmsg.senderとして送信されます。delegatecall:呼び出し先コントラクトのアドレスがmsg.senderとして送信されます。
4. 呼び出し可能な関数
call:すべてのpublicおよびexternal関数を呼び出すことができます。delegatecall:fallbackまたはreceive関数を呼び出す必要があります。
5. 使用例
call:外部コントラクトとの単純なデータ交換に適しています。delegatecall:ライブラリの実装や、アップグレード可能なコントラクトの作成に適しています。
callとdelegatecallのコード例
callの例
pragma solidity ^0.8.0;
contract Caller { function callOtherContract(address callee, uint256 value) public { // `call`を使用して`callee`コントラクトの`add`関数を呼び出す (bool success, bytes memory data) = callee.call(abi.encodeWithSignature("add(uint256)", value));
// 呼び出し結果をチェック if (success) { // 呼び出し成功 uint256 result = abi.decode(data, (uint256)); // `result`を使用して処理を行う } else { // 呼び出し失敗 // エラー処理を行う } }}
contract Callee { function add(uint256 value) public pure returns (uint256) { return value + 1; }}この例では、Callerコントラクトはcallを使用してCalleeコントラクトのadd関数を呼び出します。callはCalleeコントラクトのコンテキストで実行されるため、Calleeコントラクトの状態変数を参照・変更することができます。
delegatecallの例
pragma solidity ^0.8.0;
contract Caller { function delegatecallOtherContract(address callee, uint256 value) public { // `delegatecall`を使用して`callee`コントラクトの`add`関数を呼び出す (bool success, bytes memory data) = callee.delegatecall(abi.encodeWithSignature("add(uint256)", value));
// 呼び出し結果をチェック if (success) { // 呼び出し成功 uint256 result = abi.decode(data, (uint256)); // `result`を使用して処理を行う } else { // 呼び出し失敗 // エラー処理を行う } }}
contract Callee { fallback() external { // `delegatecall`によって呼び出された場合、`add`関数を呼び出す add(msg.value); }
function add(uint256 value) public pure returns (uint256) { return value + 1; }}この例では、Callerコントラクトはdelegatecallを使用してCalleeコントラクトのadd関数を呼び出します。delegatecallはCallerコントラクトのコンテキストで実行されるため、Callerコントラクトの状態変数を参照・変更することができます。
ポイント
callとdelegatecallは、呼び出しコンテキスト、状態変数、メッセージ送信者、呼び出し可能な関数などの違いがあります。- それぞれの機能を理解して、適切な方法で使い分けることが重要です。
まとめ
call:別のスマートコントラクトの関数を独立した関数として呼び出す場合に使用します。delegatecall:別のスマートコントラクトの関数をあたかも自身の関数のように呼び出す場合に使用します。
それぞれの特徴を理解して、適切な方法で使い分けることが重要です。