本文探討以下問題:哪種智能合約語言更有優勢,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提升了智能合約的安全性和可審計性。
蘇富比結束第二輪三箭NFT拍賣,獲得逾1090萬美元收入:6月16日消息,蘇富比在本周四完成了另一輪從三箭資本(3AC)沒收的幾種稀有NFT的拍賣,銷售額超過 1090 萬美元。
本次總共有37件來自Dmitri Cherniak,Tyler Hobbs,Jeff Davis等生成藝術家的作品。這次拍賣的亮點是Dmitri Cherniak的Ringers #879(通常被稱為“鵝”),估計售價為200萬至300萬美元。經過競標,它最終以 620 萬美元的價格賣給了著名的 NFT 投資者 6529。在拍賣會后的一條推文中,蘇富比報道說,這是有史以來第二高的生成藝術作品。
到目前為止,Grails系列拍賣已經帶來了超過1600萬美元的收入。[2023/6/16 21:40:57]
當前的情況
來源于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
Yul
開發體驗
通過查看這四張圖片,我們可以大概了解編寫每種語言的感受。就開發人員經驗而言,編寫Solidity和Vyper代碼要快得多。這些語言是高級語言,而Yul和Huff是更底層的語言。僅出于這個原因,就很容易理解為什么這么多人采用Vyper和Solidity。
美聯儲戴利:加密行業問題不會影響美聯儲的數字美元工作:金色財經報道,美聯儲戴利表示,加密行業問題不會影響美聯儲的數字美元工作。在央行數字美元方面,美聯儲將在創新與保護之間找到平衡。[2022/11/22 7:54:27]
看一下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部分詳細討論這一點。
結果:
創建合約時各個語言所消耗的gas費
正如我們所見,像Huff和Yul這樣的底層語言比Vyper和Solidity的gas效率更高,但這是為什么呢?Vyper似乎比Solidity更高效,我們有這個新的“SolandYul”部分。那是因為你實際上可以在Solidity中編寫Yul。Yul是作為Solidity開發人員在寫更接近機器代碼時而創建的。
FTX Ventures支持的Solana擴展協議Layer N預計將于明年推出主網:11月8日消息,據外媒報道,Solana擴展協議Layer N已完成秘密開發階段,其計劃在今年年底之前部署一個“沙盒”測試環境,允許任何人查看它計劃在其開發網絡上部署的測試程序,預計將于明年推出主網。與以太坊的多鏈擴展架構類似,Layer N構建于Solana之上,目標是提高可擴展性,并將與Ledger Prime和Pattern Research作為流動性合作伙伴進行合作。Layer N表示,它是第一個能夠與中心化交易所的吞吐量或速度相匹配的區塊鏈。該協議稱,它采用了一種“被稱為守護網絡的新穎執行環境,以及幾套獨特的技術創新和優化,以擴大執行規模”。
據悉,Layer N的投資者包括FTX Ventures、Solana Ventures、Solana Foundation以及Solana的聯合創始人Anatoly Yakovenko和Raj Gokal。(The Block)[2022/11/8 12:30:06]
因此,在上圖中,我們比較了原始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關于解構合約的博客幫助你從零開始學習相關知識:
以太坊網絡當前已銷毀超252.39萬枚ETH:金色財經報道,據Ultrasound數據顯示,截止目前,以太坊網絡總共銷毀2,523,964.01枚ETH。其中,ETHtransfers銷毀232,825.21枚ETH,OpenSea銷毀230,049.97枚ETH,UniswapV2銷毀134,751.10枚。注:自以太坊倫敦升級引入EIP-1559后,以太坊網絡會根據交易需求和區塊大小動態調整每筆交易的BaseFee,而這部分的費用將直接燃燒銷毀。[2022/7/10 2:02:42]
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解釋
日本民主黨黨首提議修改加密稅制以推進Web3發展:5月22日消息,日本民主黨黨首玉木雄一郎近日提議修改針對加密貨幣的稅收制度,以此推進Web3發展。根據其提議,可以通過以下兩點來防止人才和企業流向海外,1.對加密貨幣實行20%的“申告分離課稅”;2.法人持有的代幣不作為期末時價評估的對象。
據悉,日本的加密貨幣稅制一直被詬病“會導致人才外流”。而歷任外務大臣和防衛大臣等職務的河野太郎也表示,為了應對Web3趨勢,“自民黨內已經開始討論稅制改革”。
此前5月10日消息,日本首相岸田文雄(Fumio Kishida)表示,與Web3相關的增長,包括與元宇宙和NFT相關的開發將成為日本未來戰略增長的一部分,并呼吁英國商界領袖支持其項目。他表示,日本政府將進行“體制改革”,以創造環境促進新服務的創建(包括與Web3相關的基礎設施),并將投資引入到科技和創新以及創企投資和數字領域。“我們將專注于區塊鏈、NFT和元宇宙等Web3的推廣。我們將實現一個可以輕松創建新服務的社會。”(Coin Post)[2022/5/22 3:33:06]
Vyper也基本做了同樣的事情。
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:SOLLIDSOLIDDITBeNFT SolutionsLido Staked ETHMOSOLIDQuieroganar Audits
關于作者:蘇子華:36氪作者,關注Web3、元宇宙,微信號:suzihua12345喬芊:36氪消費與內容組負責人,微信號:rachel2002新加坡副總理兼財政部長黃循財不開心了.
1900/1/1 0:00:00MarsBitCryptoDaily2022年11月23日 一、今日要聞 Curve發布其穩定幣的白皮書和官方代碼CurveFinance的開發者已經發布了Curve即將推出的去中心化穩定幣cr.
1900/1/1 0:00:00背景介紹 2021年,NFT市場一直在飛速發展,自1月以來,200多億美元的市值增長足可證明其發展盛況。在此期間,越來越多的NFT項目出現在一級市場,每天都有創紀錄的銷售.
1900/1/1 0:00:00注:本文來自@Brave2049推特,MarsBit整理如下:比特幣和區塊鏈是兩回事兒。如果更相信去中心化的愿景,比特幣顯然監管壓力更小。這意味著,不需要去關注啥Web3,囤比特幣就好.
1900/1/1 0:00:00OptimisticRollup項目并不一定會輸給ZKRollup項目從目前看,以太坊L2技術演化中,Rollup成為其最重要的方向.
1900/1/1 0:00:00和許多加密推特用戶一樣,我上周花了太多時間觀看FTX新聞。我一直在關注揭露的信息,對有關公司文化的披露翻白眼。這是一種表達憤怒和懷疑的集體儀式,這是可以理解的.
1900/1/1 0:00:00