什么是智能合约?
由以太坊推广,智能合约是在区块链上存储和执行的程序。这个术语是在90年代末创造的,试图 "为理想的安全提供蓝图"。
这个蓝图规范了事件发生时各方之间的关系,使用代码,使其具有巨大的安全性,并像代码本身一样可预测。
智能合约与外部账户
与外部(以太坊)账户一样,智能合约有地址,可以持有和转移资金。然而,外部账户不受单一网络的约束。你可以用同一个账户连接到任何数量的区块链网络。
另一方面,智能合约只能连接到一个特定的网络。它们可以增强或取代现实生活中的合同,因为它们具有透明性和它们所运行的系统(区块链)的不可更改性。编写这种合同的最流行方式是通过Solidity编程语言。
介绍一下Solidity
Solidity是由Ethereum团队创建的一种编译的面向对象的编程语言,具有类似JavaScript的语法。与JavaScript不同,Solidity是强类型的,并且很好地利用了继承性。
Solidity将我们的源代码编译成可部署的字节码和应用二进制接口(ABI),以便使用其他智能合约或编程语言与字节码互动。
用Solidity写一个智能合约
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.4.17 <0.9.0;
contract Storage {
uint data;
function set(uint newData) public {
data = newData;
}
function get() public view returns (uint) {
return data;
}
}
因为智能合约的源代码通常可以随时阅读,所以最好在第一行指定你的代码的许可证,然后是 [SPDX](https://spdx.org/licenses/)-License-Identifier:
.
之后,pragma
指令告诉编译器要使用哪个版本的 Solidity。版本以0.
开始,以表明在小的、定期的更新中会有突破性的变化。我们的智能合约可以针对0.4
或更高的版本进行编译,但不能针对0.9
版本。
契约
Solidity 中的合约与 JavaScript 类非常相似,它们持有可相互作用的变量和方法。但与类不同的是,你不需要this
关键字来访问Solidity中的一个变量。在声明后也必须有分号(函数定义不算)。
我们的Storage
合同持有整数data
(由uint
类型关键字注释),并暴露了两个可以改变和显示它的函数。data
变量是一个存储变量,它将在我们合约的有效期内存在。如果我们部署了这个合约,任何人都可以调用set
和get
来修改和检索data
的值。
在 Solidity 合同中初始化我们的变量
为了用一个值初始化我们的data
变量,合约可以提供一个constructor
函数,该函数需要零或多个参数。
contract Storage {
uint data;
constructor (uint defaultData) {
data = defaultData;
}
function set(uint newData) public {
data = newData;
}
function get() public view returns (uint) {
return data;
}
}
继承
一个合约可以通过is
关键字从另一个合约继承。
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.4.17 <0.9.0;
contract C {
string public greeting = 'hello';
}
contract D {
string public farewell = 'goodbye';
}
contract E is C, D {}
合约D
将可以访问greeting
和farewell
两个变量。
Solidity 函数
Solidity 函数有以下模式。
function <function name>(<parameters type>) \[function type\] [returns (<return type>)] {}
常用的函数类型是public
,external
,private
,internal
,view
,pure
, 和payable
。
下面是支配函数可见性的类型是如何工作的。
public
:任何人都可以调用该函数external
: 除了合同之外,任何人都可以调用该函数。使用external
,而不是public
,可以有一个性能提升,并有可能节省大量的气体private
:只有持有该函数的合同可以调用它internal
:合同及其衍生物可以调用该函数。
这些类型管理对状态的访问。
view
:该函数只读取状态pure
:该函数既不读也不写状态。
请注意,payable
是在函数被调用时可以接受付款时使用的。
一个更详细的函数类型的模式会是这样的。
{public|external|private|internal} [pure|view|payable]
因此,在我们的合同中,具有public view returns (uint)
类型的get
函数是可普遍访问的,读取数据,并返回一个整数。
然而,Solidity 为我们提供了一个捷径,自动创建显示我们状态的get
函数。只需在我们的变量data
前添加关键字public
,一个data
函数就会被创建,以取代我们的get
函数。
contract Storage {
uint public data; // a data function will be created to access the `data` variable
constructor (uint defaultData) {
data = defaultData;
}
function set(uint newData) public {
data = newData;
}
}
使用Remix进行部署
为了测试和部署我们的合约到区块链网络,我们可以依靠像Remix这样的IDE来简化我们的工作,或者使用一个真正的编码环境。在这篇文章中,我们将使用Remix。
Remix是一个Solidity IDE,用于编译、部署和手动测试Solidity代码。它可以与一系列Ethereum测试网络以及主网络对接。
首先,在contracts
目录下创建一个新的合约,并将我们的合约代码复制过来。
当我们的Solidity代码被保存时,Remix会自动编译我们的代码,创建一个被发送到网络的字节码,以及一个ABI来与部署的合约互动。
我们可以在Solidity编译器标签中检查字节码和ABI。
如果我们的代码编译成功,我们就可以在部署和运行事务标签下开始部署和与之交互。
在这个选项卡中,我们可以选择我们的环境、要部署的合约以及要用哪个账户来部署。JavaScript VM
,意味着Remix将在我们的浏览器内维护一个区块链网络,使测试尽可能快地运行。
值输入与payable
函数调用有关,对我们的合约来说是不必要的。
在标签的底部,我们看到Deployed Contracts
,这表明我们可以部署一个或多个合约的多个实例。
在Contracts
下,Remix在constructor
函数内拾取了我们的defaultData
。输入一个整数,点击Deploy来部署一个新的合同。
data
按钮代表我们的public data
变量自动生成的getter,而set
按钮代表我们的set
方法。
颜色上的差异可以归因于这样一个事实,即我们的getterdata
函数并不修改我们应用程序中的状态,因此,在区块链上运行不需要任何成本。然而,我们的set
函数是一个交易类型的函数,它的运行会消耗气体和资源,就像最初的Deploy
按钮。
运行data
函数将返回我们的初始输入2021
,set
对其进行相应的修改。
结论
在这篇文章中,我们看了Solidity合约的基本构件,以及如何使用Remix IDE编写、编译、部署和测试我们的Solidity代码。从现在开始,我们应该更进一步,使用Ganache和Truffle的真实环境。祝你黑客行动愉快。
The postWriting smart contracts with Solidityappeared first onLogRocket Blog.