在 Virtual TestNet 中复现并验证交易
从固定区块创建隔离环境,通过 RPC 和 Foundry 执行可重复的 WETH 存款并验证结果。
案例目标
从固定 Ethereum 区块创建 Virtual TestNet,用相同输入重复执行 WETH deposit(),并验证重置后状态能够回到一致的起点。
示例交易与背景
本例从区块 19850321 创建 Virtual TestNet,并使用 Foundry 的 cast 向 Ethereum WETH 合约发送 1 ETH:
| 输入 | 值 |
|---|---|
| 源链 | Ethereum |
| Fork 区块 | 19850321 |
| 测试账户 | 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 |
| WETH | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
| 调用 | deposit(),value 1 ether |
以下命令只用于 Virtual TestNet。请使用测试私钥,不要把生产钱包私钥写入 shell 历史或文档。
预期回答的问题
- RPC 是否连接到预期的 Fork 区块?
deposit()是否准确增加1 WETH?- 删除并从同一区块重建后,是否可以得到相同的初始状态和执行结果?
分析步骤
-
创建 Ethereum Virtual TestNet,将 Block number 设置为
19850321。 -
复制详情页中的 Public RPC URL,并在本地设置临时变量:
export SKYLENS_RPC_URL="<YOUR_RPC_URL>" export SKYLENS_TEST_KEY="<TEST_PRIVATE_KEY>" export SKYLENS_TEST_ACCOUNT="0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" export WETH_ADDRESS="0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" -
验证链高度并记录执行前 WETH 余额:
cast block-number --rpc-url "$SKYLENS_RPC_URL" cast call "$WETH_ADDRESS" \ "balanceOf(address)(uint256)" "$SKYLENS_TEST_ACCOUNT" \ --rpc-url "$SKYLENS_RPC_URL" -
在详情页用 Fund wallet 为测试账户补充 Gas,再发送存款交易:
cast send "$WETH_ADDRESS" "deposit()" \ --value 1ether \ --private-key "$SKYLENS_TEST_KEY" \ --rpc-url "$SKYLENS_RPC_URL" -
再次查询 WETH 余额,并从 Operations 打开交易进入 Skylens。
-
删除该测试网络,从区块
19850321重新创建,重复步骤 2–5,比较两次记录。
关键证据
每次运行至少保留以下记录:
| 检查项 | 预期结果 |
|---|---|
cast block-number | 初始高度对应 Fork 区块;发送交易后按测试网规则增长 |
cast send receipt | status 成功,并返回可在 Operations 打开的交易哈希 |
| WETH 余额差 | after - before = 1000000000000000000 wei |
| Balance Changes | 测试账户约 -1 ETH、+1 WETH;另有 Gas 消耗 |
| 重置后余额 | 回到 Fork 区块对应的初始值 |
| 第二次余额差 | 仍为 1000000000000000000 wei |
余额变化应使用差值而不是假设初始 WETH 为零。这样即使 Fork 区块中的账户已有余额,结论仍然可验证。
案例结论
两次 Virtual TestNet 都从区块
19850321开始,使用相同账户、合约、value 和 calldata。每次deposit()都使 WETH 余额精确增加1e18wei;删除并重建后,状态回到相同起点,证明该场景能够被重复执行和对比。
注意事项
- Virtual TestNet RPC 仍应按外部服务处理,不要使用生产私钥。
- 需要复现主网交易时,通常从目标交易前一个区块创建网络。
- 时间相关逻辑应记录并固定 Warp time;本例的 WETH 存款不依赖时间。
- Fund wallet、部署合约和发送交易都会改变当前 TestNet 状态,重跑前应重置或重建。
