39次发布
0.2.0 | 2023年5月19日 |
---|---|
0.1.0 | 2023年5月12日 |
0.0.37 | 2023年5月12日 |
0.0.27 | 2023年4月29日 |
#10 in #forge
354 每月下载量
89KB
1.5K SLoC
forge-deploy
一个cli和相关合约,用于通过名称跟踪部署并在Solidity中重用。
它尽可能与hardhat-deploy保持兼容(工作进行中)。
forge-deploy旨在提供最小化功能集,为Foundry提供一个优雅的部署系统。
入门模板
https://github.com/wighawag/template-foundry
功能
- 为Forge合约生成类型安全的部署函数。无需传递文本字符串并希望abi编码的参数顺序正确或类型正确。
- 将部署保存到json文件(基于hardhat-deploy模式)
- 基于模板和Solidity库的模块化系统
模块化
该系统是模块化的。默认提供的部署函数提供了一组基本功能,但系统可以通过自定义函数轻松扩展。请参阅contracts/DefaultDeployerFunction.sol以及如何将其作为一个简单的库自行提供。forge-deploy真正提供的是contrats/Deployer.sol中特定的函数集来save
和get
部署
如何使用
有两种入门方式,一种是不使用npm,另一种是使用npm
使用npm
-
有一个带有npm的forge项目,并进入它
mkdir my-project; cd my-project; forge init; npm init
-
添加forge-deploy包
npm i -D forge-deploy
这将自动安装forge-deploy二进制文件
-
将生成的文件添加到.gitignore中
cat >> .gitignore <<EOF # forge-deploy /generated /deployments/localhost /deployments/31337 EOF
-
您还需要通过编辑foundry.toml允许forge在特定路径上读取和写入
cat >> foundry.toml <<EOF fs_permissions = [ { access = "read", path = "./deployments"}, { access = "read", path = "./out"}, ] EOF
-
生成类型安全的部署函数
在package.json中添加一些脚本
{ "scripts": { "compile": "forge-deploy gen-deployer && forge build", "deploy": "forge script script/Counter.s.sol --rpc-url $RPC_URL --broadcast --private-key $DEPLOYER_PRIVATE_KEY -v && forge-deploy sync;" } }
注意我们如何在脚本执行后直接执行
forge-deploy sync
。这样,forge-deploy将跟踪新的部署。 -
添加部署脚本
添加文件
script/Deploy.s.sol
并包含以下内容// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; import "forge-deploy/DeployScript.sol"; import "generated/deployer/DeployerFunctions.g.sol"; contract Deployments is DeployScript { using DeployerFunctions for Deployer; function deploy() external returns (Counter) { return deployer.deploy_Counter("MyCounter"); } }
将调用 deploy 函数,由于脚本扩展了 DeployScript(它本身扩展了来自 forge-std 的 Script),因此您将能够访问 deployer 变量。
此变量主要公开了 save 和 get 函数。部署功能实际上在像这里提供的 "DeployerFunctions.g.sol" 这样的库中实现,这是从上面的命令生成的代码:
forge-deploy gen-deployer;
-
现在可以通过 forge 脚本来执行脚本
npm run deploy
注意,在使用 anvil(本地网络)时,您需要为 forge-deploy 设置 DEPLOYMENT_CONTEXT 环境变量以保存部署
DEPLOYMENT_CONTEXT=localhost npm run deploy
这对于使用默认 chain id 31337 的 localhost 是必要的,因为 forge-deploy 默认不会在该 chainId 上保存部署(同样适用于 1337)。这样它就不会与使用 chainId=31337 的内存测试发生冲突
DEPLOYMENT_CONTEXT 环境变量还允许您在同一个网络上隔离不同的部署上下文。如果没有指定,上下文是 chainId
无需 npm
-
拥有一个 forge 项目,并进入其中
mkdir my-project; cd my-project; forge init;
-
添加forge-deploy包
forge install wighawag/[email protected];
-
直接从 lib/forge-deploy 构建 cli
cd lib/forge-deploy; cargo build --release; cp target/release/forge-deploy ../../forge-deploy;
在上面的最后一步中,我们还将其复制到项目文件夹中,以便于访问
这样,您就可以通过以下方式执行它
./forge-deploy <command>
如果您不想使用 cargo,也可以下载二进制文件: https://github.com/wighawag/forge-deploy/releases
-
在 .gitignore 中添加生成的文件和刚刚安装的二进制文件
cat >> .gitignore <<EOF # forge-deploy /generated /deployments/localhost /deployments/31337 # forge-deploy cli binary /forge-deploy EOF
-
您还需要通过编辑foundry.toml允许forge在特定路径上读取和写入
cat >> foundry.toml <<EOF fs_permissions = [ { access = "read", path = "./deployments"}, { access = "read", path = "./out"} ] EOF
-
生成类型安全的部署函数
./forge-deploy gen-deployer;
-
添加部署脚本
添加文件
script/Deploy.s.sol
并包含以下内容// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; import "forge-deploy/DeployScript.sol"; import "generated/deployer/DeployerFunctions.g.sol"; contract Deployments is DeployScript { using DeployerFunctions for Deployer; function deploy() external returns (Counter) { return deployer.deploy_Counter("MyCounter"); } }
将调用 deploy 函数,由于脚本扩展了 DeployScript(它本身扩展了来自 forge-std 的 Script),因此您将能够访问 deployer 变量。
此变量主要公开 save 和 get 函数。部署功能实际上在像这里提供的 "DeployerFunctions.g.sol" 这样的库中实现,这是从上面的命令生成的代码:
./forge-deploy gen-deployer;
-
现在可以通过 forge 脚本来执行脚本
请注意,您需要直接执行
./forge-deploy sync
例如
forge script script/Counter.s.sol --rpc-url $RPC_URL --broadcast --private-key $DEPLOYER_PRIVATE_KEY -v && ./forge-deploy sync;
使用 anvil 和默认账户
DEPLOYMENT_CONTEXT=localhost forge script script/Counter.s.sol --rpc-url http://127.0.0.1:8545 --broadcast --private-key ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -v && ./forge-deploy sync;
请注意,这里我们指定了 DEPLOYMENT_CONTEXT 环境变量。这对于使用默认 chain id 31337 的 localhost 是必要的,因为 forge-deploy 默认不会在该 chainId 上保存部署(同样适用于 1337)。这样它就不会与使用 chainId=31337 的内存测试发生冲突
DEPLOYMENT_CONTEXT 环境变量还允许您在同一个网络上隔离不同的部署上下文。如果没有指定,上下文是 chainId
快速开始
在某个地方启动 anvil
anvil;
然后复制并执行此操作,查看结果
mkdir my-forge-deploy-project;
cd my-forge-deploy-project;
forge init;
forge install wighawag/[email protected];
cd lib/forge-deploy;
cargo build --release;
cp target/release/forge-deploy ../../forge-deploy;
cd ../..;
cat >> foundry.toml <<EOF
fs_permissions = [
{ access = "read", path = "./deployments"},
{ access = "read", path = "./out"}
]
EOF
cat >> .gitignore <<EOF
# forge-deploy
/generated
/deployments/localhost
/deployments/31337
EOF
./forge-deploy gen-deployer;
cat > script/Deploy.s.sol <<EOF
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "forge-deploy/DeployScript.sol";
import "generated/deployer/DeployerFunctions.g.sol";
contract Deployments is DeployScript {
using DeployerFunctions for Deployer;
function deploy() external returns (Counter) {
return deployer.deploy_Counter("MyCounter");
}
}
EOF
DEPLOYMENT_CONTEXT=localhost forge script script/Deploy.s.sol --rpc-url http://127.0.0.1:8545 --broadcast --private-key ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 -v && ./forge-deploy sync;
在测试中可重用
forge 脚本的一个非常棒的特性,仍然保留在 forge-deploy 中,就是能够在测试中使用脚本。
这允许您在测试中重复使用部署过程!
例如,这里是对 Counter 的基本测试。将以下内容复制到现有的 test/Counter.t.sol 中,并运行测试以查看其效果
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "../src/Counter.sol";
import "../script/Deploy.s.sol";
contract CounterTest is Test {
Counter public counter;
function setUp() public {
counter = new Deployments().deploy();
counter.setNumber(0);
}
function testIncrement() public {
counter.increment();
assertEq(counter.number(), 1);
}
function testSetNumber(uint256 x) public {
counter.setNumber(x);
assertEq(counter.number(), x);
}
}
像往常一样,要运行测试,您可以执行以下操作
forge test
更多信息
请注意,生成的 Solidity 是可选的。
您也可以简单地使用默认的 deploy 函数
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "forge-deploy/DeployScript.sol";
import "forge-deploy/DefaultDeployerFunction.sol";
import "../src/Counter.sol";
contract Deployments is DeployScript {
using DefaultDeployerFunction for Deployer;
function deploy() external returns (Counter) {
return Counter(
deployer.deploy(
"MyCounter",
"Counter.sol:Counter", // forge's artifact id
"" // no arguments: empty bytes
)
);
}
}
依赖关系
~6–15MB
~194K SLoC