Solidity チートシート
コントラクトの構造
すべてのファイルはライセンスと pragma で始まります。コントラクトはデプロイの単位です。
| 構文 | 意味 |
|---|---|
// SPDX-License-Identifier: MIT | コンパイラが 1 行目に期待するライセンスコメント |
pragma solidity ^0.8.0; | このファイルが対象とするコンパイラのバージョン |
contract Counter { ... } | コントラクトを宣言(状態 + 関数) |
constructor(uint start) { count = start; } | デプロイ時に一度だけ実行される |
import "./Token.sol"; | 別のファイルをインポート |
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ライブラリパッケージをインポート |
interface IToken { function balanceOf(address a) external view returns (uint); } | インターフェースを宣言(本体なし) |
library Math { function min(uint a, uint b) internal pure returns (uint) { ... } } | 再利用可能な関数のライブラリ |
値型
整数は固定サイズで小数を持ちません。0.8 ではオーバーフロー時にリバートします。
| 型 | 格納する値 |
|---|---|
uint256 / uint | 符号なし整数、0 〜 2^256 - 1(uint は uint256) |
uint8, uint16, ... uint128 | 8 ビット刻みの、より小さい符号なし整数 |
int256 / int | 符号付き整数(負の値も可) |
bool | true または false |
address | 20 バイトのアカウントまたはコントラクトのアドレス |
address payable | transfer/send で Ether を受け取れるアドレス |
bytes32, bytes1... | 固定長のバイト配列 |
enum Status { Open, Closed } | 名前付き定数の集合。uint8 として格納 |
1 ether, 1 gwei, 1 wei | Ether の単位:1 ether = 10^18 wei |
1 days, 2 hours, 30 minutes | 時間の単位(秒換算) |
参照型とデータロケーション
配列、文字列、bytes、struct、mapping は storage、memory、calldata のいずれかに置かれます。
| 構文 | 意味 |
|---|---|
string memory name | 動的な UTF-8 文字列(一時的なコピー) |
bytes memory data | 動的なバイト配列 |
uint[] public scores; | storage 上の動的配列 |
uint[3] fixed; | 要素数 3 の固定長配列 |
uint[] memory tmp = new uint[](5); | memory 配列を確保 |
scores.push(42); | storage 配列の末尾に追加 |
scores.pop(); | 最後の要素を削除 |
scores.length | 要素数 |
storage | 永続的でオンチェーン、書き込みコストが高い |
memory | 一時的で、1 回の呼び出しの間だけ存在 |
calldata | 読み取り専用の external 関数の入力。最も安価 |
mapping と struct
mapping は長さも反復もないハッシュテーブルです。struct はフィールドをまとめます。
| 構文 | 意味 |
|---|---|
mapping(address => uint) public balances; | キーと値のストア。すべてのキーが存在する(デフォルトは 0) |
balances[msg.sender] += 1; | キーで読み書き |
mapping(address => mapping(address => uint)) allowance; | ネストした mapping |
struct User { string name; uint age; bool active; } | struct を定義 |
User memory u = User("Ada", 36, true); | memory に struct を作成 |
User memory u = User({name: "Ada", age: 36, active: true}); | 名前付きフィールドで作成 |
users[msg.sender] = u; | struct を mapping に格納 |
users[msg.sender].age = 37; | storage 上のフィールドを 1 つ更新 |
delete users[msg.sender]; | デフォルト値にリセット |
関数と可視性
すべての関数は、誰が呼び出せるか、状態を読むか書くかを宣言します。
| 構文 | 意味 |
|---|---|
function add(uint a, uint b) public pure returns (uint) { return a + b; } | パラメータと戻り値を持つ関数 |
public | どこからでも呼び出せる(内部・外部の両方) |
external | コントラクトの外部からのみ呼び出せる |
internal | このコントラクトと、それを継承するコントラクト |
private | このコントラクトのみ |
view | 状態を読むが、書き込まない |
pure | 状態を一切読まない |
payable | 呼び出しとともに Ether を受け取れる |
returns (uint sum, bool ok) | 複数の名前付き戻り値 |
(uint s, bool ok) = f(); | 複数の戻り値を分解代入 |
uint public count; | public 状態変数には自動でゲッター count() が生成される |
modifier、定数、継承
modifier でチェックを再利用し、constant と immutable で値を固定します。
| 構文 | 意味 |
|---|---|
modifier onlyOwner() { require(msg.sender == owner, "Not owner"); _; } | modifier を定義(_ = 関数本体を実行) |
function withdraw() public onlyOwner { ... } | modifier を適用 |
uint public constant MAX = 100; | コンパイル時定数 |
address public immutable owner; | コンストラクタで一度だけ設定し、以後は固定 |
contract Token is ERC20, Ownable { ... } | 他のコントラクトを継承 |
function f() public virtual { ... } | オーバーライドを許可 |
function f() public override { ... } | 親の関数をオーバーライド |
super.f(); | 親の実装を呼び出す |
abstract contract Base { function f() public virtual; } | 未実装の関数を持つコントラクト |
制御フロー
C 系言語の一般的な文。switch はなく、ループは反復ごとにガスがかかります。
| 構文 | 意味 |
|---|---|
if (x > 5) { ... } else if (x > 2) { ... } else { ... } | 条件分岐 |
for (uint i = 0; i < n; i++) { ... } | カウンタ付きループ |
while (x < 10) { x++; } | 条件が成り立つ間ループ |
do { ... } while (cond); | 少なくとも 1 回は実行 |
break; / continue; | ループを抜ける / 次の反復へスキップ |
x > 0 ? a : b | 三項演算子 |
a / b | 整数除算(余りを切り捨て) |
a % b | 余り |
a ** 2 | べき乗 |
unchecked { x++; } | オーバーフローチェックを省略(ガス節約、慎重に使用) |
エラー:require、revert、assert
チェックに失敗するとトランザクション全体が取り消され、未使用のガスは返金されます。
| 構文 | 意味 |
|---|---|
require(amount > 0, "Amount must be positive"); | 入力や状態を検証し、メッセージ付きでリバート |
revert("Not allowed"); | 無条件に中断 |
error Insufficient(uint available, uint requested); | カスタムエラーを宣言(文字列より安価) |
revert Insufficient(balance, amount); | カスタムエラーでリバート |
assert(total == a + b); | 決して失敗してはならない不変条件をチェック |
try token.transfer(to, amt) returns (bool ok) { ... } catch { ... } | 失敗する外部呼び出しを処理 |
イベント
イベントはオフチェーンのアプリが購読できるログを書き込みます。コントラクトからは読み取れません。
| 構文 | 意味 |
|---|---|
event Transfer(address indexed from, address indexed to, uint value); | イベントを宣言 |
emit Transfer(msg.sender, to, amount); | イベントを発行 |
indexed | フィルタ可能なパラメータ(イベントごとに最大 3 つ) |
event Log(string message); | 任意の ABI 型をログに記録できる |
Ether、アドレス、グローバル変数
トランザクションのコンテキストは msg、block、tx から取得します。
| 構文 | 意味 |
|---|---|
msg.sender | この関数を呼び出したアドレス |
msg.value | 呼び出しとともに送られた wei(payable が必要) |
block.timestamp | 現在のブロック時刻(エポックからの秒数) |
block.number | 現在のブロック高 |
tx.origin | トランザクションを開始した外部所有アカウント(認証には使わない) |
address(this).balance | このコントラクトの Ether 残高 |
payable(to).transfer(1 ether); | Ether を送金。失敗時はリバート |
(bool ok, ) = to.call{value: amt}(""); | 低レベルの送金。成功フラグを返す |
receive() external payable {} | 単純な Ether 送金時に実行される |
fallback() external payable {} | 一致する関数がないときに実行される |
keccak256(abi.encodePacked(a, b)) | 値をハッシュ化 |
abi.encode(x), abi.decode(data, (uint)) | ABI データをエンコード / デコード |
よく使う Solidity 構文を 1 ページに。この Solidity チートシートは、Ethereum とすべての EVM チェーンのスマートコントラクト言語のクイックリファレンスです。コントラクトの宣言、型の選択、mapping と struct へのデータ保存、適切な可視性と状態可変性を持つ関数の記述、require、modifier、イベントによるガードまでを網羅します。
ここで扱う構文は Solidity 0.8 です。デフォルトで算術オーバーフローをチェックし、Remix、Hardhat、Foundry で動作します。必要な部分をコピーするか、Solidity プレイグラウンドでライブに試してみてください。コントラクトを書き、コンパイルし、ブラウザ内の EVM で実行できます。
Solidity cheat sheet FAQ
Is this Solidity cheat sheet free?
Yes. This cheat sheet is free to use, with no sign-up required. Bookmark it and come back any time you need a quick reference.
Is this cheat sheet good for beginners?
Yes. It is organized by topic so you can find what you need at any level, and each entry links back to Coddy's free interactive Solidity course when you want to go deeper.