智慧型合約的程式語言
頁面最後更新時間: 2026年2月26日
以太坊一大好處是,對開發者而言,編寫智慧型合約的語言相對簡單。 若您有 Python 或任何花括號語言 (opens in a new tab)的使用經驗,您就能找到語法熟悉的語言。
兩種最熱門、最受管理的語言為:
- Solidity
- Vyper
Remix 整合開發環境提供一個全面的開發環境,用於透過 Solidity 和 Vyper 語言建立和測試合約。 試用瀏覽器內的 Remix IDE (opens in a new tab) 開始編寫程式。
經驗更豐富的開發者可能也會想使用 Yul (一種 Ethereum Virtual Machine 的中介語言),或 Yul+ (Yul 的擴充)。
若你有興趣,且想協助測試還處於大力開發階段的新語言,可以實驗仍在發展初期的新興智慧型合約語言 Fe。
先決條件
如果已經有編程語言的知識,特別是 JavaScript 或 Python,可以幫助你瞭解智慧型合約語言的差異。 同時,我們建議你在深入理解語言差異之前,先理解智慧型合約的概念。 智能合約簡介。
Solidity
- 實作智慧型合約的物件導向高階語言。
- 深受 C++ 語言影響的大括號語言。
- 靜態類型(編譯時已知變數類型)。
- 支援:
- 繼承(你可以延展其他合約)。
- 資料庫(你可以建立能從不同的合約調用的可重複使用代碼,如同其他物件導向程式語言中的靜態類別靜態函數)。
- 複雜的使用者定義類型。
重要連結
- 文件 (opens in a new tab)
- Solidity 語言入口網站 (opens in a new tab)
- Solidity 範例 (opens in a new tab)
- GitHub (opens in a new tab)
- Solidity Matrix 聊天室 (opens in a new tab)橋接到 Solidity Matrix 聊天室 (opens in a new tab)
- 快捷手冊 (opens in a new tab)
- Solidity 部落格 (opens in a new tab)
- Solidity Twitter (opens in a new tab)
合約範例
1// SPDX-License-Identifier: GPL-3.02pragma solidity >= 0.7.0;34contract Coin {5 // 「public」關鍵字使變數6 // 可從其他合約存取7 address public minter;8 mapping (address => uint) public balances;910 // 事件讓用戶端對您宣告的11 // 特定合約變更做出反應12 event Sent(address from, address to, uint amount);1314 // 建構函式程式碼只會在合約15 // 建立時執行16 constructor() {17 minter = msg.sender;18 }1920 // 傳送一定數量的新代幣到某個地址21 // 只能由合約建立者呼叫22 function mint(address receiver, uint amount) public {23 require(msg.sender == minter);24 require(amount < 1e60);25 balances[receiver] += amount;26 }2728 // 從任何呼叫者傳送一定數量的現有代幣29 // 到某個地址30 function send(address receiver, uint amount) public {31 require(amount <= balances[msg.sender], "餘額不足。");32 balances[msg.sender] -= amount;33 balances[receiver] += amount;34 emit Sent(msg.sender, receiver, amount);35 }36}顯示全部這個範例應該能讓你瞭解 Solidity 的合約語法。 關於函式和變數的詳細說明,請參閱文件 (opens in a new tab)。
Vyper
- Python 程式語言
- 強輸入類型
- 精巧易懂的編譯器代碼
- 有效率的產生位元組碼
- 為了提升合約安全性並更容易審核,特意提供比 Solidity 更少功能。 Vyper 不支援:
- 修飾符
- 繼承
- 行內組譯
- 函數重載
- 運算子重載
- 遞迴調用
- 無限長度迴圈
- 二進制定點
更多資訊,請閱讀 Vyper 設計理念 (opens in a new tab)。
重要連結
- 文件 (opens in a new tab)
- Vyper 範例 (opens in a new tab)
- 更多 Vyper 範例 (opens in a new tab)
- GitHub (opens in a new tab)
- Vyper 社群 Discord 聊天室 (opens in a new tab)
- 快捷手冊 (opens in a new tab)
- Vyper 智能合約開發框架與工具
- VyperPunk - 學習如何保護與攻擊 Vyper 智能合約 (opens in a new tab)
- Vyper 開發中心 (opens in a new tab)
- Vyper 精選智能合約範例 (opens in a new tab)
- Awesome Vyper 精選資源 (opens in a new tab)
範例
1# 公開拍賣23# 拍賣參數45# 受益人從最高出價者收到款項67beneficiary: public(address)8auctionStart: public(uint256)9auctionEnd: public(uint256)1011# 目前拍賣狀態1213highestBidder: public(address)14highestBid: public(uint256)1516# 結束時設為 true,不允許任何變更1718ended: public(bool)1920# 追蹤已退款的出價,以便遵循提款模式2122pendingReturns: public(HashMap[address, uint256])2324# 建立一個簡單的拍賣,競標時間為 `_bidding_time`2526# 秒,代表受益人地址 `_beneficiary`。2728@external29def __init__(_beneficiary: address, _bidding_time: uint256):30 self.beneficiary = _beneficiary31 self.auctionStart = block.timestamp32 self.auctionEnd = self.auctionStart + _bidding_time3334# 以與此交易一起傳送的價值3536# 參與競標。3738# 只有在未贏得拍賣時,3940# 價值才會被退還。4142@external43@payable44def bid():45 # 檢查競標期是否結束。46 assert block.timestamp < self.auctionEnd47 # 檢查出價是否夠高48 assert msg.value > self.highestBid49 # 追蹤前一個最高出價者的退款50 self.pendingReturns[self.highestBidder] += self.highestBid51 # 追蹤新的最高出價52 self.highestBidder = msg.sender53 self.highestBid = msg.value5455# 提領先前已退款的出價。這裡使用提款模式5657# 以避免安全問題。如果退款是直接5859# 作為 bid() 的一部分傳送,惡意的競標合約可能會阻止6061# 這些退款,從而阻止新的更高出價進入。6263@external64def withdraw():65 pending_amount: uint256 = self.pendingReturns[msg.sender]66 self.pendingReturns[msg.sender] = 067 send(msg.sender, pending_amount)6869# 結束拍賣並將最高出價7071# 傳送給受益人。7273@external74def endAuction():75 # 將與其他合約互動的函式 (即呼叫函式或傳送以太幣)76 # 分為三個階段是一個好的指導方針:77 # 1. 檢查條件78 # 2. 執行動作 (可能改變條件)79 # 3. 與其他合約互動80 # 如果這些階段混雜在一起,其他合約可能會81 # 回呼目前的合約,並修改狀態或導致82 # 效果 (以太幣支付) 被多次執行。83 # 如果內部呼叫的函式包含與外部84 # 合約的互動,它們也必須被視為與85 # 外部合約的互動。8687 # 1. 條件88 # 檢查拍賣結束時間是否已到89 assert block.timestamp >= self.auctionEnd90 # 檢查此函式是否已被呼叫過91 assert not self.ended9293 # 2. 效果94 self.ended = True9596 # 3. 互動97 send(self.beneficiary, self.highestBid)顯示全部此範例應該能讓你瞭解 Solidity 的合約語法。 關於函式和變數的詳細說明,請參閱文件 (opens in a new tab)。
Yul 和 Yul+
如果你是以太坊新手並且尚未使用過智慧型合約語言編碼,建議你從 Solidity 或 Vyper 開始。 只有在你熟悉智慧型合約安全性最佳案例和使用以太坊虛擬機的具體細節後,才可投入 Yul 或 Yul+。
Yul
- 以太坊的中階語言。
- 支援 EVM 和 Ewasm (opens in a new tab) (一種以太坊風格的 WebAssembly),其設計目標是成為這兩個平台可用的共同基準。
- 高級最佳化階段的優良目標,能使以太坊虛擬機和 eWASM 平台均等受益。
Yul+
- Yul 的低階高效延伸語言。
- 最初是為樂觀卷軸合約所設計。
- Yul+ 可以被視為 Yul 的實驗性升級建議,為其添加新功能。
重要連結
合約範例
以下簡單範例採用冪函數。 可以使用 solc --strict-assembly --bin input.yul 進行編譯。 這個範例應該
儲存在 input.yul 檔案中。
1{2 function power(base, exponent) -> result3 {4 switch exponent5 case 0 { result := 1 }6 case 1 { result := base }7 default8 {9 result := power(mul(base, base), div(exponent, 2))10 if mod(exponent, 2) { result := mul(base, result) }11 }12 }13 let res := power(calldataload(0), calldataload(32))14 mstore(0, res)15 return(0, 32)16}顯示全部如果您對智能合約已有豐富經驗,可以在這裡 (opens in a new tab)找到 Yul 的完整 ERC20 實作。
Fe
- 用於以太坊虛擬機 (EVM) 的靜態類型語言。
- 受 Python 和 Rust 所啟發。
- 目標是讓以太坊生態系統的新手開發者,都能輕鬆學習這門語言。
- Fe 還處於早期開發階段,其 Alpha 版本於 2021 年 1 月推出。
重要連結
- GitHub (opens in a new tab)
- Fe 公告 (opens in a new tab)
- Fe 2021 開發藍圖 (opens in a new tab)
- Fe Discord 聊天室 (opens in a new tab)
- Fe Twitter (opens in a new tab)
合約範例
以下為採用 Fe 的簡單合約。
1type BookMsg = bytes[100]23contract GuestBook:4 pub guest_book: map<address, BookMsg>56 event Signed:7 book_msg: BookMsg89 pub def sign(book_msg: BookMsg):10 self.guest_book[msg.sender] = book_msg1112 emit Signed(book_msg=book_msg)1314 pub def get_msg(addr: address) -> BookMsg:15 return self.guest_book[addr].to_mem()16顯示全部如何選擇
與任何其他編程語言一樣,重點在於根據合適的工作與個人偏好選擇正確工具。
如果你還沒有嘗試過任何一種語言,請考慮以下幾點:
Solidity 的優點是什麼?
- 如果你是初學者,有不少使用教學和學習工具。 更多相關資訊,請參閱透過編碼學習一節。
- 提供優良的開發者工具。
- Solidity 擁有龐大的開發者社群,這表示你很可能會很快找到問題的答案。
Vyper 的優點是什麼?
- 適合想要編寫智慧型合約的 Python 開發者入門。
- Vyper 的功能較少,因此非常適合快速製作創意原型。
- Vyper 的目的是容易審查並盡可能提高人類可讀性。
Yul 和 Yul+ 的優點是什麼?
- 簡單而實用的低階語言。
- 允許更接近原始以太坊虛擬機,有助於最佳化合約的燃料使用量。
語言比較
若要比較基本語法、合約生命週期、介面、運算子、資料結構、函式、控制流程等,請參閱這份 Auditless 快捷手冊 (opens in a new tab)