Foundry 部署脚本
部署 Foundry 合约的方式有两种,一种是命令行部署,另一种是脚本部署。
本文将介绍如何通过脚本部署 Foundry 合约。
环境配置
在 Foundry 中部署和验证合约前,需要完成以下环境设置:
- 初始化 Foundry 项目;
- 完善并加载
.env
中的变量;- 实现终端代理。
具体步骤可参考这篇文章。
1. 编写部署脚本
以 Counter.sol
合约为例,它的部署方式如下:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "forge-std/Script.sol";
import "../src/Counter.sol";
contract CounterScript is Script {
function run() public {
vm.broadcast();
new Counter();
}
}
可以看到,合约部署脚本分为以下几个部分:
- 声明:哪怕是部署脚本,也需要遵守 Solidity 的格式。
- 导入依赖:导入需要的文件和模块,包括脚本工具(
forge-std/Script.sol
)以及所要部署的目标合约(如Counter.sol
)。 - 定义部署合约:定义一个新的合约用于部署,通常命名为
<TargetContract>Script
,继承自部署框架Script
,以便调用 Foundry 作弊码。 - 入口函数:声明
run()
函数作为合约的入口。 - 部署语句:
new Counter()
语句会生成一个没有接收者的交易,且交易数据是函数字节码和构造函数的参数(如果有的话)。 - 广播语句:
vm.broadcast()
是 Foundry 的作弊代码,它会模拟广播当前的调用。
2. 执行命令脚本
接下来,我们需要在通过脚本部署合约的同时,验证该合约:
forge script script/FundMe.s.sol:FundMeScript \
--private-key $PRIVATE-KEY \
--rpc-url $SEPOLIA-RPC-URL \
--broadcast \
--verify \
--vvvv
在该命令中,我们用到了以下命令选项:
- –private-key
- –rpc-url
- –broadcast
- –verify
- –vvvv
注意:由于 Etherscan 的 API Key 已经通过 .env
添加到了环境变量,因此即便没有在命令中声明 --etherscan-api-key
,我们也可以成功验证合约。
附录
为了更好地解释部署脚本中的代码,以及部署这一行为在区块链中的实际过程,我们补充了以下两个附录:
附1:广播作弊码 vm.broadcast()
vm.broadcast()
是 Foundry 的作弊代码,它会模拟广播当前的调用。
// 部署脚本
contract CounterScript is Script {
function run() public {
vm.broadcast();
new Counter();
}
}
在这个部署脚本中,vm.broadcast()
会将 new Counter()
语句所创建的特殊交易模拟广播到全网,当该交易被矿工打包进区块并经过其他矿工的验证后,EVM 便会按照交易要求创建一个新的 Counter
实例,并保存在状态数据库中,这样便实现了 Counter
合约实例的部署。
其中,vm.broadcast()
只会广播接下来的一次调用,如果要广播多次调用,可以使用 vm.startBroadcast()
以及 vm.endBroadcast()
,例如:
contract CounterScript is Script {
function run() public {
// 替换 vm.broadcast()
vm.startBroadcast();
new Counter();
vm.stopBroadcast();
}
}
附2:合约在区块链中的部署过程
我们可以结合区块链部署合约的实际流程,来帮助我们更好地了解部署代码:
- 交易创建:
new Counter()
语句本质上是创建了一个交易,该交易的接收者为0,且交易数据是合约的字节码和构造函数的参数(如果有的话)。 - 交易广播:
vm.broadcast()
会将该交易广播到网络中,等待矿工打包。 - 交易打包:网络中会有随机的矿工将该交易打包起来,作为争取记账权的数据。
- 交易验证:当打包了该交易的矿工获得记账权后,其它节点会验证该交易所在区块的记账权的有效性。
- 创建合约实例:当包含该交易的区块被打包和验证后,EVM 便会执行这个交易中的字节码和构造函数参数,从而创建新的合约实例。并根据发送者的地址和nonce计算该合约的地址。最终,这些数据(包括合约的地址和状态)会被保存在以太坊的状态数据库中。
所以,合约的部署包含以上5个步骤,而合约的创建只是合约部署的其中一步(也是最后一步),并且合约的部署最终依靠 EVM 完成,合约的部署语句仅仅是一个命令。
参考资料
- Foundry Book: Solidity Scriping