[Solidityのはじめ方] Part5: データ型(uint, address, string, bool など)

Solidity

Solidityスマートコントラクト開発の第一歩 🚶‍♀️

Solidityでスマートコントラクトを書く上で、データ型の理解は非常に重要です。データ型とは、変数にどんな種類の情報(数値、文字、アドレスなど)を格納するかを定義するものです。Solidityは静的型付け言語であり、変数を宣言する際には必ず型を指定する必要があります。これにより、コンパイラがコードの正しさをチェックしやすくなります。

Solidityのデータ型は、大きく値型 (Value Types)参照型 (Reference Types) に分けられます。

値型 (Value Types)

値型の変数は、データそのものを直接保持します。関数に渡したり、別の変数に代入したりすると、値がコピーされます。主な値型を見ていきましょう。

ブール型 (bool)

最もシンプルな型で、true (真) または false (偽) の2つの値のみを取ります。条件分岐などでよく使われます。デフォルト値は false です。

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

contract BoolExample {
    bool public isAvailable = true;
    bool public defaultBool; // デフォルト値は false

    function toggleAvailable() public {
        isAvailable = !isAvailable; // true と false を切り替える
    }
}

整数型 (int / uint)

数値を扱うための型です。

  • int: 符号付き整数 (マイナスの値も扱える)
  • uint: 符号なし整数 (0以上の値のみ)

Solidityでは、格納できる値の範囲をビット数で指定できます (8ビットから256ビットまで、8ビット刻み)。例えば、uint8 は0から255 (28-1) まで、uint256 は0から 2256-1 までの非常に大きな数を扱えます。単に uintint と書いた場合は、uint256 および int256 と同じ意味になります。イーサリアムでは、トークンの量など負の値を取らない数値を扱うことが多いため、uint (特に uint256) がよく使われます。デフォルト値は 0 です。

注意: 整数型には扱える値の範囲に上限・下限があります。これを超えるとオーバーフローアンダーフローが発生し、予期せぬ動作や脆弱性の原因となることがあります (Step 5で詳しく学びます)。Solidity 0.8.0以降では、これらのチェックがデフォルトで有効になっています。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract IntegerExample {
    uint256 public positiveNumber = 100; // 符号なし整数 (uint でも可)
    int public negativeNumber = -50;    // 符号付き整数
    uint8 public smallUint = 255;       // 8ビット符号なし整数
    uint public defaultUint;            // デフォルト値は 0

    function add(uint a, uint b) public pure returns (uint) {
        return a + b;
    }
}

アドレス型 (address / address payable)

Ethereumのアカウント (EOA: Externally Owned Account) やスマートコントラクトのアドレス (20バイトの値) を格納するための特別な型です。

  • address: 通常のアドレス型。残高の取得 (balance) などができます。
  • address payable: address 型の機能に加え、Etherの送信 (transfer, send) が可能なアドレス型です。Etherを受け取る関数を持つコントラクトや、Etherを送金する先の変数は payable である必要があります。

アドレス型のデフォルト値は 0x0000000000000000000000000000000000000000 (ゼロアドレス) です。

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

contract AddressExample {
    address public owner;
    address payable public recipient;
    address public defaultAddress; // デフォルト値は 0x00...00

    constructor(address payable _recipient) {
        owner = msg.sender; // スマートコントラクトをデプロイした人のアドレス
        recipient = _recipient;
    }

    function getOwnerBalance() public view returns (uint) {
        return owner.balance; // アドレスのETH残高を取得
    }

    function sendEther(uint amount) public payable {
        // recipient に Ether を送信 (呼び出し元がEtherを付与する必要あり)
        bool success = recipient.transfer(amount);
        require(success, "Failed to send Ether");
    }
}

固定サイズバイト配列 (bytes1 〜 bytes32)

固定長のバイトシーケンスを格納します。bytes1 は1バイト、bytes32 は32バイトのデータを保持できます。文字列よりもガス効率が良い場合があり、ハッシュ値の格納などによく使われます。デフォルト値は全てのバイトが 0x00 で埋められたものです。

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

