etch

签名

function etch(address who, bytes calldata code) external;

描述

将地址 who 的字节码设置为 code

例子

bytes memory code = address(awesomeContract).code;
address targetAddr = makeAddr("target");
vm.etch(targetAddr, code);
log_bytes(address(targetAddr).code); // 0x6080604052348015610010...

使用 vm.etch 启用自定义预编译

一些链,如 Blast 或 Arbitrum,运行时使用自定义预编译。Foundry 在原生 EVM 上运行,并不了解这些预编译。如果你遇到由于预编译不可用而导致的回滚,可以使用 vm.etch 作弊码将缺失的预编译模拟注入到预期出现的地址。

pragma solidity 0.8.10;

import {Test} from "forge-std/Test.sol";

// Firstly, we implement a mock emulating the actual precompile behavior
contract YieldMock {
    address private constant blastContract = 0x4300000000000000000000000000000000000002;

    mapping(address => uint8) public getConfiguration;

    function configure(address contractAddress, uint8 flags) external returns (uint256) {
        require(msg.sender == blastContract);

        getConfiguration[contractAddress] = flags;
        return 0;
    }

    function claim(address, address, uint256) external pure returns (uint256) {
        return 0;
    }

    function getClaimableAmount(address) external pure returns (uint256) {
        return 0;
    }
}

contract SomeBlastTest is Test {
    function setUp() public {
        vm.createSelectFork("blastRpcUrl");
        // Deploy mock of the precompile
        YieldMock yieldMock = new YieldMock();
        // Set mock bytecode to the expected precompile address
        vm.etch(0x0000000000000000000000000000000000000100, address(yieldMock).code);
    }

    function testSomething() public {
        // Now we can interact with Blast contracts without reverts
    }
}

注入预编译的模拟可能会很棘手,因为这样的模拟不会完全模拟链上实际预编译的行为。

在上述情况下,如果配置了任何收益模式,模拟将不会导致实际收益的累积。

另请参阅

Forge 标准库