広告

第5話:コードの心臓部!「関数」を定義してコントラクトを操作可能にする

2025年7月31日

第5話:コードの心臓部!「関数」を定義してコントラクトを操作可能にする

概要

静的なデータ置き場だったコントラクトを、動的なアプリケーションに進化させる「関数」の作り方を解説します。関数の基本構造にはじまり、引数(入力)、戻り値(出力)、可視性(public/private)、そしてガス代を左右する状態可変性(view)まで、その全要素を分解。

カウンター契約の実装を通じ、状態を読み取る関数と書き換える関数を実際に作り、DAppの核心ロジックを構築するスキルを身につけます

目次
Solidity学習講座:最終版 目次(全20話)
Solidity学習講座:最終版 目次(全20話)

基礎編 第1話:未来のインターネットへようこそ!Solidityとスマートコントラクトの全体像 第2話:準備は1分!ブラウザだけで開発できる「Remix IDE」の基本操作 第3話:記念すべき初コント ...

続きを見る

はじめに

第4話までで、あなたはスマートコントラクトの「記憶」の部分、すなわち状態変数をマスターしました。uintで数を、stringで文字を、そしてaddressで参加者を定義する方法を学び、契約の骨格を設計するスキルを身につけましたね。

しかし、今のあなたのコントラクトは、まだ「ただのデータ置き場」です。一度デプロイしたら、そのデータを後から変更したり、計算したり、何かの操作を加えたりすることはできません。これではアプリケーションとは呼べません。

では、どうすれば良いのでしょうか?

その答えが、今回学ぶ**「関数(function)」です。関数とは、コントラクトに「動き」や「振る舞い」を与えるための、まさにコードの心臓部**です。状態変数が契約の「名詞」だとすれば、関数はその「動詞」にあたります。

この記事を読み終える頃、あなたはコントラクトのデータを自在に読み書きするための「関数」を定義できるようになり、あなたのプログラムは、静的なデータ置き場から、動的でインタラクティブなアプリケーションへと進化を遂げるでしょう。

関数とは?コントラクトの「振る舞い」を定義する

関数とは、特定のタスクを実行するための一連のコードをまとめたブロックのことです。これは多くのプログラミング言語に共通する概念ですが、Solidityにおける関数は特に重要な役割を持ちます。

  1. データの読み取り(Read): ブロックチェーンに記録された状態変数の値を読み取って、ユーザーに返す。
  2. データの書き込み(Write): 状態変数の値を変更し、ブロックチェーンの状態を更新する。これにはガス代がかかります。

この「読み取り」と「書き込み」を実装することで、初めてユーザーはコントラクトと対話できるようになるのです。

Solidity関数の基本構造(アナトミー)

まずは、Solidityの関数の基本的な骨格を見てみましょう。これから紹介する要素を組み合わせることで、あらゆる関数を組み立てることができます。

Solidity

function <関数名>(<引数>) <可視性> <状態可変性> returns (<戻り値の型>) {
    // ここに実行したい処理を書く
}

それでは、この構造を一つずつ分解していきます。今回は、シンプルなカウンター機能を例に見ていきましょう。

Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Counter {
    uint public count; // デフォルトで0が設定される
}

このcountという状態変数を操作する関数を作っていきます。

1. functionキーワードと関数名

すべての関数は、functionというキーワードから始まります。その後に関数の役割が分かりやすい名前をつけます。慣習として、camelCase(単語の先頭を大文字にする書き方)が使われます。

function increment() { ... } function getCount() { ... }

2. 引数(Parameters):関数への入力

**引数(ひきすう)**とは、関数が処理を行うために外部から受け取る「入力データ」のことです。「この値を使って処理をしてください」と、関数に値を渡すことができます。

例えば、カウンターの値を特定の値に設定する関数を考えてみましょう。

Solidity

function setCount(uint _newCount) public {
    count = _newCount; // 状態変数countを、受け取った_newCountの値で上書き
}

ここでは、uint型の_newCountという名前の引数を定義しています。関数が呼び出される際に渡された値が_newCountに入り、countの値を更新します。

※慣習として、引数名にはアンダースコア _ を付けて、状態変数と区別しやすくすることがよくあります。

