智能合约语言
上次编辑: , Invalid DateTime
关于以太坊的一个重要方面是,智能合约可以使用相对友好的开发者语言编程。 如果您熟悉 Python 或任何大括号语言(opens in a new tab),可以找到一种语法熟悉的语言。
最受欢迎和维护得最好的两种语言是:
- Solidity
- Vyper
更有经验的开发者也可能想要使用 Yul:一种用于以太坊虚拟机的中间语言,或者是 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 Gitter Chatroom(opens in a new tab) 桥接到 Solidity Matrix Chatroom(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 // The keyword "public" makes variables6 // accessible from other contracts7 address public minter;8 mapping (address => uint) public balances;910 // Events allow clients to react to specific11 // contract changes you declare12 event Sent(address from, address to, uint amount);1314 // Constructor code is only run when the contract15 // is created16 constructor() {17 minter = msg.sender;18 }1920 // Sends an amount of newly created coins to an address21 // Can only be called by the contract creator22 function mint(address receiver, uint amount) public {23 require(msg.sender == minter);24 require(amount < 1e60);25 balances[receiver] += amount;26 }2728 // Sends an amount of existing coins29 // from any caller to an address30 function send(address receiver, uint amount) public {31 require(amount <= balances[msg.sender], "Insufficient balance.");32 balances[msg.sender] -= amount;33 balances[receiver] += amount;34 emit Sent(msg.sender, receiver, amount);35 }36}37显示全部复制
这个示例应该能让您感觉到 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)
- VyperExamples - Vyper 漏洞示例(opens in a new tab)
- Vyper 开发中心(opens in a new tab)
- Vyper 最热门的智能合约示例(opens in a new tab)
- 出色的 Vyper 精选资源(opens in a new tab)
示例
1# Open Auction23# Auction params4# Beneficiary receives money from the highest bidder5beneficiary: public(address)6auctionStart: public(uint256)7auctionEnd: public(uint256)89# Current state of auction10highestBidder: public(address)11highestBid: public(uint256)1213# Set to true at the end, disallows any change14ended: public(bool)1516# Keep track of refunded bids so we can follow the withdraw pattern17pendingReturns: public(HashMap[address, uint256])18@external19def __init__(_beneficiary: address, _bidding_time: uint256):20 self.beneficiary = _beneficiary21 self.auctionStart = block.timestamp22 self.auctionEnd = self.auctionStart + _bidding_time2324# Bid on the auction with the value sent25# together with this transaction.26# The value will only be refunded if the27# auction is not won.28@external29@payable30def bid():31 # Check if bidding period is over.32 assert block.timestamp < self.auctionEnd33 # Check if bid is high enough34 assert msg.value > self.highestBid35 # Track the refund for the previous high bidder36 self.pendingReturns[self.highestBidder] += self.highestBid37 # Track new high bid38 self.highestBidder = msg.sender39 self.highestBid = msg.value The withdraw pattern is40# used here to avoid a security issue. If refunds were directly41# sent as part of bid(), a malicious bidding contract could block42# those refunds and thus block new higher bids from coming in.43@external44def withdraw():45 pending_amount: uint256 = self.pendingReturns[msg.sender]46 self.pendingReturns[msg.sender] = 047 send(msg.sender, pending_amount)4849# End the auction and send the highest bid50# to the beneficiary.51@external52def endAuction():53 # It is a good guideline to structure functions that interact54 # with other contracts (i.e. they call functions or send ether)55 # into three phases:56 # 1. checking conditions57 # 2. performing actions (potentially changing conditions)58 # 3. interacting with other contracts59 # If these phases are mixed up, the other contract could call60 # back into the current contract and modify the state or cause61 # effects (ether payout) to be performed multiple times.62 # If functions called internally include interaction with external63 # contracts, they also have to be considered interaction with64 # external contracts.6566 # 1. Conditions67 # Check if auction endtime has been reached68 assert block.timestamp >= self.auctionEnd69 # Check if this function has already been called70 assert not self.ended7172 # 2. Effects73 self.ended = True7475 # 3. Interaction76 send(self.beneficiary, self.highestBid)77显示全部复制
这个例子应该让您了解 Vyper 合约语法是什么样的。 有关函数和变量的详细说明,请参阅文档(opens in a new tab)。
Yul 和 Yul+
如果您是以太坊的新手并且尚未使用智能合约语言进行任何编码,我们建议您开始使用 Solidity 或 Vyper。 只有在您熟知智能合约安全最佳做法和使用 EVM 的具体细节后,才可以查看 Yul 或 Yul+。
Yul
- 以太坊的中继语言。
- 支持 EVM 和 Ewasm(opens in a new tab),一种以太坊风格的 WebAssembly,以及旨在成为两个平台均可用的公分母。
- 高级优化阶段的良好目标,既使 EVM 和 eWASM 平台均等受益。
Yul+
- Yul 的低级、高效扩展。
- 最初设计用于乐观卷叠合约。
- Yul+ 可以被视为对 Yul 的实验性升级建议,为其添加新功能。
重要的链接
- Yul 相关文档(opens in a new tab)
- Yul+ 相关文档(opens in a new tab)
- Yul+ 实战场(opens in a new tab)
- Yul+ 介绍帖子(opens in a new tab)
合约示例
以下简单示例实现了幂函数。 它可以使用 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}17显示全部