ブロックチェーン技術ブログ

ブロックチェーンと英語、数学に関するブログ

Solidity入門2 <Functions, Events, Errors>

Functions

関数は、呼び出し可能なコードの単位です.
Solidityでも、他の言語と同様に関数を定義できます.

関数には、引数と返り値を定義できます.
返り値がない場合、returns (T) を省略可能です.

function multiply(uint _a, uint _b) public view returns (uint) {
    return _a * _b;
}

Internal Function Calls / External Function Calls

関数の呼び出しには、内部呼び出し(Internal Calls)と外部呼び出し(External Calls) の2種類があります.

内部呼び出しは、Contract内に定義した関数を直接呼び出します.

外部呼び出しは、Contractのインスタンス変数もしくは this を通じて呼び出します.

Function Visibility

Solidityでは、関数の可視性が4種類あります

  • external
    他のコントラクトから呼び出すことができます.
    関数を定義したコントラクト内で、その関数を呼び出す場合、thisを通じて呼び出す必要があります.

  • public
    他のコントラクトから呼び出すことができます.
    また、関数を定義したコントラクト内で、その関数を内部呼び出しすることができます.

  • internal
    関数を定義したコントラクト内でのみ、呼び出すことができます.
    コントラクトを継承した場合、親クラスから継承したものを呼び出すこともできます.

  • private
    関数を定義したコントラクト内でのみ、呼び出すことができます.
    親クラスから継承したものを呼び出すことができません.

Function Modifiers

Function modifiers は、関数ごとの共通のチェック処理に名前をつけて、他の関数から呼び出すことができます.

require 関数は、第1引数にboolean値、第2引数にエラーメッセージをとります.
第1引数がtrueの場合、処理を続行しますが、falseの場合、処理を中断し、変更をリバートします.

コントラクトの作成者のみが残高を引き出せる

contract Wallet {
    address payable public owner;

    constructor() {
        owner = payable(msg.sender);
    }

    // メッセージを呼び出した人(msg.sender) が コントラクトの作成者(owner)であることをチェック
    modifier onlyOwner() {
        require(msg.sender == owner, "オーナーのみ引き出し可能です.");
        _;
    }

    function withdraw(uint _amount) external onlyOwner {
        owner.transfer(_amount);
    }
}

withdrawを呼び出した時に、まず onlyOwner の処理が実行され、その後に_ の場所で withdraw 本体の処理が実行されます.

一つの関数に複数のFunction Modifiersを指定することも可能です.

Events

Eventsは、Loggingやイベント・ウォッチをおこなうプロトコルです.
Eventsは、任意のパラメータを含めることが可能です.

Eventsはパラメータと一緒に、コントラクトアドレスと関連するトランザクション・ログに格納されます.
ブロックチェーンに格納されたEventsのデータは、外部からアクセス可能ですが、コントラクト内からアクセスすることはできません.

また、Eventsのパラメータを定義するときに、indexedをつけることが可能です.
パラメータに indexed を指定することで、そのパラメータを使用して、Eventsをフィルタリングすることができます.
例えば、フロントエンドでEventsをウォッチしている時に、ある値をパラメータに持つものだけ検知したい場合に使用します.

greet を呼び出した時に、Greet イベントを発火する

contract Greetiing {
    event Greet(string message);

    function greet() external {
        emit Greet("Hello");
    }
}

Greet イベントが発火された時のログ

[
    {
        "from": "0xD7ACd2a9FD159E69Bb102A1ca21C9a3e3A5F771B",
        "topic": "0xefdeaaf566f7751d16a12c7fa8909eb74120f42cba334d07dd5246c48f1fba81",
        "event": "Greet",
        "args": {
            "0": "Hello",
            "message": "Hello"
        }
    }
]

Errors

Solidityは、独自のエラーを定義して、その中に任意のパラメータを含めることができます.
エラーが発生した場合、処理が中断されて、変更がリバートされます.

bid 呼び出し時に、Cloesd が発生する

contract Auction {
    error Cloesd(string message);

    function bid() external {
        revert Cloesd("Auction was already finished");
    }
}

Cloesd が発生した時のログ

revert
    The transaction has been reverted to the initial state.
Error provided by the contract:
Cloesd
Parameters:
{
 "message": {
  "value": "Auction was already finished"
 }
}
Debug the transaction to get more information.