3. 可視性(Visibility):誰がこの関数を呼べるのか?

可視性は、誰がその関数を呼び出すことを許可されているかを定義する、セキュリティ上非常に重要な設定です。現時点では、最も重要な2つを覚えましょう。

  • public: 誰でも呼び出し可能。ユーザー(ウォレット)からも、他のスマートコントラクトからもアクセスできます。外部に公開する機能にはこれを使います。
  • private: このコントラクトの内部からのみ呼び出し可能。他の関数を補助するための、内部的な処理を書きたいときに使います。

例えば、カウンターを1増やすincrement関数は、誰でも実行できてほしいのでpublicにします。

function increment() public { ... }

4. 状態可変性(State Mutability):読み取りか、書き込みか?

これはSolidity特有の面白い概念です。関数がブロックチェーンの状態を変更する可能性があるかどうかを明示的に宣言します。

  • view: 状態を読み取るだけで、一切変更しない関数に付けます。「見るだけ」の関数です。view関数は、外部から呼び出す際にはガス代がかかりません。
  • pure: 状態の読み取りすらしない関数に付けます。引数として受け取った値同士を計算するだけ、といった純粋な計算処理に使います。

現在のcountの値を取得するgetCount関数は、値を変更せず読み取るだけなので、viewを付けるのが適切です。

Solidity

function getCount() public view returns (uint) {
    return count;
}

では、状態を変更する関数(incrementsetCount)には何を付けるのでしょうか? 答えは**「何も付けない」です。viewpureも付いていない関数は、デフォルトで状態を変更する可能性のある関数**と見なされ、実行には必ずガス代がかかります。

5. 戻り値(Return Values):関数からの出力

戻り値は、関数が処理を終えた後に、呼び出し元に返す「出力データ」です。returnsキーワードの後に、返すデータの型と変数名を指定します。

先ほどのgetCount関数は、uint型の値を返すので、returns (uint)と記述されています。関数ブロックの中のreturn count;で、実際に状態変数countの値を返しています。

完成!インタラクティブなカウンター契約

さあ、これまでに学んだ知識を総動員して、インタラクティブなCounterコントラクトを完成させましょう。

Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Counter {
    uint public count;

    // 現在のカウント数を取得する(読み取り専用、ガス代不要)
    function getCount() public view returns (uint) {
        return count;
    }

    // カウントを1増やす(状態変更、ガス代必要)
    function increment() public {
        count = count + 1;
    }

    // カウントを特定の値に設定する(状態変更、ガス代必要)
    function setCount(uint _newCount) public {
        count = _newCount;
    }
}

このコードをRemixに貼り付けてデプロイしてみてください。「Deployed Contracts」には、countpublicな状態変数についてくるゲッター関数)、getCountincrementsetCountの4つのボタンが表示されるはずです。

  • countgetCountをクリックしても、ガス代はかからず、即座に値が返ってきます。
  • 一方、incrementsetCountをクリックすると、ターミナルにトランザクションが記録されます。これは、ブロックチェーンの状態を書き換える「取引」が発生したことを意味し、実際のネットワークではガス代が発生します。

まとめ:コントラクトに命を吹き込む

お疲れ様でした!あなたは今、スマートコントラクトに命を吹き込む「関数」の作り方をマスターしました。

  • 関数は、コントラクトに「振る舞い」を与えるコードのブロックである。
  • 引数で入力を受け取り、戻り値で出力を返すことができる。
  • 可視性public/private)で、誰がアクセスできるかを制御する。
  • 状態可変性view/pure)で、ガス代の有無が決まる読み取り専用か、書き込み可能かを明示する。

ただのデータ置き場だったコントラクトが、外部からの要求に応じてデータを返し、状態を更新する、立派なアプリケーションへと進化しました。この関数の組み合わせこそが、DAppsのロジックの正体です。

さて、今回はpublicprivateという2つの可視性を紹介しました。しかし、安全なコントラクトを構築するためには、この「可視性」について、もう少し深く知る必要があります。

次回、**第6話「誰がアクセスできる?関数の振る舞いを決める4つの「可視性」」**では、internalexternalを加えた4つの可視性すべてを学び、あなたのコントラクトのセキュリティレベルを一段階引き上げます。

-Solidity