♦️
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
:別のスマートコントラクトの関数をあたかも自身の関数のように呼び出す場合に使用します。
それぞれの特徴を理解して、適切な方法で使い分けることが重要です。
Discussion