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 标准库