ガスの計算と上限管理
計算リソースの消費量を計測する単位です。取引がブロックに取り込まれる際、ネットワークのセキュリティ維持者への報酬として機能します。各取引には実行の上限(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);
}
}