本文详细讲解了如何使用Foundry和QuickNode对以太坊区块链进行fork,允许开发者在一个镜像真实链的环境中测试智能合约及其交互。包括Forking的原因、使用Foundry的优势、QuickNode的设置步骤以及如何进行基本的合约互动和账户模拟。文章结构清晰,有具体的步骤和代码示例,适合对以太坊开发有一定基础的开发者阅读。
更新于
2025年1月30日
全部 以太坊 Solidity 归档节点 智能合约 Foundry
在此页面
9分钟阅读
复制以太坊区块链允许开发者在一个控制环境中测试合约和交互,该环境镜像真实链。此指南介绍了 Foundry,这是一个越来越受以太坊开发者欢迎的工具,特别适用于复制以太坊或任何 EVM 兼容区块链。我们将着重介绍如何将 Foundry 与 QuickNode 搭配使用,以复制以太坊主网。
区块链复制是开发者的一个关键实践,它提供了一个实验智能合约的游乐场,而没有主网带来的风险。与使用测试网相比,复制有几个突出的原因:
状态准确性:复制准确复现了主网在特定区块的状态,使得开发者能够与真实数据和合约进行交互。这种精确性对于依赖区块链当前状态的测试场景至关重要,这是测试网无法提供的,因为测试网在不同状态的隔离环境中运行。
测试:确保你的合约在真实网络条件下按预期工作。复制提供了比测试网更准确、更全面的测试环境,因为它镜像了实际的主网环境,包括真实的代币余额、已部署的合约和网络活动。
调试:识别并修复在反映实时区块链的状态下的问题。复制提供了独特的好处,使得在现有合约和交易的上下文中调试合约,这对于识别和解决集成问题是无价的。
智能合约控制:在复制环境中,开发者通过模拟功能获得了对智能合约账户的无与伦比的控制能力,这使得在测试网或主网上无法执行的操作成为可能。例如,你可以像拥有者一样授权代币智能合约进行铸造或转移。这是测试网所无法做到的,除非你重新部署Token智能合约并附加你的访问控制。
与测试网相比,复制主网提供了一个更接近生产环境的近似值,并允许你更快速地进行测试,因为你不必依赖从水龙头获取测试网币和不可控的区块时间。
Foundry 在以太坊开发工具集中因其速度、简洁性和以开发者为中心的功能而脱颖而出。它是一个快速设置本地以太坊环境的完美工具,具有部署、测试和与智能合约交互的能力。Foundry 的一个显著特点是即使在脚本和测试中也能使用 Solidity。
QuickNode 在多个原因下脱颖而出,成为复制以太坊区块链的最佳选择:
可靠性和速度:QuickNode 提供高性能的端点,这对于高效可靠的区块链交互至关重要。
访问归档数据:访问完整归档节点对复制至关重要,而 QuickNode 提供开箱即用的解决方案,使你能够在任何区块进行复制。
可扩展性:随着你的开发需求增长,QuickNode 的可扩展基础设施确保你的节点能够处理增加的需求。
QuickNode 简化了访问以太坊归档数据的过程,这对于复制较旧的区块至关重要。请按照以下步骤设置你的 QuickNode 端点:
现在,让我们设置 Foundry 并配置它以使用你的 QuickNode 端点:
请遵循官方的 Foundry 安装指南。
使用 Foundry 开始一个新项目。此命令将使用默认模板创建一个名为 forked-blockchain
的新文件夹。
forge init forked-blockchain
cd forked-blockchain
接下来,我们可以开始使用 anvil
命令,它是本地测试网络节点。我们将包括我们的 QuickNode 端点 URL 和两个选项。--fork-url
标签将通过远程端点获取区块链状态,而不是从空白状态开始。其次,我们还将包括 --fork-block-number
标签,它从特定的区块号开始复制区块链状态。在本演示中,我们在第 19,000,000 个区块处复制以太坊。
将 YOUR_QUICKNODE_ENDPOINT_URL 占位符替换为设置端点后检索到的实际端点 URL。
anvil --fork-url YOUR_QUICKNODE_ENDPOINT_URL --fork-block-number 19000000
输出应类似于以下内容。Foundry 提供 10 个帐户供测试目的使用,并附带它们的公钥和私钥,以及一些与复制区块链相关的信息。
复制链运行后,你现在可以像与主以太坊网络一样与之互动。我们将介绍一些简单的方法,比如 获取区块号,以及更高级的方法,例如 与智能合约交互和模拟其他账户。
保持终端窗口运行,并在同一目录下打开一个新终端窗口。
让我们通过发送一个 cURL 请求和 Foundry 的 cast
命令来获取复制区块链的区块号。
运行以下代码以使用 Foundry 的 cast
命令获取区块号。
cast block-number
结果应与你的复制区块链的区块号匹配,而不是实际以太坊主网的区块号。
运行以下代码以发送请求获取区块号。
curl --data '{"method":"eth_blockNumber","params":[],"id":1,"jsonrpc":"2.0"}' -H "Content-Type: application/json" -X POST 127.0.0.1:8545
复制链的 RPC 服务器在 127.0.0.1:8545 上侦听,因此可以发送 RPC 请求以以类似于你在测试网或主以太坊网络上的方式与链进行交互。这允许进行广泛的区块链交互,包括查询区块号、交易细节和调试,所有这些都在你的本地环境中。
这种在本地调用 RPC 方法的能力,正如你在实时区块链上所做的,提供了对开发者的强大工具。从基本查询,如 eth_blockNumber
,到更复杂的查询,如 debug_traceTransaction
,开发者可以测试其应用在真实世界条件下的行为。有关可用 RPC 方法及其使用方法的列表,请参阅 QuickNode 的以太坊 RPC 文档。
结果是十六进制格式。要将其转换为十进制格式,你可以使用 十六进制转十进制转换器。结果应与你的复制区块链的区块号匹配,而不是实际以太坊主网的区块号。
在复制环境中使用 Foundry 的一个强大功能是能够模拟账户,如持有大量代币余额的 鲸鱼 账户。这种能力对于需要特定账户交互的测试场景是无价的,而不需要实际私钥。
让我们创建一个 Foundry 测试脚本,从一个 模仿账户 向 另一个账户 发送代币。
在本指南中,我们创建一个测试文件,将 1,000,000 USDC 从 Polygon ERC20 Bridge 发送到 Vitalik(vitalik.eth),这是 USDC 的最大持有者之一。
在 test 目录下创建一个测试文件 SendToken.t.sol
。然后,按如下所示进行修改。
这个测试文件提供了与 USDC 代币合约交互、模拟鲸鱼账户、转移代币,以及验证在复制以太坊区块链上交易成功的明确示例。
test/SendToken.t.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
// 与 USDC 代币交互的 ERC-20 接口
interface IERC20 {
function balanceOf(address) external view returns (uint256);
function transfer(address, uint256) external returns (bool);
function decimals() external view returns (uint8);
}
// TokenTransferTest 是一个设置并运行测试的合约
contract TokenTransferTest is Test {
IERC20 usdc; // USDC 的接口实例
address whale = 0x40ec5B33f54e0E8A33A975908C5BA1c14e5BbbDf; // Polygon 的 ERC20 Bridge 合约地址,作为鲸鱼账户
address recipient = 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045; // Vitalik(vitalik.eth)的地址,作为接收者
address usdcAddress = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; // USDC 合约地址在以太坊主网
// setUp 函数在每个测试之前运行,设置环境
function setUp() public {
usdc = IERC20(usdcAddress); // 初始化 USDC 合约接口
// 模拟鲸鱼账户进行测试
vm.startPrank(whale);
}
// testTokenTransfer 函数测试从鲸鱼账户到接收者的 USDC 转移
function testTokenTransfer() public {
uint256 initialBalance = usdc.balanceOf(recipient); // 获取接收者的初始余额
uint8 decimals = usdc.decimals(); // 获取 USDC 的小数位数
uint256 transferAmount = 1000000 * 10 ** decimals; // 设置要转移的 USDC 数量(100 万个代币,6 个小数位)
console.log("接收者的初始余额:", initialBalance); // 将初始余额记录到控制台
// 执行从鲸鱼到接收者的代币转移
usdc.transfer(recipient, transferAmount);
uint256 finalBalance = usdc.balanceOf(recipient); // 获取接收者的最终余额
console.log("接收者的最终余额:", finalBalance); // 将最终余额记录到控制台
// 验证接收者的余额是否增加了转移金额
assertEq(finalBalance, initialBalance + transferAmount, "代币转移失败");
vm.stopPrank(); // 停止模拟鲸鱼账户
}
}
在执行测试之前,让我们理解我们在 forge test
的调用中包括的标签:
--rpc-url:由于复制的本地区块链在另一个终端中持续运行,因此我们使用复制的本地区块链的 RPC URL。
--match-path:它允许仅在与路径匹配的源文件中运行测试。对于现有多个测试文件时很有用。
-vv:它表示第二级详细信息。它启用所有测试的日志打印。
详细信息级别
详细信息级别:
来源:Foundry 文档
现在,运行代码以测试 SendToken 文件。
forge test --rpc-url http://127.0.0.1:8545/ --match-path test/SendToken.t.sol -vv
如果你希望在每次测试时都创建一个新的复制区块链,可以使用
--fork-url
和--fork-block-number
,如同你 复制区块链时 的操作那样,而不是--rpc-url
。
控制台输出应类似于以下内容。
成功的测试结果意味着我们成功地从一个我们能够在本地环境中控制的鲸鱼账户发送了 100 万 USDC。在以下测试结果中,接收者的 USDC 余额从 64544.442234 增加到了 1064544.442234。
复制区块链上的代币不是实际代币,旨在用于开发和测试目的。
Running 1 test for test/SendToken.t.sol:TokenTransferTest
[PASS] testTokenTransfer() (gas: 41687)
Logs:
接收者的初始余额: 64544442234
接收者的最终余额: 1064544442234
测试结果:ok. 1 通过;0 失败;0 跳过;完成于 843.92µs
运行了 1 个测试套件:1 个测试通过,0 个失败,0 跳过(共 1 个测试)
相反,在你的 anvil
调用中包含 --block-time 10
标签会在测试中引入时间,模拟块在特定时间间隔(例如 10 秒)上发布。这对于观察合约随时间的表现非常重要,例如归属或代币锁定。
在本指南中,我们探讨了使用 Foundry 和 QuickNode 复制以太坊主网的过程。从设置 QuickNode 以太坊归档节点开始,我们经历了安装和配置 Foundry、复制链、与复制环境交互以及模拟账户的过程。
有关更多信息和高级用法,请参阅 Foundry 文档 和 QuickNode 指南。
订阅我们的 新闻通讯,获取更多关于 Web3 和区块链的文章和指南。如果你有任何问题或需要进一步的帮助,欢迎加入我们的 Discord 服务器,或使用下面的表单提供反馈。通过关注我们的 Twitter(@QuickNode)和我们的 Telegram 通知频道,保持与最新动态同步。
让我们知道 如果你有任何反馈或对新主题的请求。我们非常期待你的意见。
- 原文链接: quicknode.com/guides/eth...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!