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

如何在Foundry测试中以EOA地址调用合约自定义函数?

Foundry测试中以EOA地址调用合约函数的方法

直接使用this.customFunction()不可行——这种调用方式下,msg.sender会是测试合约本身的地址,而非你指定的EOA地址。要让目标EOA作为msg.sender调用合约函数,你需要用Foundry内置的vm cheatcode,以下是两种常用实现方式:

1. 使用vm.prank()或vm.startPrank()

  • 单次调用场景:先用vm.prank(EOA地址)指定后续一次调用的msg.sender,再直接调用合约函数
  • 多次调用场景:用vm.startPrank(EOA地址)开启持续伪装,之后所有合约调用的msg.sender都会是该EOA,结束时用vm.stopPrank()关闭

示例代码:

pragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "../src/MyERC20.sol";

contract MyERC20Test is Test {
    MyERC20 public myERC20;
    address public user = makeAddr("user"); // 生成测试用EOA地址

    function setUp() public {
        myERC20 = new MyERC20();
    }

    // 单次调用示例
    function testCustomFunctionWithPrank() public {
        vm.prank(user);
        myERC20.customFunction();

        // 验证状态修改(示例:假设customFunction会记录调用者)
        assertEq(myERC20.lastCaller(), user);
    }

    // 多次调用示例
    function testMultipleCallsWithStartPrank() public {
        vm.startPrank(user);
        myERC20.customFunction();
        myERC20.anotherStateChangingFunction(); // 此调用msg.sender同样为user
        vm.stopPrank();
    }
}

2. 使用vm.broadcast()

如果你需要模拟真实链上交易的广播行为(比如生成交易记录、验证gas消耗),可以用vm.broadcast(EOA地址),后续的合约调用会以该EOA作为发起者,效果和prank类似,但会完整模拟交易流程。

示例代码:

function testCustomFunctionWithBroadcast() public {
    vm.broadcast(user);
    myERC20.customFunction();

    assertEq(myERC20.lastCaller(), user);
}

补充说明

  • makeAddr("user")是Foundry提供的工具函数,快速生成无关联的测试EOA,无需私钥。如果需要给该地址分配ETH,可使用deal(user, 1 ether)。
  • 所有vm cheatcode仅在测试合约中可用,不会影响主网部署的合约逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 15:05:20