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 までの非常に大きな数を扱えます。単に uint
や int
と書いた場合は、uint256
および int256
と同じ意味になります。イーサリアムでは、トークンの量など負の値を取らない数値を扱うことが多いため、uint
(特に uint256
) がよく使われます。デフォルト値は 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) などがあります。これらは後のステップで詳しく学びますが、ここでは string
と bytes
について簡単に触れます。
文字列 (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 Documentation – Types: https://docs.soliditylang.org/en/latest/types.html
- Solidity by Example – Data Types: https://solidity-by-example.org/primitives/
コメント