以太坊开发者文档03 智能合约语言
智能合约语言
以太坊的一个重要方面是智能合约可以使用相对开发人员友好的语言进行编程。如果您熟悉 Python 或 任何大括号语言,您可以发现一种有熟悉语法的语言。
两种最活跃且维护最频繁的语言是:
- Solidity
- Vyper
更有经验的开发人员可能还想使用 Yul,一种用于以太坊虚拟机的中间语言,或 Yul+,一种对 Yul 的扩展。
如果您好奇并想帮助测试仍在大力开发的新语言,您可以尝试使用 Fe,这是一种新兴的智能合约语言,目前仍处于起步阶段。
先决条件
以前的编程语言知识,尤其是 JavaScript 或 Python 知识,可以帮助您理解智能合约语言的差异。我们还建议您在深入到研究语言对比之前将智能合约作为概念理解。智能合约简介。
Solidity
用于实现智能合约的面向对象的高级语言
受 C++ 影响最深的花括号语言
静态类型语言(变量的类型在编译时已知)
支持:
- 继承(你可以扩展其他合约)
- 库(你可以创建可从不同合约调用的可重用代码 - 例如其他面向对象编程语言中静态类中的静态函数)
- 复杂的用户定义类型
重要链接
- Documentation
- Solidity Language Portal
- Solidity by Example
- GitHub
- Solidity Gitter Chatroom 桥接到 Solidity Matrix Chatroom
- Cheat Sheet
- Solidity Blog
- Solidity Twitter
合约示例
// SPDX-License-Identifier: GPL-3.0
pragma solidity >= 0.7.0;
contract Coin {
// The keyword "public" makes variables
// accessible from other contracts
address public minter;
mapping (address => uint) public balances;
// Events allow clients to react to specific
// contract changes you declare
event Sent(address from, address to, uint amount);
// Constructor code is only run when the contract
// is created
constructor() {
minter = msg.sender;
}
// Sends an amount of newly created coins to an address
// Can only be called by the contract creator
function mint(address receiver, uint amount) public {
require(msg.sender == minter);
require(amount < 1e60);
balances[receiver] += amount;
}
// Sends an amount of existing coins
// from any caller to an address
function send(address receiver, uint amount) public {
require(amount <= balances[msg.sender], "Insufficient balance.");
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}
这个例子应该让你了解 Solidity 合约的语法是什么样的。有关函数和变量的更详细描述,请参阅文档。
Vyper
Pythonic 编程语言
强类型
小而易懂的编译器代码
高效的字节码生成
功能故意设计地比 Solidity 少,目的是让合约更安全、更容易审计。 Vyper 不支持:
- 修饰符
- 继承
- 内联汇编
- 函数重载
- 运算符重载
- 递归调用
- 无限长循环
- 二进制不动点
重要链接
- Documentation
- Vyper by Example
- More Vyper by Example
- GitHub
- Vyper community Discord chat
- Cheat Sheet
- Smart contract development frameworks and tools for Vyper
- VyperPunk - learn to secure and hack Vyper smart contracts
- VyperExamples - Vyper vulnerability examples
- Vyper Hub for development
- Vyper greatest hits smart contract examples
- Awesome Vyper curated resources
示例
# Open Auction
# Auction params
# Beneficiary receives money from the highest bidder
beneficiary: public(address)
auctionStart: public(uint256)
auctionEnd: public(uint256)
# Current state of auction
highestBidder: public(address)
highestBid: public(uint256)
# Set to true at the end, disallows any change
ended: public(bool)
# Keep track of refunded bids so we can follow the withdraw pattern
pendingReturns: public(HashMap[address, uint256])
# Create a simple auction with `_bidding_time`
# seconds bidding time on behalf of the
# beneficiary address `_beneficiary`.
@external
def __init__(_beneficiary: address, _bidding_time: uint256):
self.beneficiary = _beneficiary
self.auctionStart = block.timestamp
self.auctionEnd = self.auctionStart + _bidding_time
# Bid on the auction with the value sent
# together with this transaction.
# The value will only be refunded if the
# auction is not won.
@external
@payable
def bid():
# Check if bidding period is over.
assert block.timestamp < self.auctionEnd
# Check if bid is high enough
assert msg.value > self.highestBid
# Track the refund for the previous high bidder
self.pendingReturns[self.highestBidder] += self.highestBid
# Track new high bid
self.highestBidder = msg.sender
self.highestBid = msg.value
# Withdraw a previously refunded bid. The withdraw pattern is
# used here to avoid a security issue. If refunds were directly
# sent as part of bid(), a malicious bidding contract could block
# those refunds and thus block new higher bids from coming in.
@external
def withdraw():
pending_amount: uint256 = self.pendingReturns[msg.sender]
self.pendingReturns[msg.sender] = 0
send(msg.sender, pending_amount)
# End the auction and send the highest bid
# to the beneficiary.
@external
def endAuction():
# It is a good guideline to structure functions that interact
# with other contracts (i.e. they call functions or send ether)
# into three phases:
# 1. checking conditions
# 2. performing actions (potentially changing conditions)
# 3. interacting with other contracts
# If these phases are mixed up, the other contract could call
# back into the current contract and modify the state or cause
# effects (ether payout) to be performed multiple times.
# If functions called internally include interaction with external
# contracts, they also have to be considered interaction with
# external contracts.
# 1. Conditions
# Check if auction endtime has been reached
assert block.timestamp >= self.auctionEnd
# Check if this function has already been called
assert not self.ended
# 2. Effects
self.ended = True
# 3. Interaction
send(self.beneficiary, self.highestBid)
这个例子应该让你了解 Vyper 合约语法是什么样的。有关函数和变量的更详细描述,请参阅文档。
Yul 和 Yul+
如果您是以太坊的新手,并且尚未使用智能合约语言进行任何编码,我们建议您开始使用 Solidity 或 Vyper。只有在您熟悉了智能合约安全最佳实践和使用 EVM 的具体细节后,才能研究 Yul 或 Yul+。
FE
- 以太坊虚拟机 (EVM) 的静态类型语言。
- 受 Python 和 Rust 的启发。
- 旨在易于学习——即使对于刚接触以太坊生态系统的开发人员也是如此。
- Fe 开发仍处于早期阶段,该语言于 2021 年 1 月发布了 alpha 版本。
如何选择
与任何其他编程语言一样,这主要是关于为正确的工作以及个人喜好选择正确的工具。
如果您还没有尝试过任何语言,请考虑以下几点:
Solidity 有什么优点?
- 如果你是初学者,有很多教程和学习工具。在“通过编码学习”部分中查看更多相关信息。
- 提供良好的开发人员工具。
- Solidity 拥有庞大的开发者社区,这意味着您很可能很快就能找到问题的答案。
Vyper 有什么优点?
- 对于想要编写智能合约的 Python 开发人员来说,这是入门的好方法。
- Vyper 的功能数量较少,因此非常适合快速制作创意原型。
- Vyper 旨在易于审核并最大限度地提高人类可读性。
Yul 和 Yul+ 有什么优点?
- 简单而实用的低级语言
- 允许更接近原始 EVM,这有助于优化合约的 gas 使用
语言比较
有关基本语法、合约生命周期、接口、运算符、数据结构、函数、控制流等的比较,请查看 Auditless 的 cheatsheet。