Solidity

【Solidity】第4章第3回:マッピング(mapping)の基礎

本記事では、Solidityにおけるマッピング(mapping)の基本的な使い方について解説します。マッピングは、キーと値のペアを効率的に管理するためのデータ構造で、スマートコントラクト開発において非常に重要な役割を果たします。

0. 記事の概要

この記事を読むメリット

  • マッピングの基本を理解:キーと値のペアを効率的に管理する方法を学べます。
  • スマートコントラクトの応用力向上:マッピングを使用してデータを簡潔に管理できます。
  • セキュリティの向上:マッピングを使用したデータ保護のベストプラクティスを学びます。

この記事で学べること

  • マッピングの基本構文と使い方
  • マッピングを使用したデータ管理の実例
  • マッピングにおけるよくあるエラーとその解決策

1. マッピングとは?

1.1 マッピングの概要

マッピングは、キーと値のペアを管理するデータ構造です。Solidityでは、mapping(keyType => valueType)の形式で定義します。

1.2 マッピングの基本構文

// マッピングの基本例
contract MappingExample {
    mapping(address => uint256) public balances;

    function setBalance(address account, uint256 amount) public {
        balances[account] = amount;
    }

    function getBalance(address account) public view returns (uint256) {
        return balances[account];
    }
}

動作解説

このコードでは、アドレスをキー、残高を値として管理するマッピングを定義しています。setBalance関数で残高を設定し、getBalance関数で残高を取得できます。

2. マッピングの特徴

2.1 マッピングの特性

  • キーは一意でなければならない
  • 未初期化のキーはデフォルト値を持つ
  • キーと値のペアはストレージに永続的に保存される

2.2 デフォルト値の取り扱い

未初期化のキーにアクセスすると、その型のデフォルト値が返されます。

// デフォルト値の例
contract DefaultValueExample {
    mapping(address => uint256) public balances;

    function checkDefaultValue(address account) public view returns (uint256) {
        return balances[account]; // 初期値は0
    }
}

動作解説

指定されたアドレスがbalancesマッピングに登録されていない場合でも、値は0が返されます。

3. マッピングを使用したデータ管理の実例

3.1 ユーザー登録システム

// ユーザー登録システムの例
contract UserRegistry {
    struct User {
        string name;
        uint256 age;
    }

    mapping(address => User) public users;

    function registerUser(string memory name, uint256 age) public {
        users[msg.sender] = User(name, age);
    }

    function getUser(address userAddress) public view returns (string memory, uint256) {
        User memory user = users[userAddress];
        return (user.name, user.age);
    }
}

動作解説

このコードは、mappingを使用してユーザー情報をアドレスに紐づけて管理します。

3.2 投票システムの例

// 投票システムの例
contract VotingSystem {
    mapping(address => bool) public hasVoted;

    function vote() public {
        require(!hasVoted[msg.sender], "既に投票済みです");
        hasVoted[msg.sender] = true;
    }
}

動作解説

この例では、mappingを使用して、ユーザーが投票したかどうかを追跡します。

4. よくあるエラーとその解決策

4.1 未初期化キーの誤解

未初期化のキーにアクセスするとデフォルト値が返されるため、登録の有無を別途追跡する必要があります。

4.2 高コストな操作

マッピングではキーのリストを取得できないため、すべてのキーを列挙するには別途配列を管理する必要があります。

5. 練習問題

以下の課題に挑戦してみましょう:

  1. アドレスごとに残高を追跡するマッピングを作成し、送金機能を実装してください。
  2. ユーザーの登録履歴を追跡する機能を追加し、登録の有無を確認する関数を作成してください。

6. まとめ

本記事では、Solidityのマッピングの基本を学びました。この強力なデータ構造を使用することで、スマートコントラクトでの効率的なデータ管理が可能になります。次回は、マッピングと構造体の組み合わせについて詳しく解説します。