调用PriceConverter的getConversionRate触发Revert错误排查
问题分析与解决方案
你的测试失败核心原因是本地测试环境(如Anvil)中不存在你指定的Chainlink价格预言机合约,调用latestRoundData()时因目标合约不存在直接触发Revert,而非因为ETH金额不足的预期Revert。
具体问题点
- 你使用的价格预言机地址
0x694AA1769357215DE4FAC081bf1f309aDC325306是Sepolia测试网的ETH/USD喂价地址,但本地测试链没有部署该合约,静态调用会直接失败。 - 测试代码未预期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
相关产品推荐
相关产品推荐

