買以太坊 買以太坊
Ctrl+D 買以太坊
ads

DIT:四大 EVM 編程語言權衡對比:Solidity、Vyper、Huff 及 Yul_SOL

Author:

Time:1900/1/1 0:00:00

本文探討以下問題:哪種智能合約語言更有優勢,Solidity還是Vyper?最近,關于哪種是“最好的”智能合約語言存在很多爭論,當然了,每一種語言都有它的支持者。

這篇文章是為了回答這場辯論最根本的問題:

我應該使用哪一種智能合約語言?

為了弄清問題的本質,我們將先討論語言的工具和可用性,然后再考慮智能合約開發者主要關心的問題之一:gas優化。具體來說,我們將研究四種EVM語言:Solidity、Vyper、Huff和Yul。Rust并不在其中,它應該出現在一篇關于非EVM鏈的文章。

但首先,劇透一下結果。

Solidity、Vyper、Huff和Yul都是可以讓你完成工作的優秀語言。Solidity和Vyper是高級語言,大多數人都會用到。但是如果你有興趣編寫近乎匯編的代碼,那Yul和Huff也可以勝任。

所以如果你堅持選擇其中一個使用,那就拋硬幣吧:因為無論你選擇哪種語言,都是可以完成項目的。如果你是智能合約的新手,完全可以使用任何一種語言來開始你旅程。

此外,這些語言也一直在變化,你可以挑選特定的智能合約和數據,從而使得運行它們的不同的語言,表現出來的更好或者更差的效果。所以請注意,為了避免不客觀,我們在比較不同語言在gas優化上的優劣時,都選擇了最簡的智能合約作為例子,如果你有更好的例子,也請分享給我們!

現在,如果你是這個領域的老手,讓我們深入了解這些語言,看看它們的細節吧。

EVM編程語言

我們將要研究的四種語言如下:

Solidity:目前DeFiTVL占比最大的語言。是一種高級語言,類似于JavaScript。Vyper:目前DeFiTVL排名第二的語言。也是一種高級語言,類似于Python。Huff:一種類似于匯編的底層語言。Yul:一種類似于匯編的底層語言,內置于Solidity。為什么是這四個?

使用這四種語言,是因為它們都與EVM兼容,而且其中的Solidity和Vyper是迄今為止最受歡迎的兩種語言。我添加了Yul,因為在不考慮Yul的情況下,與Solidity進行gas優化比較是不全面的。我們添加了Huff是因為想以一種不是Yul,但是與幾乎就是在用opcode編寫合約的語言作為基準。

就EVM而言,在Vyper和Solidity之后,第三、第四和第五的流行程度也越來越高。對于沒有在本文中比較的語言;只是因為它們的使用度不高。然而,有許多很有前景的智能合約語言正在興起,我期待能夠在未來嘗試它們。

什么是Solidity?

Solidity是一種面向對象的編程語言,用于在以太坊和其他區塊鏈上來編寫智能合約。Solidity深受C++、Python和JavaScript的影響,并且專為EVM而設計。

什么是Vyper?

Vyper是一種面向合約的類似于Python的編程語言,也是為EVM設計的。Vyper增強了可讀性,并且限制了某些用法,從而改進了Solidity。理論上,Vyper提升了智能合約的安全性和可審計性。

OKX Ventures合伙人Jeff Ren:Web3正在重塑創作者經濟:3月22日,OKX Ventures合伙人Jeff Ren受邀出席香港2023 OUTLAND藝術展并參與圓桌討論,與香港本土企業Keneti創始人兼管理合伙人Jehan Chu,以及NFT收藏者Karma Pocket共講。

Jeff Ren在討論中表示,Web3正在重塑創作者經濟,Web3利用區塊鏈技術讓人們構建一個開放、自由、透明的社區,有效地溝通、分享快樂和價值,并降低信任成本和溝通成本。比如NFT生成藝術,利用智能合約創建,并以NFT形式存儲在區塊鏈上,將代碼和藝術融合在一起,讓創作者通過NFT分享快樂,獲得創作收益的同時,增加NFT持有者的社區歸屬感,讓持有者覺得他們是社區的一部分。

據悉,OKX Ventures是全球領先數字資產交易平臺OKX旗下的投資機構,專注于探索全球優質項目,支持最前沿的區塊鏈技術創新,已成功投資了基礎設施、DeFi、GameFi、Web3、元宇宙及NFT五大領域的超300個項目,推動全球區塊鏈行業的可持續發展。[2023/3/22 13:19:50]

當前的情況

來源于DefiLlama語言分析數據

