|
| 1 | +// SPDX-License-Identifier: MIT |
| 2 | +pragma solidity >=0.6.2 <0.9.0; |
| 3 | + |
| 4 | +pragma experimental ABIEncoderV2; |
| 5 | + |
| 6 | +// Cheatcodes are marked as view/pure/none using the following rules: |
| 7 | +// 0. A call's observable behaviour includes its return value, logs, reverts and state writes. |
| 8 | +// 1. If you can influence a later call's observable behaviour, you're neither `view` nor `pure` (you are modifying some state be it the EVM, interpreter, filesystem, etc), |
| 9 | +// 2. Otherwise if you can be influenced by an earlier call, or if reading some state, you're `view`, |
| 10 | +// 3. Otherwise you're `pure`. |
| 11 | + |
| 12 | +interface VmSafe { |
| 13 | + struct Log { |
| 14 | + bytes32[] topics; |
| 15 | + bytes data; |
| 16 | + } |
| 17 | + |
| 18 | + // Loads a storage slot from an address (who, slot) |
| 19 | + function load(address, bytes32) external view returns (bytes32); |
| 20 | + // Signs data, (privateKey, digest) => (v, r, s) |
| 21 | + function sign(uint256, bytes32) external pure returns (uint8, bytes32, bytes32); |
| 22 | + // Gets the address for a given private key, (privateKey) => (address) |
| 23 | + function addr(uint256) external pure returns (address); |
| 24 | + // Gets the nonce of an account |
| 25 | + function getNonce(address) external view returns (uint64); |
| 26 | + // Performs a foreign function call via the terminal, (stringInputs) => (result) |
| 27 | + function ffi(string[] calldata) external returns (bytes memory); |
| 28 | + // Sets environment variables, (name, value) |
| 29 | + function setEnv(string calldata, string calldata) external; |
| 30 | + // Reads environment variables, (name) => (value) |
| 31 | + function envBool(string calldata) external view returns (bool); |
| 32 | + function envUint(string calldata) external view returns (uint256); |
| 33 | + function envInt(string calldata) external view returns (int256); |
| 34 | + function envAddress(string calldata) external view returns (address); |
| 35 | + function envBytes32(string calldata) external view returns (bytes32); |
| 36 | + function envString(string calldata) external view returns (string memory); |
| 37 | + function envBytes(string calldata) external view returns (bytes memory); |
| 38 | + // Reads environment variables as arrays, (name, delim) => (value[]) |
| 39 | + function envBool(string calldata, string calldata) external view returns (bool[] memory); |
| 40 | + function envUint(string calldata, string calldata) external view returns (uint256[] memory); |
| 41 | + function envInt(string calldata, string calldata) external view returns (int256[] memory); |
| 42 | + function envAddress(string calldata, string calldata) external view returns (address[] memory); |
| 43 | + function envBytes32(string calldata, string calldata) external view returns (bytes32[] memory); |
| 44 | + function envString(string calldata, string calldata) external view returns (string[] memory); |
| 45 | + function envBytes(string calldata, string calldata) external view returns (bytes[] memory); |
| 46 | + // Records all storage reads and writes |
| 47 | + function record() external; |
| 48 | + // Gets all accessed reads and write slot from a recording session, for a given address |
| 49 | + function accesses(address) external returns (bytes32[] memory reads, bytes32[] memory writes); |
| 50 | + // Gets the _creation_ bytecode from an artifact file. Takes in the relative path to the json file |
| 51 | + function getCode(string calldata) external view returns (bytes memory); |
| 52 | + // Gets the _deployed_ bytecode from an artifact file. Takes in the relative path to the json file |
| 53 | + function getDeployedCode(string calldata) external view returns (bytes memory); |
| 54 | + // Labels an address in call traces |
| 55 | + function label(address, string calldata) external; |
| 56 | + // Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain |
| 57 | + function broadcast() external; |
| 58 | + // Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain |
| 59 | + function broadcast(address) external; |
| 60 | + // Has the next call (at this call depth only) create a transaction with the private key provided as the sender that can later be signed and sent onchain |
| 61 | + function broadcast(uint256) external; |
| 62 | + // Using the address that calls the test contract, has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain |
| 63 | + function startBroadcast() external; |
| 64 | + // Has all subsequent calls (at this call depth only) create transactions with the address provided that can later be signed and sent onchain |
| 65 | + function startBroadcast(address) external; |
| 66 | + // Has all subsequent calls (at this call depth only) create transactions with the private key provided that can later be signed and sent onchain |
| 67 | + function startBroadcast(uint256) external; |
| 68 | + // Stops collecting onchain transactions |
| 69 | + function stopBroadcast() external; |
| 70 | + // Reads the entire content of file to string, (path) => (data) |
| 71 | + function readFile(string calldata) external view returns (string memory); |
| 72 | + // Reads the entire content of file as binary. Path is relative to the project root. (path) => (data) |
| 73 | + function readFileBinary(string calldata) external view returns (bytes memory); |
| 74 | + // Get the path of the current project root |
| 75 | + function projectRoot() external view returns (string memory); |
| 76 | + // Reads next line of file to string, (path) => (line) |
| 77 | + function readLine(string calldata) external view returns (string memory); |
| 78 | + // Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does. |
| 79 | + // (path, data) => () |
| 80 | + function writeFile(string calldata, string calldata) external; |
| 81 | + // Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does. |
| 82 | + // Path is relative to the project root. (path, data) => () |
| 83 | + function writeFileBinary(string calldata, bytes calldata) external; |
| 84 | + // Writes line to file, creating a file if it does not exist. |
| 85 | + // (path, data) => () |
| 86 | + function writeLine(string calldata, string calldata) external; |
| 87 | + // Closes file for reading, resetting the offset and allowing to read it from beginning with readLine. |
| 88 | + // (path) => () |
| 89 | + function closeFile(string calldata) external; |
| 90 | + // Removes file. This cheatcode will revert in the following situations, but is not limited to just these cases: |
| 91 | + // - Path points to a directory. |
| 92 | + // - The file doesn't exist. |
| 93 | + // - The user lacks permissions to remove the file. |
| 94 | + // (path) => () |
| 95 | + function removeFile(string calldata) external; |
| 96 | + // Convert values to a string, (value) => (stringified value) |
| 97 | + function toString(address) external pure returns (string memory); |
| 98 | + function toString(bytes calldata) external pure returns (string memory); |
| 99 | + function toString(bytes32) external pure returns (string memory); |
| 100 | + function toString(bool) external pure returns (string memory); |
| 101 | + function toString(uint256) external pure returns (string memory); |
| 102 | + function toString(int256) external pure returns (string memory); |
| 103 | + // Convert values from a string, (string) => (parsed value) |
| 104 | + function parseBytes(string calldata) external pure returns (bytes memory); |
| 105 | + function parseAddress(string calldata) external pure returns (address); |
| 106 | + function parseUint(string calldata) external pure returns (uint256); |
| 107 | + function parseInt(string calldata) external pure returns (int256); |
| 108 | + function parseBytes32(string calldata) external pure returns (bytes32); |
| 109 | + function parseBool(string calldata) external pure returns (bool); |
| 110 | + // Record all the transaction logs |
| 111 | + function recordLogs() external; |
| 112 | + // Gets all the recorded logs, () => (logs) |
| 113 | + function getRecordedLogs() external returns (Log[] memory); |
| 114 | + // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index} |
| 115 | + function deriveKey(string calldata, uint32) external pure returns (uint256); |
| 116 | + // Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path {path}{index} |
| 117 | + function deriveKey(string calldata, string calldata, uint32) external pure returns (uint256); |
| 118 | + // Adds a private key to the local forge wallet and returns the address |
| 119 | + function rememberKey(uint256) external returns (address); |
| 120 | + // |
| 121 | + // parseJson |
| 122 | + // |
| 123 | + // ---- |
| 124 | + // In case the returned value is a JSON object, it's encoded as a ABI-encoded tuple. As JSON objects |
| 125 | + // don't have the notion of ordered, but tuples do, they JSON object is encoded with it's fields ordered in |
| 126 | + // ALPHABETICAL ordser. That means that in order to succesfully decode the tuple, we need to define a tuple that |
| 127 | + // encodes the fields in the same order, which is alphabetical. In the case of Solidity structs, they are encoded |
| 128 | + // as tuples, with the attributes in the order in which they are defined. |
| 129 | + // For example: json = { 'a': 1, 'b': 0xa4tb......3xs} |
| 130 | + // a: uint256 |
| 131 | + // b: address |
| 132 | + // To decode that json, we need to define a struct or a tuple as follows: |
| 133 | + // struct json = { uint256 a; address b; } |
| 134 | + // If we defined a json struct with the opposite order, meaning placing the address b first, it would try to |
| 135 | + // decode the tuple in that order, and thus fail. |
| 136 | + // ---- |
| 137 | + // Given a string of JSON, return it as ABI-encoded, (stringified json, key) => (ABI-encoded data) |
| 138 | + function parseJson(string calldata, string calldata) external pure returns (bytes memory); |
| 139 | + function parseJson(string calldata) external pure returns (bytes memory); |
| 140 | + // |
| 141 | + // writeJson |
| 142 | + // |
| 143 | + // ---- |
| 144 | + // Let's assume we want to write the following JSON to a file: |
| 145 | + // |
| 146 | + // { "boolean": true, "number": 342, "object": { "title": "finally json serialization" } } |
| 147 | + // |
| 148 | + // ``` |
| 149 | + // string memory json1 = "some key"; |
| 150 | + // vm.serializeBool(json1, "boolean", true); |
| 151 | + // vm.serializeBool(json1, "number", uint256(342)); |
| 152 | + // json2 = "some other key"; |
| 153 | + // string memory output = vm.serializeString(json2, "title", "finally json serialization"); |
| 154 | + // vm.serialize(json1, "object", output); |
| 155 | + // vm.writeJson(json1, "./output/example.json"); |
| 156 | + // ``` |
| 157 | + // The critical insight is that every invocation of serialization will return the stringified version of the JSON |
| 158 | + // up to that point. That means we can construct arbitrary JSON objects and then use the return stringified version |
| 159 | + // to serialize them as values to another JSON object. |
| 160 | + // |
| 161 | + // json1 and json2 are simply keys used by the backend to keep track of the objects. So vm.serializeJson(json1,..) |
| 162 | + // will find the object in-memory that is keyed by "some key". // writeJson |
| 163 | + function serializeBool(string calldata, string calldata, bool) external returns (string memory); |
| 164 | + function serializeUint(string calldata, string calldata, uint256) external returns (string memory); |
| 165 | + function serializeInt(string calldata, string calldata, int256) external returns (string memory); |
| 166 | + function serializeAddress(string calldata, string calldata, address) external returns (string memory); |
| 167 | + function serializeBytes32(string calldata, string calldata, bytes32) external returns (string memory); |
| 168 | + function serializeString(string calldata, string calldata, string calldata) external returns (string memory); |
| 169 | + function serializeBytes(string calldata, string calldata, bytes calldata) external returns (string memory); |
| 170 | + |
| 171 | + function serializeBool(string calldata, string calldata, bool[] calldata) external returns (string memory); |
| 172 | + function serializeUint(string calldata, string calldata, uint256[] calldata) external returns (string memory); |
| 173 | + function serializeInt(string calldata, string calldata, int256[] calldata) external returns (string memory); |
| 174 | + function serializeAddress(string calldata, string calldata, address[] calldata) external returns (string memory); |
| 175 | + function serializeBytes32(string calldata, string calldata, bytes32[] calldata) external returns (string memory); |
| 176 | + function serializeString(string calldata, string calldata, string[] calldata) external returns (string memory); |
| 177 | + function serializeBytes(string calldata, string calldata, bytes[] calldata) external returns (string memory); |
| 178 | + function writeJson(string calldata, string calldata) external; |
| 179 | + function writeJson(string calldata, string calldata, string calldata) external; |
| 180 | + // Returns the RPC url for the given alias |
| 181 | + function rpcUrl(string calldata) external view returns (string memory); |
| 182 | + // Returns all rpc urls and their aliases `[alias, url][]` |
| 183 | + function rpcUrls() external view returns (string[2][] memory); |
| 184 | + // If the condition is false, discard this run's fuzz inputs and generate new ones. |
| 185 | + function assume(bool) external pure; |
| 186 | +} |
| 187 | + |
| 188 | +interface Vm is VmSafe { |
| 189 | + // Sets block.timestamp (newTimestamp) |
| 190 | + function warp(uint256) external; |
| 191 | + // Sets block.height (newHeight) |
| 192 | + function roll(uint256) external; |
| 193 | + // Sets block.basefee (newBasefee) |
| 194 | + function fee(uint256) external; |
| 195 | + // Sets block.difficulty (newDifficulty) |
| 196 | + function difficulty(uint256) external; |
| 197 | + // Sets block.chainid |
| 198 | + function chainId(uint256) external; |
| 199 | + // Stores a value to an address' storage slot, (who, slot, value) |
| 200 | + function store(address, bytes32, bytes32) external; |
| 201 | + // Sets the nonce of an account; must be higher than the current nonce of the account |
| 202 | + function setNonce(address, uint64) external; |
| 203 | + // Sets the *next* call's msg.sender to be the input address |
| 204 | + function prank(address) external; |
| 205 | + // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called |
| 206 | + function startPrank(address) external; |
| 207 | + // Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input |
| 208 | + function prank(address, address) external; |
| 209 | + // Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input |
| 210 | + function startPrank(address, address) external; |
| 211 | + // Resets subsequent calls' msg.sender to be `address(this)` |
| 212 | + function stopPrank() external; |
| 213 | + // Sets an address' balance, (who, newBalance) |
| 214 | + function deal(address, uint256) external; |
| 215 | + // Sets an address' code, (who, newCode) |
| 216 | + function etch(address, bytes calldata) external; |
| 217 | + // Expects an error on next call |
| 218 | + function expectRevert(bytes calldata) external; |
| 219 | + function expectRevert(bytes4) external; |
| 220 | + function expectRevert() external; |
| 221 | + // Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData). |
| 222 | + // Call this function, then emit an event, then call a function. Internally after the call, we check if |
| 223 | + // logs were emitted in the expected order with the expected topics and data (as specified by the booleans) |
| 224 | + function expectEmit(bool, bool, bool, bool) external; |
| 225 | + function expectEmit(bool, bool, bool, bool, address) external; |
| 226 | + // Mocks a call to an address, returning specified data. |
| 227 | + // Calldata can either be strict or a partial match, e.g. if you only |
| 228 | + // pass a Solidity selector to the expected calldata, then the entire Solidity |
| 229 | + // function will be mocked. |
| 230 | + function mockCall(address, bytes calldata, bytes calldata) external; |
| 231 | + // Mocks a call to an address with a specific msg.value, returning specified data. |
| 232 | + // Calldata match takes precedence over msg.value in case of ambiguity. |
| 233 | + function mockCall(address, uint256, bytes calldata, bytes calldata) external; |
| 234 | + // Clears all mocked calls |
| 235 | + function clearMockedCalls() external; |
| 236 | + // Expects a call to an address with the specified calldata. |
| 237 | + // Calldata can either be a strict or a partial match |
| 238 | + function expectCall(address, bytes calldata) external; |
| 239 | + // Expects a call to an address with the specified msg.value and calldata |
| 240 | + function expectCall(address, uint256, bytes calldata) external; |
| 241 | + // Sets block.coinbase (who) |
| 242 | + function coinbase(address) external; |
| 243 | + // Snapshot the current state of the evm. |
| 244 | + // Returns the id of the snapshot that was created. |
| 245 | + // To revert a snapshot use `revertTo` |
| 246 | + function snapshot() external returns (uint256); |
| 247 | + // Revert the state of the evm to a previous snapshot |
| 248 | + // Takes the snapshot id to revert to. |
| 249 | + // This deletes the snapshot and all snapshots taken after the given snapshot id. |
| 250 | + function revertTo(uint256) external returns (bool); |
| 251 | + // Creates a new fork with the given endpoint and block and returns the identifier of the fork |
| 252 | + function createFork(string calldata, uint256) external returns (uint256); |
| 253 | + // Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork |
| 254 | + function createFork(string calldata) external returns (uint256); |
| 255 | + // Creates a new fork with the given endpoint and at the block the given transaction was mined in, and replays all transaction mined in the block before the transaction |
| 256 | + function createFork(string calldata, bytes32) external returns (uint256); |
| 257 | + // Creates _and_ also selects a new fork with the given endpoint and block and returns the identifier of the fork |
| 258 | + function createSelectFork(string calldata, uint256) external returns (uint256); |
| 259 | + // Creates _and_ also selects new fork with the given endpoint and at the block the given transaction was mined in, and replays all transaction mined in the block before the transaction |
| 260 | + function createSelectFork(string calldata, bytes32) external returns (uint256); |
| 261 | + // Creates _and_ also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork |
| 262 | + function createSelectFork(string calldata) external returns (uint256); |
| 263 | + // Takes a fork identifier created by `createFork` and sets the corresponding forked state as active. |
| 264 | + function selectFork(uint256) external; |
| 265 | + /// Returns the currently active fork |
| 266 | + /// Reverts if no fork is currently active |
| 267 | + function activeFork() external view returns (uint256); |
| 268 | + // Updates the currently active fork to given block number |
| 269 | + // This is similar to `roll` but for the currently active fork |
| 270 | + function rollFork(uint256) external; |
| 271 | + // Updates the currently active fork to given transaction |
| 272 | + // this will `rollFork` with the number of the block the transaction was mined in and replays all transaction mined before it in the block |
| 273 | + function rollFork(bytes32) external; |
| 274 | + // Updates the given fork to given block number |
| 275 | + function rollFork(uint256 forkId, uint256 blockNumber) external; |
| 276 | + // Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block |
| 277 | + function rollFork(uint256 forkId, bytes32 transaction) external; |
| 278 | + // Marks that the account(s) should use persistent storage across fork swaps in a multifork setup |
| 279 | + // Meaning, changes made to the state of this account will be kept when switching forks |
| 280 | + function makePersistent(address) external; |
| 281 | + function makePersistent(address, address) external; |
| 282 | + function makePersistent(address, address, address) external; |
| 283 | + function makePersistent(address[] calldata) external; |
| 284 | + // Revokes persistent status from the address, previously added via `makePersistent` |
| 285 | + function revokePersistent(address) external; |
| 286 | + function revokePersistent(address[] calldata) external; |
| 287 | + // Returns true if the account is marked as persistent |
| 288 | + function isPersistent(address) external view returns (bool); |
| 289 | + // In forking mode, explicitly grant the given address cheatcode access |
| 290 | + function allowCheatcodes(address) external; |
| 291 | + // Fetches the given transaction from the active fork and executes it on the current state |
| 292 | + function transact(bytes32 txHash) external; |
| 293 | + // Fetches the given transaction from the given fork and executes it on the current state |
| 294 | + function transact(uint256 forkId, bytes32 txHash) external; |
| 295 | +} |
0 commit comments