イーサリアムスマートコントラクト開発におけるSolidity基礎仕様

ガスの計算と上限管理

計算リソースの消費量を計測する単位です。取引がブロックに取り込まれる際、ネットワークのセキュリティ維持者への報酬として機能します。各取引には実行の上限(gasLimit)と単価(gasPrice)が設定され、バリデーターは単価が高いものから優先的に処理します。実行中に設定した上限を超えた場合、処理は即座に停止し、それまでの状態変更は全て元に戻されます(リバート)。消費されなかったガスは発信元に返還されますが、上限到達時は返還対象外となります。

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

contract GasDemo {
    uint256 public counter = 0;

    // 故意にガスを使い切るデモンストレーション
    function exhaustGas() external {
        while (true) {
            counter++;
        }
    }
}

ノードクライアントの構成

イーサリアムプロトコルを実装したソフトウェアです。データを完全に同期する「フルノード」は、ネットワークの全履歴をローカルに保持するため信頼性が高いものの、ストレージと計算資源の要件が厳しくなります。一方、「ライトノード」はブロックヘッダーのみを同期し、フルノードにクエリを発行して必要なデータを取得するため、リソース消費が少なくモバイルウォレットや軽量アプリケーションに適しています。

通貨単位と変数のスコープ

ネットワーク上の取引は最小単位「wei」で処理されます。1 ether は 10 の 18 乗 wei に相当します。Solidity ではデフォルトでこの単位がサポートされており、コード内で直接記述可能です。

変数は保存先と寿命によって分類されます。

  • 状態変数:コントラクト内の関数外で宣言され、ブロックチェーン上に永久に保存されます。
  • 局所変数:関数内で宣言され、実行時のメモリ上で一時的に保持されるのみで、チェーンには記録されません。
  • グローバル変数:ブロック情報や取引メタデータ(例:msg.sender, block.timestamp)にアクセスするための予約済みの変数群です。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract VariableTypes {
    string public storeData = "Initial";
    uint256 public recordCount = 0;

    function process() external {
        uint256 tempVal = 789; // メモリ上の局所変数
        address caller = msg.sender;
        uint256 currentBlock = block.number;
        // 処理ロジック
    }
}

定数と不変変数の最適化

コンパイル時に値が決定される定数(constant)はバイトコードに直接埋め込まれ、ガス消費を抑えられます。一方、不変変数(immutable)はデプロイ時(コンストラクタ内)に一度だけ値を設定でき、その後変更不可となります。これらもチェーン上のストレージではなくバイトコードやメモリに配置されるため、コスト効率が優れています。

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

contract FixedValues {
    address public immutable DEPLOYER;
    uint256 public immutable START_TIME;

    constructor(uint256 _startTime) {
        DEPLOYER = msg.sender;
        START_TIME = _startTime;
    }
}

制御構文と関数修飾子

条件分岐やループ構文は一般的なプログラミング言語と類似していますが、ループ処理には注意が必要です。イテレーション回数が不明瞭なループはガス上限に達し、取引が失敗するリスクがあるため、可能な限り配列の全走査を避ける設計が推奨されます。

関数修飾子 view はチェーン上の状態を読み取れますが変更はできません。pure は状態の読み取りも書き込みも禁止され、入力引数のみで計算を完結させます。これらの修飾子を持つ関数は、外部から呼び出された場合(トランザクションではなくコールとして)、ガス消費を回避できます。

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

contract LogicFlow {
    function checkRange(uint256 _value) external pure returns (uint8) {
        if (_value < 10) return 0;
        if (_value < 20) return 1;
        return 2;
    }

    function evaluate(bool _flag) external pure returns (uint256) {
        return _flag ? 100 : 200;
    }
}

マッピングの構造と制約

キーと値のペアを格納する連想配列です。mapping(KeyType => ValueType) で定義されます。内部でハッシュテーブルを使用するため、全てのキーを列挙するイテレーションはサポートされていません。存在しないキーにアクセスすると、型のデフォルト値が返されます。

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

contract DataStore {
    mapping(address => uint256) public balances;

    function update(address _user, uint256 _amount) external {
        balances[_user] = _amount;
    }

    function clear(address _user) external {
        delete balances[_user];
    }
}

イベントログの発行と活用

EVM のログ機能を抽象化したもので、オンチェーンのストレージと比較して極めて低コストでデータを記録できます。フロントエンドやインデクサーは RPC を通じてイベントを購読し、UI の更新やデータ分析に活用します。indexed 修飾子を付与したパラメータは、フィルタリングや高速検索の対象となります(最大3つまで)。イベントの出力はトピック(関数シグネチャのハッシュ)と引数の配列としてログに保存され、外部システムから効率的に解析可能です。

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

contract Logger {
    event RecordCreated(address indexed author, string content);

    function write(string memory _msg) external {
        emit RecordCreated(msg.sender, _msg);
    }
}

タグ: ethereum solidity smart-contracts evm gas-mechanisms

7月12日 19:07 投稿