You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用PriceConverter的getConversionRate触发Revert错误排查

问题分析与解决方案

你的测试失败核心原因是本地测试环境(如Anvil)中不存在你指定的Chainlink价格预言机合约,调用latestRoundData()时因目标合约不存在直接触发Revert,而非因为ETH金额不足的预期Revert。

具体问题点

  1. 你使用的价格预言机地址0x694AA1769357215DE4FAC081bf1f309aDC325306是Sepolia测试网的ETH/USD喂价地址,但本地测试链没有部署该合约,静态调用会直接失败。
  2. 测试代码未预期Revert行为,Foundry默认将Revert视为测试失败,即便这是业务逻辑预期的结果。

解决方案:使用Mock合约模拟价格预言机

在本地测试中,我们需要部署一个模拟Chainlink喂价的Mock合约,返回固定价格,让FundMe合约能正常调用价格转换函数。

步骤1:编写Mock合约

创建测试用的Mock价格预言机合约,模拟latestRoundData()返回固定价格:

// test/mocks/MockAggregatorV3Interface.sol
pragma solidity ^0.8.18;

interface AggregatorV3Interface {
    function decimals() external view returns (uint8);
    function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80);
}

contract MockAggregatorV3Interface is AggregatorV3Interface {
    function decimals() external pure returns (uint8) {
        return 8; // Chainlink ETH/USD喂价默认8位小数
    }

    function latestRoundData() external pure returns (uint80, int256, uint256, uint256, uint80) {
        // 模拟ETH价格为2000 USD,转换为8位小数格式
        return (0, 2000e8, 0, 0, 0);
    }
}

步骤2:修改测试文件

在测试的setUp阶段部署Mock合约,并将其地址传入FundMe合约初始化,同时添加vm.expectRevert()验证预期的业务逻辑Revert:

// test/FundMeTest.t.sol
pragma solidity ^0.8.18;

import "forge-std/Test.sol";
import "../src/FundMe.sol";
import "./mocks/MockAggregatorV3Interface.sol";

contract FundMeTest is Test {
    FundMe fundMe;
    MockAggregatorV3Interface mockPriceFeed;
    address public USER = makeAddr("user");
    // 假设MINIMUM_USD为50 USD,0.01 ETH按2000 USD算仅为20 USD,满足"金额不足"的测试条件
    uint256 public constant INSUFFICIENT_ETH = 0.01 ether;

    function setUp() public {
        // 部署Mock价格预言机
        mockPriceFeed = new MockAggregatorV3Interface();
        // 初始化FundMe合约,传入Mock地址
        fundMe = new FundMe(address(mockPriceFeed));
        // 给测试用户转ETH
        vm.deal(USER, 10 ether);
    }

    function testFundFailsWithoutEnoughEth() public {
        vm.prank(USER);
        // 预期触发"金额不足"的Revert,错误信息需与合约中一致
        vm.expectRevert("You need to spend more ETH!");
        fundMe.fund{value: INSUFFICIENT_ETH}();
    }
}

步骤3:验证测试执行

运行测试命令时确保测试函数名匹配:

forge test --match-test testFundFailsWithoutEnoughEth -vvv

额外注意事项

  • 确认FundMe合约的构造函数正确接收并初始化s_priceFeed变量。
  • 若你的MINIMUM_USD定义不同,需调整INSUFFICIENT_ETH的值,确保其转换后的USD金额小于MINIMUM_USD。
  • 测试中必须使用vm.expectRevert()声明预期的Revert行为,否则Foundry会将任何Revert判定为测试失败。

内容的提问来源于stack exchange,提问作者Abdallah Jawhary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 04:10:03