根據DefiLlama的數據,截至目前,在DeFi領域,Solidity智能合約獲得了87%的TVL,而Vyper智能合約獲得了8%。

因此,如果你純粹基于受歡迎程度來選擇語言的話,除了Solidity,就不需要看別的了。

比較相同的合約

現在讓我們了解每種語言寫出的合約的是什么樣的,然后比較它們的gas性能。

這是用每種語言編寫的四份幾乎相同的合同。做了大致相同的事情,它們都:

Storageslot0有一個私有變量number(uint256)。有一個帶有readNumber()函數簽名的函數,它讀取storageslot0中的內容。允許你使用storeNumber(uint256)函數簽名更新該變量。這就是這個合約做的操作。

我們用來比較語言的所有代碼都在這個GitHubrepo中:

https://github.com/PatrickAlphaC/sc-language-comparison

Solidity

Vyper

Huff

比特幣波動率創歷史新低:金色財經報道,據Reflexivity Research聯合創始人Will Clemente在社交媒體發文稱,自 12 月初以來,比特幣波動性一直在下降,目前基本維持在16,000美元區間。數據顯示比特幣波動率于12月25日觸及“0.34”歷史低位,分析顯示,每次波動率低于“1”時,都會出現看漲反彈,迄今只有一次例外(發生在2018 年 10 月)。[2022/12/27 22:10:14]

Yul

開發體驗

通過查看這四張圖片,我們可以大概了解編寫每種語言的感受。就開發人員經驗而言,編寫Solidity和Vyper代碼要快得多。這些語言是高級語言,而Yul和Huff是更底層的語言。僅出于這個原因,就很容易理解為什么這么多人采用Vyper和Solidity。

看一下Vyper和Solidity,你可以清楚地感覺到Vyper是從Python中汲取了靈感,而Solidity是從JavaScript和Java中汲取靈感。因此,如果你對于這幾種語言更熟悉的話,那就能很好地使用對應的智能合約語言。

Vyper旨在成為一種簡約、易于審計的編程語言,而Solidity旨在成為一種通用的智能合約語言。編碼的體驗在語法層面上也是如此,但每個人肯定都有自己的主觀感受。

我不會過多地討論工具,因為大多數這些語言都有非常相似的工具。主流框架,包括Hardhat、ape、titanoboa、Brownie和Foundry,都支持Vyper和Solidity。Solidity在這大多數框架中,都被優先支持,而Vyper需要使用插件才能與Hardhat等工具一起使用。然而,titanoboa是專為與Vyper一起工作而構建的,除此以外,大多數工具對二者支持都很好。

哪一種智能合約語言更節省gas?

現在是重頭戲。在比較智能合約的gas性能時,需要牢記兩點:

合約創建gas成本運行時gas成本

你如何實現智能合約會對這些因素產生重大影響。例如,你可能在合約代碼中存儲大量數組,這使得部署成本高昂但運行函數的成本更低。或者,你可以讓你的函數動態生成數組,從而使合約的部署成本更低,但運行函數成本更高。

那么,讓我們看看這四個合約,并將它們的合約創建gas消耗與其運行時gas消耗進行比較。你可以在我的?sc-language-comparisonrepo?中找到所有的代碼,包括用于比較它們所使用的框架和工具。

sc-language-comparisonrepo:

https://github.com/PatrickAlphaC/sc-language-comparison

Gas消耗比較-總結

以下是我們如何編譯本節的智能合約:

注意:我也可以為Solidity編譯使用–via-ir標志。另請注意,Vyper和Solidity在其合約末尾添加了“metadata”。這占總gas成本的一小部分增加,但不足以改變下面的排名。我將在metadata部分詳細討論這一點。

專家:Web3.0賦能資產管理新型監管和創新發展:金色財經報道,在12月10日舉行的"全球資產管理中心?上海國際活動周2022"分論壇——“資產管理信義責任國際論壇2022”上,上海區塊鏈技術研究中心主任、中國電子學會區塊鏈分會副主任委員馬小峰指出,Web3.0可以在滿足監管前提下,進一步幫助合規集成共享數據,提高相關效率,從而推動更多業務創新,賦能資產管理新型監管和創新發展。(上證報)[2022/12/10 21:36:27]

結果:

創建合約時各個語言所消耗的gas費

正如我們所見,像Huff和Yul這樣的底層語言比Vyper和Solidity的gas效率更高,但這是為什么呢?Vyper似乎比Solidity更高效,我們有這個新的“SolandYul”部分。那是因為你實際上可以在Solidity中編寫Yul。Yul是作為Solidity開發人員在寫更接近機器代碼時而創建的。

