♦️

Solidityにおけるtransfer、send、callの違い

2024/04/09に公開

SolidityでETHを送金する方法は主に3つあります。transfersendcallです。それぞれ異なる動作をするため、状況に合わせて使い分けることが重要です。

1. 動作

  • transfer
    • 最も基本的な送金方法
    • 2300 gasを消費
    • エラーが発生した場合、例外を送出
    • 呼び出し元コントラクトのコード実行を継続
    • 非推奨
  • send
    • transferと似ている
    • 2300 gasを消費
    • エラーが発生した場合、falseを返す
    • 呼び出し元コントラクトのコード実行を継続
    • 非推奨
  • call
    • 任意の量のgasを設定可能
    • エラーが発生した場合、例外を送出
    • 呼び出し元コントラクトのコード実行を継続
    • 推奨

2. 注意事項

  • transfersendは、payableアドレスにのみ使用可能
  • callは、address型に送金可能
  • callは、fallback関数またはreceive関数を呼び出す
  • callは、他のコントラクトとのデータ交換にも使用可能
  • transfersendは、将来のバージョンで廃止される可能性があります

3. 使用例

  • transfer
    • 少額のETHを送金する場合
    • 送金先の信頼が高い場合
  • send
    • transferよりも多くのgasが必要な場合
    • 送金先の信頼が低い場合
  • call
    • 他のコントラクトとデータ交換する場合
    • 複雑な送金処理を行う場合
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract SendEther {
    function sendViaTransfer(address payable _to) public payable {
        // This function is no longer recommended for sending Ether.
        _to.transfer(msg.value);
    }

    function sendViaSend(address payable _to) public payable {
        // Send returns a boolean value indicating success or failure.
        // This function is not recommended for sending Ether.
        bool sent = _to.send(msg.value);
        require(sent, "Failed to send Ether");
    }

    function sendViaCall(address payable _to) public payable {
        // Call returns a boolean value indicating success or failure.
        // This is the current recommended method to use.
        (bool sent, bytes memory data) = _to.call{value: msg.value}("");
        require(sent, "Failed to send Ether");
    }
}

4. まとめ

機能 transfer send call
動作 基本的な送金 拡張的な送金 汎用的な呼び出し
gas 2300 2300 設定可能
エラー処理 例外 false 例外
使用例 少額送金 信頼性の低い送金 データ交換
推奨 非推奨 非推奨 推奨

それぞれの特徴を理解して、適切な方法で使い分けることが重要です。

参考資料

Discussion