乙太坊最流行的智慧合約開發語言Solidity新版本發佈

編譯:登鏈翻譯計劃; 來源:soliditylang.org

Solidity 編譯器的最新版本 v0.8.22的發佈。 0.8.22版本的編譯器包含了一系列的語言和編譯器改進,例如檔級事件定義、unchecked 迴圈增量優化、支援導入 EVM 彙編 JSON 等等。

重要提示

本次發佈廢棄了對低於 Constantinople(君士坦丁堡) 版本的 EVM 的支持,這些版本越來越難以維護。 這些古老的版本在乙太坊主網和測試網路上早已過時,我們懷疑它們對其他網路也不再相關。 複雜的代碼路徑和解決方案會減慢針對新版本的功能開發和測試的速度,因此我們希望在未來的編譯器版本中停止支持它們。 如果你依賴這些 EVM 版本的支援,請與我們聯繫[6] 。

新功能亮點

unchecked 迴圈增量

在增加迴圈計數器時使用 unchecked 算術運算是為了 gas 優化[7] 的常見做法。 讓我們以以下迴圈和計數器 i 的示例來說明:

for (uint i = 0; i < array.length; ++i) { acc += 陣列[i] ;i 未被循環體修改 }

在許多情況下(詳見下文的精確條件),比較操作將確保 i 永遠不會達到其類型的最大值,因此可以安全地假設在達到最大值之前迴圈將停止。 在這種情況下,對計數器進行安全檢查將是多餘的,也是一種 gas 的浪費。 這就會鼓勵使用者使用冗長的 unchecked 模式,將計數器增量包裝在迴圈體內的unchecked算術塊中,繞過檢查:

for (uint i = 0; i < array.length;){ acc += 陣列[i] ; unchecked { i++; } -- 我在沒有溢出檢查的情況下遞增 -- 使用的 gas 更少 }

Solidity 0.8.22 引入了一種溢出檢查優化,自動生成了對於迴圈計數器的 unchecked 算術增量。 這個新的優化消除了在迴圈體中使用類似前面示例中的冗長 unchecked 增量模式的需要。

相比之下,新的優化使用戶能夠在不犧牲gas效率的情況下返回到原始的、更易讀的代碼。

新優化避免溢出檢查的精確條件如下:

  • 循環條件是形如 i < ... 的比較,其中 i 是一個局部變數(從現在開始稱為“循環計數器”)。
  • 此比較必須在與循環計數器相同的類型上執行,即右側的類型必須可以隱式轉換為迴圈計數器的類型,以使迴圈計數器在比較之前不會被隱式擴展。
  • 循環計數器必須是內置整數類型的局部變數。
  • 循環運算式必須是循環計數器的前綴或後綴遞增,即 i++ 或 ++i。
  • 循環計數器不能在迴圈條件或循環體中被修改。

為了澄清第二個條件,考慮以下代碼片段:

for (uint8 i = 0; in < UINT16(1000); ++I) { 環體 }

在這種情況下, i 在比較之前被轉換為 uint16,並且條件實際上永遠不會為假,因此無法刪除遞增的溢出檢查。

另外,請注意, < 是唯一會觸發該優化的比較運算符。 故意排除了運算子 <= 和其他運算符。 此外,該運算符必須是內置的 - 用戶定義的 < 不符合條件。

該優化是直接的且總是有益的,因此即使使用通用設置 settings.optimizer.enabled 禁用了優化器的其餘部分,它也會被啟用。 可以通過在標準 JSON 輸入中將 settings.optimizer.details.simpleCounterForLoopUncheckedIncrement 設置為 false 來明確關閉它。 無法使用命令列介面禁用它。

調整Yul優化器以重新生成零字面量

新版本在 0.8.20 版本引入的 PUSH0 操作碼的支持基礎上進行了構建,通過將 Rematerialiser[8] [9] 優化步驟擴展為始終重新生成零字面量而不是將其存儲為變數引用,從而允許使用 PUSH0 而不是 DUP 來降低gas成本。 為確保有效執行此操作,將 Rematerialiser 和 UnusedPruner 步驟添加到了Yul優化器的預設清理序列中。