因此,在上圖中,我們比較了原始Yul、原始Solidity和Solidity-Yul組合。我們代碼的Solidity-Yul版本如下所示:

Yul和Solidity結合的合約

稍后你將看到一個示例,其中這個inline-Yul對gas消耗產生了重大影響。稍后我們將看看為什么存在這些gas差異,但現在讓我們看看與Foundry中的單個測試相關的gas消耗。

我們的測試函數

這將測試將數字77存儲在storage中,然后從storage中讀取這個數字的gas成本。以下是運行此測試的結果。

SimpleStorage讀和寫的gas對比

我們沒有Yul的數據,因為獲取這個數據必須制作一個Yul-Foundry插件,我不想做-而且結果可能會與Huff相似。請記住,這是運行整個測試函數的gas成本,而不僅僅是單個函數。

Gas消耗對

好,我們來分析一下這個數據。我們需要回答的第一個問題是:為什么Huff和Yul合約的創建比Vyper和Solidity的gas效率高得多?我們可以通過直接查看這些合約的字節碼來找到答案。

當你寫智能合約時,它通常被分成兩個或三個不同的部分。

合約創建代碼運行時代碼Metadata(非必需)

對于這部分,了解opcode的基礎知識很重要。OpenZeppelin關于解構合約的博客幫助你從零開始學習相關知識:

QTC推出移動端錢包:據官方消息,QTC官方開發的移動端app錢包即將面世,適用于iOS和Android系統,全球范圍內都可以在App Store內下載使用,目前正在進行Android和iOS系統測試,預計在7月30日24:00前完成,并全網開源。[2022/7/21 2:28:23]

https://blog.openzeppelin.com/deconstructing-a-solidity-contract-part-i-introduction-832efd2d7737/

合約創建代碼

合約創建代碼是字節碼的第一部分,告訴EVM將該合約寫到到鏈上。你通常可以通過在生成的二進制文件中查找CODECOPYopcode(39),然后找到它在鏈上的位置,并使用RETURNopcode(f3)返回并結束調用。

你還會注意到很多feopcode,這是INVALID操作碼。Solidity添加這些作為標記以顯示運行時、合約創建和metadata代碼之間的差異。f3是RETURN操作碼,通常是函數或context的結尾。

你可能會認為,因為Yul-Solidity的合約創建字節碼所占空間最大而Huff的字節碼所占空間最小,所以Huff最便宜而Yul-Solidity最貴。但是當你復制整個代碼庫并將其發到到鏈上時,代碼庫的大小會產生很大的差異,這才是決定性因素。然而,這個合約創建代碼確實讓我們了解了編譯器的工作原理,即他們將如何編譯合約。

怎么讀取Opcode和Stack

