在以太坊上部署智能合约和管理交易
要在以太坊上构建去中心化应用,您需要知道如何发送交易、签名并广播到网络。通过交易可以转移以太币、部署自己的合约以及与其他智能合约交互。在本教程中,我们将向您演示如何放心地执行这些操作,并介绍一些有助于简化开发工作流的相关代码库和命令。
要在以太坊上构建去中心化应用,您需要知道如何发送交易、签名并广播到网络。通过交易可以转移以太币、部署自己的合约以及与其他智能合约交互。在本教程中,我们将向您演示如何放心地执行这些操作,并介绍一些有助于简化开发工作流的相关代码库和命令。
创建以太坊交易
交易是指在区块链上改变状态的操作。发送以太币、令牌以及创建或使用智能合约中的函数都属于交易。如果您对以太坊中的交易还不太熟悉,可查看这些有关账户、合约以及以太坊交易类型的实用介绍。在本资源库中,您还将找到一系列脚本,向您演示如何使用下面两种最常用的 Javascript 库与以太坊交互:web3.js 和 ethers.js。有关 web3.js 与 ethers.js 的更多比较信息,请参阅我们的技术指南,其中详细阐述了两者的相同点和不同点。
流程的第一步是创建交易有效负载。它的作用是表达您希望执行的操作类型以及您愿意为执行该操作支付多少费用(汽油费)。我们来看看这些属性:
from:数据,20 字节
- 发起交易的地址。
to:数据,20 字节
- (在创建新合约时可选):接收交易的地址。
value:数量
- (可选):和该交易一起发送的整数值。
gas:数量
- (可选,默认:90000) :为执行该交易而提供的汽油整数值。它将返回未用完的汽油。
汽油价格:数量
- (可选,默认:未定):您愿意为该交易支付的汽油单价整数值(单位:gwei)。
data:数据
- 对于合约部署:编译的合约代码。
- 对于合约交互:所调用方法的签名哈希以及编码参数。有关详细信息,请参阅以太坊合约 ABI。
- 对于简单的以太币转移:“数据”为空。
nonce:数量
- (可选):nonce 整数值。它将维持交易的处理顺序,并且使您可以覆盖使用相同 nonce 的未处理交易。
作为去中心化应用开发者,您可以依赖于 Web3 实用程序库为您填充其中的大部分详细信息。下面将更加详细地阐述如何根据您需要执行的操作类型来设计这些交易。
对交易签名
生成交易后,您需要对它签名,它才会被以太坊网络所接受。签名有两个作用:1) 证明该交易确实来自您的账户,2) 授权网络从您的账户中扣取交易汽油费。
以太坊交易签名的方式有多种,包括:
- 使用具有当地托管私钥的首选 Web3 库的签名功能
- 使用单独的签名服务 (EthSigner)
- 将该签名过程分派给用户钱包(例如,Metamask 或 Gnosis、Argent(经由 WalletConnect)
- 使用以太坊节点内置的签名功能
下面提供了不同方法的几个示例:
在大多数案例中,Web3 实用程序库(例如 ethers.js 或 web3.js)通常会获取生成并签名的交易,将交易序列化,然后通过 eth_sendRawTransaction RPC 调用将它发送到节点。
如果您选择使用以太坊节点的内置签名功能(比如上一个情景),库将使用另一个 RPC 调用 — eth_sendTransaction
,将纯文本形式的未签名交易详情发送到节点。Infura 不支持该交互模式,因此如果您希望使用这种方法,则目前需要有自己托管的节点。需要注意的是,由于该功能要求节点存储私钥并且会使 RPC 暴露在网络上,因此被视为是一种不安全的做法(未经授权访问节点可能会泄露您的私钥,使攻击者能够以您的名义对交易签名)。如果您运行自己的节点,Hyperledger Besu 提供一项非常实用的代理服务 — EthSigner,可帮助您对交易签名,将您的密钥安全地存储在单独的文件或密钥库中,并实现 eth_sendTransaction
方法。Ethsigner 可以与任何以太坊客户端一起使用,还支持 Infura。您需要为 Ethsigner 配置一位签名者或多位签名者,才能进行交易。
使用 Infura 发送以太坊交易
交易签名后,需要将交易广播到以太坊网络,使其他节点可以看到它,矿工可以将它加入到区块链中。
Infura 提供标准 eth_sendRawTransaction RPC 方法。库通常在后台使用该方法广播交易,因此您无需手动调用 RPC 方法。
在某个时间,以太坊矿工将获得交易副本,完成该交易所在新区块的工作量证明,并将该区块及工作量证明一起广播到整个网络。收到该区块的每个节点都将重新执行包含在其中的交易,并更新以太坊虚拟机 (EVM)* 的状态。
*注:哪些矿工收到哪些交易、矿工是如何选中这些交易的,以及矿工在完成区块的工作量证明后如何将其广播到网络,这些问题非常复杂。为了简单起见,我们在本教程中不作深入讨论。
以太币转移
以太币转移是最简单的交易形式,因为它是 EVM 原生指令,不需要使用智能合约。我们只需要指定目的地址、汽油价格以及需要发送的以太币值(面值为 wei,1 wei = 1e-18 以太币)。然后对交易签名,这会为它分配 nonce 值和签名。
示例:签名并通过一个简单交易发送以太币
先决条件:确保已安装 Node.js 12+,并且具有可用的 Infura 项目 ID。复制该资源库并运行:
cd demo-eth-tx/
npm install
# Add your Infura Project ID below
echo 'INFURA_PROJECT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' > .env
该脚本用于使用 ethers.js 库在两个账户之间发送一小笔以太币。运行它并等待矿工挖到交易:
node ethers/send.js
相同脚本,使用 web3.js 库。运行:
node web3/send.js
智能合约的编译和部署
合约部署是另外一个 EVM 原生操作,与以太币转移看起来几乎相同,但在本情景中,我们将为 data 参数而不是 to 参数提供一个值。
我们为 data 传递的实际参数将由我们所部署的合约的字节代码组成。使用 solc 编译器(如果使用 Solidity(首选))可以推导出合约的字节代码。
注:当您开始构建自己的智能合约时,可能需要使用开发套件,例如 Truffle、Buidler 或 Remix。这些工具将减轻您的工作,因为您无需手动编译智能合约代码。
示例:使用智能合约
现在我们来介绍编写、部署智能合约以及与它交互的必需步骤。
先从简单合约 (Demo.sol) 开始:
contract Demo {
event Echo(string message);
function echo(string calldata message) external {
emit Echo(message);
}
}
该合约采用单一方法(名为 echo),任何人都可以使用 message 进行调用。它将发送一个事件,该事件回传输入的 message。
合约编译
在网络上部署合约之前,我们需要先编译合约。这里包含一个简单的 compile.js 脚本可用于此目的:
node compile.js
编译合约后,在主目录中将显示一个 Demo.json 文件。该文件包括合约字节代码(在部署时必须使用)以及合约交互所必需的应用程序二进制接口 (ABI)。
合约部署
下面这些部署脚本对 ethers.js 和 web3.js 均适用。运行其中的任何脚本都可以部署合约:
node ethers/deploy.js
# or
node web3/deploy.js
部署合约后,您将收到交易哈希。您可以使用区块浏览器或 getTransaction()
和 eth.getTransactionReceipt()
进行检查。矿工挖到部署交易后,脚本将输出新合约的地址。
合约交互
部署合约后,您可以与合约交互。您需要通过将合约地址传递到 to
参数,并传递一些数据告诉合约如何执行 data
参数,来设计交易。
Web3 实用程序库为您提供用于签发合约的高层接口,并且为您生成 data 参数。
下面简单解释这些库的后台操作:data 字段的第一部分是与所调用的合约方法关联的函数选择器。我们可以通过获得函数名称哈希的前 4 个字节及其括号内的参数类型(删除所有空格)来计算函数选择器。例如,字符串 transfer(address,uint256) 可以散列到 4 字节函数签名 0xa9059cbb 中。函数签名与 RLP 编码的函数参数(在本例中为地址和令牌数)连接,构成交易 data 字段。有关合约 ABI 规范和参数编码工作的更多信息,请参阅 Solidity ABI 规范。
下面这些合约交互脚本对 ethers.js 和 web3.js 均适用。这些脚本配置为与已有的较早合约交互,但您可以编辑 ethers/call.js 的这一行或 web3/call.js 的这一行,然后将其替换为新部署合约的地址。
您现在可以运行:
node ethers/call.js
# or
node web3/call.js
恭喜!您已经部署了以太坊智能合约并和它交互。您现在可以继续构建一些精彩内容!🚀
Infura 为开发者提供对以太坊和 IPFS 网络的快速可靠访问。我们提供免费核心服务以及开发者构建去中心化应用所需的一切工具和资源。如果您需要请求更多数量以及获得直接支持,请查看 Infura+ 以获取适合您项目的计划。
衷心感谢 Lucian Boca 对本指南的编写做出的广泛贡献。有关更多 Web3 教程,请查看 Infura 博客或订阅我们的新闻资讯。 🧡