contract BytesExample {
    bytes1 public oneByte = 0xb5; // 1バイトデータ
    bytes32 public hashValue = 0x123...abc; // 32バイトデータ (例: Keccak256ハッシュ)
    bytes2 public defaultBytes2; // デフォルト値は 0x0000
}

列挙型 (enum)

ユーザーが定義できる型で、定数に名前をつけて管理しやすくします。例えば、コントラクトの状態などを分かりやすく表現できます。内部的には uint として扱われます (通常は uint8)。デフォルト値は最初に定義されたメンバー (以下の例では Pending) です。

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

contract EnumExample {
    enum Status { Pending, Shipped, Delivered, Canceled } // 状態を定義

    Status public currentStatus; // デフォルトは Status.Pending (0)

    function ship() public {
        require(currentStatus == Status.Pending, "Order must be pending to ship.");
        currentStatus = Status.Shipped;
    }

    function deliver() public {
        require(currentStatus == Status.Shipped, "Order must be shipped to deliver.");
        currentStatus = Status.Delivered;
    }

    function getStatus() public view returns (Status) {
        return currentStatus;
    }
}

参照型 (Reference Types)

参照型の変数は、データの値そのものではなく、データが格納されている場所 (メモリやストレージ) を指し示します。そのため、代入や関数の引数として渡す際に、データの場所に関する情報だけがコピーされ、データ自体がコピーされるわけではありません (ただし、ストレージとメモリ間での代入など、場所が変わる場合はコピーが発生します)。

参照型には、配列 (Arrays)、構造体 (Structs)、マッピング (Mappings)、文字列 (string)、動的バイト配列 (bytes) などがあります。これらは後のステップで詳しく学びますが、ここでは stringbytes について簡単に触れます。

文字列 (string)

UTF-8エンコードされた可変長の文字列を扱います。内部的には動的なバイト配列 (bytes) として扱われますが、文字列としての操作が可能です。ただし、Solidityの文字列操作は他の言語ほど機能豊富ではなく、ガス代も比較的高くなる傾向があります。デフォルト値は空文字列 "" です。

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

contract StringExample {
    string public message = "Hello Solidity!";
    string public defaultString; // デフォルト値は "" (空文字列)

    function updateMessage(string memory newMessage) public {
        message = newMessage;
    }

    // 文字列の連結 (ガス代が高め)
    function concatenate(string memory a, string memory b) public pure returns (string memory) {
        return string(abi.encodePacked(a, " ", b));
    }
}

関数の引数やローカル変数として string を使う場合、memory または calldata というデータロケーションを指定する必要があります (Step 4で詳しく学びます)。

動的バイト配列 (bytes)

可変長のバイトシーケンスを格納します。任意のバイナリデータを扱うのに適しています。string と似ていますが、UTF-8エンコーディングを前提としません。デフォルト値は空のバイト配列 0x です。

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

contract DynamicBytesExample {
    bytes public dynamicData;
    bytes public defaultBytes; // デフォルト値は 0x

    function setData(bytes memory newData) public {
        dynamicData = newData;
    }

    function getDataLength() public view returns (uint) {
        return dynamicData.length;
    }
}

今回はSolidityの基本的なデータ型、特に bool, uint/int, address, bytesN, enum, string, bytes について学びました。

ポイント 💡

  • Solidityは静的型付け言語で、変数宣言時に型指定が必須。
  • 値型 (bool, int, uint, address, bytesN, enum) はデータを直接保持し、コピーされる。
  • 参照型 (string, bytes, 配列, 構造体, マッピング) はデータの場所を参照する。
  • 各型にはデフォルト値がある (例: boolfalse, uint0, address0x0...0, string"")。
  • 適切な型を選択することは、コードの可読性、安全性、そしてガス効率 (トランザクション手数料) に影響します。

これらのデータ型は、スマートコントラクトの状態を管理し、ロジックを組み立てるための基礎となります。次のステップでは、これらの型を使って変数や定数を定義する方法を学びます。🚀

参考情報:

コメント

タイトルとURLをコピーしました