広告

第10話:条件分岐と繰り返し!if文とforループでロジックを組む

2025年7月31日

第10話:条件分岐と繰り返し!if文とforループでロジックを組む

概要

スマートコントラクトに「知性」を与える、if文(条件分岐)とforループ(繰り返し)の徹底ガイド。状況に応じて振る舞いを変えるif-elseのロジック構築法と、特定の処理を繰り返すforループの使い方を学びます。

特に、ガス代高騰を招き、契約を機能不全に陥らせる危険なループのパターンと、その対策を重点的に解説。安全で賢いロジックを組むための必須知識です。

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

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

続きを見る

はじめに

第9話では、eventを使ってコントラクトの内部で起きた出来事を外部の世界へ通知する方法を学び、DApp開発の全体像が見えてきましたね。

これであなたは、データを定義し(struct, mapping)、機能を実装し(function)、その結果を通知する(event)という、アプリケーションの基本要素をすべて手に入れました。しかし、これまでの関数は、コードが上から下へ、一本道で実行されるだけの、いわば「素直すぎる」プログラムでした。

実際のアプリケーションは、もっと複雑な判断を要求します。 「もしユーザーが会員なら、特典を与える」 「もし残高が足りなければ、エラーを返す」 「配列に入っている全てのアドレスに、順番に処理を行う」

こうした、状況に応じて振る舞いを変える「賢い」ロジックを実装するのが、今回学ぶ**if文(条件分岐)forループ(繰り返し)という制御構文**です。これらは、あなたのコントラクトに「思考力」を与える、まさにプログラムの脳みそにあたる部分です。

if文:コントラクトに「判断力」を与える 🧠

if文は、プログラミングにおける最も基本的な制御構文で、「もし〜という条件が真(true)ならば、{ }内の処理を実行する」という条件分岐を実現します。

その基本構文は、多くの言語と共通しており、非常に直感的です。

Solidity

if (条件式) {
    // 条件式が真(true)のときに実行される処理
}

条件式では、以下のような比較演算子がよく使われます。

  • == : 等しい
  • != : 等しくない
  • > : より大きい
  • < : より小さい
  • >= : 以上
  • <= : 以下

それでは、具体的な例を見ていきましょう。会員ステータスによって、アクセスレベルが変わる機能を実装してみます。

Solidity

// ユーザー情報を管理するコントラクト
contract AccessControl {
    struct User {
        bool isMember;
        // ... 他のユーザー情報
    }
    mapping(address => User) public users;

    // ... ユーザー登録機能などは省略 ...

    // アクセスレベルを確認する関数
    function getAccessLevel() public view returns (string memory) {
        // もし、この関数を呼び出した人(msg.sender)が会員(isMember == true)なら
        if (users[msg.sender].isMember == true) {
            return "フルアクセスを許可します";
        }

        // ifの条件に当てはまらなかった場合
        return "制限付きアクセスです";
    }
}

elseelse ifで、より複雑な分岐を

if文には、elseブロックを組み合わせることで、「もし条件が真ならAを、そうでなければBを実行する」という処理を簡潔に書くことができます。

Solidity

function getAccessLevelWithElse() public view returns (string memory) {
    if (users[msg.sender].isMember == true) {
        return "フルアクセスを許可します";
    } else {
        return "制限付きアクセスです";
    }
}

さらに、else ifを使えば、複数の条件で分岐させることも可能です。

Solidity

mapping(address => uint) public pointBalance;

function checkPointRank() public view returns (string memory) {
    uint points = pointBalance[msg.sender];

    if (points >= 1000) {
        return "プラチナランク";
    } else if (points >= 500) {
        return "ゴールドランク";
    } else if (points >= 100) {
        return "シルバーランク";
    } else {
        return "ブロンズランク";
    }
}

このように、if文を使いこなすことで、関数は状況に応じて最適な応答を返す「判断力」を持つことができるのです。

forループ:処理を「繰り返す」力 ⚙️

forループは、特定の処理を何度も繰り返し実行するための構文です。配列の各要素に対して同じ処理を行いたい場合などに使われます。

基本構文は以下の通りです。

Solidity

for (初期化; 条件式; 加算処理) {
    // 繰り返したい処理
}
  • 初期化: ループの開始前に一度だけ実行されます(例: uint i = 0;)。
  • 条件式: 各ループの開始前に評価されます。真である限りループは続きます。
  • 加算処理: 各ループの終了後に実行されます(例: i++)。

例えば、1から10までの合計を計算する、安全なforループは以下のようになります。

Solidity

function sumFirstTenNumbers() public pure returns (uint) {
    uint total = 0;
    // iを1から始め、10になるまで1ずつ増やしながらループする
    for (uint i = 1; i <= 10; i++) {
        total = total + i;
    }
    return total;
}

⚠️【超重要】forループとガス代の危険な関係

ここで、Solidityにおけるforループの最も重要な注意点をお伝えします。それは、ループ処理は非常に多くのガス代を消費する可能性がある、ということです。

もし、ループの回数が大きすぎたり、ループの上限が定まっていなかったりすると、1回のトランザクションで消費できるガス代の上限(ブロックガスリミット)を簡単に超えてしまいます。そうなると、その関数は永遠に実行不可能になり、コントラクトが意図せず機能停止(Denial of Service)に陥る、という深刻な事態を招きかねません。

鉄則:Solidityのforループは、繰り返し回数が少なく、固定されている、と確信できる場合にのみ使用してください。 ユーザーが任意に追加できるような、要素数が変動する配列に対してループ処理を行うのは、原則として避けるべき危険なパターンです。

安全な使い方を理解した上で、例を見てみましょう。固定された少人数の役員リストに、報酬を分配するようなケースです。

Solidity

// 役員リスト(少人数で固定されていると仮定)
address[] public executives = [
    0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2,
    0x4B20993Bc481177ec7E8f571ceCaE8A9e22C02db
];
mapping(address => uint) public rewards;

function distributeRewards(uint totalReward) public {
    // 警告:このパターンはexecutivesの要素数が少ないからこそ安全です!
    require(executives.length > 0, "No executives.");
    uint rewardPerPerson = totalReward / executives.length;

    for (uint i = 0; i < executives.length; i++) {
        address executive = executives[i];
        rewards[executive] += rewardPerPerson;
    }
}

この例では、ループ回数がexecutives.length(この場合は2回)と決まっているので安全ですが、もしexecutivesに誰でもアドレスを追加できるような機能があれば、非常に危険なコードになります。

まとめ:コントラクトにロジックという魂を

お疲れ様でした!記念すべき第10話では、あなたのコントラクトに「思考する力」を与える、if文とforループを学びました。

  • if, else if, else を使うことで、条件に応じた分岐処理が可能になる。
  • forループを使うことで、繰り返し処理が可能になる。
  • ただし、forループのガス代消費には細心の注意が必要。

これであなたは、Solidity言語の基本的な構成要素(データ型、変数、関数、イベント、制御構文)のほとんどを網羅したことになります。これは大きなマイルストーンです。

これまでの10話で、あなたは「部品」の種類と使い方を学びました。次のステージでは、よりSolidityらしい、イーサリアムのブロックチェーンと密接に関わる概念に焦点を当てていきます。

次回、**第11話「誰が?いくらで?「msg.sender」と「msg.value」でトランザクション情報を取得」**では、これまでも度々登場したmsg.senderを深掘りするとともに、関数呼び出しと同時にETH(イーサ)を受け取るための超重要変数、msg.valueについて学びます。いよいよ、あなたのコントラクトがお金を受け取れるようになります!

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

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

続きを見る

-Solidity