添加對導入 EVM 彙編 JSON 的支持(實驗性)

這個新版本添加了對導入 EVM 彙編的實驗性支援,為外部工具在位元組碼生成之前執行超級優化提供了可能性。 此功能的主要目的是定義一種低級 EVM 彙編的序列化格式,使編譯器生成的彙編可以被導出、修改和重新導入,從而恢復正常的編譯過程。

重要提示:這是一個實驗性功能,目前不適用於生產環境。 我們在此版本中提供此功能,以便你嘗試並提供反饋。

允許在檔案級別定義事件

Solidity 0.8.22 允許你在文件級別定義事件。 現在,事件定義可以放在合約範圍之外。 這為代碼組織提供了另一種選擇,無需人為地將事件包裝在庫中。

此外,此版本還修復了一個錯誤,該錯誤導致在為代碼發出在外部合約或介面中定義的事件時生成 NatSpec 時出錯。 在上一個版本(0.8.21)中,Solidity編譯器添加了對在當前合約未繼承的合約和介面中定義的事件的限定訪問的支援,但該錯誤阻止了該功能的完全使用。

通過此錯誤修復和允許文件級別事件定義,Solidity的最新版本使用戶能夠編譯以下範例而不會出現任何錯誤:

接口 I { 事件 ForeignEvent(); } 合約 C { 事件 ForeignEvent(); } 事件 E(); 合約 D { 函數 f() public { 發出外部事件將在 0.8.21 上觸發內部錯誤 發出 I.ForeignEvent(); 發出 C.ForeignEvent(); 發出檔級事件。新功能。 發出 E(); } }

完整的更改紀錄

語言特性

  • 允許在檔案等級定義事件。

編譯器特性

  • 代碼產生器:當計數變數不會溢出時,刪除某些for迴圈的冗餘溢出檢查。
  • 命令行介面:添加--no-import-callback選項,防止編譯器載入未在 CLI 或標準 JSON 輸入中明確給出的源檔。
  • 命令行介面:添加實驗性的--import-asm-json選項,可以導入以--asm-json使用的格式的 EVM 彙編。
  • 命令行介面:對於在編譯 pipeline 之外產生的錯誤消息,使用適當的嚴重性和著色。
  • EVM:棄用對“homestead”、“tangerineWhistle”、“spuriousDragon”和“byzantium” EVM 版本的支援。
  • 解析器(Parser):刪除實驗性的錯誤恢復模式(--error-recovery / settings.parserErrorRecovery)。
  • SMTChecker:支援使用者定義的運算符。
  • Yul 優化器:如果支援PUSH0,優先使用零字面量而不是將零值存儲在變數中。
  • Yul 優化器:在預設的清理序列的末尾運行Rematerializer和UnusedPruner步驟。

Bug 修復

  • 代碼產生器:修復通過 via-IR 代碼生成器輸出的結果依賴於導入回調中發現的文件的問題。 在某些情況下,不同的 AST ID 分配會改變內部調度中函數的順序,導致表面上不同但在語義上等效的位元組碼。
  • NatSpec:修復在請求合約的用戶文檔或開發文檔時出現內部錯誤的問題,該合約發出了在外部合約或介面中定義的事件。
  • SMTChecker:修復編碼錯誤,導致迴圈在完成後展開。
  • SMTChecker:修復常量條件檢查的不一致性,當 while 或 for 迴圈在條件檢查之前展開時。
  • Yul 優化器:修復在 CSE 期間受編譯器生成的Yul變數名影響替換決策的問題,在某些情況下導致不同(但等效)的位元組碼。
查看原文
此頁面可能包含第三方內容,僅供參考(非陳述或保證),不應被視為 Gate 認可其觀點表述,也不得被視為財務或專業建議。詳見聲明
  • 讚賞
  • 留言
  • 分享
留言
0/400
暫無留言
交易,隨時隨地
qrCode
掃碼下載 Gate APP
社群列表
繁體中文
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)