diff --git a/src/StdChains.sol b/src/StdChains.sol index b77933e8..3562d502 100644 --- a/src/StdChains.sol +++ b/src/StdChains.sol @@ -65,7 +65,8 @@ abstract contract StdChains { bool private fallbackToDefaultRpcUrls = true; - // The RPC URL will be fetched from config or defaultRpcUrls if possible. + /// @notice Returns chain data for the given alias, with the RPC URL resolved from config or defaults. + /// @dev Reverts if `chainAlias` is empty or has not been registered. function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) { require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string."); @@ -79,6 +80,8 @@ abstract contract StdChains { chain = getChainWithUpdatedRpcUrl(chainAlias, chain); } + /// @notice Returns chain data for the given chain ID, with the RPC URL resolved from config or defaults. + /// @dev Reverts if `chainId` is `0` or has not been registered. function getChain(uint256 chainId) internal virtual returns (Chain memory chain) { require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0."); initializeStdChains(); @@ -94,7 +97,7 @@ abstract contract StdChains { chain = getChainWithUpdatedRpcUrl(chainAlias, chain); } - // set chain info, with priority to argument's rpcUrl field. + /// @notice Registers chain data under `chainAlias`, with priority given to the argument's `rpcUrl` field. function setChain(string memory chainAlias, ChainData memory chain) internal virtual { require( bytes(chainAlias).length != 0, @@ -127,7 +130,7 @@ abstract contract StdChains { idToAlias[chain.chainId] = chainAlias; } - // set chain info, with priority to argument's rpcUrl field. + /// @notice Registers chain data under `chainAlias`, with priority given to the argument's `rpcUrl` field. function setChain(string memory chainAlias, Chain memory chain) internal virtual { setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl})); } @@ -184,6 +187,7 @@ abstract contract StdChains { return chain; } + /// @notice Sets whether to fall back to default RPC URLs when no URL is configured for a chain. function setFallbackToDefaultRpcUrls(bool useDefault) internal { fallbackToDefaultRpcUrls = useDefault; } diff --git a/src/StdCheats.sol b/src/StdCheats.sol index cfece45e..672d8139 100644 --- a/src/StdCheats.sol +++ b/src/StdCheats.sol @@ -203,7 +203,7 @@ abstract contract StdCheatsSafe { ForgeAddress } - // Checks that `addr` is not blacklisted by token contracts that have a blacklist. + /// @notice Assumes `addr` is not blacklisted by `token`, skipping the fuzz run if it is. function assumeNotBlacklisted(address token, address addr) internal view virtual { // Nothing to check if `token` is not a contract. uint256 tokenCodeSize; @@ -224,14 +224,13 @@ abstract contract StdCheatsSafe { vm.assume(!success || abi.decode(returnData, (bool)) == false); } - // Checks that `addr` is not blacklisted by token contracts that have a blacklist. - // This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for - // backwards compatibility, since this name was used in the original PR which already has - // a release. This function can be removed in a future release once we want a breaking change. + /// @notice Assumes `addr` is not blacklisted by `token`, skipping the fuzz run if it is. + /// @dev Deprecated alias for `assumeNotBlacklisted`. Will be removed in a future breaking release. function assumeNoBlacklisted(address token, address addr) internal view virtual { assumeNotBlacklisted(token, addr); } + /// @notice Assumes `addr` does not match `addressType`, skipping the fuzz run if it does. function assumeAddressIsNot(address addr, AddressType addressType) internal virtual { if (addressType == AddressType.Payable) { assumeNotPayable(addr); @@ -246,11 +245,13 @@ abstract contract StdCheatsSafe { } } + /// @notice Assumes `addr` does not match `addressType1` or `addressType2`, skipping the fuzz run if it does. function assumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internal virtual { assumeAddressIsNot(addr, addressType1); assumeAddressIsNot(addr, addressType2); } + /// @notice Assumes `addr` does not match any of the three given address types, skipping the fuzz run if it does. function assumeAddressIsNot( address addr, AddressType addressType1, @@ -262,6 +263,7 @@ abstract contract StdCheatsSafe { assumeAddressIsNot(addr, addressType3); } + /// @notice Assumes `addr` does not match any of the four given address types, skipping the fuzz run if it does. function assumeAddressIsNot( address addr, AddressType addressType1, @@ -297,25 +299,29 @@ abstract contract StdCheatsSafe { return success; } - // NOTE: This function may result in state changes depending on the fallback/receive logic - // implemented by `addr`, which should be taken into account when this function is used. See the - // `_isPayable` method for more information. + /// @notice Assumes `addr` is a payable address, skipping the fuzz run if it is not. + /// @dev May cause state changes depending on `addr`'s fallback or receive logic. function assumePayable(address addr) internal virtual { vm.assume(_isPayable(addr)); } + /// @notice Assumes `addr` is not a payable address, skipping the fuzz run if it is. + /// @dev May cause state changes depending on `addr`'s fallback or receive logic. function assumeNotPayable(address addr) internal virtual { vm.assume(!_isPayable(addr)); } + /// @notice Assumes `addr` is not the zero address, skipping the fuzz run if it is. function assumeNotZeroAddress(address addr) internal pure virtual { vm.assume(addr != address(0)); } + /// @notice Assumes `addr` is not a precompile on the current chain, skipping the fuzz run if it is. function assumeNotPrecompile(address addr) internal pure virtual { assumeNotPrecompile(addr, _pureChainId()); } + /// @notice Assumes `addr` is not a precompile on `chainId`, skipping the fuzz run if it is. function assumeNotPrecompile(address addr, uint256 chainId) internal pure virtual { // Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific // address), but the same rationale for excluding them applies so we include those too. @@ -339,6 +345,7 @@ abstract contract StdCheatsSafe { // forgefmt: disable-end } + /// @notice Assumes `addr` is not a Forge-reserved address (vm, console, Create2Deployer), skipping the fuzz run if it is. function assumeNotForgeAddress(address addr) internal pure virtual { // vm, console, and Create2Deployer addresses vm.assume( @@ -347,6 +354,7 @@ abstract contract StdCheatsSafe { ); } + /// @notice Assumes `addr` has no code and is not a precompile, zero, or Forge-reserved address. function assumeUnusedAddress(address addr) internal view virtual { uint256 size; assembly { @@ -359,6 +367,7 @@ abstract contract StdCheatsSafe { assumeNotForgeAddress(addr); } + /// @notice Reads and parses an EIP-1559 broadcast artifact from `path`. function readEIP1559ScriptArtifact(string memory path) internal view @@ -379,6 +388,7 @@ abstract contract StdCheatsSafe { return artifact; } + /// @notice Converts an array of raw EIP-1559 transactions to the user-friendly `Tx1559` format. function rawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internal pure virtual returns (Tx1559[] memory) { Tx1559[] memory txs = new Tx1559[](rawTxs.length); for (uint256 i; i < rawTxs.length; i++) { @@ -387,6 +397,7 @@ abstract contract StdCheatsSafe { return txs; } + /// @notice Converts a single raw EIP-1559 transaction to the user-friendly `Tx1559` format. function rawToConvertedEIPTx1559(RawTx1559 memory rawTx) internal pure virtual returns (Tx1559 memory) { Tx1559 memory transaction; transaction.arguments = rawTx.arguments; @@ -399,6 +410,7 @@ abstract contract StdCheatsSafe { return transaction; } + /// @notice Converts raw EIP-1559 transaction detail fields to the user-friendly `Tx1559Detail` format. function rawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail) internal pure @@ -417,6 +429,7 @@ abstract contract StdCheatsSafe { return txDetail; } + /// @notice Reads all EIP-1559 transactions from the broadcast artifact at `path`. function readTx1559s(string memory path) internal view virtual returns (Tx1559[] memory) { string memory deployData = vm.readFile(path); bytes memory parsedDeployData = vm.parseJson(deployData, ".transactions"); @@ -424,6 +437,7 @@ abstract contract StdCheatsSafe { return rawToConvertedEIPTx1559s(rawTxs); } + /// @notice Reads the EIP-1559 transaction at `index` from the broadcast artifact at `path`. function readTx1559(string memory path, uint256 index) internal view virtual returns (Tx1559 memory) { string memory deployData = vm.readFile(path); string memory key = string(abi.encodePacked(".transactions[", vm.toString(index), "]")); @@ -432,7 +446,7 @@ abstract contract StdCheatsSafe { return rawToConvertedEIPTx1559(rawTx); } - // Analogous to readTransactions, but for receipts. + /// @notice Reads all transaction receipts from the broadcast artifact at `path`. function readReceipts(string memory path) internal view virtual returns (Receipt[] memory) { string memory deployData = vm.readFile(path); bytes memory parsedDeployData = vm.parseJson(deployData, ".receipts"); @@ -440,6 +454,7 @@ abstract contract StdCheatsSafe { return rawToConvertedReceipts(rawReceipts); } + /// @notice Reads the transaction receipt at `index` from the broadcast artifact at `path`. function readReceipt(string memory path, uint256 index) internal view virtual returns (Receipt memory) { string memory deployData = vm.readFile(path); string memory key = string(abi.encodePacked(".receipts[", vm.toString(index), "]")); @@ -448,6 +463,7 @@ abstract contract StdCheatsSafe { return rawToConvertedReceipt(rawReceipt); } + /// @notice Converts an array of raw receipts to the user-friendly `Receipt` format. function rawToConvertedReceipts(RawReceipt[] memory rawReceipts) internal pure virtual returns (Receipt[] memory) { Receipt[] memory receipts = new Receipt[](rawReceipts.length); for (uint256 i; i < rawReceipts.length; i++) { @@ -456,6 +472,7 @@ abstract contract StdCheatsSafe { return receipts; } + /// @notice Converts a single raw receipt to the user-friendly `Receipt` format. function rawToConvertedReceipt(RawReceipt memory rawReceipt) internal pure virtual returns (Receipt memory) { Receipt memory receipt; receipt.blockHash = rawReceipt.blockHash; @@ -474,6 +491,7 @@ abstract contract StdCheatsSafe { return receipt; } + /// @notice Converts an array of raw receipt logs to the user-friendly `ReceiptLog` format. function rawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs) internal pure @@ -495,9 +513,7 @@ abstract contract StdCheatsSafe { return logs; } - // Deploy a contract by fetching the contract bytecode from - // the artifacts directory - // e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))` + /// @notice Deploys a contract from the artifacts directory with ABI-encoded constructor arguments. function deployCode(string memory what, bytes memory args) internal virtual returns (address addr) { bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); assembly ("memory-safe") { @@ -507,6 +523,7 @@ abstract contract StdCheatsSafe { require(addr != address(0), "StdCheats deployCode(string,bytes): Deployment failed."); } + /// @notice Deploys a contract from the artifacts directory. function deployCode(string memory what) internal virtual returns (address addr) { bytes memory bytecode = vm.getCode(what); assembly ("memory-safe") { @@ -516,7 +533,7 @@ abstract contract StdCheatsSafe { require(addr != address(0), "StdCheats deployCode(string): Deployment failed."); } - /// @dev deploy contract with value on construction + /// @notice Deploys a contract from the artifacts directory with ABI-encoded constructor arguments, sending `val` wei on construction. function deployCode(string memory what, bytes memory args, uint256 val) internal virtual returns (address addr) { bytes memory bytecode = abi.encodePacked(vm.getCode(what), args); assembly ("memory-safe") { @@ -526,6 +543,7 @@ abstract contract StdCheatsSafe { require(addr != address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed."); } + /// @notice Deploys a contract from the artifacts directory, sending `val` wei on construction. function deployCode(string memory what, uint256 val) internal virtual returns (address addr) { bytes memory bytecode = vm.getCode(what); assembly ("memory-safe") { @@ -535,22 +553,20 @@ abstract contract StdCheatsSafe { require(addr != address(0), "StdCheats deployCode(string,uint256): Deployment failed."); } - // creates a labeled address and the corresponding private key + /// @notice Creates a labeled address and the corresponding private key derived from `name`. function makeAddrAndKey(string memory name) internal virtual returns (address addr, uint256 privateKey) { privateKey = uint256(keccak256(abi.encodePacked(name))); addr = vm.addr(privateKey); vm.label(addr, name); } - // creates a labeled address + /// @notice Creates a labeled address derived from `name`. function makeAddr(string memory name) internal virtual returns (address addr) { (addr,) = makeAddrAndKey(name); } - // Destroys an account immediately, sending the balance to beneficiary. - // Destroying means: balance will be zero, code will be empty, and nonce will be 0 - // This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce - // only after tx ends, this will run immediately. + /// @notice Immediately destroys `who`, zeroing its balance, code, and nonce, and sending its balance to `beneficiary`. + /// @dev Unlike `selfdestruct`, this takes effect immediately within the same transaction. function destroyAccount(address who, address beneficiary) internal virtual { uint256 currBalance = who.balance; vm.etch(who, abi.encode()); @@ -561,11 +577,12 @@ abstract contract StdCheatsSafe { vm.deal(beneficiary, currBalance + beneficiaryBalance); } - // creates a struct containing both a labeled address and the corresponding private key + /// @notice Creates an `Account` struct with a labeled address and private key derived from `name`. function makeAccount(string memory name) internal virtual returns (Account memory account) { (account.addr, account.key) = makeAddrAndKey(name); } + /// @notice Derives a private key from `mnemonic` at `index`, stores it in the local wallet, and returns the address and key. function deriveRememberKey(string memory mnemonic, uint32 index) internal virtual @@ -580,24 +597,29 @@ abstract contract StdCheatsSafe { return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); } + /// @notice Returns whether the current test environment is running against a forked network. function isFork() internal view virtual returns (bool status) { try vm.activeFork() { status = true; } catch (bytes memory) {} } + /// @notice Skips the test body when running against a forked network. modifier skipWhenForking() { if (!isFork()) { _; } } + /// @notice Skips the test body when not running against a forked network. modifier skipWhenNotForking() { if (isFork()) { _; } } + /// @notice Disables gas metering for the duration of the function, re-enabling it on exit. + /// @dev When nested, gas metering is only resumed at the end of the outermost function that uses this modifier. modifier noGasMetering() { vm.pauseGasMetering(); // To prevent turning gas monitoring back on with nested functions that use this modifier, @@ -650,76 +672,87 @@ abstract contract StdCheats is StdCheatsSafe { Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; - // Skip forward or rewind time by the specified number of seconds + /// @notice Advances the block timestamp forward by `time` seconds. function skip(uint256 time) internal virtual { vm.warp(vm.getBlockTimestamp() + time); } + /// @notice Rewinds the block timestamp backward by `time` seconds. function rewind(uint256 time) internal virtual { vm.warp(vm.getBlockTimestamp() - time); } - // Setup a prank from an address that has some ether + /// @notice Sets up a single-call prank from `msgSender`, giving it `2**128` wei. function hoax(address msgSender) internal virtual { vm.deal(msgSender, 1 << 128); vm.prank(msgSender); } + /// @notice Sets up a single-call prank from `msgSender`, giving it `give` wei. function hoax(address msgSender, uint256 give) internal virtual { vm.deal(msgSender, give); vm.prank(msgSender); } + /// @notice Sets up a single-call prank from `msgSender` with `origin` as `tx.origin`, giving `msgSender` `2**128` wei. function hoax(address msgSender, address origin) internal virtual { vm.deal(msgSender, 1 << 128); vm.prank(msgSender, origin); } + /// @notice Sets up a single-call prank from `msgSender` with `origin` as `tx.origin`, giving `msgSender` `give` wei. function hoax(address msgSender, address origin, uint256 give) internal virtual { vm.deal(msgSender, give); vm.prank(msgSender, origin); } - // Start perpetual prank from an address that has some ether + /// @notice Starts a persistent prank from `msgSender`, giving it `2**128` wei. function startHoax(address msgSender) internal virtual { vm.deal(msgSender, 1 << 128); vm.startPrank(msgSender); } + /// @notice Starts a persistent prank from `msgSender`, giving it `give` wei. function startHoax(address msgSender, uint256 give) internal virtual { vm.deal(msgSender, give); vm.startPrank(msgSender); } - // Start perpetual prank from an address that has some ether - // tx.origin is set to the origin parameter + /// @notice Starts a persistent prank from `msgSender` with `origin` as `tx.origin`, giving `msgSender` `2**128` wei. function startHoax(address msgSender, address origin) internal virtual { vm.deal(msgSender, 1 << 128); vm.startPrank(msgSender, origin); } + /// @notice Starts a persistent prank from `msgSender` with `origin` as `tx.origin`, giving `msgSender` `give` wei. function startHoax(address msgSender, address origin, uint256 give) internal virtual { vm.deal(msgSender, give); vm.startPrank(msgSender, origin); } + /// @notice Changes the active prank to `msgSender`. + /// @dev Deprecated. Use `vm.startPrank` instead. function changePrank(address msgSender) internal virtual { console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead."); vm.stopPrank(); vm.startPrank(msgSender); } + /// @notice Changes the active prank to `msgSender` with `txOrigin` as `tx.origin`. + /// @dev Deprecated. Use `vm.startPrank` instead. function changePrank(address msgSender, address txOrigin) internal virtual { console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead."); vm.stopPrank(); vm.startPrank(msgSender, txOrigin); } + /// @notice Expects a call to `callee` with `data` and mocks it to return `returnData`. function expectAndMockCall(address callee, bytes memory data, bytes memory returnData) internal virtual { vm.expectCall(callee, data); vm.mockCall(callee, data, returnData); } + /// @notice Expects exactly `count` calls to `callee` with `data` and mocks them to return `returnData`. function expectAndMockCall(address callee, bytes memory data, uint64 count, bytes memory returnData) internal virtual @@ -728,6 +761,7 @@ abstract contract StdCheats is StdCheatsSafe { vm.mockCall(callee, data, returnData); } + /// @notice Expects a call to `callee` with `msgValue` and `data` and mocks it to return `returnData`. function expectAndMockCall(address callee, uint256 msgValue, bytes memory data, bytes memory returnData) internal virtual @@ -736,6 +770,7 @@ abstract contract StdCheats is StdCheatsSafe { vm.mockCall(callee, msgValue, data, returnData); } + /// @notice Expects exactly `count` calls to `callee` with `msgValue` and `data` and mocks them to return `returnData`. function expectAndMockCall( address callee, uint256 msgValue, @@ -747,6 +782,8 @@ abstract contract StdCheats is StdCheatsSafe { vm.mockCall(callee, msgValue, data, returnData); } + /// @notice Expects a call to `callee` with `msgValue` and `data` forwarding `gas`, and mocks it to return `returnData`. + /// @dev `gas` only applies to the call expectation; the mock call ignores `gas`. function expectAndMockCall(address callee, uint256 msgValue, uint64 gas, bytes memory data, bytes memory returnData) internal virtual @@ -755,6 +792,8 @@ abstract contract StdCheats is StdCheatsSafe { vm.mockCall(callee, msgValue, data, returnData); } + /// @notice Expects exactly `count` calls to `callee` with `msgValue` and `data` forwarding `gas`, and mocks them to return `returnData`. + /// @dev `gas` only applies to the call expectation; the mock call ignores `gas`. function expectAndMockCall( address callee, uint256 msgValue, @@ -767,24 +806,22 @@ abstract contract StdCheats is StdCheatsSafe { vm.mockCall(callee, msgValue, data, returnData); } - // The same as Vm's `deal` - // Use the alternative signature for ERC20 tokens + /// @notice Sets the ETH balance of `to` to `give`. function deal(address to, uint256 give) internal virtual { vm.deal(to, give); } - // Set the balance of an account for any ERC20 token - // Use the alternative signature to update `totalSupply` + /// @notice Sets the ERC20 `token` balance of `to` to `give`. function deal(address token, address to, uint256 give) internal virtual { deal(token, to, give, false); } - // Set the balance of an account for any ERC1155 token - // Use the alternative signature to update `totalSupply` + /// @notice Sets the ERC1155 `token` balance of `to` for token `id` to `give`. function dealERC1155(address token, address to, uint256 id, uint256 give) internal virtual { dealERC1155(token, to, id, give, false); } + /// @notice Sets the ERC20 `token` balance of `to` to `give`, optionally adjusting the total supply. function deal(address token, address to, uint256 give, bool adjust) internal virtual { // get current balance (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to)); @@ -806,6 +843,7 @@ abstract contract StdCheats is StdCheatsSafe { } } + /// @notice Sets the ERC1155 `token` balance of `to` for token `id` to `give`, optionally adjusting the total supply. function dealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internal virtual { // get current balance (, bytes memory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id)); @@ -831,6 +869,7 @@ abstract contract StdCheats is StdCheatsSafe { } } + /// @notice Transfers ownership of ERC721 `token` with `id` to `to`, updating balances accordingly. function dealERC721(address token, address to, uint256 id) internal virtual { // check if token id is already minted and the actual owner. (bool successMinted, bytes memory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id)); @@ -853,14 +892,20 @@ abstract contract StdCheats is StdCheatsSafe { stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to); } + /// @notice Etches the runtime bytecode of `what` (from the artifacts directory) at `where`. + /// @dev Runs the contract's creation code via `vm.etch` + a self-call, then etches the resulting runtime code at `where`. Constructor side-effects on other contracts are not preserved. function deployCodeTo(string memory what, address where) internal virtual { deployCodeTo(what, "", 0, where); } + /// @notice Etches the runtime bytecode of `what` (from the artifacts directory) at `where`, using `args` as ABI-encoded constructor arguments. + /// @dev Runs the contract's creation code via `vm.etch` + a self-call, then etches the resulting runtime code at `where`. Constructor side-effects on other contracts are not preserved. function deployCodeTo(string memory what, bytes memory args, address where) internal virtual { deployCodeTo(what, args, 0, where); } + /// @notice Etches the runtime bytecode of `what` (from the artifacts directory) at `where`, using `args` as ABI-encoded constructor arguments and sending `value` wei to the constructor. + /// @dev Runs the contract's creation code via `vm.etch` + a self-call, then etches the resulting runtime code at `where`. Constructor side-effects on other contracts are not preserved. function deployCodeTo(string memory what, bytes memory args, uint256 value, address where) internal virtual { bytes memory creationCode = vm.getCode(what); vm.etch(where, abi.encodePacked(creationCode, args)); diff --git a/src/StdJson.sol b/src/StdJson.sol index 065d75b5..2c894422 100644 --- a/src/StdJson.sol +++ b/src/StdJson.sol @@ -26,78 +26,94 @@ import {VmSafe} from "./Vm.sol"; library stdJson { VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); - /// @dev Returns whether `key` exists in `json`. - /// `key` uses the same selector syntax as `vm.parseJson*`, such as `.a` or `$`. + /// @notice Returns whether `key` exists in `json`. + /// @dev `key` uses the same selector syntax as `vm.parseJson*`, such as `.a` or `$`. function keyExists(string memory json, string memory key) internal view returns (bool) { return vm.keyExistsJson(json, key); } - /// @dev ABI-encodes the JSON value selected by `key`. - /// `key` uses the same selector syntax as `vm.parseJson*`, such as `.a` or `$`. + /// @notice ABI-encodes the JSON value selected by `key`. + /// @dev `key` uses the same selector syntax as `vm.parseJson*`, such as `.a` or `$`. function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) { return vm.parseJson(json, key); } + /// @notice Reads a uint256 value at `key` from `json`. function readUint(string memory json, string memory key) internal pure returns (uint256) { return vm.parseJsonUint(json, key); } + /// @notice Reads a uint256 array at `key` from `json`. function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) { return vm.parseJsonUintArray(json, key); } + /// @notice Reads an int256 value at `key` from `json`. function readInt(string memory json, string memory key) internal pure returns (int256) { return vm.parseJsonInt(json, key); } + /// @notice Reads an int256 array at `key` from `json`. function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) { return vm.parseJsonIntArray(json, key); } + /// @notice Reads a bytes32 value at `key` from `json`. function readBytes32(string memory json, string memory key) internal pure returns (bytes32) { return vm.parseJsonBytes32(json, key); } + /// @notice Reads a bytes32 array at `key` from `json`. function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) { return vm.parseJsonBytes32Array(json, key); } + /// @notice Reads a string value at `key` from `json`. function readString(string memory json, string memory key) internal pure returns (string memory) { return vm.parseJsonString(json, key); } + /// @notice Reads a string array at `key` from `json`. function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) { return vm.parseJsonStringArray(json, key); } + /// @notice Reads an address value at `key` from `json`. function readAddress(string memory json, string memory key) internal pure returns (address) { return vm.parseJsonAddress(json, key); } + /// @notice Reads an address array at `key` from `json`. function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) { return vm.parseJsonAddressArray(json, key); } + /// @notice Reads a bool value at `key` from `json`. function readBool(string memory json, string memory key) internal pure returns (bool) { return vm.parseJsonBool(json, key); } + /// @notice Reads a bool array at `key` from `json`. function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) { return vm.parseJsonBoolArray(json, key); } + /// @notice Reads a bytes value at `key` from `json`. function readBytes(string memory json, string memory key) internal pure returns (bytes memory) { return vm.parseJsonBytes(json, key); } + /// @notice Reads a bytes array at `key` from `json`. function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) { return vm.parseJsonBytesArray(json, key); } + /// @notice Reads a uint256 value at `key` from `json`, returning `defaultValue` if the key does not exist. function readUintOr(string memory json, string memory key, uint256 defaultValue) internal view returns (uint256) { return keyExists(json, key) ? readUint(json, key) : defaultValue; } + /// @notice Reads a uint256 array at `key` from `json`, returning `defaultValue` if the key does not exist. function readUintArrayOr(string memory json, string memory key, uint256[] memory defaultValue) internal view @@ -106,10 +122,12 @@ library stdJson { return keyExists(json, key) ? readUintArray(json, key) : defaultValue; } + /// @notice Reads an int256 value at `key` from `json`, returning `defaultValue` if the key does not exist. function readIntOr(string memory json, string memory key, int256 defaultValue) internal view returns (int256) { return keyExists(json, key) ? readInt(json, key) : defaultValue; } + /// @notice Reads an int256 array at `key` from `json`, returning `defaultValue` if the key does not exist. function readIntArrayOr(string memory json, string memory key, int256[] memory defaultValue) internal view @@ -118,6 +136,7 @@ library stdJson { return keyExists(json, key) ? readIntArray(json, key) : defaultValue; } + /// @notice Reads a bytes32 value at `key` from `json`, returning `defaultValue` if the key does not exist. function readBytes32Or(string memory json, string memory key, bytes32 defaultValue) internal view @@ -126,6 +145,7 @@ library stdJson { return keyExists(json, key) ? readBytes32(json, key) : defaultValue; } + /// @notice Reads a bytes32 array at `key` from `json`, returning `defaultValue` if the key does not exist. function readBytes32ArrayOr(string memory json, string memory key, bytes32[] memory defaultValue) internal view @@ -134,6 +154,7 @@ library stdJson { return keyExists(json, key) ? readBytes32Array(json, key) : defaultValue; } + /// @notice Reads a string value at `key` from `json`, returning `defaultValue` if the key does not exist. function readStringOr(string memory json, string memory key, string memory defaultValue) internal view @@ -142,6 +163,7 @@ library stdJson { return keyExists(json, key) ? readString(json, key) : defaultValue; } + /// @notice Reads a string array at `key` from `json`, returning `defaultValue` if the key does not exist. function readStringArrayOr(string memory json, string memory key, string[] memory defaultValue) internal view @@ -150,6 +172,7 @@ library stdJson { return keyExists(json, key) ? readStringArray(json, key) : defaultValue; } + /// @notice Reads an address value at `key` from `json`, returning `defaultValue` if the key does not exist. function readAddressOr(string memory json, string memory key, address defaultValue) internal view @@ -158,6 +181,7 @@ library stdJson { return keyExists(json, key) ? readAddress(json, key) : defaultValue; } + /// @notice Reads an address array at `key` from `json`, returning `defaultValue` if the key does not exist. function readAddressArrayOr(string memory json, string memory key, address[] memory defaultValue) internal view @@ -166,10 +190,12 @@ library stdJson { return keyExists(json, key) ? readAddressArray(json, key) : defaultValue; } + /// @notice Reads a bool value at `key` from `json`, returning `defaultValue` if the key does not exist. function readBoolOr(string memory json, string memory key, bool defaultValue) internal view returns (bool) { return keyExists(json, key) ? readBool(json, key) : defaultValue; } + /// @notice Reads a bool array at `key` from `json`, returning `defaultValue` if the key does not exist. function readBoolArrayOr(string memory json, string memory key, bool[] memory defaultValue) internal view @@ -178,6 +204,7 @@ library stdJson { return keyExists(json, key) ? readBoolArray(json, key) : defaultValue; } + /// @notice Reads a bytes value at `key` from `json`, returning `defaultValue` if the key does not exist. function readBytesOr(string memory json, string memory key, bytes memory defaultValue) internal view @@ -186,6 +213,7 @@ library stdJson { return keyExists(json, key) ? readBytes(json, key) : defaultValue; } + /// @notice Reads a bytes array at `key` from `json`, returning `defaultValue` if the key does not exist. function readBytesArrayOr(string memory json, string memory key, bytes[] memory defaultValue) internal view @@ -194,22 +222,27 @@ library stdJson { return keyExists(json, key) ? readBytesArray(json, key) : defaultValue; } + /// @notice Serializes a JSON object `rootObject` under `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { return vm.serializeJson(jsonKey, rootObject); } + /// @notice Serializes a bool `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { return vm.serializeBool(jsonKey, key, value); } + /// @notice Serializes a bool array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, bool[] memory value) internal returns (string memory) { return vm.serializeBool(jsonKey, key, value); } + /// @notice Serializes a uint256 `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { return vm.serializeUint(jsonKey, key, value); } + /// @notice Serializes a uint256 array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, uint256[] memory value) internal returns (string memory) @@ -217,10 +250,12 @@ library stdJson { return vm.serializeUint(jsonKey, key, value); } + /// @notice Serializes an int256 `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { return vm.serializeInt(jsonKey, key, value); } + /// @notice Serializes an int256 array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, int256[] memory value) internal returns (string memory) @@ -228,10 +263,12 @@ library stdJson { return vm.serializeInt(jsonKey, key, value); } + /// @notice Serializes an address `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { return vm.serializeAddress(jsonKey, key, value); } + /// @notice Serializes an address array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, address[] memory value) internal returns (string memory) @@ -239,10 +276,12 @@ library stdJson { return vm.serializeAddress(jsonKey, key, value); } + /// @notice Serializes a bytes32 `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { return vm.serializeBytes32(jsonKey, key, value); } + /// @notice Serializes a bytes32 array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, bytes32[] memory value) internal returns (string memory) @@ -250,10 +289,12 @@ library stdJson { return vm.serializeBytes32(jsonKey, key, value); } + /// @notice Serializes a bytes `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { return vm.serializeBytes(jsonKey, key, value); } + /// @notice Serializes a bytes array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, bytes[] memory value) internal returns (string memory) @@ -261,10 +302,12 @@ library stdJson { return vm.serializeBytes(jsonKey, key, value); } + /// @notice Serializes a string `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, string memory value) internal returns (string memory) { return vm.serializeString(jsonKey, key, value); } + /// @notice Serializes a string array `value` under `key` within `jsonKey` and returns the serialized JSON string. function serialize(string memory jsonKey, string memory key, string[] memory value) internal returns (string memory) @@ -272,10 +315,12 @@ library stdJson { return vm.serializeString(jsonKey, key, value); } + /// @notice Writes the serialized JSON object `jsonKey` to `path`. function write(string memory jsonKey, string memory path) internal { vm.writeJson(jsonKey, path); } + /// @notice Writes the value at `valueKey` from the serialized JSON object `jsonKey` to `path`. function write(string memory jsonKey, string memory path, string memory valueKey) internal { vm.writeJson(jsonKey, path, valueKey); } diff --git a/src/StdStorage.sol b/src/StdStorage.sol index 9d496ca1..a4c0bb68 100644 --- a/src/StdStorage.sol +++ b/src/StdStorage.sol @@ -28,10 +28,12 @@ library stdStorageSafe { Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); uint256 constant UINT256_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; + /// @notice Returns the 4-byte function selector for `sigStr`. function sigs(string memory sigStr) internal pure returns (bytes4) { return bytes4(keccak256(bytes(sigStr))); } + /// @notice Returns the encoded call parameters (keys or raw calldata) for the configured target function. function getCallParams(StdStorage storage self) internal view returns (bytes memory) { if (self._calldata.length == 0) { return flatten(self._keys); @@ -40,7 +42,7 @@ library stdStorageSafe { } } - // Calls target contract with configured parameters + /// @notice Calls the target contract with the configured parameters and returns the success flag and return value. function callTarget(StdStorage storage self) internal view returns (bool, bytes32) { bytes memory cd = abi.encodePacked(self._sig, getCallParams(self)); (bool success, bytes memory rdat) = self._target.staticcall(cd); @@ -49,9 +51,8 @@ library stdStorageSafe { return (success, result); } - // Tries mutating slot value to determine if the targeted value is stored in it. - // If current value is 0, then we are setting slot value to type(uint256).max - // Otherwise, we set it to 0. That way, return value should always be affected. + /// @notice Returns whether mutating `slot` changes the return value of the configured target call. + /// @dev Temporarily writes either `type(uint256).max` or `0` to the slot to detect sensitivity. function checkSlotMutatesCall(StdStorage storage self, bytes32 slot) internal returns (bool) { bytes32 prevSlotValue = vm.load(self._target, slot); (bool success, bytes32 prevReturnValue) = callTarget(self); @@ -66,8 +67,7 @@ library stdStorageSafe { return (success && (prevReturnValue != newReturnValue)); } - // Tries setting one of the bits in slot to 1 until return value changes. - // Index of resulted bit is an offset packed slot has from left/right side + /// @notice Searches for the bit offset of the packed variable within `slot` from the left or right side. function findOffset(StdStorage storage self, bytes32 slot, bool left) internal returns (bool, uint256) { for (uint256 offset = 0; offset < 256; offset++) { uint256 valueToPut = left ? (1 << (255 - offset)) : (1 << offset); @@ -82,6 +82,7 @@ library stdStorageSafe { return (false, 0); } + /// @notice Returns whether both offsets were found, along with the left and right bit offsets of the packed variable within `slot`. function findOffsets(StdStorage storage self, bytes32 slot) internal returns (bool, uint256, uint256) { bytes32 prevSlotValue = vm.load(self._target, slot); @@ -93,6 +94,7 @@ library stdStorageSafe { return (foundLeft && foundRight, offsetLeft, offsetRight); } + /// @notice Finds the storage slot for the configured target and returns its data, clearing the configuration. function find(StdStorage storage self) internal returns (FindData storage) { return find(self, true); } @@ -169,46 +171,55 @@ library stdStorageSafe { return self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))]; } + /// @notice Sets the target contract address for the storage lookup. function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { self._target = _target; return self; } + /// @notice Sets the target function selector for the storage lookup. function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { self._sig = _sig; return self; } + /// @notice Sets the target function selector from a signature string for the storage lookup. function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { self._sig = sigs(_sig); return self; } + /// @notice Sets raw calldata to use instead of ABI-encoded keys for the target call. function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { self._calldata = _calldata; return self; } + /// @notice Adds an address mapping key to the storage lookup path. function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { self._keys.push(bytes32(uint256(uint160(who)))); return self; } + /// @notice Adds a uint256 mapping key to the storage lookup path. function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { self._keys.push(bytes32(amt)); return self; } + /// @notice Adds a bytes32 mapping key to the storage lookup path. function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { self._keys.push(key); return self; } + /// @notice Enables detection and handling of values packed into shared storage slots. function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { self._enable_packed_slots = true; return self; } + /// @notice Sets the struct field depth for storage lookups into nested structs. function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { self._depth = _depth; return self; @@ -222,10 +233,13 @@ library stdStorageSafe { return abi.encode(value); } + /// @notice Reads the found storage slot value as bytes32. function read_bytes32(StdStorage storage self) internal returns (bytes32) { return abi.decode(read(self), (bytes32)); } + /// @notice Reads the found storage slot value as bool. + /// @dev Reverts if the stored value is neither `0` nor `1`. function read_bool(StdStorage storage self) internal returns (bool) { int256 v = read_int(self); if (v == 0) return false; @@ -233,18 +247,22 @@ library stdStorageSafe { revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool."); } + /// @notice Reads the found storage slot value as address. function read_address(StdStorage storage self) internal returns (address) { return abi.decode(read(self), (address)); } + /// @notice Reads the found storage slot value as uint256. function read_uint(StdStorage storage self) internal returns (uint256) { return abi.decode(read(self), (uint256)); } + /// @notice Reads the found storage slot value as int256. function read_int(StdStorage storage self) internal returns (int256) { return abi.decode(read(self), (int256)); } + /// @notice Returns the parent mapping slot index and the key used to reach the found slot. function parent(StdStorage storage self) internal returns (uint256, bytes32) { address who = self._target; uint256 field_depth = self._depth; @@ -259,6 +277,7 @@ library stdStorageSafe { return (uint256(parent_slot), key); } + /// @notice Returns the root mapping slot index by traversing the mapping parent chain. function root(StdStorage storage self) internal returns (uint256) { address who = self._target; uint256 field_depth = self._depth; @@ -306,6 +325,7 @@ library stdStorageSafe { return result; } + /// @notice Resets all configured parameters on `self`. function clear(StdStorage storage self) internal { delete self._target; delete self._sig; @@ -315,8 +335,8 @@ library stdStorageSafe { delete self._calldata; } - // Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight` - // (slotValue & mask) >> offsetRight will be the value of the given packed variable + /// @notice Returns a bitmask with ones in the bit range `[offsetRight, 255 - offsetLeft]`. + /// @dev `(slotValue & mask) >> offsetRight` extracts the packed variable's value. function getMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internal pure returns (uint256 mask) { // mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight; // using assembly because (1 << 256) causes overflow @@ -325,7 +345,7 @@ library stdStorageSafe { } } - // Returns slot value with updated packed variable. + /// @notice Returns `curValue` with the packed variable at `[offsetRight, 255 - offsetLeft]` replaced by `varValue`. function getUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight) internal pure @@ -338,70 +358,87 @@ library stdStorageSafe { library stdStorage { Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + /// @notice Returns the 4-byte function selector for `sigStr`. function sigs(string memory sigStr) internal pure returns (bytes4) { return stdStorageSafe.sigs(sigStr); } + /// @notice Finds the storage slot index for the configured target, clearing the configuration. function find(StdStorage storage self) internal returns (uint256) { return find(self, true); } + /// @notice Finds the storage slot index for the configured target, optionally clearing the configuration. function find(StdStorage storage self, bool _clear) internal returns (uint256) { return stdStorageSafe.find(self, _clear).slot; } + /// @notice Sets the target contract address for the storage lookup. function target(StdStorage storage self, address _target) internal returns (StdStorage storage) { return stdStorageSafe.target(self, _target); } + /// @notice Sets the target function selector for the storage lookup. function sig(StdStorage storage self, bytes4 _sig) internal returns (StdStorage storage) { return stdStorageSafe.sig(self, _sig); } + /// @notice Sets the target function selector from a signature string for the storage lookup. function sig(StdStorage storage self, string memory _sig) internal returns (StdStorage storage) { return stdStorageSafe.sig(self, _sig); } + /// @notice Adds an address mapping key to the storage lookup path. function with_key(StdStorage storage self, address who) internal returns (StdStorage storage) { return stdStorageSafe.with_key(self, who); } + /// @notice Adds a uint256 mapping key to the storage lookup path. function with_key(StdStorage storage self, uint256 amt) internal returns (StdStorage storage) { return stdStorageSafe.with_key(self, amt); } + /// @notice Adds a bytes32 mapping key to the storage lookup path. function with_key(StdStorage storage self, bytes32 key) internal returns (StdStorage storage) { return stdStorageSafe.with_key(self, key); } + /// @notice Sets raw calldata to use instead of ABI-encoded keys for the target call. function with_calldata(StdStorage storage self, bytes memory _calldata) internal returns (StdStorage storage) { return stdStorageSafe.with_calldata(self, _calldata); } + /// @notice Enables detection and handling of values packed into shared storage slots. function enable_packed_slots(StdStorage storage self) internal returns (StdStorage storage) { return stdStorageSafe.enable_packed_slots(self); } + /// @notice Sets the struct field depth for storage lookups into nested structs. function depth(StdStorage storage self, uint256 _depth) internal returns (StdStorage storage) { return stdStorageSafe.depth(self, _depth); } + /// @notice Resets all configured parameters on `self`. function clear(StdStorage storage self) internal { stdStorageSafe.clear(self); } + /// @notice Writes `who` to the found storage slot and verifies the value was applied correctly. function checked_write(StdStorage storage self, address who) internal { checked_write(self, bytes32(uint256(uint160(who)))); } + /// @notice Writes `amt` to the found storage slot and verifies the value was applied correctly. function checked_write(StdStorage storage self, uint256 amt) internal { checked_write(self, bytes32(amt)); } + /// @notice Writes `val` to the found storage slot and verifies the value was applied correctly. function checked_write_int(StdStorage storage self, int256 val) internal { checked_write(self, bytes32(uint256(val))); } + /// @notice Writes `write` to the found storage slot and verifies the value was applied correctly. function checked_write(StdStorage storage self, bool write) internal { bytes32 t; assembly ("memory-safe") { @@ -410,6 +447,7 @@ library stdStorage { checked_write(self, t); } + /// @notice Writes `set` to the found storage slot and verifies the value was applied correctly. function checked_write(StdStorage storage self, bytes32 set) internal { address who = self._target; bytes4 fsig = self._sig; @@ -446,30 +484,37 @@ library stdStorage { clear(self); } + /// @notice Reads the found storage slot value as bytes32. function read_bytes32(StdStorage storage self) internal returns (bytes32) { return stdStorageSafe.read_bytes32(self); } + /// @notice Reads the found storage slot value as bool. function read_bool(StdStorage storage self) internal returns (bool) { return stdStorageSafe.read_bool(self); } + /// @notice Reads the found storage slot value as address. function read_address(StdStorage storage self) internal returns (address) { return stdStorageSafe.read_address(self); } + /// @notice Reads the found storage slot value as uint256. function read_uint(StdStorage storage self) internal returns (uint256) { return stdStorageSafe.read_uint(self); } + /// @notice Reads the found storage slot value as int256. function read_int(StdStorage storage self) internal returns (int256) { return stdStorageSafe.read_int(self); } + /// @notice Returns the parent mapping slot index and the key used to reach the found slot. function parent(StdStorage storage self) internal returns (uint256, bytes32) { return stdStorageSafe.parent(self); } + /// @notice Returns the root mapping slot index by traversing the mapping parent chain. function root(StdStorage storage self) internal returns (uint256) { return stdStorageSafe.root(self); } diff --git a/src/StdStyle.sol b/src/StdStyle.sol index ad63400f..5a9ceb34 100644 --- a/src/StdStyle.sol +++ b/src/StdStyle.sol @@ -23,310 +23,387 @@ library StdStyle { return string(abi.encodePacked(style, self, RESET)); } + /// @notice Returns `self` wrapped in red ANSI color codes. function red(string memory self) internal pure returns (string memory) { return styleConcat(RED, self); } + /// @notice Returns the string representation of `self` wrapped in red ANSI color codes. function red(uint256 self) internal pure returns (string memory) { return red(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in red ANSI color codes. function red(int256 self) internal pure returns (string memory) { return red(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in red ANSI color codes. function red(address self) internal pure returns (string memory) { return red(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in red ANSI color codes. function red(bool self) internal pure returns (string memory) { return red(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in red ANSI color codes. function redBytes(bytes memory self) internal pure returns (string memory) { return red(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in red ANSI color codes. function redBytes32(bytes32 self) internal pure returns (string memory) { return red(vm.toString(self)); } + /// @notice Returns `self` wrapped in green ANSI color codes. function green(string memory self) internal pure returns (string memory) { return styleConcat(GREEN, self); } + /// @notice Returns the string representation of `self` wrapped in green ANSI color codes. function green(uint256 self) internal pure returns (string memory) { return green(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in green ANSI color codes. function green(int256 self) internal pure returns (string memory) { return green(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in green ANSI color codes. function green(address self) internal pure returns (string memory) { return green(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in green ANSI color codes. function green(bool self) internal pure returns (string memory) { return green(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in green ANSI color codes. function greenBytes(bytes memory self) internal pure returns (string memory) { return green(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in green ANSI color codes. function greenBytes32(bytes32 self) internal pure returns (string memory) { return green(vm.toString(self)); } + /// @notice Returns `self` wrapped in yellow ANSI color codes. function yellow(string memory self) internal pure returns (string memory) { return styleConcat(YELLOW, self); } + /// @notice Returns the string representation of `self` wrapped in yellow ANSI color codes. function yellow(uint256 self) internal pure returns (string memory) { return yellow(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in yellow ANSI color codes. function yellow(int256 self) internal pure returns (string memory) { return yellow(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in yellow ANSI color codes. function yellow(address self) internal pure returns (string memory) { return yellow(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in yellow ANSI color codes. function yellow(bool self) internal pure returns (string memory) { return yellow(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in yellow ANSI color codes. function yellowBytes(bytes memory self) internal pure returns (string memory) { return yellow(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in yellow ANSI color codes. function yellowBytes32(bytes32 self) internal pure returns (string memory) { return yellow(vm.toString(self)); } + /// @notice Returns `self` wrapped in blue ANSI color codes. function blue(string memory self) internal pure returns (string memory) { return styleConcat(BLUE, self); } + /// @notice Returns the string representation of `self` wrapped in blue ANSI color codes. function blue(uint256 self) internal pure returns (string memory) { return blue(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in blue ANSI color codes. function blue(int256 self) internal pure returns (string memory) { return blue(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in blue ANSI color codes. function blue(address self) internal pure returns (string memory) { return blue(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in blue ANSI color codes. function blue(bool self) internal pure returns (string memory) { return blue(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in blue ANSI color codes. function blueBytes(bytes memory self) internal pure returns (string memory) { return blue(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in blue ANSI color codes. function blueBytes32(bytes32 self) internal pure returns (string memory) { return blue(vm.toString(self)); } + /// @notice Returns `self` wrapped in magenta ANSI color codes. function magenta(string memory self) internal pure returns (string memory) { return styleConcat(MAGENTA, self); } + /// @notice Returns the string representation of `self` wrapped in magenta ANSI color codes. function magenta(uint256 self) internal pure returns (string memory) { return magenta(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in magenta ANSI color codes. function magenta(int256 self) internal pure returns (string memory) { return magenta(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in magenta ANSI color codes. function magenta(address self) internal pure returns (string memory) { return magenta(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in magenta ANSI color codes. function magenta(bool self) internal pure returns (string memory) { return magenta(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in magenta ANSI color codes. function magentaBytes(bytes memory self) internal pure returns (string memory) { return magenta(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in magenta ANSI color codes. function magentaBytes32(bytes32 self) internal pure returns (string memory) { return magenta(vm.toString(self)); } + /// @notice Returns `self` wrapped in cyan ANSI color codes. function cyan(string memory self) internal pure returns (string memory) { return styleConcat(CYAN, self); } + /// @notice Returns the string representation of `self` wrapped in cyan ANSI color codes. function cyan(uint256 self) internal pure returns (string memory) { return cyan(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in cyan ANSI color codes. function cyan(int256 self) internal pure returns (string memory) { return cyan(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in cyan ANSI color codes. function cyan(address self) internal pure returns (string memory) { return cyan(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in cyan ANSI color codes. function cyan(bool self) internal pure returns (string memory) { return cyan(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in cyan ANSI color codes. function cyanBytes(bytes memory self) internal pure returns (string memory) { return cyan(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in cyan ANSI color codes. function cyanBytes32(bytes32 self) internal pure returns (string memory) { return cyan(vm.toString(self)); } + /// @notice Returns `self` wrapped in bold ANSI style codes. function bold(string memory self) internal pure returns (string memory) { return styleConcat(BOLD, self); } + /// @notice Returns the string representation of `self` wrapped in bold ANSI style codes. function bold(uint256 self) internal pure returns (string memory) { return bold(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in bold ANSI style codes. function bold(int256 self) internal pure returns (string memory) { return bold(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in bold ANSI style codes. function bold(address self) internal pure returns (string memory) { return bold(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in bold ANSI style codes. function bold(bool self) internal pure returns (string memory) { return bold(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in bold ANSI style codes. function boldBytes(bytes memory self) internal pure returns (string memory) { return bold(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in bold ANSI style codes. function boldBytes32(bytes32 self) internal pure returns (string memory) { return bold(vm.toString(self)); } + /// @notice Returns `self` wrapped in dim ANSI style codes. function dim(string memory self) internal pure returns (string memory) { return styleConcat(DIM, self); } + /// @notice Returns the string representation of `self` wrapped in dim ANSI style codes. function dim(uint256 self) internal pure returns (string memory) { return dim(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in dim ANSI style codes. function dim(int256 self) internal pure returns (string memory) { return dim(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in dim ANSI style codes. function dim(address self) internal pure returns (string memory) { return dim(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in dim ANSI style codes. function dim(bool self) internal pure returns (string memory) { return dim(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in dim ANSI style codes. function dimBytes(bytes memory self) internal pure returns (string memory) { return dim(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in dim ANSI style codes. function dimBytes32(bytes32 self) internal pure returns (string memory) { return dim(vm.toString(self)); } + /// @notice Returns `self` wrapped in italic ANSI style codes. function italic(string memory self) internal pure returns (string memory) { return styleConcat(ITALIC, self); } + /// @notice Returns the string representation of `self` wrapped in italic ANSI style codes. function italic(uint256 self) internal pure returns (string memory) { return italic(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in italic ANSI style codes. function italic(int256 self) internal pure returns (string memory) { return italic(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in italic ANSI style codes. function italic(address self) internal pure returns (string memory) { return italic(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in italic ANSI style codes. function italic(bool self) internal pure returns (string memory) { return italic(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in italic ANSI style codes. function italicBytes(bytes memory self) internal pure returns (string memory) { return italic(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in italic ANSI style codes. function italicBytes32(bytes32 self) internal pure returns (string memory) { return italic(vm.toString(self)); } + /// @notice Returns `self` wrapped in underline ANSI style codes. function underline(string memory self) internal pure returns (string memory) { return styleConcat(UNDERLINE, self); } + /// @notice Returns the string representation of `self` wrapped in underline ANSI style codes. function underline(uint256 self) internal pure returns (string memory) { return underline(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in underline ANSI style codes. function underline(int256 self) internal pure returns (string memory) { return underline(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in underline ANSI style codes. function underline(address self) internal pure returns (string memory) { return underline(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in underline ANSI style codes. function underline(bool self) internal pure returns (string memory) { return underline(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in underline ANSI style codes. function underlineBytes(bytes memory self) internal pure returns (string memory) { return underline(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in underline ANSI style codes. function underlineBytes32(bytes32 self) internal pure returns (string memory) { return underline(vm.toString(self)); } + /// @notice Returns `self` wrapped in inverse ANSI style codes. function inverse(string memory self) internal pure returns (string memory) { return styleConcat(INVERSE, self); } + /// @notice Returns the string representation of `self` wrapped in inverse ANSI style codes. function inverse(uint256 self) internal pure returns (string memory) { return inverse(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in inverse ANSI style codes. function inverse(int256 self) internal pure returns (string memory) { return inverse(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in inverse ANSI style codes. function inverse(address self) internal pure returns (string memory) { return inverse(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in inverse ANSI style codes. function inverse(bool self) internal pure returns (string memory) { return inverse(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in inverse ANSI style codes. function inverseBytes(bytes memory self) internal pure returns (string memory) { return inverse(vm.toString(self)); } + /// @notice Returns the string representation of `self` wrapped in inverse ANSI style codes. function inverseBytes32(bytes32 self) internal pure returns (string memory) { return inverse(vm.toString(self)); } diff --git a/src/StdToml.sol b/src/StdToml.sol index 71ee6607..a5198d82 100644 --- a/src/StdToml.sol +++ b/src/StdToml.sol @@ -23,74 +23,92 @@ import {VmSafe} from "./Vm.sol"; library stdToml { VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); + /// @notice Returns whether `key` exists in `toml`. function keyExists(string memory toml, string memory key) internal view returns (bool) { return vm.keyExistsToml(toml, key); } + /// @notice ABI-encodes the TOML value selected by `key`. function parseRaw(string memory toml, string memory key) internal pure returns (bytes memory) { return vm.parseToml(toml, key); } + /// @notice Reads a uint256 value at `key` from `toml`. function readUint(string memory toml, string memory key) internal pure returns (uint256) { return vm.parseTomlUint(toml, key); } + /// @notice Reads a uint256 array at `key` from `toml`. function readUintArray(string memory toml, string memory key) internal pure returns (uint256[] memory) { return vm.parseTomlUintArray(toml, key); } + /// @notice Reads an int256 value at `key` from `toml`. function readInt(string memory toml, string memory key) internal pure returns (int256) { return vm.parseTomlInt(toml, key); } + /// @notice Reads an int256 array at `key` from `toml`. function readIntArray(string memory toml, string memory key) internal pure returns (int256[] memory) { return vm.parseTomlIntArray(toml, key); } + /// @notice Reads a bytes32 value at `key` from `toml`. function readBytes32(string memory toml, string memory key) internal pure returns (bytes32) { return vm.parseTomlBytes32(toml, key); } + /// @notice Reads a bytes32 array at `key` from `toml`. function readBytes32Array(string memory toml, string memory key) internal pure returns (bytes32[] memory) { return vm.parseTomlBytes32Array(toml, key); } + /// @notice Reads a string value at `key` from `toml`. function readString(string memory toml, string memory key) internal pure returns (string memory) { return vm.parseTomlString(toml, key); } + /// @notice Reads a string array at `key` from `toml`. function readStringArray(string memory toml, string memory key) internal pure returns (string[] memory) { return vm.parseTomlStringArray(toml, key); } + /// @notice Reads an address value at `key` from `toml`. function readAddress(string memory toml, string memory key) internal pure returns (address) { return vm.parseTomlAddress(toml, key); } + /// @notice Reads an address array at `key` from `toml`. function readAddressArray(string memory toml, string memory key) internal pure returns (address[] memory) { return vm.parseTomlAddressArray(toml, key); } + /// @notice Reads a bool value at `key` from `toml`. function readBool(string memory toml, string memory key) internal pure returns (bool) { return vm.parseTomlBool(toml, key); } + /// @notice Reads a bool array at `key` from `toml`. function readBoolArray(string memory toml, string memory key) internal pure returns (bool[] memory) { return vm.parseTomlBoolArray(toml, key); } + /// @notice Reads a bytes value at `key` from `toml`. function readBytes(string memory toml, string memory key) internal pure returns (bytes memory) { return vm.parseTomlBytes(toml, key); } + /// @notice Reads a bytes array at `key` from `toml`. function readBytesArray(string memory toml, string memory key) internal pure returns (bytes[] memory) { return vm.parseTomlBytesArray(toml, key); } + /// @notice Reads a uint256 value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readUintOr(string memory toml, string memory key, uint256 defaultValue) internal view returns (uint256) { return keyExists(toml, key) ? readUint(toml, key) : defaultValue; } + /// @notice Reads a uint256 array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readUintArrayOr(string memory toml, string memory key, uint256[] memory defaultValue) internal view @@ -99,10 +117,12 @@ library stdToml { return keyExists(toml, key) ? readUintArray(toml, key) : defaultValue; } + /// @notice Reads an int256 value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readIntOr(string memory toml, string memory key, int256 defaultValue) internal view returns (int256) { return keyExists(toml, key) ? readInt(toml, key) : defaultValue; } + /// @notice Reads an int256 array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readIntArrayOr(string memory toml, string memory key, int256[] memory defaultValue) internal view @@ -111,6 +131,7 @@ library stdToml { return keyExists(toml, key) ? readIntArray(toml, key) : defaultValue; } + /// @notice Reads a bytes32 value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readBytes32Or(string memory toml, string memory key, bytes32 defaultValue) internal view @@ -119,6 +140,7 @@ library stdToml { return keyExists(toml, key) ? readBytes32(toml, key) : defaultValue; } + /// @notice Reads a bytes32 array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readBytes32ArrayOr(string memory toml, string memory key, bytes32[] memory defaultValue) internal view @@ -127,6 +149,7 @@ library stdToml { return keyExists(toml, key) ? readBytes32Array(toml, key) : defaultValue; } + /// @notice Reads a string value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readStringOr(string memory toml, string memory key, string memory defaultValue) internal view @@ -135,6 +158,7 @@ library stdToml { return keyExists(toml, key) ? readString(toml, key) : defaultValue; } + /// @notice Reads a string array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readStringArrayOr(string memory toml, string memory key, string[] memory defaultValue) internal view @@ -143,6 +167,7 @@ library stdToml { return keyExists(toml, key) ? readStringArray(toml, key) : defaultValue; } + /// @notice Reads an address value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readAddressOr(string memory toml, string memory key, address defaultValue) internal view @@ -151,6 +176,7 @@ library stdToml { return keyExists(toml, key) ? readAddress(toml, key) : defaultValue; } + /// @notice Reads an address array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readAddressArrayOr(string memory toml, string memory key, address[] memory defaultValue) internal view @@ -159,10 +185,12 @@ library stdToml { return keyExists(toml, key) ? readAddressArray(toml, key) : defaultValue; } + /// @notice Reads a bool value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readBoolOr(string memory toml, string memory key, bool defaultValue) internal view returns (bool) { return keyExists(toml, key) ? readBool(toml, key) : defaultValue; } + /// @notice Reads a bool array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readBoolArrayOr(string memory toml, string memory key, bool[] memory defaultValue) internal view @@ -171,6 +199,7 @@ library stdToml { return keyExists(toml, key) ? readBoolArray(toml, key) : defaultValue; } + /// @notice Reads a bytes value at `key` from `toml`, returning `defaultValue` if the key does not exist. function readBytesOr(string memory toml, string memory key, bytes memory defaultValue) internal view @@ -179,6 +208,7 @@ library stdToml { return keyExists(toml, key) ? readBytes(toml, key) : defaultValue; } + /// @notice Reads a bytes array at `key` from `toml`, returning `defaultValue` if the key does not exist. function readBytesArrayOr(string memory toml, string memory key, bytes[] memory defaultValue) internal view @@ -187,22 +217,28 @@ library stdToml { return keyExists(toml, key) ? readBytesArray(toml, key) : defaultValue; } + /// @notice Serializes a JSON object `rootObject` under `jsonKey` and returns the serialized string. + /// @dev Values are accumulated as JSON in memory; conversion to TOML happens on `write`. function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { return vm.serializeJson(jsonKey, rootObject); } + /// @notice Serializes a bool `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { return vm.serializeBool(jsonKey, key, value); } + /// @notice Serializes a bool array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, bool[] memory value) internal returns (string memory) { return vm.serializeBool(jsonKey, key, value); } + /// @notice Serializes a uint256 `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { return vm.serializeUint(jsonKey, key, value); } + /// @notice Serializes a uint256 array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, uint256[] memory value) internal returns (string memory) @@ -210,10 +246,12 @@ library stdToml { return vm.serializeUint(jsonKey, key, value); } + /// @notice Serializes an int256 `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { return vm.serializeInt(jsonKey, key, value); } + /// @notice Serializes an int256 array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, int256[] memory value) internal returns (string memory) @@ -221,10 +259,12 @@ library stdToml { return vm.serializeInt(jsonKey, key, value); } + /// @notice Serializes an address `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { return vm.serializeAddress(jsonKey, key, value); } + /// @notice Serializes an address array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, address[] memory value) internal returns (string memory) @@ -232,10 +272,12 @@ library stdToml { return vm.serializeAddress(jsonKey, key, value); } + /// @notice Serializes a bytes32 `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { return vm.serializeBytes32(jsonKey, key, value); } + /// @notice Serializes a bytes32 array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, bytes32[] memory value) internal returns (string memory) @@ -243,10 +285,12 @@ library stdToml { return vm.serializeBytes32(jsonKey, key, value); } + /// @notice Serializes a bytes `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { return vm.serializeBytes(jsonKey, key, value); } + /// @notice Serializes a bytes array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, bytes[] memory value) internal returns (string memory) @@ -254,10 +298,12 @@ library stdToml { return vm.serializeBytes(jsonKey, key, value); } + /// @notice Serializes a string `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, string memory value) internal returns (string memory) { return vm.serializeString(jsonKey, key, value); } + /// @notice Serializes a string array `value` under `key` within `jsonKey` and returns the serialized string. function serialize(string memory jsonKey, string memory key, string[] memory value) internal returns (string memory) @@ -265,10 +311,12 @@ library stdToml { return vm.serializeString(jsonKey, key, value); } + /// @notice Writes the serialized object `jsonKey` to `path` as a TOML file. function write(string memory jsonKey, string memory path) internal { vm.writeToml(jsonKey, path); } + /// @notice Writes the value at `valueKey` from the serialized object `jsonKey` to `path` as a TOML file. function write(string memory jsonKey, string memory path, string memory valueKey) internal { vm.writeToml(jsonKey, path, valueKey); }