コンテンツへスキップ
0%

Yulとは?

Mark Jonathas headshot

執筆者 Mark Jonathas

2023年7月28日 公開読了時間 2 分

YulはSolidityより低レベルのプログラミング言語で、スマートコントラクト内でアセンブリ言語の一種を記述するために使用できる中間言語です。Yulはスマートコントラクトの中で使われることが多いですが、スマートコントラクト全体をYulだけで記述することも可能です。

Yulを理解することでスマートコントラクトのレベルを上げ、solidityの内部で何が起きているかを理解できるようになります。それはひいてはユーザーのガスコストを削減する助けになります。

スマートコントラクト内のYulは以下のような構文で識別できます。

この記事の残りの部分では、Yulの基本を例を通して解説します。Remixで実際に手を動かしながら進めることをお勧めします。

Yulにおける変数の代入、演算、評価

最初に取り上げるべきトピックは単純な演算です。Yulには+、-、、/、%、、<、>、=があります。

Yulの演算子一覧に>=や<=が含まれていないことに注意してください。Yulにはこれらの演算子は存在しません。また、評価結果はtrueやfalseではなく、それぞれ1または0になります。それでは、Yulの学習を始めましょう。

Instruction
Explanation

let

変数を定義する前に必要です。すべての値はバイトであるため、値の型を指定する必要はありません。

:=

Solidityにおける相当表現: x = y

add(x,y)

Solidityにおける相当表現: x + y

sub(x,y)

Solidityにおける相当表現: x - y

mul(x,y)

Solidityにおける相当表現: x * y

div(x,y)

Solidityにおける相当表現: x / y(yが0の場合は0)

mod(x,y)

Solidityにおける相当表現: x % y(yが0の場合は0)

lt(x,y)

Solidityにおける相当表現: x < y

gt(x,y)

Solidityにおける相当表現: x > y

eq(x,y)

Solidityにおける相当表現: x == y

iszero(x)

Solidityにおける相当表現: x == 0

先へ進む前に、簡単な例を見てみましょう。

Yulにおけるforループとif文

forループとif文の両方を学ぶために、数列の中に偶数がいくつあるかを数える関数を書いてみましょう。

if文の構文はSolidityと似ていますが、条件を括弧で囲む必要はありません。

forループについては、_i_の宣言とインクリメントの際には波括弧を使いますが、条件の評価には使いません。また、ループの1回の反復をスキップするために_continue_を使用しています。Yulではbreak文も使用できます。

Yulにおけるストレージの仕組み

スマートコントラクトには2²⁵⁶個のスロットがあります。変数を宣言する際は、スロット0から始めて順にインクリメントしていきます。各スロットは256ビット(32バイト)の長さで、これがuint256やbytes32という名前の由来です。すべての変数は16進数に変換されます。uint128のような変数を使用する場合、その変数のためにスロット全体を使うわけではありません。代わりに、左側が0でパディングされます。

Yulのストレージがどのように機能するかについてさらに詳しく知りたい方は、以下を扱っている別の記事をお読みください。

  1. 配列
  2. 動的配列
  3. マッピング
  4. ネストされたマッピング

Yulでパックされた変数を読み書きする方法

変数をパックするとは、変数の合計ストレージサイズが32バイト以内に収まるように順序を決め、複数の変数を1つのスロットに一緒に収められるようにすることです。変数をパックすることでガスを節約でき、スマートコントラクトの最適化における重要なテクニックです。

例えば、0x0000000000000000000000000000020x000000000000000000000000000001はそれぞれ16バイト(スロットの半分)を占めるため、同じスロットにぴったり収まります。

Yulでパックされたストレージ変数を読み書きする方法についてさらに詳しく知りたい方は、詳細記事をお読みください。

Yulにおけるメモリの仕組み

メモリはストレージとは異なる振る舞いをします。永続的ではないため、関数の実行が終わるとすべての変数はクリアされます。Yulにおけるメモリの用途の一部は次の通りです。

  1. 外部呼び出しに対する戻り値の返却
  2. 外部呼び出しのための関数値の設定
  3. 外部呼び出しからの値の取得
  4. エラー文字列によるリバート
  5. メッセージのログ出力

Yulのメモリがどのように機能するかについてさらに詳しく知りたい方は、このトピックをより深く掘り下げた別の記事をお読みください。

Yulにおけるコントラクト呼び出しの仕組み

Yulの構文、ストレージ、メモリの仕組みを理解したら、次はコントラクトの呼び出しです。Yulシリーズの最終記事では、Yulでコントラクトがどのように呼び出されるかを、特に以下を通して説明しています。

  1. call() - アドレスaにあるコントラクトを呼び出し、エラー時は0、成功時は1を返す
  2. staticcall() - call(g, a, 0, in, insize, out, outsize)と同一だが、状態変更を許可しない
  3. delegatecall() - callcodeと同一だが、callerとcallvalueも保持する‍

コントラクト呼び出しの定義に関する詳細は、Yul言語のドキュメントを参照してください。

Background gradient

ブロックチェーンで魔法を生み出す

Alchemyは、最も強力なweb3開発者向けプロダクトとツールを、豊富なリソース、コミュニティ、そして卓越したサポートと組み合わせて提供します。