跳至內容
0%

什麼是 Yul?

發布於 2023年7月28日閱讀時間 2 分鐘

Yul 是一種中間程式語言,可用來在智能合約中撰寫組合語言的形式。雖然我們常看到 Yul 用在智能合約內部,但你也可以完全用 Yul 撰寫一個智能合約。

理解 Yul 能提升你的智能合約撰寫能力,並讓你了解 solidity 底層的運作原理,進而幫助你節省使用者的 gas 成本。

我們可以透過以下語法在智能合約中辨識出 Yul。

在本文接下來的部分,我們將透過範例討論使用 Yul 的基礎知識,並建議你在 Remix 中一併操作。

Yul 中的變數賦值、運算與求值

我們首先要介紹的是簡單的運算。Yul 有 +、-、、/、%、、<、> 和 =。

請注意,>= 和 <= 並不在 Yul 可用運算子的清單中,因為 Yul 沒有這些運算子。此外,求值的結果不是 true 或 false,而是分別對應 1 或 0。話不多說,我們開始學習一些 Yul 吧!

Instruction
Explanation

let

This is required before defining a variable. Since all values are bytes, there is no need to assign a value type.

:=

Solidity equivalent: x = y

add(x,y)

Solidity equivalent: x + y

sub(x,y)

Solidity equivalent: x - y

mul(x,y)

Solidity equivalent: x * y

div(x,y)

Solidity equivalent: x / y (or 0 if y equals 0)

mod(x,y)

Solidity equivalent: x % y (or 0 if y equals 0)

lt(x,y)

Solidity equivalent: x < y

gt(x,y)

Solidity equivalent: x > y

eq(x,y)

Solidity equivalent: x == y

iszero(x)

Solidity equivalent: x == 0

在繼續之前,讓我們先快速看一個範例。

Yul 中的 for 迴圈與 if 陳述式

為了學習 for 迴圈和 if 陳述式,讓我們撰寫一個函式,計算一系列數字中有多少個偶數。

if 陳述式的語法與 Solidity 類似,但你不需要將條件放在括號中。

至於 for 迴圈,請注意我們在宣告 i 及遞增 i 時使用了大括號,但在評估條件時則沒有使用。此外,我們用了 continue 來跳過迴圈的某次迭代。在 Yul 中我們也可以使用 break 陳述式。

Yul 中儲存體(storage)的運作方式

一個智能合約有 2²⁵⁶ 個儲存槽(slot)。在宣告變數時,我們從第 0 個槽開始,依序遞增。每個槽長度為 256 位元(32 bytes);這也是 uint256 和 bytes32 名稱的由來。所有變數都會被轉換為十六進位。如果使用的是像 uint128 這樣的變數,我們不會用整個槽來儲存它,而是在左側以 0 填補。

想進一步了解 Yul 儲存體的運作方式,可以閱讀我們另一篇涵蓋以下主題的文章:

  1. 陣列(Arrays)
  2. 動態陣列(Dynamic arrays)
  3. 映射(Mappings)
  4. 巢狀映射(Nested Mappings)

如何在 Yul 中讀寫封裝變數(packed variables)

封裝變數(packing variables)指的是安排變數順序,使其儲存空間總和小於 32 bytes,讓它們能一起放入同一個槽中!封裝變數可以節省 gas,是智能合約優化的重要技巧。

舉例來說,0x0000000000000000000000000000020x000000000000000000000000000001 剛好能完美地放入同一個槽,因為它們各佔 16 bytes(半個槽)。

想進一步了解如何在 Yul 中讀寫封裝儲存變數,歡迎閱讀我們的深入解析文章!

Yul 中的記憶體(memory)如何運作?

記憶體的行為與儲存體不同,因為它不具持久性(也就是說,一旦函式執行完畢,所有變數都會被清除)。Yul 中記憶體的一些用途包括:

  1. 回傳外部呼叫的值
  2. 設定外部呼叫的函式值
  3. 從外部呼叫取得值
  4. 以錯誤訊息字串進行 revert
  5. 記錄訊息(logging)

想進一步了解 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 開發者產品與工具,並提供資源、社群與卓越的支援。