作弊码参考
作弊码为你提供强大的断言,改变 EVM 状态的能力,模拟数据等功能。
通过使用作弊码地址(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D
)来提供作弊码。
ℹ️ 注意
如果在测试中使用模糊地址时遇到此地址的错误,你可能希望通过使用以下行将其从模糊测试中排除:
vm.assume(address_ != 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D);
你还可以通过 Forge 标准库的 Test
合约中提供的 vm
轻松访问作弊码。
Forge 标准库作弊码
Forge 标准库实现了作弊码的包装器,这些包装器结合了多个标准作弊码,以改进开发体验。这些技术上不是作弊码,而是 Forge 作弊码的组合。
你可以在参考部分中查看 Forge 标准库作弊码包装器的列表。你可以参考Forge 标准库源代码 以了解包装器在内部是如何工作的。
作弊码类型
以下是有关不同 Forge 作弊码的一些子部分。
- Environment: 改变以太坊虚拟机状态的作弊码。
- Assertions: 强大的断言作弊码
- Fuzzer: 配置模糊器的作弊码
- External: 与外部状态(文件、命令等)交互的作弊码
- Utilities: 较小的实用程序作弊码
- Forking: 分叉模式作弊码
- Snapshots: 快照作弊码
- RPC: 与 RPC 相关的作弊码
- File: 用于处理文件的作弊码
添加新的作弊码
如果你需要新功能,请考虑贡献到 Foundry 的代码库以添加作弊码。
作弊码接口
这是 Forge 中所有作弊码的 Solidity 接口。
interface CheatCodes {
// This allows us to getRecordedLogs()
struct Log {
bytes32[] topics;
bytes data;
}
// Possible caller modes for readCallers()
enum CallerMode {
None,
Broadcast,
RecurrentBroadcast,
Prank,
RecurrentPrank
}
enum AccountAccessKind {
Call,
DelegateCall,
CallCode,
StaticCall,
Create,
SelfDestruct,
Resume
}
struct Wallet {
address addr;
uint256 publicKeyX;
uint256 publicKeyY;
uint256 privateKey;
}
struct ChainInfo {
uint256 forkId;
uint256 chainId;
}
struct AccountAccess {
ChainInfo chainInfo;
AccountAccessKind kind;
address account;
address accessor;
bool initialized;
uint256 oldBalance;
uint256 newBalance;
bytes deployedCode;
uint256 value;
bytes data;
bool reverted;
StorageAccess[] storageAccesses;
}
struct StorageAccess {
address account;
bytes32 slot;
bool isWrite;
bytes32 previousValue;
bytes32 newValue;
bool reverted;
}
// Derives a private key from the name, labels the account with that name, and returns the wallet
function createWallet(string calldata) external returns (Wallet memory);
// Generates a wallet from the private key and returns the wallet
function createWallet(uint256) external returns (Wallet memory);
// Generates a wallet from the private key, labels the account with that name, and returns the wallet
function createWallet(uint256, string calldata) external returns (Wallet memory);
// Signs data, (Wallet, digest) => (v, r, s)
function sign(Wallet calldata, bytes32) external returns (uint8, bytes32, bytes32);
// Get nonce for a Wallet
function getNonce(Wallet calldata) external returns (uint64);
// Set block.timestamp
function warp(uint256) external;
// Set block.number
function roll(uint256) external;
// Set block.basefee
function fee(uint256) external;
// Set block.difficulty
// Does not work from the Paris hard fork and onwards, and will revert instead.
function difficulty(uint256) external;
// Set block.prevrandao
// Does not work before the Paris hard fork, and will revert instead.
function prevrandao(bytes32) external;
// Set block.chainid
function chainId(uint256) external;
// Loads a storage slot from an address
function load(address account, bytes32 slot) external returns (bytes32);
// Stores a value to an address' storage slot
function store(address account, bytes32 slot, bytes32 value) external;
// Signs data
function sign(uint256 privateKey, bytes32 digest)
external
returns (uint8 v, bytes32 r, bytes32 s);
// Computes address for a given private key
function addr(uint256 privateKey) external returns (address);
// Derive a private key from a provided mnemonic string,
// or mnemonic file path, at the derivation path m/44'/60'/0'/0/{index}.
function deriveKey(string calldata, uint32) external returns (uint256);
// Derive a private key from a provided mnemonic string, or mnemonic file path,
// at the derivation path {path}{index}
function deriveKey(string calldata, string calldata, uint32) external returns (uint256);
// Gets the nonce of an account
function getNonce(address account) external returns (uint64);
// Sets the nonce of an account
// The new nonce must be higher than the current nonce of the account
function setNonce(address account, uint64 nonce) external;
// Performs a foreign function call via terminal
function ffi(string[] calldata) external returns (bytes memory);
// Set environment variables, (name, value)
function setEnv(string calldata, string calldata) external;
// Read environment variables, (name) => (value)
function envBool(string calldata) external returns (bool);
function envUint(string calldata) external returns (uint256);
function envInt(string calldata) external returns (int256);
function envAddress(string calldata) external returns (address);
function envBytes32(string calldata) external returns (bytes32);
function envString(string calldata) external returns (string memory);
function envBytes(string calldata) external returns (bytes memory);
// Read environment variables as arrays, (name, delim) => (value[])
function envBool(string calldata, string calldata)
external
returns (bool[] memory);
function envUint(string calldata, string calldata)
external
returns (uint256[] memory);
function envInt(string calldata, string calldata)
external
returns (int256[] memory);
function envAddress(string calldata, string calldata)
external
returns (address[] memory);
function envBytes32(string calldata, string calldata)
external
returns (bytes32[] memory);
function envString(string calldata, string calldata)
external
returns (string[] memory);
function envBytes(string calldata, string calldata)
external
returns (bytes[] memory);
// Read environment variables with default value, (name, value) => (value)
function envOr(string calldata, bool) external returns (bool);
function envOr(string calldata, uint256) external returns (uint256);
function envOr(string calldata, int256) external returns (int256);
function envOr(string calldata, address) external returns (address);
function envOr(string calldata, bytes32) external returns (bytes32);
function envOr(string calldata, string calldata) external returns (string memory);
function envOr(string calldata, bytes calldata) external returns (bytes memory);
// Read environment variables as arrays with default value, (name, value[]) => (value[])
function envOr(string calldata, string calldata, bool[] calldata) external returns (bool[] memory);
function envOr(string calldata, string calldata, uint256[] calldata) external returns (uint256[] memory);
function envOr(string calldata, string calldata, int256[] calldata) external returns (int256[] memory);
function envOr(string calldata, string calldata, address[] calldata) external returns (address[] memory);
function envOr(string calldata, string calldata, bytes32[] calldata) external returns (bytes32[] memory);
function envOr(string calldata, string calldata, string[] calldata) external returns (string[] memory);
function envOr(string calldata, string calldata, bytes[] calldata) external returns (bytes[] memory);
// Convert Solidity types to strings
function toString(address) external returns(string memory);
function toString(bytes calldata) external returns(string memory);
function toString(bytes32) external returns(string memory);
function toString(bool) external returns(string memory);
function toString(uint256) external returns(string memory);
function toString(int256) external returns(string memory);
// Sets the *next* call's msg.sender to be the input address
function prank(address) external;
// Sets all subsequent calls' msg.sender to be the input address
// until `stopPrank` is called
function startPrank(address) external;
// Sets the *next* call's msg.sender to be the input address,
// and the tx.origin to be the second input
function prank(address, address) external;
// Sets all subsequent calls' msg.sender to be the input address until
// `stopPrank` is called, and the tx.origin to be the second input
function startPrank(address, address) external;
// Resets subsequent calls' msg.sender to be `address(this)`
function stopPrank() external;
// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification
function readCallers() external returns (CallerMode callerMode, address msgSender, address txOrigin);
// Sets an address' balance
function deal(address who, uint256 newBalance) external;
// Sets an address' code
function etch(address who, bytes calldata code) external;
// Marks a test as skipped. Must be called at the top of the test.
function skip(bool skip) external;
// Expects an error on next call
function expectRevert() external;
function expectRevert(bytes calldata) external;
function expectRevert(bytes4) external;
// Record all storage reads and writes
function record() external;
// Gets all accessed reads and write slot from a recording session,
// for a given address
function accesses(address)
external
returns (bytes32[] memory reads, bytes32[] memory writes);
// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order,
// along with the context of the calls.
function startStateDiffRecording() external;
// Returns an ordered array of all account accesses from a `startStateDiffRecording` session.
function stopAndReturnStateDiff() external returns (AccountAccess[] memory accesses);
// Record all the transaction logs
function recordLogs() external;
// Gets all the recorded logs
function getRecordedLogs() external returns (Log[] memory);
// Prepare an expected log with the signature:
// (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).
//
// Call this function, then emit an event, then call a function.
// Internally after the call, we check if logs were emitted in the expected order
// with the expected topics and data (as specified by the booleans)
//
// The second form also checks supplied address against emitting contract.
function expectEmit(bool, bool, bool, bool) external;
function expectEmit(bool, bool, bool, bool, address) external;
// Mocks a call to an address, returning specified data.
//
// Calldata can either be strict or a partial match, e.g. if you only
// pass a Solidity selector to the expected calldata, then the entire Solidity
// function will be mocked.
function mockCall(address, bytes calldata, bytes calldata) external;
// Reverts a call to an address, returning the specified error
//
// Calldata can either be strict or a partial match, e.g. if you only
// pass a Solidity selector to the expected calldata, then the entire Solidity
// function will be mocked.
function mockCallRevert(address where, bytes calldata data, bytes calldata retdata) external;
/// Whenever a call is made to `callee` with calldata `data`, this cheatcode instead calls
/// `target` with the same calldata. This functionality is similar to a delegate call made to
/// `target` contract from `callee`.
/// Can be used to substitute a call to a function with another implementation that captures
/// the primary logic of the original function but is easier to reason about.
/// If calldata is not a strict match then partial match by selector is attempted.
function mockFunction(address callee, address target, bytes calldata data) external;
// Clears all mocked and reverted mocked calls
function clearMockedCalls() external;
// Expect a call to an address with the specified calldata.
// Calldata can either be strict or a partial match
function expectCall(address callee, bytes calldata data) external;
// Expect a call to an address with the specified
// calldata and message value.
// Calldata can either be strict or a partial match
function expectCall(address callee, uint256, bytes calldata data) external;
// Gets the _creation_ bytecode from an artifact file. Takes in the relative path to the json file
function getCode(string calldata) external returns (bytes memory);
// Gets the _deployed_ bytecode from an artifact file. Takes in the relative path to the json file
function getDeployedCode(string calldata) external returns (bytes memory);
// Label an address in test traces
function label(address addr, string calldata label) external;
// Retrieve the label of an address
function getLabel(address addr) external returns (string memory);
// When fuzzing, generate new inputs if conditional not met
function assume(bool) external;
/// Discard this run's fuzz inputs and generate new ones if next call reverted.
function assumeNoRevert() external;
// Set block.coinbase (who)
function coinbase(address) external;
// Using the address that calls the test contract or the address provided
// as the sender, has the next call (at this call depth only) create a
// transaction that can later be signed and sent onchain
function broadcast() external;
function broadcast(address) external;
// Using the address that calls the test contract or the address provided
// as the sender, has all subsequent calls (at this call depth only) create
// transactions that can later be signed and sent onchain
function startBroadcast() external;
function startBroadcast(address) external;
function startBroadcast(uint256 privateKey) external;
// Stops collecting onchain transactions
function stopBroadcast() external;
// Reads the entire content of file to string, (path) => (data)
function readFile(string calldata) external returns (string memory);
// Get the path of the current project root
function projectRoot() external returns (string memory);
// Reads next line of file to string, (path) => (line)
function readLine(string calldata) external returns (string memory);
// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.
// (path, data) => ()
function writeFile(string calldata, string calldata) external;
// Writes line to file, creating a file if it does not exist.
// (path, data) => ()
function writeLine(string calldata, string calldata) external;
// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.
// (path) => ()
function closeFile(string calldata) external;
// Removes file. This cheatcode will revert in the following situations, but is not limited to just these cases:
// - Path points to a directory.
// - The file doesn't exist.
// - The user lacks permissions to remove the file.
// (path) => ()
function removeFile(string calldata) external;
// Returns true if the given path points to an existing entity, else returns false
// (path) => (bool)
function exists(string calldata) external returns (bool);
// Returns true if the path exists on disk and is pointing at a regular file, else returns false
// (path) => (bool)
function isFile(string calldata) external returns (bool);
// Returns true if the path exists on disk and is pointing at a directory, else returns false
// (path) => (bool)
function isDir(string calldata) external returns (bool);
// Return the value(s) that correspond to 'key'
function parseJson(string memory json, string memory key) external returns (bytes memory);
// Return the entire json file
function parseJson(string memory json) external returns (bytes memory);
// Check if a key exists in a json string
function keyExists(string memory json, string memory key) external returns (bytes memory);
// Get list of keys in a json string
function parseJsonKeys(string memory json, string memory key) external returns (string[] memory);
// Snapshot the current state of the evm.
// Returns the id of the snapshot that was created.
// To revert a snapshot use `revertTo`
function snapshot() external returns (uint256);
// Revert the state of the evm to a previous snapshot
// Takes the snapshot id to revert to.
// This deletes the snapshot and all snapshots taken after the given snapshot id.
function revertTo(uint256) external returns (bool);
// Creates a new fork with the given endpoint and block,
// and returns the identifier of the fork
function createFork(string calldata, uint256) external returns (uint256);
// Creates a new fork with the given endpoint and the _latest_ block,
// and returns the identifier of the fork
function createFork(string calldata) external returns (uint256);
// Creates _and_ also selects a new fork with the given endpoint and block,
// and returns the identifier of the fork
function createSelectFork(string calldata, uint256)
external
returns (uint256);
// Creates _and_ also selects a new fork with the given endpoint and the
// latest block and returns the identifier of the fork
function createSelectFork(string calldata) external returns (uint256);
// Takes a fork identifier created by `createFork` and
// sets the corresponding forked state as active.
function selectFork(uint256) external;
// Returns the currently active fork
// Reverts if no fork is currently active
function activeFork() external returns (uint256);
// Updates the currently active fork to given block number
// This is similar to `roll` but for the currently active fork
function rollFork(uint256) external;
// Updates the given fork to given block number
function rollFork(uint256 forkId, uint256 blockNumber) external;
// Fetches the given transaction from the active fork and executes it on the current state
function transact(bytes32) external;
// Fetches the given transaction from the given fork and executes it on the current state
function transact(uint256, bytes32) external;
// Marks that the account(s) should use persistent storage across
// fork swaps in a multifork setup, meaning, changes made to the state
// of this account will be kept when switching forks
function makePersistent(address) external;
function makePersistent(address, address) external;
function makePersistent(address, address, address) external;
function makePersistent(address[] calldata) external;
// Revokes persistent status from the address, previously added via `makePersistent`
function revokePersistent(address) external;
function revokePersistent(address[] calldata) external;
// Returns true if the account is marked as persistent
function isPersistent(address) external returns (bool);
/// Returns the RPC url for the given alias
function rpcUrl(string calldata) external returns (string memory);
/// Returns all rpc urls and their aliases `[alias, url][]`
function rpcUrls() external returns (string[2][] memory);
}