Solidity スマートコントラクト言語

Solidityはイーサリアムエコシステムで最も人気のあるスマートコントラクト言語です。構文はJavaScriptに似ていますが、ブロックチェーン上で動作するため、多くの獨特な概念を理解する必要があります。

Solidityのデータ型

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

contract DataTypes {
    // === 基本型 ===
    bool public isActive;           // true / false
    uint256 public count;           // 符号なし整数(0 〜 2^256-1)
    int256 public balance;          // 符号あり整数
    address public owner;           // イーサリアムアドレス(20バイト)
    bytes32 public hash;            // 32バイトのデータ
    string public name;             // 文字列
    
    // === 列挙型 ===
    enum Status { Pending, Active, Inactive, Banned }
    Status public userStatus;
    
    // === 構造体 ===
    struct User {
        string name;
        uint256 age;
        address wallet;
        bool isVerified;
    }
    
    User public defaultUser;
    
    // === 配列 ===
    uint256[] public numbers;       // 動的配列
    uint256[10] public fixedArray;  // 固定サイズ配列
    User[] public users;            // 構造体配列
    
    // === マッピング — 最も重要なデータ構造 ===
    mapping(address => uint256) public balances;      // アドレス → 残高
    mapping(uint256 => address) public idToAddress;   // ID → アドレス
    mapping(address => mapping(uint256 => bool)) public hasClaimed;  // ネスト
    
    constructor() {
        owner = msg.sender;
    }
}

関数修飾子

contract FunctionModifiers {
    address public owner;
    bool public paused;
    
    constructor() {
        owner = msg.sender;
    }
    
    // === 可視性修飾子 ===
    function publicFunction() public {}     // 誰でも呼び出し可能
    function externalFunction() external {} // 外部からのみ(ガス節約)
    function internalFunction() internal {} // このコントラクトと子のみ
    function privateFunction() private {}   // このコントラクトのみ
    
    // === 状態変更修飾子 ===
    function pureFunction() public pure returns (uint256) {
        // pure: ブロックチェーン状態を読み書きしない
        return 42;
    }
    
    function viewFunction() public view returns (address) {
        // view: 読み取りのみ、変更しない
        return owner;
    }
    
    function payableFunction() public payable {
        // payable: ETHを受信可能
    }
    
    // === カスタム修飾子 ===
    modifier onlyOwner() {
        require(msg.sender == owner, "Not the contract owner");
        _;  // 元の関数を実行
    }
    
    modifier whenNotPaused() {
        require(!paused, "Contract is paused");
        _;
    }
    
    function withdraw() public onlyOwner {
        payable(owner).transfer(address(this).balance);
    }
    
    function togglePause() public onlyOwner {
        paused = !paused;
    }
}

イベント(Events)

イベントはSolidityで非常に重要な機能です。発行されるとブロックチェーンのトランザクションログに記録され、フロントエンドがリッスンできます:

contract EventsExample {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Deposit(address indexed user, uint256 amount, uint256 timestamp);
    
    mapping(address => uint256) public balances;
    
    function deposit() public payable {
        balances[msg.sender] += msg.value;
        emit Deposit(msg.sender, msg.value, block.timestamp);
    }
    
    function transfer(address to, uint256 amount) public {
        require(balances[msg.sender] >= amount, "Insufficient balance");
        balances[msg.sender] -= amount;
        balances[to] += amount;
        emit Transfer(msg.sender, to, amount);
    }
}

継承(Inheritance)

contract Base {
    event Log(string message);
    function foo() public virtual { emit Log("Base.foo"); }
}

contract Middle is Base {
    function foo() public virtual override { emit Log("Middle.foo"); }
}

contract Child is Middle {
    function foo() public override {
        super.foo();
        emit Log("Child.foo");
    }
}

エラーハンドリング

contract ErrorHandling {
    // 1. require() — 最も一般的。ガス返金あり
    function checkRequire(uint256 x) public pure {
        require(x > 0, "Value must be positive");
    }
    
    // 2. revert() — 条件付きリバート
    function checkRevert(uint256 x) public pure {
        if (x == 0) { revert("Value cannot be zero"); }
    }
    
    // 3. assert() — 内部エラー用(全ガス消費)
    function checkAssert(uint256 x) public pure {
        assert(x <= type(uint256).max);
    }
}

単位とグローバル変数

contract UnitsGlobals {
    // === イーサ単位 ===
    uint256 public weiUnit = 1 wei;
    uint256 public gweiUnit = 1 gwei;      // = 10^9 wei
    uint256 public etherUnit = 1 ether;     // = 10^18 wei
    
    // === 時間単位 ===
    uint256 public oneMinute = 1 minutes;
    uint256 public oneHour = 1 hours;
    uint256 public oneDay = 1 days;
    uint256 public oneWeek = 1 weeks;
    
    // === グローバル変数 ===
    function getGlobals() public view returns (
        address, uint256, uint256, uint256
    ) {
        return (
            msg.sender,      // 呼び出し元のアドレス
            block.timestamp,  // 現在のブロックタイムスタンプ
            block.number,     // 現在のブロック番号
            block.chainid     // チェーンID(1 = Ethereumメインネット)
        );
    }
}

Vibe Codingでスマートコントラクト作成

🔥 【Solidity Vibeプロンプト】 「クラウドファンディングのスマートコントラクトを作成: 1. 募資金額(例:10 ETH)と期限を設定 2. 誰でも期限内に寄付可能 3. 目標達成時、所有者が資金を引き出せる 4. 未達成時、寄付者は返金を受け取れる 5. 寄付と返金時にイベントを発行 6. OpenZeppelinのOwnableでアクセス制御」

まとめ

| 概念 | 説明 | |------|------| | データ型 | uint, int, bool, address, bytes, string, enum, struct | | マッピング | キー・バリューストア、最も一般的なデータ構造 | | 可視性 | public, external, internal, private | | 修飾子 | pure, view, payable, カスタム (onlyOwner等) | | イベント | ブロックチェーンログ、フロントエンドで購読 | | エラー処理 | require()(ガス返金), revert()(条件付き), assert()(不変条件) | | 単位 | wei, gwei, ether; seconds, minutes, hours, days | | グローバル変数 | msg.sender, block.timestamp, block.number, block.chainid | | 継承 | virtual/overrideによる多重継承 |

練習問題

💡 Vibe練習: AIにクラウドファンディングコントラクトを作成してもらいましょう:

  1. ユーザーがETHを寄付できる
  2. 目標金額と期限を設定
  3. 目標未達時は寄付者に返金
  4. すべてのアクションでイベントを発行
  5. 修飾子でアクセス制御

次の章

次章では、学んだ知識を活かして、バーン機能・税金・一時停止機構を備えた本格的なERC-20トークンを発行します!

会員限定無料チュートリアル

このチャプターは登録会員限定の無料コンテンツです!ログインまたは登録してすぐにロックを解除してください。

今すぐログイン / 登録