Solidity 是一种静态类型的花括号编程语言,旨在开发在以太坊上运行的智能合约。
特性
Solidity 正在迅速发展。
作为一门相对年轻的语言,Solidity 正在快速发展。
我们的目标是每 2-3 周发布一次常规(非破坏性)版本,每年大约发布两次破坏性版本。
您可以关注 Solidity Github 项目中新功能的实施情况。
您可以通过从默认分支 (develop
) 切换到 breaking branch
来查看下一个重大版本即将发生的更改。
Solidity 是一种静态类型的花括号编程语言,旨在开发在以太坊上运行的智能合约。
作为一门相对年轻的语言,Solidity 正在快速发展。
我们的目标是每 2-3 周发布一次常规(非破坏性)版本,每年大约发布两次破坏性版本。
您可以关注 Solidity Github 项目中新功能的实施情况。
您可以通过从默认分支 (develop
) 切换到 breaking branch
来查看下一个重大版本即将发生的更改。
让我们从一个基本示例开始,该示例设置变量的值并将其公开以供其他合约访问。
如果您现在不了解所有内容也没关系,我们稍后会详细介绍。
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.16 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);
balances[receiver] += amount;
}
// Errors allow you to provide information about
// why an operation failed. They are returned
// to the caller of the function.
error InsufficientBalance(uint requested, uint available);
// Sends an amount of existing coins
// from any caller to an address
function send(address receiver, uint amount) public {
if (amount > balances[msg.sender])
revert InsufficientBalance({
requested: amount,
available: balances[msg.sender]
});
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}
以下合约实现了最简单的加密货币形式。
该合约仅允许其创建者创建新硬币(可能有不同的发行方案)。
任何人都可以互相发送硬币,而无需使用用户名和密码进行注册,您所需要的只是一个以太坊密钥对。
pragma solidity ^0.8.4;
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);
balances[receiver] += amount;
}
// Errors allow you to provide information about
// why an operation failed. They are returned
// to the caller of the function.
error InsufficientBalance(uint requested, uint available);
// Sends an amount of existing coins
// from any caller to an address
function send(address receiver, uint amount) public {
if (amount > balances[msg.sender])
revert InsufficientBalance({
requested: amount,
available: balances[msg.sender]
});
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}
区块链作为一个概念对于程序员来说并不难理解。
原因是大多数复杂性(挖掘、散列、椭圆曲线密码学、点对点网络等)只是为了为平台提供一组特定的功能和承诺。
一旦你接受了这些给定的功能,你就不必担心底层技术——或者你是否必须知道亚马逊的 AWS 在内部是如何工作的才能使用它?
区块链是一个全球共享的交易数据库。
这意味着每个人都可以通过参与网络来读取数据库中的条目。
如果要更改数据库中的某些内容,则必须创建一个必须被所有其他人接受的所谓事务。
事务一词意味着您要进行的更改(假设您要同时更改两个值)要么根本没有完成,要么完全应用。
以太坊虚拟机或 EVM 是以太坊中智能合约的运行时环境。
它不仅是沙盒,而且实际上是完全隔离的,这意味着在 EVM 内运行的代码无法访问网络、文件系统或其他进程。
智能合约甚至对其他智能合约的访问权限有限。
以太坊中有两种账户共享相同的地址空间:由公钥-私钥对(即人类)控制的外部账户和由与账户一起存储的代码控制的合约账户。
外部账户的地址由公钥确定,而合约的地址在合约创建时确定(它来源于创建者地址和从该地址发送的交易数量,即所谓的“ 随机数”)。
无论账户是否存储代码,EVM 都会平等对待这两种类型。
Solidity 版本遵循语义版本控制。
此外,主版本 0(即 0.x.y)的补丁级别版本将不包含重大更改。
这意味着使用版本 0.x.y 编译的代码可以预期使用 0.x.z 编译,其中 z > y。
除了发布之外,我们还提供夜间开发版本,目的是让开发人员更容易尝试即将推出的功能并提供早期反馈。
但是请注意,虽然夜间构建通常非常稳定,但它们包含来自开发分支的前沿代码,并且不能保证始终有效。尽管我们尽了最大努力,但它们可能包含未记录和/或损坏的更改,这些更改不会成为实际版本的一部分。它们不适用于生产用途。
部署合约时,您应该使用最新发布的 Solidity 版本。
以下合约相当复杂,但展示了 Solidity 的许多功能。
它实现了一个投票合约。
当然,电子投票的主要问题是如何将投票权分配给正确的人以及如何防止操纵。
我们不会在这里解决所有问题,但至少我们将展示如何进行委托投票,以便同时自动计算投票并且完全透明。
这个想法是为每张选票创建一份合同,为每个选项提供一个短名称。
然后,担任主席的合约的创建者将分别授予每个地址的投票权。
然后,地址背后的人可以选择自己投票或将投票委托给他们信任的人。
在投票时间结束时,winningProposal() 将返回得票最多的提案。
源文件可以包含任意数量的合约定义、import、pragma 和 using for 指令和结构、枚举、函数、错误和常量变量定义。
如果智能合约的源代码可用,则可以更好地建立对智能合约的信任。由于提供源代码总是涉及版权方面的法律问题,Solidity 编译器鼓励使用机器可读的 SPDX 许可证标识符。
每个源文件都应以说明其许可证的注释开头:
// SPDX-License-Identifier: MIT
Solidity 中的契约类似于面向对象语言中的类。
每个合约都可以包含状态变量、函数、函数修饰符、事件、错误、结构类型和枚举类型的声明。
此外,合约可以继承自其他合约。
还有一些特殊类型的合约,称为库和接口。
关于合同的部分包含比本部分更多的详细信息,用于提供快速概述。
状态变量是其值永久存储在合约存储中的变量。
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.4.0 =0.7.1 =0.4.22 =0.4.21 uint) balances;
function transfer(address to, uint amount) public {
uint balance = balances[msg.sender];
if (balance =0.4.0 =0.4.0 <0.9.0;
contract Purchase {
enum State { Created, Locked, Inactive } // Enum
}
Solidity 是一种静态类型语言,这意味着需要指定每个变量(状态和本地)的类型。
Solidity 提供了几种基本类型,它们可以组合成复杂类型。
此外,类型可以在包含运算符的表达式中相互交互。
有关各种运算符的快速参考,请参阅运算符的优先顺序。
Solidity 中不存在“未定义”或“空”值的概念,但新声明的变量始终具有取决于其类型的默认值。
要处理任何意外值,您应该使用 revert 函数来恢复整个事务,或者返回一个带有第二个 bool 值表示成功的元组。
以下类型也称为值类型,因为这些类型的变量总是按值传递,即当它们用作函数参数或赋值时,它们总是被复制。