目前,EVM是一個基于堆棧的機器,這意味著你所做的大部分“事情”都是從堆棧中push和pull內容。你會在左邊看到我們有opcode,在右邊我們有兩個斜杠(//)表示它們是注釋,以及在同一行執行opcode后堆棧的樣子,左邊是棧頂部,右邊是棧底。

Huffopcode的解釋

Huff合約的創建只做了它能做的最簡單的事情。它獲取你編寫的代碼,并將其返回到鏈上。

Yulopcode的解釋

Yul做同樣的事情,它使用了一些不同的opcode,但本質上,它只是將你的合約代碼放在鏈上,使用盡可能少的操作碼和一個INVALIDopcode。

Vyperopcode解釋

Vyper也基本做了同樣的事情。

以太坊L2網絡總鎖倉量為44.7億美元:金色財經報道,L2BEAT數據顯示,截至5月30日,以太坊Layer2上總鎖倉量為44.7億美元。其中鎖倉量最高的為擴容方案Arbitrum,約24.億美元,占比53.97%。其次是dYdX,鎖倉量9.54億美元,占比21.33%。Optimism占據第三,鎖倉量4.69億美元,占比10.5%。[2022/5/30 3:49:48]

Solidityopcode解釋

現在讓我們看看Solidity的opcode。

Solidity做了更多的事情。Solidity做的第一件事是創建一個叫FreeMemoryPointer的東西。為了在內存中創建動態數組,你需要記錄內存的哪些部分是空閑可供使用的。我們不會在合約構造代碼中使用這個FreeMemoryPointer,但這是它在背后需要做的第一件事。這是語言之間的第一個主要區別:內存管理。每種語言處理內存的方式不同。

接下來,Solidity編譯器查看你的代碼,并注意到你的構造函數不是payable。因此,為了確保你不會在創建合約時錯誤地發送了ETH,它使用CALLVALUEopcode檢查以確保你沒有在創建合約時發送任何通證。這是語言之間的第二個主要區別:它們各自對常見問題有不同的檢查和保護。

最后,Solidity也做了其他語言所做的事情:它將你的合約發到在鏈上。

我們將跳過Solidity-Yul,它的工作方式與Solidity自身類似。

檢查和保護

從這個意義上說,Solidity似乎“更安全”,因為它比其他語言有更多的保護。但是,如果你要向Vyper代碼添加一個構造函數然后重新編譯,你會注意到一些不同之處。

Vyper語言的構造函數

編譯它,你的合約創建代碼看起來更像Solidity的。

它仍然沒有Solidity所具有的內存管理,但是你會看到它使用構造函數檢查callvalue。如果你使構造函數payable并重新編譯,則該檢查將消失。

因此,僅通過查看這些合約創建時的配置,我們就可以得出兩個結論:

在HuffandYul中,你需要自己顯性地寫檢查操作。而Solidity和Vyper將為你進行檢查,Solidity可能會做更多的檢查和保護。

這將是語言之間最大的權衡之一:它們在幕后執行哪些檢查?Huff和Yul這兩種語言不會在幕后做任何事情。所以你的代碼會更省gas,但你會更難避免和追蹤錯誤。

運行時代碼

現在我們對幕后發生的事情有了一定的了解,我們可以看看合約的不同函數是如何執行的,以及它們為何以這種方式執行。

讓我們看看調用storeNumber()函數,在每種語言中,它的值都為77。我通過使用像forgetest–debug“testStorageAndReadSol”這樣的命令使用ForgeDebugFeature來獲取opcode。我還使用了HuffVSCodeExtension。

Huffopcode解釋

有趣的是,如果我們沒有STOP操作碼,我們的Huff代碼實際上會添加一組opcode來返回我們剛剛存儲的值,使其比Vyper代碼更貴。不過這段代碼看起來還是很直觀的,那我們就來看看Vyper是怎么做的吧。我們暫時跳過Yul,因為結果會非常相似。

Vyperopcode解釋

可以看到在存儲值的同時做了一些檢查:

對于functionselector來說,calldata是否有足夠的字節?他們的value是通過call發送的嗎?calldata的大小和functionselector+uint256的大小一樣嗎?所有這些檢查都增加了我們的計算量,但它們也意味著我們更有可能不犯錯誤。

Solidityopcode解釋

這里有很多東西要解釋。這與Huff代碼之間的一些主要區別是什么?

我們設置了一個freememorypointer。我們檢查了發送的value。我們檢查了functionselector的calldata大小。我們檢查了uint256的大小。

Solidity和Vyper之間的主要區別是什么?

Freememorypointer的設置。Stack在某些時候要深度要大很多。這兩者結合起來似乎是Vyper比Solidity便宜的原因。同樣有趣的是,Solidity使用ISZEROopcode進行檢查,而Vyper使用XORopcode;兩者似乎都需要大約相同的gas。正是這些微小的設計差異造成所有的不同。

所以我們現在可以明白為什么Huff和Yul在gas上更便宜:它們只執行你告訴他們的操作,僅此而已,而Vyper和Solidity試圖保護你不犯錯誤。

FreeMemoryPointer

那么這個freememorypointer有什么用呢?Solidity與Vyper之間的gas消耗似乎存在很大差異。freememorypointer是一個控制內存管理的特性——任何時候你添加一些東西到你的內存數組,你的freememorypointer都只是指向它的末尾,就像這樣:

這很有用,因為我們可能需要將動態數組等數據結構加載到內存中。對于動態數組,我們不知道它有多大,所以我們需要知道內存在哪里結束。

在Vyper中,因為沒有動態的數據結構,你不得不說出像數組這樣的對象到底有多大。知道這一點,Vyper可以在編譯時分配內存,并且沒有freememorypointer。

這意味著在內存管理方面,Vyper可以比Solidity進行更多的gas優化。缺點是使用Vyper你需要明確說明你的數據結構的大小并且不能有動態內存。然而,Vyper團隊實際上將此視為一個優勢。

動態數組

暫且不談內存問題,使用Vyper確實必須聲明數組的邊界。在Solidity中,你可以聲明一個沒有大小的數組。在Vyper中,你可以有一個動態數組,但它必須是“有界的”。

這對開發人員體驗很不好,但是,在Web3中,這也可以被視為針對拒絕服務攻擊的保護措施,并防止你的函數中產生大量gas成本。

如果你的數組變得太大,并且你對其進行遍歷,則可能會消耗大量gas。但是,如果你顯性地聲明數組的邊界,你將知道最壞情況。

Solidityvs.Yulvs.SolYul

看看我上面的圖表,使用Solidity和Yul似乎是最糟糕的選擇,因為合約創建代碼要貴得多。這可能適用于較小的項目,因為Solidity做了一些操作來讓Yul運行,但大規模呢?

以Solidity版本和SolYul版本編寫的最受歡迎的項目之一是Seaport項目。

Seaport項目Logo

使用這些語言的最佳方面之一是你可以運行命令來直接從源代碼測試每個合約的gas使用效率。我們添加了一個PR來幫助測試純Solidity合約的gas消耗的命令,因為Sol-Yul合約已經進行了測試。結果非常驚人,你可以在gas-report.txt和gas-report-reference.txt中看到所有數據。

Seaport中合約創建gas消耗的差別

Seaport中函數調用gas消耗的差別

平均而言,函數調用在SolYul版本上的性能提高了25%,而合約創建的性能提高了40%。

這節省了大量的gas。我想知道他們在純粹的Yul中可以節省多少?我想知道他們在Vypervs.Sol-Yul中會節省多少?

Metadata

最后,Metadata。Vyper和Solidity都在合約末尾附加了一些額外的“Metadata”。雖然數量很少,但我們在這里的比較中基本上會忽略它。你可以手動將其刪除,但Solidity團隊也在建一個PR,你可以在編譯時將其刪除。

總結

以下是我對這些語言的看法:

如果你正在編寫智能合約,請使用Vyper或Solidity。它們都是高級語言,有檢查和保護,比如說檢查調用數據大小以及你是否在不應該的情況下不小心發送了ETH。它們都是很棒的語言,所以選擇其中一個并慢慢學習。如果你需要性能特別的高的代碼,Yul和Huff是很棒的工具。雖然我不建議大多數人用這些語言編程,但它們還是值得學習和理解,會讓你更好地了解EVM。Solidity和Vyper之間gas成本的主要區別之一是Solidity中的freememorypointer-一旦你達到高級水平并希望了解工具之間的潛在差異之一,請記住這一點。LookingForward

這些語言將繼續發展,我們也可能會看到更多的語言出現,比如Reachprogramminglanguage和fe。

Solidity和Vyper團隊致力于開發intermediaterepresentationcompilationstep。Solidity團隊有一個–via-ir的flag,這將有助于優化Solidity代碼,Vyper團隊也有他們的venom作為intermediaterepresentation。

無論你選擇哪種語言,你都可以編寫一些很棒的智能合約。祝編碼愉快!

Tags:SOLLIDDITSOLIDsol幣價格走勢圖BolideSmartCredit TokenSOLID幣

幣贏交易所
IGC:一文詳解AIGC:推動元宇宙發展的加速器_igc幣價格

由AI作畫應用Midjourney生成的繪畫作品《太空歌劇院》在今年9月美國科羅納州博覽會上獲得藝術比賽一等獎,吸引了不少人的眼球.

1900/1/1 0:00:00
NFT:Arbitrum鏈游The Beacon該怎么玩?_SNFTS價格

關于TheBeacon TheBeacon是由TreasureDAO在Arbitrum鏈上發行的像素風Free2Play動作角色扮演游戲,游戲玩法包括單人闖關、組隊冒險、休閑裝扮等.

1900/1/1 0:00:00
WEB:觀點:2022年第三季度,獲得 VC 資金最多的行業是 Web3,這是為什么?_3WEB價格

本周,Pitchbook發布了最新的新興技術指標(ETI)報告,該報告跟蹤了全球最成功的風險投資公司的早期投資活動,以“衡量哪些科技領域正在吸引風險投資公司的注意力”.

1900/1/1 0:00:00
ENS:Buidler DAO:以 ENS 為例深度分析 Web3 域名系統的技術設計_web3域名交易記錄

以ENS為例剖析web3域名系統設計注冊地址:https://app.ens.domains/web3域名系統,簡而言之就是基于區塊鏈的分布式、去中心化的命名系統,與DNS類似.

1900/1/1 0:00:00
LINK:“坐牢”到下個牛市可持有的6大項目_Chain

從長遠來看,超過90%的幣圈項目都會失敗。如果你是一個長期持有者,那么你的首要工作就是弄清楚哪些項目能夠活下來。這里有6個我認為可以存活多年的項目.

1900/1/1 0:00:00
THE:最新以太坊路線圖內容注釋_ARK

譯者注:本文基于最新以太坊路線圖進行內容注解,下圖為ECN譯制的中文版。文中有許多鏈接,進入網頁版查看更多:https://www.ethereum.cn/Eth2/annotated-ethe.

1900/1/1 0:00:00
ads