├── lib └── forge-std │ ├── .gitattributes │ ├── .gitignore │ ├── lib │ └── ds-test │ │ ├── .gitignore │ │ ├── default.nix │ │ ├── Makefile │ │ ├── package.json │ │ ├── .github │ │ └── workflows │ │ │ └── build.yml │ │ └── demo │ │ └── demo.sol │ ├── .gitmodules │ ├── test │ ├── compilation │ │ ├── CompilationTest.sol │ │ ├── CompilationScript.sol │ │ ├── CompilationTestBase.sol │ │ └── CompilationScriptBase.sol │ ├── Vm.t.sol │ ├── StdError.t.sol │ ├── StdStyle.t.sol │ ├── StdMath.t.sol │ ├── StdChains.t.sol │ ├── fixtures │ │ └── broadcast.log.json │ └── StdStorage.t.sol │ ├── package.json │ ├── src │ ├── interfaces │ │ ├── IERC165.sol │ │ ├── IERC20.sol │ │ ├── IMulticall3.sol │ │ ├── IERC1155.sol │ │ ├── IERC721.sol │ │ └── IERC4626.sol │ ├── Script.sol │ ├── StdError.sol │ ├── Test.sol │ ├── StdMath.sol │ ├── Base.sol │ ├── StdInvariant.sol │ ├── StdJson.sol │ ├── mocks │ │ ├── MockERC721.sol │ │ └── MockERC20.sol │ ├── StdUtils.sol │ ├── StdStyle.sol │ └── StdChains.sol │ ├── .github │ └── workflows │ │ ├── sync.yml │ │ └── ci.yml │ ├── foundry.toml │ ├── LICENSE-MIT │ ├── README.md │ └── LICENSE-APACHE ├── .gitmodules ├── foundry.toml ├── .gitignore ├── .github └── workflows │ └── test.yml ├── README.md └── src └── ERC404.sol /lib/forge-std/.gitattributes: -------------------------------------------------------------------------------- 1 | src/Vm.sol linguist-generated 2 | -------------------------------------------------------------------------------- /lib/forge-std/.gitignore: -------------------------------------------------------------------------------- 1 | cache/ 2 | out/ 3 | .vscode 4 | .idea 5 | -------------------------------------------------------------------------------- /lib/forge-std/lib/ds-test/.gitignore: -------------------------------------------------------------------------------- 1 | /.dapple 2 | /build 3 | /out 4 | /cache/ 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/forge-std"] 2 | path = lib/forge-std 3 | url = https://github.com/foundry-rs/forge-std 4 | -------------------------------------------------------------------------------- /lib/forge-std/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/ds-test"] 2 | path = lib/ds-test 3 | url = https://github.com/dapphub/ds-test 4 | -------------------------------------------------------------------------------- /lib/forge-std/lib/ds-test/default.nix: -------------------------------------------------------------------------------- 1 | { solidityPackage, dappsys }: solidityPackage { 2 | name = "ds-test"; 3 | src = ./src; 4 | } 5 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = "src" 3 | out = "out" 4 | libs = ["lib"] 5 | 6 | # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiler files 2 | cache/ 3 | out/ 4 | 5 | # Ignores development broadcast logs 6 | !/broadcast 7 | /broadcast/*/31337/ 8 | /broadcast/**/dry-run/ 9 | 10 | # Docs 11 | docs/ 12 | 13 | # Dotenv file 14 | .env 15 | -------------------------------------------------------------------------------- /lib/forge-std/lib/ds-test/Makefile: -------------------------------------------------------------------------------- 1 | all:; dapp build 2 | 3 | test: 4 | -dapp --use solc:0.4.23 build 5 | -dapp --use solc:0.4.26 build 6 | -dapp --use solc:0.5.17 build 7 | -dapp --use solc:0.6.12 build 8 | -dapp --use solc:0.7.5 build 9 | 10 | demo: 11 | DAPP_SRC=demo dapp --use solc:0.7.5 build 12 | -hevm dapp-test --verbose 3 13 | 14 | .PHONY: test demo 15 | -------------------------------------------------------------------------------- /lib/forge-std/lib/ds-test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ds-test", 3 | "version": "1.0.0", 4 | "description": "Assertions, equality checks and other test helpers ", 5 | "bugs": "https://github.com/dapphub/ds-test/issues", 6 | "license": "GPL-3.0", 7 | "author": "Contributors to ds-test", 8 | "files": [ 9 | "src/*" 10 | ], 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/dapphub/ds-test.git" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/forge-std/test/compilation/CompilationTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | pragma experimental ABIEncoderV2; 5 | 6 | import "../../src/Test.sol"; 7 | 8 | // The purpose of this contract is to benchmark compilation time to avoid accidentally introducing 9 | // a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207 10 | contract CompilationTest is Test {} 11 | -------------------------------------------------------------------------------- /lib/forge-std/test/compilation/CompilationScript.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | pragma experimental ABIEncoderV2; 5 | 6 | import "../../src/Script.sol"; 7 | 8 | // The purpose of this contract is to benchmark compilation time to avoid accidentally introducing 9 | // a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207 10 | contract CompilationScript is Script {} 11 | -------------------------------------------------------------------------------- /lib/forge-std/test/compilation/CompilationTestBase.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | pragma experimental ABIEncoderV2; 5 | 6 | import "../../src/Test.sol"; 7 | 8 | // The purpose of this contract is to benchmark compilation time to avoid accidentally introducing 9 | // a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207 10 | contract CompilationTestBase is TestBase {} 11 | -------------------------------------------------------------------------------- /lib/forge-std/test/compilation/CompilationScriptBase.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | pragma experimental ABIEncoderV2; 5 | 6 | import "../../src/Script.sol"; 7 | 8 | // The purpose of this contract is to benchmark compilation time to avoid accidentally introducing 9 | // a change that results in very long compilation times with via-ir. See https://github.com/foundry-rs/forge-std/issues/207 10 | contract CompilationScriptBase is ScriptBase {} 11 | -------------------------------------------------------------------------------- /lib/forge-std/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "forge-std", 3 | "version": "1.7.6", 4 | "description": "Forge Standard Library is a collection of helpful contracts and libraries for use with Forge and Foundry.", 5 | "homepage": "https://book.getfoundry.sh/forge/forge-std", 6 | "bugs": "https://github.com/foundry-rs/forge-std/issues", 7 | "license": "(Apache-2.0 OR MIT)", 8 | "author": "Contributors to Forge Standard Library", 9 | "files": [ 10 | "src/**/*" 11 | ], 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/foundry-rs/forge-std.git" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/forge-std/src/interfaces/IERC165.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2; 3 | 4 | interface IERC165 { 5 | /// @notice Query if a contract implements an interface 6 | /// @param interfaceID The interface identifier, as specified in ERC-165 7 | /// @dev Interface identification is specified in ERC-165. This function 8 | /// uses less than 30,000 gas. 9 | /// @return `true` if the contract implements `interfaceID` and 10 | /// `interfaceID` is not 0xffffffff, `false` otherwise 11 | function supportsInterface(bytes4 interfaceID) external view returns (bool); 12 | } 13 | -------------------------------------------------------------------------------- /lib/forge-std/test/Vm.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0 <0.9.0; 3 | 4 | import {Test} from "../src/Test.sol"; 5 | import {Vm, VmSafe} from "../src/Vm.sol"; 6 | 7 | contract VmTest is Test { 8 | // This test ensures that functions are never accidentally removed from a Vm interface, or 9 | // inadvertently moved between Vm and VmSafe. This test must be updated each time a function is 10 | // added to or removed from Vm or VmSafe. 11 | function test_interfaceId() public { 12 | assertEq(type(VmSafe).interfaceId, bytes4(0x01ec102d), "VmSafe"); 13 | assertEq(type(Vm).interfaceId, bytes4(0xa63eed6b), "Vm"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: workflow_dispatch 4 | 5 | env: 6 | FOUNDRY_PROFILE: ci 7 | 8 | jobs: 9 | check: 10 | strategy: 11 | fail-fast: true 12 | 13 | name: Foundry project 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | with: 18 | submodules: recursive 19 | 20 | - name: Install Foundry 21 | uses: foundry-rs/foundry-toolchain@v1 22 | with: 23 | version: nightly 24 | 25 | - name: Run Forge build 26 | run: | 27 | forge --version 28 | forge build --sizes 29 | id: build 30 | 31 | - name: Run Forge tests 32 | run: | 33 | forge test -vvv 34 | id: test 35 | -------------------------------------------------------------------------------- /lib/forge-std/.github/workflows/sync.yml: -------------------------------------------------------------------------------- 1 | name: Sync Release Branch 2 | 3 | on: 4 | release: 5 | types: 6 | - created 7 | 8 | jobs: 9 | sync-release-branch: 10 | runs-on: ubuntu-latest 11 | if: startsWith(github.event.release.tag_name, 'v1') 12 | steps: 13 | - name: Check out the repo 14 | uses: actions/checkout@v3 15 | with: 16 | fetch-depth: 0 17 | ref: v1 18 | 19 | - name: Configure Git 20 | run: | 21 | git config user.name github-actions[bot] 22 | git config user.email 41898282+github-actions[bot]@users.noreply.github.com 23 | 24 | - name: Sync Release Branch 25 | run: | 26 | git fetch --tags 27 | git checkout v1 28 | git reset --hard ${GITHUB_REF} 29 | git push --force 30 | -------------------------------------------------------------------------------- /lib/forge-std/foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | fs_permissions = [{ access = "read-write", path = "./"}] 3 | 4 | [rpc_endpoints] 5 | # The RPC URLs are modified versions of the default for testing initialization. 6 | mainnet = "https://mainnet.infura.io/v3/b1d3925804e74152b316ca7da97060d3" # Different API key. 7 | optimism_goerli = "https://goerli.optimism.io/" # Adds a trailing slash. 8 | arbitrum_one_goerli = "https://goerli-rollup.arbitrum.io/rpc/" # Adds a trailing slash. 9 | needs_undefined_env_var = "${UNDEFINED_RPC_URL_PLACEHOLDER}" 10 | 11 | [fmt] 12 | # These are all the `forge fmt` defaults. 13 | line_length = 120 14 | tab_width = 4 15 | bracket_spacing = false 16 | int_types = 'long' 17 | multiline_func_header = 'attributes_first' 18 | quote_style = 'double' 19 | number_underscore = 'preserve' 20 | single_line_statement_blocks = 'preserve' 21 | ignore = ["src/console.sol", "src/console2.sol"] -------------------------------------------------------------------------------- /lib/forge-std/src/Script.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | // 💬 ABOUT 5 | // Forge Std's default Script. 6 | 7 | // 🧩 MODULES 8 | import {console} from "./console.sol"; 9 | import {console2} from "./console2.sol"; 10 | import {safeconsole} from "./safeconsole.sol"; 11 | import {StdChains} from "./StdChains.sol"; 12 | import {StdCheatsSafe} from "./StdCheats.sol"; 13 | import {stdJson} from "./StdJson.sol"; 14 | import {stdMath} from "./StdMath.sol"; 15 | import {StdStorage, stdStorageSafe} from "./StdStorage.sol"; 16 | import {StdStyle} from "./StdStyle.sol"; 17 | import {StdUtils} from "./StdUtils.sol"; 18 | import {VmSafe} from "./Vm.sol"; 19 | 20 | // 📦 BOILERPLATE 21 | import {ScriptBase} from "./Base.sol"; 22 | 23 | // ⭐️ SCRIPT 24 | abstract contract Script is ScriptBase, StdChains, StdCheatsSafe, StdUtils { 25 | // Note: IS_SCRIPT() must return true. 26 | bool public IS_SCRIPT = true; 27 | } 28 | -------------------------------------------------------------------------------- /lib/forge-std/src/StdError.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Test 3 | pragma solidity >=0.6.2 <0.9.0; 4 | 5 | library stdError { 6 | bytes public constant assertionError = abi.encodeWithSignature("Panic(uint256)", 0x01); 7 | bytes public constant arithmeticError = abi.encodeWithSignature("Panic(uint256)", 0x11); 8 | bytes public constant divisionError = abi.encodeWithSignature("Panic(uint256)", 0x12); 9 | bytes public constant enumConversionError = abi.encodeWithSignature("Panic(uint256)", 0x21); 10 | bytes public constant encodeStorageError = abi.encodeWithSignature("Panic(uint256)", 0x22); 11 | bytes public constant popError = abi.encodeWithSignature("Panic(uint256)", 0x31); 12 | bytes public constant indexOOBError = abi.encodeWithSignature("Panic(uint256)", 0x32); 13 | bytes public constant memOverflowError = abi.encodeWithSignature("Panic(uint256)", 0x41); 14 | bytes public constant zeroVarError = abi.encodeWithSignature("Panic(uint256)", 0x51); 15 | } 16 | -------------------------------------------------------------------------------- /lib/forge-std/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright Contributors to Forge Standard Library 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE O THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE.R 26 | -------------------------------------------------------------------------------- /lib/forge-std/lib/ds-test/.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "Build" 2 | on: 3 | pull_request: 4 | push: 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | - uses: cachix/install-nix-action@v20 11 | with: 12 | nix_path: nixpkgs=channel:nixos-unstable 13 | extra_nix_config: | 14 | access-tokens = github.com=${{ secrets.GITHUB_TOKEN }} 15 | 16 | - name: setup dapp binary cache 17 | uses: cachix/cachix-action@v12 18 | with: 19 | name: dapp 20 | 21 | - name: install dapptools 22 | run: nix profile install github:dapphub/dapptools#dapp --accept-flake-config 23 | 24 | - name: install foundry 25 | uses: foundry-rs/foundry-toolchain@v1 26 | 27 | - name: test with solc-0.5.17 28 | run: dapp --use solc-0.5.17 test -v 29 | 30 | - name: test with solc-0.6.11 31 | run: dapp --use solc-0.6.11 test -v 32 | 33 | - name: test with solc-0.7.6 34 | run: dapp --use solc-0.7.6 test -v 35 | 36 | - name: test with solc-0.8.18 37 | run: dapp --use solc-0.8.18 test -v 38 | 39 | - name: Run tests with foundry 40 | run: forge test -vvv 41 | 42 | -------------------------------------------------------------------------------- /lib/forge-std/src/Test.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | pragma experimental ABIEncoderV2; 5 | 6 | // 💬 ABOUT 7 | // Forge Std's default Test. 8 | 9 | // 🧩 MODULES 10 | import {console} from "./console.sol"; 11 | import {console2} from "./console2.sol"; 12 | import {safeconsole} from "./safeconsole.sol"; 13 | import {StdAssertions} from "./StdAssertions.sol"; 14 | import {StdChains} from "./StdChains.sol"; 15 | import {StdCheats} from "./StdCheats.sol"; 16 | import {stdError} from "./StdError.sol"; 17 | import {StdInvariant} from "./StdInvariant.sol"; 18 | import {stdJson} from "./StdJson.sol"; 19 | import {stdMath} from "./StdMath.sol"; 20 | import {StdStorage, stdStorage} from "./StdStorage.sol"; 21 | import {StdStyle} from "./StdStyle.sol"; 22 | import {StdUtils} from "./StdUtils.sol"; 23 | import {Vm} from "./Vm.sol"; 24 | 25 | // 📦 BOILERPLATE 26 | import {TestBase} from "./Base.sol"; 27 | import {DSTest} from "ds-test/test.sol"; 28 | 29 | // ⭐️ TEST 30 | abstract contract Test is TestBase, DSTest, StdAssertions, StdChains, StdCheats, StdInvariant, StdUtils { 31 | // Note: IS_TEST() must return true. 32 | // Note: Must have failure system, https://github.com/dapphub/ds-test/blob/cd98eff28324bfac652e63a239a60632a761790b/src/test.sol#L39-L76. 33 | } 34 | -------------------------------------------------------------------------------- /lib/forge-std/src/StdMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | library stdMath { 5 | int256 private constant INT256_MIN = -57896044618658097711785492504343953926634992332820282019728792003956564819968; 6 | 7 | function abs(int256 a) internal pure returns (uint256) { 8 | // Required or it will fail when `a = type(int256).min` 9 | if (a == INT256_MIN) { 10 | return 57896044618658097711785492504343953926634992332820282019728792003956564819968; 11 | } 12 | 13 | return uint256(a > 0 ? a : -a); 14 | } 15 | 16 | function delta(uint256 a, uint256 b) internal pure returns (uint256) { 17 | return a > b ? a - b : b - a; 18 | } 19 | 20 | function delta(int256 a, int256 b) internal pure returns (uint256) { 21 | // a and b are of the same sign 22 | // this works thanks to two's complement, the left-most bit is the sign bit 23 | if ((a ^ b) > -1) { 24 | return delta(abs(a), abs(b)); 25 | } 26 | 27 | // a and b are of opposite signs 28 | return abs(a) + abs(b); 29 | } 30 | 31 | function percentDelta(uint256 a, uint256 b) internal pure returns (uint256) { 32 | uint256 absDelta = delta(a, b); 33 | 34 | return absDelta * 1e18 / b; 35 | } 36 | 37 | function percentDelta(int256 a, int256 b) internal pure returns (uint256) { 38 | uint256 absDelta = delta(a, b); 39 | uint256 absB = abs(b); 40 | 41 | return absDelta * 1e18 / absB; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/forge-std/src/Base.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | import {StdStorage} from "./StdStorage.sol"; 5 | import {Vm, VmSafe} from "./Vm.sol"; 6 | 7 | abstract contract CommonBase { 8 | // Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D. 9 | address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code")))); 10 | // console.sol and console2.sol work by executing a staticcall to this address. 11 | address internal constant CONSOLE = 0x000000000000000000636F6e736F6c652e6c6f67; 12 | // Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. 13 | address internal constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; 14 | // Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38. 15 | address internal constant DEFAULT_SENDER = address(uint160(uint256(keccak256("foundry default caller")))); 16 | // Address of the test contract, deployed by the DEFAULT_SENDER. 17 | address internal constant DEFAULT_TEST_CONTRACT = 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f; 18 | // Deterministic deployment address of the Multicall3 contract. 19 | address internal constant MULTICALL3_ADDRESS = 0xcA11bde05977b3631167028862bE2a173976CA11; 20 | // The order of the secp256k1 curve. 21 | uint256 internal constant SECP256K1_ORDER = 22 | 115792089237316195423570985008687907852837564279074904382605163141518161494337; 23 | 24 | uint256 internal constant UINT256_MAX = 25 | 115792089237316195423570985008687907853269984665640564039457584007913129639935; 26 | 27 | Vm internal constant vm = Vm(VM_ADDRESS); 28 | StdStorage internal stdstore; 29 | } 30 | 31 | abstract contract TestBase is CommonBase {} 32 | 33 | abstract contract ScriptBase is CommonBase { 34 | VmSafe internal constant vmSafe = VmSafe(VM_ADDRESS); 35 | } 36 | -------------------------------------------------------------------------------- /lib/forge-std/src/interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2; 3 | 4 | /// @dev Interface of the ERC20 standard as defined in the EIP. 5 | /// @dev This includes the optional name, symbol, and decimals metadata. 6 | interface IERC20 { 7 | /// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`). 8 | event Transfer(address indexed from, address indexed to, uint256 value); 9 | 10 | /// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value` 11 | /// is the new allowance. 12 | event Approval(address indexed owner, address indexed spender, uint256 value); 13 | 14 | /// @notice Returns the amount of tokens in existence. 15 | function totalSupply() external view returns (uint256); 16 | 17 | /// @notice Returns the amount of tokens owned by `account`. 18 | function balanceOf(address account) external view returns (uint256); 19 | 20 | /// @notice Moves `amount` tokens from the caller's account to `to`. 21 | function transfer(address to, uint256 amount) external returns (bool); 22 | 23 | /// @notice Returns the remaining number of tokens that `spender` is allowed 24 | /// to spend on behalf of `owner` 25 | function allowance(address owner, address spender) external view returns (uint256); 26 | 27 | /// @notice Sets `amount` as the allowance of `spender` over the caller's tokens. 28 | /// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 29 | function approve(address spender, uint256 amount) external returns (bool); 30 | 31 | /// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism. 32 | /// `amount` is then deducted from the caller's allowance. 33 | function transferFrom(address from, address to, uint256 amount) external returns (bool); 34 | 35 | /// @notice Returns the name of the token. 36 | function name() external view returns (string memory); 37 | 38 | /// @notice Returns the symbol of the token. 39 | function symbol() external view returns (string memory); 40 | 41 | /// @notice Returns the decimals places of the token. 42 | function decimals() external view returns (uint8); 43 | } 44 | -------------------------------------------------------------------------------- /lib/forge-std/src/interfaces/IMulticall3.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | pragma experimental ABIEncoderV2; 5 | 6 | interface IMulticall3 { 7 | struct Call { 8 | address target; 9 | bytes callData; 10 | } 11 | 12 | struct Call3 { 13 | address target; 14 | bool allowFailure; 15 | bytes callData; 16 | } 17 | 18 | struct Call3Value { 19 | address target; 20 | bool allowFailure; 21 | uint256 value; 22 | bytes callData; 23 | } 24 | 25 | struct Result { 26 | bool success; 27 | bytes returnData; 28 | } 29 | 30 | function aggregate(Call[] calldata calls) 31 | external 32 | payable 33 | returns (uint256 blockNumber, bytes[] memory returnData); 34 | 35 | function aggregate3(Call3[] calldata calls) external payable returns (Result[] memory returnData); 36 | 37 | function aggregate3Value(Call3Value[] calldata calls) external payable returns (Result[] memory returnData); 38 | 39 | function blockAndAggregate(Call[] calldata calls) 40 | external 41 | payable 42 | returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); 43 | 44 | function getBasefee() external view returns (uint256 basefee); 45 | 46 | function getBlockHash(uint256 blockNumber) external view returns (bytes32 blockHash); 47 | 48 | function getBlockNumber() external view returns (uint256 blockNumber); 49 | 50 | function getChainId() external view returns (uint256 chainid); 51 | 52 | function getCurrentBlockCoinbase() external view returns (address coinbase); 53 | 54 | function getCurrentBlockDifficulty() external view returns (uint256 difficulty); 55 | 56 | function getCurrentBlockGasLimit() external view returns (uint256 gaslimit); 57 | 58 | function getCurrentBlockTimestamp() external view returns (uint256 timestamp); 59 | 60 | function getEthBalance(address addr) external view returns (uint256 balance); 61 | 62 | function getLastBlockHash() external view returns (bytes32 blockHash); 63 | 64 | function tryAggregate(bool requireSuccess, Call[] calldata calls) 65 | external 66 | payable 67 | returns (Result[] memory returnData); 68 | 69 | function tryBlockAndAggregate(bool requireSuccess, Call[] calldata calls) 70 | external 71 | payable 72 | returns (uint256 blockNumber, bytes32 blockHash, Result[] memory returnData); 73 | } 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NOTICE 2 | 3 | This repository has been deprecated, ongoing efforts on ERC404 have moved [here](https://github.com/Pandora-Labs-Org/erc404). 4 | 5 | # ERC404 6 | 7 | ERC404 is an experimental, mixed ERC20 / ERC721 implementation with native liquidity and fractionalization. While these two standards are not designed to be mixed, this implementation strives to do so in as robust a manner as possible while minimizing tradeoffs. 8 | 9 | In it's current implementation, ERC404 effectively isolates ERC20 / ERC721 standard logic or introduces pathing where possible. Pathing could best be described as a lossy encoding scheme in which token amount data and ids occupy shared space under the assumption that negligible token transfers occupying id space do not or do not need to occur. 10 | 11 | This standard is entirely experimental and unaudited, while testing has been conducted in an effort to ensure execution is as accurate as possible. The nature of overlapping standards, however, does imply that integrating protocols will not fully understand their mixed function. 12 | 13 | ## ERC721 Notes 14 | 15 | The ERC721 implementation here is a bit non-standard, where tokens are instead burned and minted repeatedly as per underlying / fractional transfers. This is a aspect of the concept's design is deliberate, with the goal of creating an NFT that has native fractionalization, liquidity and encourages some aspects of trading / engagement to farm unique trait sets. 16 | 17 | ## Licensing 18 | 19 | This software is released under the MIT License. 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /lib/forge-std/test/StdError.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0 <0.9.0; 3 | 4 | import "../src/StdError.sol"; 5 | import "../src/Test.sol"; 6 | 7 | contract StdErrorsTest is Test { 8 | ErrorsTest test; 9 | 10 | function setUp() public { 11 | test = new ErrorsTest(); 12 | } 13 | 14 | function test_ExpectAssertion() public { 15 | vm.expectRevert(stdError.assertionError); 16 | test.assertionError(); 17 | } 18 | 19 | function test_ExpectArithmetic() public { 20 | vm.expectRevert(stdError.arithmeticError); 21 | test.arithmeticError(10); 22 | } 23 | 24 | function test_ExpectDiv() public { 25 | vm.expectRevert(stdError.divisionError); 26 | test.divError(0); 27 | } 28 | 29 | function test_ExpectMod() public { 30 | vm.expectRevert(stdError.divisionError); 31 | test.modError(0); 32 | } 33 | 34 | function test_ExpectEnum() public { 35 | vm.expectRevert(stdError.enumConversionError); 36 | test.enumConversion(1); 37 | } 38 | 39 | function test_ExpectEncodeStg() public { 40 | vm.expectRevert(stdError.encodeStorageError); 41 | test.encodeStgError(); 42 | } 43 | 44 | function test_ExpectPop() public { 45 | vm.expectRevert(stdError.popError); 46 | test.pop(); 47 | } 48 | 49 | function test_ExpectOOB() public { 50 | vm.expectRevert(stdError.indexOOBError); 51 | test.indexOOBError(1); 52 | } 53 | 54 | function test_ExpectMem() public { 55 | vm.expectRevert(stdError.memOverflowError); 56 | test.mem(); 57 | } 58 | 59 | function test_ExpectIntern() public { 60 | vm.expectRevert(stdError.zeroVarError); 61 | test.intern(); 62 | } 63 | } 64 | 65 | contract ErrorsTest { 66 | enum T { 67 | T1 68 | } 69 | 70 | uint256[] public someArr; 71 | bytes someBytes; 72 | 73 | function assertionError() public pure { 74 | assert(false); 75 | } 76 | 77 | function arithmeticError(uint256 a) public pure { 78 | a -= 100; 79 | } 80 | 81 | function divError(uint256 a) public pure { 82 | 100 / a; 83 | } 84 | 85 | function modError(uint256 a) public pure { 86 | 100 % a; 87 | } 88 | 89 | function enumConversion(uint256 a) public pure { 90 | T(a); 91 | } 92 | 93 | function encodeStgError() public { 94 | /// @solidity memory-safe-assembly 95 | assembly { 96 | sstore(someBytes.slot, 1) 97 | } 98 | keccak256(someBytes); 99 | } 100 | 101 | function pop() public { 102 | someArr.pop(); 103 | } 104 | 105 | function indexOOBError(uint256 a) public pure { 106 | uint256[] memory t = new uint256[](0); 107 | t[a]; 108 | } 109 | 110 | function mem() public pure { 111 | uint256 l = 2 ** 256 / 32; 112 | new uint256[](l); 113 | } 114 | 115 | function intern() public returns (uint256) { 116 | function(uint256) internal returns (uint256) x; 117 | x(2); 118 | return 7; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /lib/forge-std/src/StdInvariant.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | pragma experimental ABIEncoderV2; 5 | 6 | abstract contract StdInvariant { 7 | struct FuzzSelector { 8 | address addr; 9 | bytes4[] selectors; 10 | } 11 | 12 | struct FuzzInterface { 13 | address addr; 14 | string[] artifacts; 15 | } 16 | 17 | address[] private _excludedContracts; 18 | address[] private _excludedSenders; 19 | address[] private _targetedContracts; 20 | address[] private _targetedSenders; 21 | 22 | string[] private _excludedArtifacts; 23 | string[] private _targetedArtifacts; 24 | 25 | FuzzSelector[] private _targetedArtifactSelectors; 26 | FuzzSelector[] private _targetedSelectors; 27 | 28 | FuzzInterface[] private _targetedInterfaces; 29 | 30 | // Functions for users: 31 | // These are intended to be called in tests. 32 | 33 | function excludeContract(address newExcludedContract_) internal { 34 | _excludedContracts.push(newExcludedContract_); 35 | } 36 | 37 | function excludeSender(address newExcludedSender_) internal { 38 | _excludedSenders.push(newExcludedSender_); 39 | } 40 | 41 | function excludeArtifact(string memory newExcludedArtifact_) internal { 42 | _excludedArtifacts.push(newExcludedArtifact_); 43 | } 44 | 45 | function targetArtifact(string memory newTargetedArtifact_) internal { 46 | _targetedArtifacts.push(newTargetedArtifact_); 47 | } 48 | 49 | function targetArtifactSelector(FuzzSelector memory newTargetedArtifactSelector_) internal { 50 | _targetedArtifactSelectors.push(newTargetedArtifactSelector_); 51 | } 52 | 53 | function targetContract(address newTargetedContract_) internal { 54 | _targetedContracts.push(newTargetedContract_); 55 | } 56 | 57 | function targetSelector(FuzzSelector memory newTargetedSelector_) internal { 58 | _targetedSelectors.push(newTargetedSelector_); 59 | } 60 | 61 | function targetSender(address newTargetedSender_) internal { 62 | _targetedSenders.push(newTargetedSender_); 63 | } 64 | 65 | function targetInterface(FuzzInterface memory newTargetedInterface_) internal { 66 | _targetedInterfaces.push(newTargetedInterface_); 67 | } 68 | 69 | // Functions for forge: 70 | // These are called by forge to run invariant tests and don't need to be called in tests. 71 | 72 | function excludeArtifacts() public view returns (string[] memory excludedArtifacts_) { 73 | excludedArtifacts_ = _excludedArtifacts; 74 | } 75 | 76 | function excludeContracts() public view returns (address[] memory excludedContracts_) { 77 | excludedContracts_ = _excludedContracts; 78 | } 79 | 80 | function excludeSenders() public view returns (address[] memory excludedSenders_) { 81 | excludedSenders_ = _excludedSenders; 82 | } 83 | 84 | function targetArtifacts() public view returns (string[] memory targetedArtifacts_) { 85 | targetedArtifacts_ = _targetedArtifacts; 86 | } 87 | 88 | function targetArtifactSelectors() public view returns (FuzzSelector[] memory targetedArtifactSelectors_) { 89 | targetedArtifactSelectors_ = _targetedArtifactSelectors; 90 | } 91 | 92 | function targetContracts() public view returns (address[] memory targetedContracts_) { 93 | targetedContracts_ = _targetedContracts; 94 | } 95 | 96 | function targetSelectors() public view returns (FuzzSelector[] memory targetedSelectors_) { 97 | targetedSelectors_ = _targetedSelectors; 98 | } 99 | 100 | function targetSenders() public view returns (address[] memory targetedSenders_) { 101 | targetedSenders_ = _targetedSenders; 102 | } 103 | 104 | function targetInterfaces() public view returns (FuzzInterface[] memory targetedInterfaces_) { 105 | targetedInterfaces_ = _targetedInterfaces; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /lib/forge-std/.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | push: 7 | branches: 8 | - master 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v3 15 | 16 | - name: Install Foundry 17 | uses: onbjerg/foundry-toolchain@v1 18 | with: 19 | version: nightly 20 | 21 | - name: Print forge version 22 | run: forge --version 23 | 24 | # Backwards compatibility checks: 25 | # - the oldest and newest version of each supported minor version 26 | # - versions with specific issues 27 | - name: Check compatibility with latest 28 | if: always() 29 | run: | 30 | output=$(forge build --skip test) 31 | 32 | if echo "$output" | grep -q "Warning"; then 33 | echo "$output" 34 | exit 1 35 | fi 36 | 37 | - name: Check compatibility with 0.8.0 38 | if: always() 39 | run: | 40 | output=$(forge build --skip test --use solc:0.8.0) 41 | 42 | if echo "$output" | grep -q "Warning"; then 43 | echo "$output" 44 | exit 1 45 | fi 46 | 47 | - name: Check compatibility with 0.7.6 48 | if: always() 49 | run: | 50 | output=$(forge build --skip test --use solc:0.7.6) 51 | 52 | if echo "$output" | grep -q "Warning"; then 53 | echo "$output" 54 | exit 1 55 | fi 56 | 57 | - name: Check compatibility with 0.7.0 58 | if: always() 59 | run: | 60 | output=$(forge build --skip test --use solc:0.7.0) 61 | 62 | if echo "$output" | grep -q "Warning"; then 63 | echo "$output" 64 | exit 1 65 | fi 66 | 67 | - name: Check compatibility with 0.6.12 68 | if: always() 69 | run: | 70 | output=$(forge build --skip test --use solc:0.6.12) 71 | 72 | if echo "$output" | grep -q "Warning"; then 73 | echo "$output" 74 | exit 1 75 | fi 76 | 77 | - name: Check compatibility with 0.6.2 78 | if: always() 79 | run: | 80 | output=$(forge build --skip test --use solc:0.6.2) 81 | 82 | if echo "$output" | grep -q "Warning"; then 83 | echo "$output" 84 | exit 1 85 | fi 86 | 87 | # via-ir compilation time checks. 88 | - name: Measure compilation time of Test with 0.8.17 --via-ir 89 | if: always() 90 | run: forge build --skip test --contracts test/compilation/CompilationTest.sol --use solc:0.8.17 --via-ir 91 | 92 | - name: Measure compilation time of TestBase with 0.8.17 --via-ir 93 | if: always() 94 | run: forge build --skip test --contracts test/compilation/CompilationTestBase.sol --use solc:0.8.17 --via-ir 95 | 96 | - name: Measure compilation time of Script with 0.8.17 --via-ir 97 | if: always() 98 | run: forge build --skip test --contracts test/compilation/CompilationScript.sol --use solc:0.8.17 --via-ir 99 | 100 | - name: Measure compilation time of ScriptBase with 0.8.17 --via-ir 101 | if: always() 102 | run: forge build --skip test --contracts test/compilation/CompilationScriptBase.sol --use solc:0.8.17 --via-ir 103 | 104 | test: 105 | runs-on: ubuntu-latest 106 | steps: 107 | - uses: actions/checkout@v3 108 | 109 | - name: Install Foundry 110 | uses: onbjerg/foundry-toolchain@v1 111 | with: 112 | version: nightly 113 | 114 | - name: Print forge version 115 | run: forge --version 116 | 117 | - name: Run tests 118 | run: forge test -vvv 119 | 120 | fmt: 121 | runs-on: ubuntu-latest 122 | steps: 123 | - uses: actions/checkout@v3 124 | 125 | - name: Install Foundry 126 | uses: onbjerg/foundry-toolchain@v1 127 | with: 128 | version: nightly 129 | 130 | - name: Print forge version 131 | run: forge --version 132 | 133 | - name: Check formatting 134 | run: forge fmt --check 135 | -------------------------------------------------------------------------------- /lib/forge-std/test/StdStyle.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.7.0 <0.9.0; 3 | 4 | import "../src/Test.sol"; 5 | 6 | contract StdStyleTest is Test { 7 | function test_StyleColor() public pure { 8 | console2.log(StdStyle.red("StdStyle.red String Test")); 9 | console2.log(StdStyle.red(uint256(10e18))); 10 | console2.log(StdStyle.red(int256(-10e18))); 11 | console2.log(StdStyle.red(true)); 12 | console2.log(StdStyle.red(address(0))); 13 | console2.log(StdStyle.redBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D")); 14 | console2.log(StdStyle.redBytes32("StdStyle.redBytes32")); 15 | console2.log(StdStyle.green("StdStyle.green String Test")); 16 | console2.log(StdStyle.green(uint256(10e18))); 17 | console2.log(StdStyle.green(int256(-10e18))); 18 | console2.log(StdStyle.green(true)); 19 | console2.log(StdStyle.green(address(0))); 20 | console2.log(StdStyle.greenBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D")); 21 | console2.log(StdStyle.greenBytes32("StdStyle.greenBytes32")); 22 | console2.log(StdStyle.yellow("StdStyle.yellow String Test")); 23 | console2.log(StdStyle.yellow(uint256(10e18))); 24 | console2.log(StdStyle.yellow(int256(-10e18))); 25 | console2.log(StdStyle.yellow(true)); 26 | console2.log(StdStyle.yellow(address(0))); 27 | console2.log(StdStyle.yellowBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D")); 28 | console2.log(StdStyle.yellowBytes32("StdStyle.yellowBytes32")); 29 | console2.log(StdStyle.blue("StdStyle.blue String Test")); 30 | console2.log(StdStyle.blue(uint256(10e18))); 31 | console2.log(StdStyle.blue(int256(-10e18))); 32 | console2.log(StdStyle.blue(true)); 33 | console2.log(StdStyle.blue(address(0))); 34 | console2.log(StdStyle.blueBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D")); 35 | console2.log(StdStyle.blueBytes32("StdStyle.blueBytes32")); 36 | console2.log(StdStyle.magenta("StdStyle.magenta String Test")); 37 | console2.log(StdStyle.magenta(uint256(10e18))); 38 | console2.log(StdStyle.magenta(int256(-10e18))); 39 | console2.log(StdStyle.magenta(true)); 40 | console2.log(StdStyle.magenta(address(0))); 41 | console2.log(StdStyle.magentaBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D")); 42 | console2.log(StdStyle.magentaBytes32("StdStyle.magentaBytes32")); 43 | console2.log(StdStyle.cyan("StdStyle.cyan String Test")); 44 | console2.log(StdStyle.cyan(uint256(10e18))); 45 | console2.log(StdStyle.cyan(int256(-10e18))); 46 | console2.log(StdStyle.cyan(true)); 47 | console2.log(StdStyle.cyan(address(0))); 48 | console2.log(StdStyle.cyanBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D")); 49 | console2.log(StdStyle.cyanBytes32("StdStyle.cyanBytes32")); 50 | } 51 | 52 | function test_StyleFontWeight() public pure { 53 | console2.log(StdStyle.bold("StdStyle.bold String Test")); 54 | console2.log(StdStyle.bold(uint256(10e18))); 55 | console2.log(StdStyle.bold(int256(-10e18))); 56 | console2.log(StdStyle.bold(address(0))); 57 | console2.log(StdStyle.bold(true)); 58 | console2.log(StdStyle.boldBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D")); 59 | console2.log(StdStyle.boldBytes32("StdStyle.boldBytes32")); 60 | console2.log(StdStyle.dim("StdStyle.dim String Test")); 61 | console2.log(StdStyle.dim(uint256(10e18))); 62 | console2.log(StdStyle.dim(int256(-10e18))); 63 | console2.log(StdStyle.dim(address(0))); 64 | console2.log(StdStyle.dim(true)); 65 | console2.log(StdStyle.dimBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D")); 66 | console2.log(StdStyle.dimBytes32("StdStyle.dimBytes32")); 67 | console2.log(StdStyle.italic("StdStyle.italic String Test")); 68 | console2.log(StdStyle.italic(uint256(10e18))); 69 | console2.log(StdStyle.italic(int256(-10e18))); 70 | console2.log(StdStyle.italic(address(0))); 71 | console2.log(StdStyle.italic(true)); 72 | console2.log(StdStyle.italicBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D")); 73 | console2.log(StdStyle.italicBytes32("StdStyle.italicBytes32")); 74 | console2.log(StdStyle.underline("StdStyle.underline String Test")); 75 | console2.log(StdStyle.underline(uint256(10e18))); 76 | console2.log(StdStyle.underline(int256(-10e18))); 77 | console2.log(StdStyle.underline(address(0))); 78 | console2.log(StdStyle.underline(true)); 79 | console2.log(StdStyle.underlineBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D")); 80 | console2.log(StdStyle.underlineBytes32("StdStyle.underlineBytes32")); 81 | console2.log(StdStyle.inverse("StdStyle.inverse String Test")); 82 | console2.log(StdStyle.inverse(uint256(10e18))); 83 | console2.log(StdStyle.inverse(int256(-10e18))); 84 | console2.log(StdStyle.inverse(address(0))); 85 | console2.log(StdStyle.inverse(true)); 86 | console2.log(StdStyle.inverseBytes(hex"7109709ECfa91a80626fF3989D68f67F5b1DD12D")); 87 | console2.log(StdStyle.inverseBytes32("StdStyle.inverseBytes32")); 88 | } 89 | 90 | function test_StyleCombined() public pure { 91 | console2.log(StdStyle.red(StdStyle.bold("Red Bold String Test"))); 92 | console2.log(StdStyle.green(StdStyle.dim(uint256(10e18)))); 93 | console2.log(StdStyle.yellow(StdStyle.italic(int256(-10e18)))); 94 | console2.log(StdStyle.blue(StdStyle.underline(address(0)))); 95 | console2.log(StdStyle.magenta(StdStyle.inverse(true))); 96 | } 97 | 98 | function test_StyleCustom() public pure { 99 | console2.log(h1("Custom Style 1")); 100 | console2.log(h2("Custom Style 2")); 101 | } 102 | 103 | function h1(string memory a) private pure returns (string memory) { 104 | return StdStyle.cyan(StdStyle.inverse(StdStyle.bold(a))); 105 | } 106 | 107 | function h2(string memory a) private pure returns (string memory) { 108 | return StdStyle.magenta(StdStyle.bold(StdStyle.underline(a))); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /lib/forge-std/src/StdJson.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.0 <0.9.0; 3 | 4 | pragma experimental ABIEncoderV2; 5 | 6 | import {VmSafe} from "./Vm.sol"; 7 | 8 | // Helpers for parsing and writing JSON files 9 | // To parse: 10 | // ``` 11 | // using stdJson for string; 12 | // string memory json = vm.readFile("some_peth"); 13 | // json.parseUint(""); 14 | // ``` 15 | // To write: 16 | // ``` 17 | // using stdJson for string; 18 | // string memory json = "deploymentArtifact"; 19 | // Contract contract = new Contract(); 20 | // json.serialize("contractAddress", address(contract)); 21 | // json = json.serialize("deploymentTimes", uint(1)); 22 | // // store the stringified JSON to the 'json' variable we have been using as a key 23 | // // as we won't need it any longer 24 | // string memory json2 = "finalArtifact"; 25 | // string memory final = json2.serialize("depArtifact", json); 26 | // final.write(""); 27 | // ``` 28 | 29 | library stdJson { 30 | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); 31 | 32 | function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) { 33 | return vm.parseJson(json, key); 34 | } 35 | 36 | function readUint(string memory json, string memory key) internal pure returns (uint256) { 37 | return vm.parseJsonUint(json, key); 38 | } 39 | 40 | function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) { 41 | return vm.parseJsonUintArray(json, key); 42 | } 43 | 44 | function readInt(string memory json, string memory key) internal pure returns (int256) { 45 | return vm.parseJsonInt(json, key); 46 | } 47 | 48 | function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) { 49 | return vm.parseJsonIntArray(json, key); 50 | } 51 | 52 | function readBytes32(string memory json, string memory key) internal pure returns (bytes32) { 53 | return vm.parseJsonBytes32(json, key); 54 | } 55 | 56 | function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) { 57 | return vm.parseJsonBytes32Array(json, key); 58 | } 59 | 60 | function readString(string memory json, string memory key) internal pure returns (string memory) { 61 | return vm.parseJsonString(json, key); 62 | } 63 | 64 | function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) { 65 | return vm.parseJsonStringArray(json, key); 66 | } 67 | 68 | function readAddress(string memory json, string memory key) internal pure returns (address) { 69 | return vm.parseJsonAddress(json, key); 70 | } 71 | 72 | function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) { 73 | return vm.parseJsonAddressArray(json, key); 74 | } 75 | 76 | function readBool(string memory json, string memory key) internal pure returns (bool) { 77 | return vm.parseJsonBool(json, key); 78 | } 79 | 80 | function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) { 81 | return vm.parseJsonBoolArray(json, key); 82 | } 83 | 84 | function readBytes(string memory json, string memory key) internal pure returns (bytes memory) { 85 | return vm.parseJsonBytes(json, key); 86 | } 87 | 88 | function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) { 89 | return vm.parseJsonBytesArray(json, key); 90 | } 91 | 92 | function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { 93 | return vm.serializeJson(jsonKey, rootObject); 94 | } 95 | 96 | function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { 97 | return vm.serializeBool(jsonKey, key, value); 98 | } 99 | 100 | function serialize(string memory jsonKey, string memory key, bool[] memory value) 101 | internal 102 | returns (string memory) 103 | { 104 | return vm.serializeBool(jsonKey, key, value); 105 | } 106 | 107 | function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { 108 | return vm.serializeUint(jsonKey, key, value); 109 | } 110 | 111 | function serialize(string memory jsonKey, string memory key, uint256[] memory value) 112 | internal 113 | returns (string memory) 114 | { 115 | return vm.serializeUint(jsonKey, key, value); 116 | } 117 | 118 | function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { 119 | return vm.serializeInt(jsonKey, key, value); 120 | } 121 | 122 | function serialize(string memory jsonKey, string memory key, int256[] memory value) 123 | internal 124 | returns (string memory) 125 | { 126 | return vm.serializeInt(jsonKey, key, value); 127 | } 128 | 129 | function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { 130 | return vm.serializeAddress(jsonKey, key, value); 131 | } 132 | 133 | function serialize(string memory jsonKey, string memory key, address[] memory value) 134 | internal 135 | returns (string memory) 136 | { 137 | return vm.serializeAddress(jsonKey, key, value); 138 | } 139 | 140 | function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { 141 | return vm.serializeBytes32(jsonKey, key, value); 142 | } 143 | 144 | function serialize(string memory jsonKey, string memory key, bytes32[] memory value) 145 | internal 146 | returns (string memory) 147 | { 148 | return vm.serializeBytes32(jsonKey, key, value); 149 | } 150 | 151 | function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { 152 | return vm.serializeBytes(jsonKey, key, value); 153 | } 154 | 155 | function serialize(string memory jsonKey, string memory key, bytes[] memory value) 156 | internal 157 | returns (string memory) 158 | { 159 | return vm.serializeBytes(jsonKey, key, value); 160 | } 161 | 162 | function serialize(string memory jsonKey, string memory key, string memory value) 163 | internal 164 | returns (string memory) 165 | { 166 | return vm.serializeString(jsonKey, key, value); 167 | } 168 | 169 | function serialize(string memory jsonKey, string memory key, string[] memory value) 170 | internal 171 | returns (string memory) 172 | { 173 | return vm.serializeString(jsonKey, key, value); 174 | } 175 | 176 | function write(string memory jsonKey, string memory path) internal { 177 | vm.writeJson(jsonKey, path); 178 | } 179 | 180 | function write(string memory jsonKey, string memory path, string memory valueKey) internal { 181 | vm.writeJson(jsonKey, path, valueKey); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /lib/forge-std/src/interfaces/IERC1155.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2; 3 | 4 | import "./IERC165.sol"; 5 | 6 | /// @title ERC-1155 Multi Token Standard 7 | /// @dev See https://eips.ethereum.org/EIPS/eip-1155 8 | /// Note: The ERC-165 identifier for this interface is 0xd9b67a26. 9 | interface IERC1155 is IERC165 { 10 | /// @dev 11 | /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). 12 | /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender). 13 | /// - The `_from` argument MUST be the address of the holder whose balance is decreased. 14 | /// - The `_to` argument MUST be the address of the recipient whose balance is increased. 15 | /// - The `_id` argument MUST be the token type being transferred. 16 | /// - The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by. 17 | /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). 18 | /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). 19 | event TransferSingle( 20 | address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value 21 | ); 22 | 23 | /// @dev 24 | /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). 25 | /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender). 26 | /// - The `_from` argument MUST be the address of the holder whose balance is decreased. 27 | /// - The `_to` argument MUST be the address of the recipient whose balance is increased. 28 | /// - The `_ids` argument MUST be the list of tokens being transferred. 29 | /// - The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in _ids) the holder balance is decreased by and match what the recipient balance is increased by. 30 | /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). 31 | /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). 32 | event TransferBatch( 33 | address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values 34 | ); 35 | 36 | /// @dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absence of an event assumes disabled). 37 | event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); 38 | 39 | /// @dev MUST emit when the URI is updated for a token ID. URIs are defined in RFC 3986. 40 | /// The URI MUST point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema". 41 | event URI(string _value, uint256 indexed _id); 42 | 43 | /// @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call). 44 | /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard). 45 | /// - MUST revert if `_to` is the zero address. 46 | /// - MUST revert if balance of holder for token `_id` is lower than the `_value` sent. 47 | /// - MUST revert on any other error. 48 | /// - MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard). 49 | /// - After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). 50 | /// @param _from Source address 51 | /// @param _to Target address 52 | /// @param _id ID of the token type 53 | /// @param _value Transfer amount 54 | /// @param _data Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to` 55 | function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external; 56 | 57 | /// @notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call). 58 | /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard). 59 | /// - MUST revert if `_to` is the zero address. 60 | /// - MUST revert if length of `_ids` is not the same as length of `_values`. 61 | /// - MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient. 62 | /// - MUST revert on any other error. 63 | /// - MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard). 64 | /// - Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc). 65 | /// - After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). 66 | /// @param _from Source address 67 | /// @param _to Target address 68 | /// @param _ids IDs of each token type (order and length must match _values array) 69 | /// @param _values Transfer amounts per token type (order and length must match _ids array) 70 | /// @param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to` 71 | function safeBatchTransferFrom( 72 | address _from, 73 | address _to, 74 | uint256[] calldata _ids, 75 | uint256[] calldata _values, 76 | bytes calldata _data 77 | ) external; 78 | 79 | /// @notice Get the balance of an account's tokens. 80 | /// @param _owner The address of the token holder 81 | /// @param _id ID of the token 82 | /// @return The _owner's balance of the token type requested 83 | function balanceOf(address _owner, uint256 _id) external view returns (uint256); 84 | 85 | /// @notice Get the balance of multiple account/token pairs 86 | /// @param _owners The addresses of the token holders 87 | /// @param _ids ID of the tokens 88 | /// @return The _owner's balance of the token types requested (i.e. balance for each (owner, id) pair) 89 | function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) 90 | external 91 | view 92 | returns (uint256[] memory); 93 | 94 | /// @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens. 95 | /// @dev MUST emit the ApprovalForAll event on success. 96 | /// @param _operator Address to add to the set of authorized operators 97 | /// @param _approved True if the operator is approved, false to revoke approval 98 | function setApprovalForAll(address _operator, bool _approved) external; 99 | 100 | /// @notice Queries the approval status of an operator for a given owner. 101 | /// @param _owner The owner of the tokens 102 | /// @param _operator Address of authorized operator 103 | /// @return True if the operator is approved, false if not 104 | function isApprovedForAll(address _owner, address _operator) external view returns (bool); 105 | } 106 | -------------------------------------------------------------------------------- /lib/forge-std/lib/ds-test/demo/demo.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import "../src/test.sol"; 5 | 6 | contract DemoTest is DSTest { 7 | function test_this() public pure { 8 | require(true); 9 | } 10 | function test_logs() public { 11 | emit log("-- log(string)"); 12 | emit log("a string"); 13 | 14 | emit log("-- log_named_uint(string, uint)"); 15 | emit log_named_uint("uint", 512); 16 | 17 | emit log("-- log_named_int(string, int)"); 18 | emit log_named_int("int", -512); 19 | 20 | emit log("-- log_named_address(string, address)"); 21 | emit log_named_address("address", address(this)); 22 | 23 | emit log("-- log_named_bytes32(string, bytes32)"); 24 | emit log_named_bytes32("bytes32", "a string"); 25 | 26 | emit log("-- log_named_bytes(string, bytes)"); 27 | emit log_named_bytes("bytes", hex"cafefe"); 28 | 29 | emit log("-- log_named_string(string, string)"); 30 | emit log_named_string("string", "a string"); 31 | 32 | emit log("-- log_named_decimal_uint(string, uint, uint)"); 33 | emit log_named_decimal_uint("decimal uint", 1.0e18, 18); 34 | 35 | emit log("-- log_named_decimal_int(string, int, uint)"); 36 | emit log_named_decimal_int("decimal int", -1.0e18, 18); 37 | } 38 | event log_old_named_uint(bytes32,uint); 39 | function test_old_logs() public { 40 | emit log_old_named_uint("key", 500); 41 | emit log_named_bytes32("bkey", "val"); 42 | } 43 | function test_trace() public view { 44 | this.echo("string 1", "string 2"); 45 | } 46 | function test_multiline() public { 47 | emit log("a multiline\\nstring"); 48 | emit log("a multiline string"); 49 | emit log_bytes("a string"); 50 | emit log_bytes("a multiline\nstring"); 51 | emit log_bytes("a multiline\\nstring"); 52 | emit logs(hex"0000"); 53 | emit log_named_bytes("0x0000", hex"0000"); 54 | emit logs(hex"ff"); 55 | } 56 | function echo(string memory s1, string memory s2) public pure 57 | returns (string memory, string memory) 58 | { 59 | return (s1, s2); 60 | } 61 | 62 | function prove_this(uint x) public { 63 | emit log_named_uint("sym x", x); 64 | assertGt(x + 1, 0); 65 | } 66 | 67 | function test_logn() public { 68 | assembly { 69 | log0(0x01, 0x02) 70 | log1(0x01, 0x02, 0x03) 71 | log2(0x01, 0x02, 0x03, 0x04) 72 | log3(0x01, 0x02, 0x03, 0x04, 0x05) 73 | } 74 | } 75 | 76 | event MyEvent(uint, uint indexed, uint, uint indexed); 77 | function test_events() public { 78 | emit MyEvent(1, 2, 3, 4); 79 | } 80 | 81 | function test_asserts() public { 82 | string memory err = "this test has failed!"; 83 | emit log("## assertTrue(bool)\n"); 84 | assertTrue(false); 85 | emit log("\n"); 86 | assertTrue(false, err); 87 | 88 | emit log("\n## assertEq(address,address)\n"); 89 | assertEq(address(this), msg.sender); 90 | emit log("\n"); 91 | assertEq(address(this), msg.sender, err); 92 | 93 | emit log("\n## assertEq32(bytes32,bytes32)\n"); 94 | assertEq32("bytes 1", "bytes 2"); 95 | emit log("\n"); 96 | assertEq32("bytes 1", "bytes 2", err); 97 | 98 | emit log("\n## assertEq(bytes32,bytes32)\n"); 99 | assertEq32("bytes 1", "bytes 2"); 100 | emit log("\n"); 101 | assertEq32("bytes 1", "bytes 2", err); 102 | 103 | emit log("\n## assertEq(uint,uint)\n"); 104 | assertEq(uint(0), 1); 105 | emit log("\n"); 106 | assertEq(uint(0), 1, err); 107 | 108 | emit log("\n## assertEq(int,int)\n"); 109 | assertEq(-1, -2); 110 | emit log("\n"); 111 | assertEq(-1, -2, err); 112 | 113 | emit log("\n## assertEqDecimal(int,int,uint)\n"); 114 | assertEqDecimal(-1.0e18, -1.1e18, 18); 115 | emit log("\n"); 116 | assertEqDecimal(-1.0e18, -1.1e18, 18, err); 117 | 118 | emit log("\n## assertEqDecimal(uint,uint,uint)\n"); 119 | assertEqDecimal(uint(1.0e18), 1.1e18, 18); 120 | emit log("\n"); 121 | assertEqDecimal(uint(1.0e18), 1.1e18, 18, err); 122 | 123 | emit log("\n## assertGt(uint,uint)\n"); 124 | assertGt(uint(0), 0); 125 | emit log("\n"); 126 | assertGt(uint(0), 0, err); 127 | 128 | emit log("\n## assertGt(int,int)\n"); 129 | assertGt(-1, -1); 130 | emit log("\n"); 131 | assertGt(-1, -1, err); 132 | 133 | emit log("\n## assertGtDecimal(int,int,uint)\n"); 134 | assertGtDecimal(-2.0e18, -1.1e18, 18); 135 | emit log("\n"); 136 | assertGtDecimal(-2.0e18, -1.1e18, 18, err); 137 | 138 | emit log("\n## assertGtDecimal(uint,uint,uint)\n"); 139 | assertGtDecimal(uint(1.0e18), 1.1e18, 18); 140 | emit log("\n"); 141 | assertGtDecimal(uint(1.0e18), 1.1e18, 18, err); 142 | 143 | emit log("\n## assertGe(uint,uint)\n"); 144 | assertGe(uint(0), 1); 145 | emit log("\n"); 146 | assertGe(uint(0), 1, err); 147 | 148 | emit log("\n## assertGe(int,int)\n"); 149 | assertGe(-1, 0); 150 | emit log("\n"); 151 | assertGe(-1, 0, err); 152 | 153 | emit log("\n## assertGeDecimal(int,int,uint)\n"); 154 | assertGeDecimal(-2.0e18, -1.1e18, 18); 155 | emit log("\n"); 156 | assertGeDecimal(-2.0e18, -1.1e18, 18, err); 157 | 158 | emit log("\n## assertGeDecimal(uint,uint,uint)\n"); 159 | assertGeDecimal(uint(1.0e18), 1.1e18, 18); 160 | emit log("\n"); 161 | assertGeDecimal(uint(1.0e18), 1.1e18, 18, err); 162 | 163 | emit log("\n## assertLt(uint,uint)\n"); 164 | assertLt(uint(0), 0); 165 | emit log("\n"); 166 | assertLt(uint(0), 0, err); 167 | 168 | emit log("\n## assertLt(int,int)\n"); 169 | assertLt(-1, -1); 170 | emit log("\n"); 171 | assertLt(-1, -1, err); 172 | 173 | emit log("\n## assertLtDecimal(int,int,uint)\n"); 174 | assertLtDecimal(-1.0e18, -1.1e18, 18); 175 | emit log("\n"); 176 | assertLtDecimal(-1.0e18, -1.1e18, 18, err); 177 | 178 | emit log("\n## assertLtDecimal(uint,uint,uint)\n"); 179 | assertLtDecimal(uint(2.0e18), 1.1e18, 18); 180 | emit log("\n"); 181 | assertLtDecimal(uint(2.0e18), 1.1e18, 18, err); 182 | 183 | emit log("\n## assertLe(uint,uint)\n"); 184 | assertLe(uint(1), 0); 185 | emit log("\n"); 186 | assertLe(uint(1), 0, err); 187 | 188 | emit log("\n## assertLe(int,int)\n"); 189 | assertLe(0, -1); 190 | emit log("\n"); 191 | assertLe(0, -1, err); 192 | 193 | emit log("\n## assertLeDecimal(int,int,uint)\n"); 194 | assertLeDecimal(-1.0e18, -1.1e18, 18); 195 | emit log("\n"); 196 | assertLeDecimal(-1.0e18, -1.1e18, 18, err); 197 | 198 | emit log("\n## assertLeDecimal(uint,uint,uint)\n"); 199 | assertLeDecimal(uint(2.0e18), 1.1e18, 18); 200 | emit log("\n"); 201 | assertLeDecimal(uint(2.0e18), 1.1e18, 18, err); 202 | 203 | emit log("\n## assertEq(string,string)\n"); 204 | string memory s1 = "string 1"; 205 | string memory s2 = "string 2"; 206 | assertEq(s1, s2); 207 | emit log("\n"); 208 | assertEq(s1, s2, err); 209 | 210 | emit log("\n## assertEq0(bytes,bytes)\n"); 211 | assertEq0(hex"abcdef01", hex"abcdef02"); 212 | emit log("\n"); 213 | assertEq0(hex"abcdef01", hex"abcdef02", err); 214 | } 215 | } 216 | 217 | contract DemoTestWithSetUp { 218 | function setUp() public { 219 | } 220 | function test_pass() public pure { 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /lib/forge-std/src/mocks/MockERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | /// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production. 5 | /// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol 6 | contract MockERC721 { 7 | /*////////////////////////////////////////////////////////////// 8 | EVENTS 9 | //////////////////////////////////////////////////////////////*/ 10 | 11 | event Transfer(address indexed from, address indexed to, uint256 indexed id); 12 | 13 | event Approval(address indexed owner, address indexed spender, uint256 indexed id); 14 | 15 | event ApprovalForAll(address indexed owner, address indexed operator, bool approved); 16 | 17 | /*////////////////////////////////////////////////////////////// 18 | METADATA STORAGE/LOGIC 19 | //////////////////////////////////////////////////////////////*/ 20 | 21 | string public name; 22 | 23 | string public symbol; 24 | 25 | function tokenURI(uint256 id) public view virtual returns (string memory) {} 26 | 27 | /*////////////////////////////////////////////////////////////// 28 | ERC721 BALANCE/OWNER STORAGE 29 | //////////////////////////////////////////////////////////////*/ 30 | 31 | mapping(uint256 => address) internal _ownerOf; 32 | 33 | mapping(address => uint256) internal _balanceOf; 34 | 35 | function ownerOf(uint256 id) public view virtual returns (address owner) { 36 | require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); 37 | } 38 | 39 | function balanceOf(address owner) public view virtual returns (uint256) { 40 | require(owner != address(0), "ZERO_ADDRESS"); 41 | 42 | return _balanceOf[owner]; 43 | } 44 | 45 | /*////////////////////////////////////////////////////////////// 46 | ERC721 APPROVAL STORAGE 47 | //////////////////////////////////////////////////////////////*/ 48 | 49 | mapping(uint256 => address) public getApproved; 50 | 51 | mapping(address => mapping(address => bool)) public isApprovedForAll; 52 | 53 | /*////////////////////////////////////////////////////////////// 54 | INITIALIZE 55 | //////////////////////////////////////////////////////////////*/ 56 | 57 | /// @dev A bool to track whether the contract has been initialized. 58 | bool private initialized; 59 | 60 | /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and 61 | /// syntaxes, we add an initialization function that can be called only once. 62 | function initialize(string memory _name, string memory _symbol) public { 63 | require(!initialized, "ALREADY_INITIALIZED"); 64 | 65 | name = _name; 66 | symbol = _symbol; 67 | 68 | initialized = true; 69 | } 70 | 71 | /*////////////////////////////////////////////////////////////// 72 | ERC721 LOGIC 73 | //////////////////////////////////////////////////////////////*/ 74 | 75 | function approve(address spender, uint256 id) public virtual { 76 | address owner = _ownerOf[id]; 77 | 78 | require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); 79 | 80 | getApproved[id] = spender; 81 | 82 | emit Approval(owner, spender, id); 83 | } 84 | 85 | function setApprovalForAll(address operator, bool approved) public virtual { 86 | isApprovedForAll[msg.sender][operator] = approved; 87 | 88 | emit ApprovalForAll(msg.sender, operator, approved); 89 | } 90 | 91 | function transferFrom(address from, address to, uint256 id) public virtual { 92 | require(from == _ownerOf[id], "WRONG_FROM"); 93 | 94 | require(to != address(0), "INVALID_RECIPIENT"); 95 | 96 | require( 97 | msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" 98 | ); 99 | 100 | // Underflow of the sender's balance is impossible because we check for 101 | // ownership above and the recipient's balance can't realistically overflow. 102 | _balanceOf[from]--; 103 | 104 | _balanceOf[to]++; 105 | 106 | _ownerOf[id] = to; 107 | 108 | delete getApproved[id]; 109 | 110 | emit Transfer(from, to, id); 111 | } 112 | 113 | function safeTransferFrom(address from, address to, uint256 id) public virtual { 114 | transferFrom(from, to, id); 115 | 116 | require( 117 | !_isContract(to) 118 | || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") 119 | == IERC721TokenReceiver.onERC721Received.selector, 120 | "UNSAFE_RECIPIENT" 121 | ); 122 | } 123 | 124 | function safeTransferFrom(address from, address to, uint256 id, bytes memory data) public virtual { 125 | transferFrom(from, to, id); 126 | 127 | require( 128 | !_isContract(to) 129 | || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) 130 | == IERC721TokenReceiver.onERC721Received.selector, 131 | "UNSAFE_RECIPIENT" 132 | ); 133 | } 134 | 135 | /*////////////////////////////////////////////////////////////// 136 | ERC165 LOGIC 137 | //////////////////////////////////////////////////////////////*/ 138 | 139 | function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) { 140 | return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165 141 | || interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721 142 | || interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata 143 | } 144 | 145 | /*////////////////////////////////////////////////////////////// 146 | INTERNAL MINT/BURN LOGIC 147 | //////////////////////////////////////////////////////////////*/ 148 | 149 | function _mint(address to, uint256 id) internal virtual { 150 | require(to != address(0), "INVALID_RECIPIENT"); 151 | 152 | require(_ownerOf[id] == address(0), "ALREADY_MINTED"); 153 | 154 | // Counter overflow is incredibly unrealistic. 155 | 156 | _balanceOf[to]++; 157 | 158 | _ownerOf[id] = to; 159 | 160 | emit Transfer(address(0), to, id); 161 | } 162 | 163 | function _burn(uint256 id) internal virtual { 164 | address owner = _ownerOf[id]; 165 | 166 | require(owner != address(0), "NOT_MINTED"); 167 | 168 | _balanceOf[owner]--; 169 | 170 | delete _ownerOf[id]; 171 | 172 | delete getApproved[id]; 173 | 174 | emit Transfer(owner, address(0), id); 175 | } 176 | 177 | /*////////////////////////////////////////////////////////////// 178 | INTERNAL SAFE MINT LOGIC 179 | //////////////////////////////////////////////////////////////*/ 180 | 181 | function _safeMint(address to, uint256 id) internal virtual { 182 | _mint(to, id); 183 | 184 | require( 185 | !_isContract(to) 186 | || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") 187 | == IERC721TokenReceiver.onERC721Received.selector, 188 | "UNSAFE_RECIPIENT" 189 | ); 190 | } 191 | 192 | function _safeMint(address to, uint256 id, bytes memory data) internal virtual { 193 | _mint(to, id); 194 | 195 | require( 196 | !_isContract(to) 197 | || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) 198 | == IERC721TokenReceiver.onERC721Received.selector, 199 | "UNSAFE_RECIPIENT" 200 | ); 201 | } 202 | 203 | /*////////////////////////////////////////////////////////////// 204 | HELPERS 205 | //////////////////////////////////////////////////////////////*/ 206 | 207 | function _isContract(address _addr) private view returns (bool) { 208 | uint256 codeLength; 209 | 210 | // Assembly required for versions < 0.8.0 to check extcodesize. 211 | assembly { 212 | codeLength := extcodesize(_addr) 213 | } 214 | 215 | return codeLength > 0; 216 | } 217 | } 218 | 219 | interface IERC721TokenReceiver { 220 | function onERC721Received(address, address, uint256, bytes calldata) external returns (bytes4); 221 | } 222 | -------------------------------------------------------------------------------- /lib/forge-std/src/mocks/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | /// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production. 5 | /// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.sol 6 | contract MockERC20 { 7 | /*////////////////////////////////////////////////////////////// 8 | EVENTS 9 | //////////////////////////////////////////////////////////////*/ 10 | 11 | event Transfer(address indexed from, address indexed to, uint256 amount); 12 | 13 | event Approval(address indexed owner, address indexed spender, uint256 amount); 14 | 15 | /*////////////////////////////////////////////////////////////// 16 | METADATA STORAGE 17 | //////////////////////////////////////////////////////////////*/ 18 | 19 | string public name; 20 | 21 | string public symbol; 22 | 23 | uint8 public decimals; 24 | 25 | /*////////////////////////////////////////////////////////////// 26 | ERC20 STORAGE 27 | //////////////////////////////////////////////////////////////*/ 28 | 29 | uint256 public totalSupply; 30 | 31 | mapping(address => uint256) public balanceOf; 32 | 33 | mapping(address => mapping(address => uint256)) public allowance; 34 | 35 | /*////////////////////////////////////////////////////////////// 36 | EIP-2612 STORAGE 37 | //////////////////////////////////////////////////////////////*/ 38 | 39 | uint256 internal INITIAL_CHAIN_ID; 40 | 41 | bytes32 internal INITIAL_DOMAIN_SEPARATOR; 42 | 43 | mapping(address => uint256) public nonces; 44 | 45 | /*////////////////////////////////////////////////////////////// 46 | INITIALIZE 47 | //////////////////////////////////////////////////////////////*/ 48 | 49 | /// @dev A bool to track whether the contract has been initialized. 50 | bool private initialized; 51 | 52 | /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and 53 | /// syntaxes, we add an initialization function that can be called only once. 54 | function initialize(string memory _name, string memory _symbol, uint8 _decimals) public { 55 | require(!initialized, "ALREADY_INITIALIZED"); 56 | 57 | name = _name; 58 | symbol = _symbol; 59 | decimals = _decimals; 60 | 61 | INITIAL_CHAIN_ID = _pureChainId(); 62 | INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); 63 | 64 | initialized = true; 65 | } 66 | 67 | /*////////////////////////////////////////////////////////////// 68 | ERC20 LOGIC 69 | //////////////////////////////////////////////////////////////*/ 70 | 71 | function approve(address spender, uint256 amount) public virtual returns (bool) { 72 | allowance[msg.sender][spender] = amount; 73 | 74 | emit Approval(msg.sender, spender, amount); 75 | 76 | return true; 77 | } 78 | 79 | function transfer(address to, uint256 amount) public virtual returns (bool) { 80 | balanceOf[msg.sender] = _sub(balanceOf[msg.sender], amount); 81 | balanceOf[to] = _add(balanceOf[to], amount); 82 | 83 | emit Transfer(msg.sender, to, amount); 84 | 85 | return true; 86 | } 87 | 88 | function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) { 89 | uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. 90 | 91 | if (allowed != ~uint256(0)) allowance[from][msg.sender] = _sub(allowed, amount); 92 | 93 | balanceOf[from] = _sub(balanceOf[from], amount); 94 | balanceOf[to] = _add(balanceOf[to], amount); 95 | 96 | emit Transfer(from, to, amount); 97 | 98 | return true; 99 | } 100 | 101 | /*////////////////////////////////////////////////////////////// 102 | EIP-2612 LOGIC 103 | //////////////////////////////////////////////////////////////*/ 104 | 105 | function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) 106 | public 107 | virtual 108 | { 109 | require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); 110 | 111 | address recoveredAddress = ecrecover( 112 | keccak256( 113 | abi.encodePacked( 114 | "\x19\x01", 115 | DOMAIN_SEPARATOR(), 116 | keccak256( 117 | abi.encode( 118 | keccak256( 119 | "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" 120 | ), 121 | owner, 122 | spender, 123 | value, 124 | nonces[owner]++, 125 | deadline 126 | ) 127 | ) 128 | ) 129 | ), 130 | v, 131 | r, 132 | s 133 | ); 134 | 135 | require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); 136 | 137 | allowance[recoveredAddress][spender] = value; 138 | 139 | emit Approval(owner, spender, value); 140 | } 141 | 142 | function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { 143 | return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); 144 | } 145 | 146 | function computeDomainSeparator() internal view virtual returns (bytes32) { 147 | return keccak256( 148 | abi.encode( 149 | keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), 150 | keccak256(bytes(name)), 151 | keccak256("1"), 152 | _pureChainId(), 153 | address(this) 154 | ) 155 | ); 156 | } 157 | 158 | /*////////////////////////////////////////////////////////////// 159 | INTERNAL MINT/BURN LOGIC 160 | //////////////////////////////////////////////////////////////*/ 161 | 162 | function _mint(address to, uint256 amount) internal virtual { 163 | totalSupply = _add(totalSupply, amount); 164 | balanceOf[to] = _add(balanceOf[to], amount); 165 | 166 | emit Transfer(address(0), to, amount); 167 | } 168 | 169 | function _burn(address from, uint256 amount) internal virtual { 170 | balanceOf[from] = _sub(balanceOf[from], amount); 171 | totalSupply = _sub(totalSupply, amount); 172 | 173 | emit Transfer(from, address(0), amount); 174 | } 175 | 176 | /*////////////////////////////////////////////////////////////// 177 | INTERNAL SAFE MATH LOGIC 178 | //////////////////////////////////////////////////////////////*/ 179 | 180 | function _add(uint256 a, uint256 b) internal pure returns (uint256) { 181 | uint256 c = a + b; 182 | require(c >= a, "ERC20: addition overflow"); 183 | return c; 184 | } 185 | 186 | function _sub(uint256 a, uint256 b) internal pure returns (uint256) { 187 | require(a >= b, "ERC20: subtraction underflow"); 188 | return a - b; 189 | } 190 | 191 | /*////////////////////////////////////////////////////////////// 192 | HELPERS 193 | //////////////////////////////////////////////////////////////*/ 194 | 195 | // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no 196 | // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We 197 | // can't simply access the chain ID in a normal view or pure function because the solc View Pure 198 | // Checker changed `chainid` from pure to view in 0.8.0. 199 | function _viewChainId() private view returns (uint256 chainId) { 200 | // Assembly required since `block.chainid` was introduced in 0.8.0. 201 | assembly { 202 | chainId := chainid() 203 | } 204 | 205 | address(this); // Silence warnings in older Solc versions. 206 | } 207 | 208 | function _pureChainId() private pure returns (uint256 chainId) { 209 | function() internal view returns (uint256) fnIn = _viewChainId; 210 | function() internal pure returns (uint256) pureChainId; 211 | assembly { 212 | pureChainId := fnIn 213 | } 214 | chainId = pureChainId(); 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /lib/forge-std/README.md: -------------------------------------------------------------------------------- 1 | # Forge Standard Library • [![CI status](https://github.com/foundry-rs/forge-std/actions/workflows/ci.yml/badge.svg)](https://github.com/foundry-rs/forge-std/actions/workflows/ci.yml) 2 | 3 | Forge Standard Library is a collection of helpful contracts and libraries for use with [Forge and Foundry](https://github.com/foundry-rs/foundry). It leverages Forge's cheatcodes to make writing tests easier and faster, while improving the UX of cheatcodes. 4 | 5 | **Learn how to use Forge-Std with the [📖 Foundry Book (Forge-Std Guide)](https://book.getfoundry.sh/forge/forge-std.html).** 6 | 7 | ## Install 8 | 9 | ```bash 10 | forge install foundry-rs/forge-std 11 | ``` 12 | 13 | ## Contracts 14 | ### stdError 15 | 16 | This is a helper contract for errors and reverts. In Forge, this contract is particularly helpful for the `expectRevert` cheatcode, as it provides all compiler builtin errors. 17 | 18 | See the contract itself for all error codes. 19 | 20 | #### Example usage 21 | 22 | ```solidity 23 | 24 | import "forge-std/Test.sol"; 25 | 26 | contract TestContract is Test { 27 | ErrorsTest test; 28 | 29 | function setUp() public { 30 | test = new ErrorsTest(); 31 | } 32 | 33 | function testExpectArithmetic() public { 34 | vm.expectRevert(stdError.arithmeticError); 35 | test.arithmeticError(10); 36 | } 37 | } 38 | 39 | contract ErrorsTest { 40 | function arithmeticError(uint256 a) public { 41 | uint256 a = a - 100; 42 | } 43 | } 44 | ``` 45 | 46 | ### stdStorage 47 | 48 | This is a rather large contract due to all of the overloading to make the UX decent. Primarily, it is a wrapper around the `record` and `accesses` cheatcodes. It can *always* find and write the storage slot(s) associated with a particular variable without knowing the storage layout. The one _major_ caveat to this is while a slot can be found for packed storage variables, we can't write to that variable safely. If a user tries to write to a packed slot, the execution throws an error, unless it is uninitialized (`bytes32(0)`). 49 | 50 | This works by recording all `SLOAD`s and `SSTORE`s during a function call. If there is a single slot read or written to, it immediately returns the slot. Otherwise, behind the scenes, we iterate through and check each one (assuming the user passed in a `depth` parameter). If the variable is a struct, you can pass in a `depth` parameter which is basically the field depth. 51 | 52 | I.e.: 53 | ```solidity 54 | struct T { 55 | // depth 0 56 | uint256 a; 57 | // depth 1 58 | uint256 b; 59 | } 60 | ``` 61 | 62 | #### Example usage 63 | 64 | ```solidity 65 | import "forge-std/Test.sol"; 66 | 67 | contract TestContract is Test { 68 | using stdStorage for StdStorage; 69 | 70 | Storage test; 71 | 72 | function setUp() public { 73 | test = new Storage(); 74 | } 75 | 76 | function testFindExists() public { 77 | // Lets say we want to find the slot for the public 78 | // variable `exists`. We just pass in the function selector 79 | // to the `find` command 80 | uint256 slot = stdstore.target(address(test)).sig("exists()").find(); 81 | assertEq(slot, 0); 82 | } 83 | 84 | function testWriteExists() public { 85 | // Lets say we want to write to the slot for the public 86 | // variable `exists`. We just pass in the function selector 87 | // to the `checked_write` command 88 | stdstore.target(address(test)).sig("exists()").checked_write(100); 89 | assertEq(test.exists(), 100); 90 | } 91 | 92 | // It supports arbitrary storage layouts, like assembly based storage locations 93 | function testFindHidden() public { 94 | // `hidden` is a random hash of a bytes, iteration through slots would 95 | // not find it. Our mechanism does 96 | // Also, you can use the selector instead of a string 97 | uint256 slot = stdstore.target(address(test)).sig(test.hidden.selector).find(); 98 | assertEq(slot, uint256(keccak256("my.random.var"))); 99 | } 100 | 101 | // If targeting a mapping, you have to pass in the keys necessary to perform the find 102 | // i.e.: 103 | function testFindMapping() public { 104 | uint256 slot = stdstore 105 | .target(address(test)) 106 | .sig(test.map_addr.selector) 107 | .with_key(address(this)) 108 | .find(); 109 | // in the `Storage` constructor, we wrote that this address' value was 1 in the map 110 | // so when we load the slot, we expect it to be 1 111 | assertEq(uint(vm.load(address(test), bytes32(slot))), 1); 112 | } 113 | 114 | // If the target is a struct, you can specify the field depth: 115 | function testFindStruct() public { 116 | // NOTE: see the depth parameter - 0 means 0th field, 1 means 1st field, etc. 117 | uint256 slot_for_a_field = stdstore 118 | .target(address(test)) 119 | .sig(test.basicStruct.selector) 120 | .depth(0) 121 | .find(); 122 | 123 | uint256 slot_for_b_field = stdstore 124 | .target(address(test)) 125 | .sig(test.basicStruct.selector) 126 | .depth(1) 127 | .find(); 128 | 129 | assertEq(uint(vm.load(address(test), bytes32(slot_for_a_field))), 1); 130 | assertEq(uint(vm.load(address(test), bytes32(slot_for_b_field))), 2); 131 | } 132 | } 133 | 134 | // A complex storage contract 135 | contract Storage { 136 | struct UnpackedStruct { 137 | uint256 a; 138 | uint256 b; 139 | } 140 | 141 | constructor() { 142 | map_addr[msg.sender] = 1; 143 | } 144 | 145 | uint256 public exists = 1; 146 | mapping(address => uint256) public map_addr; 147 | // mapping(address => Packed) public map_packed; 148 | mapping(address => UnpackedStruct) public map_struct; 149 | mapping(address => mapping(address => uint256)) public deep_map; 150 | mapping(address => mapping(address => UnpackedStruct)) public deep_map_struct; 151 | UnpackedStruct public basicStruct = UnpackedStruct({ 152 | a: 1, 153 | b: 2 154 | }); 155 | 156 | function hidden() public view returns (bytes32 t) { 157 | // an extremely hidden storage slot 158 | bytes32 slot = keccak256("my.random.var"); 159 | assembly { 160 | t := sload(slot) 161 | } 162 | } 163 | } 164 | ``` 165 | 166 | ### stdCheats 167 | 168 | This is a wrapper over miscellaneous cheatcodes that need wrappers to be more dev friendly. Currently there are only functions related to `prank`. In general, users may expect ETH to be put into an address on `prank`, but this is not the case for safety reasons. Explicitly this `hoax` function should only be used for address that have expected balances as it will get overwritten. If an address already has ETH, you should just use `prank`. If you want to change that balance explicitly, just use `deal`. If you want to do both, `hoax` is also right for you. 169 | 170 | 171 | #### Example usage: 172 | ```solidity 173 | 174 | // SPDX-License-Identifier: MIT 175 | pragma solidity ^0.8.0; 176 | 177 | import "forge-std/Test.sol"; 178 | 179 | // Inherit the stdCheats 180 | contract StdCheatsTest is Test { 181 | Bar test; 182 | function setUp() public { 183 | test = new Bar(); 184 | } 185 | 186 | function testHoax() public { 187 | // we call `hoax`, which gives the target address 188 | // eth and then calls `prank` 189 | hoax(address(1337)); 190 | test.bar{value: 100}(address(1337)); 191 | 192 | // overloaded to allow you to specify how much eth to 193 | // initialize the address with 194 | hoax(address(1337), 1); 195 | test.bar{value: 1}(address(1337)); 196 | } 197 | 198 | function testStartHoax() public { 199 | // we call `startHoax`, which gives the target address 200 | // eth and then calls `startPrank` 201 | // 202 | // it is also overloaded so that you can specify an eth amount 203 | startHoax(address(1337)); 204 | test.bar{value: 100}(address(1337)); 205 | test.bar{value: 100}(address(1337)); 206 | vm.stopPrank(); 207 | test.bar(address(this)); 208 | } 209 | } 210 | 211 | contract Bar { 212 | function bar(address expectedSender) public payable { 213 | require(msg.sender == expectedSender, "!prank"); 214 | } 215 | } 216 | ``` 217 | 218 | ### Std Assertions 219 | 220 | Expand upon the assertion functions from the `DSTest` library. 221 | 222 | ### `console.log` 223 | 224 | Usage follows the same format as [Hardhat](https://hardhat.org/hardhat-network/reference/#console-log). 225 | It's recommended to use `console2.sol` as shown below, as this will show the decoded logs in Forge traces. 226 | 227 | ```solidity 228 | // import it indirectly via Test.sol 229 | import "forge-std/Test.sol"; 230 | // or directly import it 231 | import "forge-std/console2.sol"; 232 | ... 233 | console2.log(someValue); 234 | ``` 235 | 236 | If you need compatibility with Hardhat, you must use the standard `console.sol` instead. 237 | Due to a bug in `console.sol`, logs that use `uint256` or `int256` types will not be properly decoded in Forge traces. 238 | 239 | ```solidity 240 | // import it indirectly via Test.sol 241 | import "forge-std/Test.sol"; 242 | // or directly import it 243 | import "forge-std/console.sol"; 244 | ... 245 | console.log(someValue); 246 | ``` 247 | 248 | ## License 249 | 250 | Forge Standard Library is offered under either [MIT](LICENSE-MIT) or [Apache 2.0](LICENSE-APACHE) license. 251 | -------------------------------------------------------------------------------- /lib/forge-std/test/StdMath.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0 <0.9.0; 3 | 4 | import "../src/StdMath.sol"; 5 | import "../src/Test.sol"; 6 | 7 | contract StdMathMock is Test { 8 | function exposed_percentDelta(uint256 a, uint256 b) public pure returns (uint256) { 9 | return stdMath.percentDelta(a, b); 10 | } 11 | 12 | function exposed_percentDelta(int256 a, int256 b) public pure returns (uint256) { 13 | return stdMath.percentDelta(a, b); 14 | } 15 | } 16 | 17 | contract StdMathTest is Test { 18 | function test_GetAbs() external { 19 | assertEq(stdMath.abs(-50), 50); 20 | assertEq(stdMath.abs(50), 50); 21 | assertEq(stdMath.abs(-1337), 1337); 22 | assertEq(stdMath.abs(0), 0); 23 | 24 | assertEq(stdMath.abs(type(int256).min), (type(uint256).max >> 1) + 1); 25 | assertEq(stdMath.abs(type(int256).max), (type(uint256).max >> 1)); 26 | } 27 | 28 | function testFuzz_GetAbs(int256 a) external { 29 | uint256 manualAbs = getAbs(a); 30 | 31 | uint256 abs = stdMath.abs(a); 32 | 33 | assertEq(abs, manualAbs); 34 | } 35 | 36 | function test_GetDelta_Uint() external { 37 | assertEq(stdMath.delta(uint256(0), uint256(0)), 0); 38 | assertEq(stdMath.delta(uint256(0), uint256(1337)), 1337); 39 | assertEq(stdMath.delta(uint256(0), type(uint64).max), type(uint64).max); 40 | assertEq(stdMath.delta(uint256(0), type(uint128).max), type(uint128).max); 41 | assertEq(stdMath.delta(uint256(0), type(uint256).max), type(uint256).max); 42 | 43 | assertEq(stdMath.delta(0, uint256(0)), 0); 44 | assertEq(stdMath.delta(1337, uint256(0)), 1337); 45 | assertEq(stdMath.delta(type(uint64).max, uint256(0)), type(uint64).max); 46 | assertEq(stdMath.delta(type(uint128).max, uint256(0)), type(uint128).max); 47 | assertEq(stdMath.delta(type(uint256).max, uint256(0)), type(uint256).max); 48 | 49 | assertEq(stdMath.delta(1337, uint256(1337)), 0); 50 | assertEq(stdMath.delta(type(uint256).max, type(uint256).max), 0); 51 | assertEq(stdMath.delta(5000, uint256(1250)), 3750); 52 | } 53 | 54 | function testFuzz_GetDelta_Uint(uint256 a, uint256 b) external { 55 | uint256 manualDelta; 56 | if (a > b) { 57 | manualDelta = a - b; 58 | } else { 59 | manualDelta = b - a; 60 | } 61 | 62 | uint256 delta = stdMath.delta(a, b); 63 | 64 | assertEq(delta, manualDelta); 65 | } 66 | 67 | function test_GetDelta_Int() external { 68 | assertEq(stdMath.delta(int256(0), int256(0)), 0); 69 | assertEq(stdMath.delta(int256(0), int256(1337)), 1337); 70 | assertEq(stdMath.delta(int256(0), type(int64).max), type(uint64).max >> 1); 71 | assertEq(stdMath.delta(int256(0), type(int128).max), type(uint128).max >> 1); 72 | assertEq(stdMath.delta(int256(0), type(int256).max), type(uint256).max >> 1); 73 | 74 | assertEq(stdMath.delta(0, int256(0)), 0); 75 | assertEq(stdMath.delta(1337, int256(0)), 1337); 76 | assertEq(stdMath.delta(type(int64).max, int256(0)), type(uint64).max >> 1); 77 | assertEq(stdMath.delta(type(int128).max, int256(0)), type(uint128).max >> 1); 78 | assertEq(stdMath.delta(type(int256).max, int256(0)), type(uint256).max >> 1); 79 | 80 | assertEq(stdMath.delta(-0, int256(0)), 0); 81 | assertEq(stdMath.delta(-1337, int256(0)), 1337); 82 | assertEq(stdMath.delta(type(int64).min, int256(0)), (type(uint64).max >> 1) + 1); 83 | assertEq(stdMath.delta(type(int128).min, int256(0)), (type(uint128).max >> 1) + 1); 84 | assertEq(stdMath.delta(type(int256).min, int256(0)), (type(uint256).max >> 1) + 1); 85 | 86 | assertEq(stdMath.delta(int256(0), -0), 0); 87 | assertEq(stdMath.delta(int256(0), -1337), 1337); 88 | assertEq(stdMath.delta(int256(0), type(int64).min), (type(uint64).max >> 1) + 1); 89 | assertEq(stdMath.delta(int256(0), type(int128).min), (type(uint128).max >> 1) + 1); 90 | assertEq(stdMath.delta(int256(0), type(int256).min), (type(uint256).max >> 1) + 1); 91 | 92 | assertEq(stdMath.delta(1337, int256(1337)), 0); 93 | assertEq(stdMath.delta(type(int256).max, type(int256).max), 0); 94 | assertEq(stdMath.delta(type(int256).min, type(int256).min), 0); 95 | assertEq(stdMath.delta(type(int256).min, type(int256).max), type(uint256).max); 96 | assertEq(stdMath.delta(5000, int256(1250)), 3750); 97 | } 98 | 99 | function testFuzz_GetDelta_Int(int256 a, int256 b) external { 100 | uint256 absA = getAbs(a); 101 | uint256 absB = getAbs(b); 102 | uint256 absDelta = absA > absB ? absA - absB : absB - absA; 103 | 104 | uint256 manualDelta; 105 | if ((a >= 0 && b >= 0) || (a < 0 && b < 0)) { 106 | manualDelta = absDelta; 107 | } 108 | // (a < 0 && b >= 0) || (a >= 0 && b < 0) 109 | else { 110 | manualDelta = absA + absB; 111 | } 112 | 113 | uint256 delta = stdMath.delta(a, b); 114 | 115 | assertEq(delta, manualDelta); 116 | } 117 | 118 | function test_GetPercentDelta_Uint() external { 119 | StdMathMock stdMathMock = new StdMathMock(); 120 | 121 | assertEq(stdMath.percentDelta(uint256(0), uint256(1337)), 1e18); 122 | assertEq(stdMath.percentDelta(uint256(0), type(uint64).max), 1e18); 123 | assertEq(stdMath.percentDelta(uint256(0), type(uint128).max), 1e18); 124 | assertEq(stdMath.percentDelta(uint256(0), type(uint192).max), 1e18); 125 | 126 | assertEq(stdMath.percentDelta(1337, uint256(1337)), 0); 127 | assertEq(stdMath.percentDelta(type(uint192).max, type(uint192).max), 0); 128 | assertEq(stdMath.percentDelta(0, uint256(2500)), 1e18); 129 | assertEq(stdMath.percentDelta(2500, uint256(2500)), 0); 130 | assertEq(stdMath.percentDelta(5000, uint256(2500)), 1e18); 131 | assertEq(stdMath.percentDelta(7500, uint256(2500)), 2e18); 132 | 133 | vm.expectRevert(stdError.divisionError); 134 | stdMathMock.exposed_percentDelta(uint256(1), 0); 135 | } 136 | 137 | function testFuzz_GetPercentDelta_Uint(uint192 a, uint192 b) external { 138 | vm.assume(b != 0); 139 | uint256 manualDelta; 140 | if (a > b) { 141 | manualDelta = a - b; 142 | } else { 143 | manualDelta = b - a; 144 | } 145 | 146 | uint256 manualPercentDelta = manualDelta * 1e18 / b; 147 | uint256 percentDelta = stdMath.percentDelta(a, b); 148 | 149 | assertEq(percentDelta, manualPercentDelta); 150 | } 151 | 152 | function test_GetPercentDelta_Int() external { 153 | // We deploy a mock version so we can properly test the revert. 154 | StdMathMock stdMathMock = new StdMathMock(); 155 | 156 | assertEq(stdMath.percentDelta(int256(0), int256(1337)), 1e18); 157 | assertEq(stdMath.percentDelta(int256(0), -1337), 1e18); 158 | assertEq(stdMath.percentDelta(int256(0), type(int64).min), 1e18); 159 | assertEq(stdMath.percentDelta(int256(0), type(int128).min), 1e18); 160 | assertEq(stdMath.percentDelta(int256(0), type(int192).min), 1e18); 161 | assertEq(stdMath.percentDelta(int256(0), type(int64).max), 1e18); 162 | assertEq(stdMath.percentDelta(int256(0), type(int128).max), 1e18); 163 | assertEq(stdMath.percentDelta(int256(0), type(int192).max), 1e18); 164 | 165 | assertEq(stdMath.percentDelta(1337, int256(1337)), 0); 166 | assertEq(stdMath.percentDelta(type(int192).max, type(int192).max), 0); 167 | assertEq(stdMath.percentDelta(type(int192).min, type(int192).min), 0); 168 | 169 | assertEq(stdMath.percentDelta(type(int192).min, type(int192).max), 2e18); // rounds the 1 wei diff down 170 | assertEq(stdMath.percentDelta(type(int192).max, type(int192).min), 2e18 - 1); // rounds the 1 wei diff down 171 | assertEq(stdMath.percentDelta(0, int256(2500)), 1e18); 172 | assertEq(stdMath.percentDelta(2500, int256(2500)), 0); 173 | assertEq(stdMath.percentDelta(5000, int256(2500)), 1e18); 174 | assertEq(stdMath.percentDelta(7500, int256(2500)), 2e18); 175 | 176 | vm.expectRevert(stdError.divisionError); 177 | stdMathMock.exposed_percentDelta(int256(1), 0); 178 | } 179 | 180 | function testFuzz_GetPercentDelta_Int(int192 a, int192 b) external { 181 | vm.assume(b != 0); 182 | uint256 absA = getAbs(a); 183 | uint256 absB = getAbs(b); 184 | uint256 absDelta = absA > absB ? absA - absB : absB - absA; 185 | 186 | uint256 manualDelta; 187 | if ((a >= 0 && b >= 0) || (a < 0 && b < 0)) { 188 | manualDelta = absDelta; 189 | } 190 | // (a < 0 && b >= 0) || (a >= 0 && b < 0) 191 | else { 192 | manualDelta = absA + absB; 193 | } 194 | 195 | uint256 manualPercentDelta = manualDelta * 1e18 / absB; 196 | uint256 percentDelta = stdMath.percentDelta(a, b); 197 | 198 | assertEq(percentDelta, manualPercentDelta); 199 | } 200 | 201 | /*////////////////////////////////////////////////////////////////////////// 202 | HELPERS 203 | //////////////////////////////////////////////////////////////////////////*/ 204 | 205 | function getAbs(int256 a) private pure returns (uint256) { 206 | if (a < 0) { 207 | return a == type(int256).min ? uint256(type(int256).max) + 1 : uint256(-a); 208 | } 209 | 210 | return uint256(a); 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /lib/forge-std/src/interfaces/IERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2; 3 | 4 | import "./IERC165.sol"; 5 | 6 | /// @title ERC-721 Non-Fungible Token Standard 7 | /// @dev See https://eips.ethereum.org/EIPS/eip-721 8 | /// Note: the ERC-165 identifier for this interface is 0x80ac58cd. 9 | interface IERC721 is IERC165 { 10 | /// @dev This emits when ownership of any NFT changes by any mechanism. 11 | /// This event emits when NFTs are created (`from` == 0) and destroyed 12 | /// (`to` == 0). Exception: during contract creation, any number of NFTs 13 | /// may be created and assigned without emitting Transfer. At the time of 14 | /// any transfer, the approved address for that NFT (if any) is reset to none. 15 | event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); 16 | 17 | /// @dev This emits when the approved address for an NFT is changed or 18 | /// reaffirmed. The zero address indicates there is no approved address. 19 | /// When a Transfer event emits, this also indicates that the approved 20 | /// address for that NFT (if any) is reset to none. 21 | event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); 22 | 23 | /// @dev This emits when an operator is enabled or disabled for an owner. 24 | /// The operator can manage all NFTs of the owner. 25 | event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); 26 | 27 | /// @notice Count all NFTs assigned to an owner 28 | /// @dev NFTs assigned to the zero address are considered invalid, and this 29 | /// function throws for queries about the zero address. 30 | /// @param _owner An address for whom to query the balance 31 | /// @return The number of NFTs owned by `_owner`, possibly zero 32 | function balanceOf(address _owner) external view returns (uint256); 33 | 34 | /// @notice Find the owner of an NFT 35 | /// @dev NFTs assigned to zero address are considered invalid, and queries 36 | /// about them do throw. 37 | /// @param _tokenId The identifier for an NFT 38 | /// @return The address of the owner of the NFT 39 | function ownerOf(uint256 _tokenId) external view returns (address); 40 | 41 | /// @notice Transfers the ownership of an NFT from one address to another address 42 | /// @dev Throws unless `msg.sender` is the current owner, an authorized 43 | /// operator, or the approved address for this NFT. Throws if `_from` is 44 | /// not the current owner. Throws if `_to` is the zero address. Throws if 45 | /// `_tokenId` is not a valid NFT. When transfer is complete, this function 46 | /// checks if `_to` is a smart contract (code size > 0). If so, it calls 47 | /// `onERC721Received` on `_to` and throws if the return value is not 48 | /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. 49 | /// @param _from The current owner of the NFT 50 | /// @param _to The new owner 51 | /// @param _tokenId The NFT to transfer 52 | /// @param data Additional data with no specified format, sent in call to `_to` 53 | function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable; 54 | 55 | /// @notice Transfers the ownership of an NFT from one address to another address 56 | /// @dev This works identically to the other function with an extra data parameter, 57 | /// except this function just sets data to "". 58 | /// @param _from The current owner of the NFT 59 | /// @param _to The new owner 60 | /// @param _tokenId The NFT to transfer 61 | function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; 62 | 63 | /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE 64 | /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE 65 | /// THEY MAY BE PERMANENTLY LOST 66 | /// @dev Throws unless `msg.sender` is the current owner, an authorized 67 | /// operator, or the approved address for this NFT. Throws if `_from` is 68 | /// not the current owner. Throws if `_to` is the zero address. Throws if 69 | /// `_tokenId` is not a valid NFT. 70 | /// @param _from The current owner of the NFT 71 | /// @param _to The new owner 72 | /// @param _tokenId The NFT to transfer 73 | function transferFrom(address _from, address _to, uint256 _tokenId) external payable; 74 | 75 | /// @notice Change or reaffirm the approved address for an NFT 76 | /// @dev The zero address indicates there is no approved address. 77 | /// Throws unless `msg.sender` is the current NFT owner, or an authorized 78 | /// operator of the current owner. 79 | /// @param _approved The new approved NFT controller 80 | /// @param _tokenId The NFT to approve 81 | function approve(address _approved, uint256 _tokenId) external payable; 82 | 83 | /// @notice Enable or disable approval for a third party ("operator") to manage 84 | /// all of `msg.sender`'s assets 85 | /// @dev Emits the ApprovalForAll event. The contract MUST allow 86 | /// multiple operators per owner. 87 | /// @param _operator Address to add to the set of authorized operators 88 | /// @param _approved True if the operator is approved, false to revoke approval 89 | function setApprovalForAll(address _operator, bool _approved) external; 90 | 91 | /// @notice Get the approved address for a single NFT 92 | /// @dev Throws if `_tokenId` is not a valid NFT. 93 | /// @param _tokenId The NFT to find the approved address for 94 | /// @return The approved address for this NFT, or the zero address if there is none 95 | function getApproved(uint256 _tokenId) external view returns (address); 96 | 97 | /// @notice Query if an address is an authorized operator for another address 98 | /// @param _owner The address that owns the NFTs 99 | /// @param _operator The address that acts on behalf of the owner 100 | /// @return True if `_operator` is an approved operator for `_owner`, false otherwise 101 | function isApprovedForAll(address _owner, address _operator) external view returns (bool); 102 | } 103 | 104 | /// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02. 105 | interface IERC721TokenReceiver { 106 | /// @notice Handle the receipt of an NFT 107 | /// @dev The ERC721 smart contract calls this function on the recipient 108 | /// after a `transfer`. This function MAY throw to revert and reject the 109 | /// transfer. Return of other than the magic value MUST result in the 110 | /// transaction being reverted. 111 | /// Note: the contract address is always the message sender. 112 | /// @param _operator The address which called `safeTransferFrom` function 113 | /// @param _from The address which previously owned the token 114 | /// @param _tokenId The NFT identifier which is being transferred 115 | /// @param _data Additional data with no specified format 116 | /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` 117 | /// unless throwing 118 | function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) 119 | external 120 | returns (bytes4); 121 | } 122 | 123 | /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension 124 | /// @dev See https://eips.ethereum.org/EIPS/eip-721 125 | /// Note: the ERC-165 identifier for this interface is 0x5b5e139f. 126 | interface IERC721Metadata is IERC721 { 127 | /// @notice A descriptive name for a collection of NFTs in this contract 128 | function name() external view returns (string memory _name); 129 | 130 | /// @notice An abbreviated name for NFTs in this contract 131 | function symbol() external view returns (string memory _symbol); 132 | 133 | /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. 134 | /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC 135 | /// 3986. The URI may point to a JSON file that conforms to the "ERC721 136 | /// Metadata JSON Schema". 137 | function tokenURI(uint256 _tokenId) external view returns (string memory); 138 | } 139 | 140 | /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension 141 | /// @dev See https://eips.ethereum.org/EIPS/eip-721 142 | /// Note: the ERC-165 identifier for this interface is 0x780e9d63. 143 | interface IERC721Enumerable is IERC721 { 144 | /// @notice Count NFTs tracked by this contract 145 | /// @return A count of valid NFTs tracked by this contract, where each one of 146 | /// them has an assigned and queryable owner not equal to the zero address 147 | function totalSupply() external view returns (uint256); 148 | 149 | /// @notice Enumerate valid NFTs 150 | /// @dev Throws if `_index` >= `totalSupply()`. 151 | /// @param _index A counter less than `totalSupply()` 152 | /// @return The token identifier for the `_index`th NFT, 153 | /// (sort order not specified) 154 | function tokenByIndex(uint256 _index) external view returns (uint256); 155 | 156 | /// @notice Enumerate NFTs assigned to an owner 157 | /// @dev Throws if `_index` >= `balanceOf(_owner)` or if 158 | /// `_owner` is the zero address, representing invalid NFTs. 159 | /// @param _owner An address where we are interested in NFTs owned by them 160 | /// @param _index A counter less than `balanceOf(_owner)` 161 | /// @return The token identifier for the `_index`th NFT assigned to `_owner`, 162 | /// (sort order not specified) 163 | function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); 164 | } 165 | -------------------------------------------------------------------------------- /lib/forge-std/test/StdChains.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.7.0 <0.9.0; 3 | 4 | import "../src/Test.sol"; 5 | 6 | contract StdChainsMock is Test { 7 | function exposed_getChain(string memory chainAlias) public returns (Chain memory) { 8 | return getChain(chainAlias); 9 | } 10 | 11 | function exposed_getChain(uint256 chainId) public returns (Chain memory) { 12 | return getChain(chainId); 13 | } 14 | 15 | function exposed_setChain(string memory chainAlias, ChainData memory chainData) public { 16 | setChain(chainAlias, chainData); 17 | } 18 | 19 | function exposed_setFallbackToDefaultRpcUrls(bool useDefault) public { 20 | setFallbackToDefaultRpcUrls(useDefault); 21 | } 22 | } 23 | 24 | contract StdChainsTest is Test { 25 | function test_ChainRpcInitialization() public { 26 | // RPCs specified in `foundry.toml` should be updated. 27 | assertEq(getChain(1).rpcUrl, "https://mainnet.infura.io/v3/b1d3925804e74152b316ca7da97060d3"); 28 | assertEq(getChain("optimism_goerli").rpcUrl, "https://goerli.optimism.io/"); 29 | assertEq(getChain("arbitrum_one_goerli").rpcUrl, "https://goerli-rollup.arbitrum.io/rpc/"); 30 | 31 | // Environment variables should be the next fallback 32 | assertEq(getChain("arbitrum_nova").rpcUrl, "https://nova.arbitrum.io/rpc"); 33 | vm.setEnv("ARBITRUM_NOVA_RPC_URL", "myoverride"); 34 | assertEq(getChain("arbitrum_nova").rpcUrl, "myoverride"); 35 | vm.setEnv("ARBITRUM_NOVA_RPC_URL", "https://nova.arbitrum.io/rpc"); 36 | 37 | // Cannot override RPCs defined in `foundry.toml` 38 | vm.setEnv("MAINNET_RPC_URL", "myoverride2"); 39 | assertEq(getChain("mainnet").rpcUrl, "https://mainnet.infura.io/v3/b1d3925804e74152b316ca7da97060d3"); 40 | 41 | // Other RPCs should remain unchanged. 42 | assertEq(getChain(31337).rpcUrl, "http://127.0.0.1:8545"); 43 | assertEq(getChain("sepolia").rpcUrl, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001"); 44 | } 45 | 46 | function testFuzz_Rpc(string memory rpcAlias) internal { 47 | string memory rpcUrl = getChain(rpcAlias).rpcUrl; 48 | vm.createSelectFork(rpcUrl); 49 | } 50 | 51 | // Ensure we can connect to the default RPC URL for each chain. 52 | // function testRpcs() public { 53 | // testRpc("mainnet"); 54 | // testRpc("goerli"); 55 | // testRpc("sepolia"); 56 | // testRpc("optimism"); 57 | // testRpc("optimism_goerli"); 58 | // testRpc("arbitrum_one"); 59 | // testRpc("arbitrum_one_goerli"); 60 | // testRpc("arbitrum_nova"); 61 | // testRpc("polygon"); 62 | // testRpc("polygon_mumbai"); 63 | // testRpc("avalanche"); 64 | // testRpc("avalanche_fuji"); 65 | // testRpc("bnb_smart_chain"); 66 | // testRpc("bnb_smart_chain_testnet"); 67 | // testRpc("gnosis_chain"); 68 | // testRpc("moonbeam"); 69 | // testRpc("moonriver"); 70 | // testRpc("moonbase"); 71 | // testRpc("base_goerli"); 72 | // testRpc("base"); 73 | // } 74 | 75 | function test_ChainNoDefault() public { 76 | // We deploy a mock to properly test the revert. 77 | StdChainsMock stdChainsMock = new StdChainsMock(); 78 | 79 | vm.expectRevert("StdChains getChain(string): Chain with alias \"does_not_exist\" not found."); 80 | stdChainsMock.exposed_getChain("does_not_exist"); 81 | } 82 | 83 | function test_SetChainFirstFails() public { 84 | // We deploy a mock to properly test the revert. 85 | StdChainsMock stdChainsMock = new StdChainsMock(); 86 | 87 | vm.expectRevert("StdChains setChain(string,ChainData): Chain ID 31337 already used by \"anvil\"."); 88 | stdChainsMock.exposed_setChain("anvil2", ChainData("Anvil", 31337, "URL")); 89 | } 90 | 91 | function test_ChainBubbleUp() public { 92 | // We deploy a mock to properly test the revert. 93 | StdChainsMock stdChainsMock = new StdChainsMock(); 94 | 95 | stdChainsMock.exposed_setChain("needs_undefined_env_var", ChainData("", 123456789, "")); 96 | vm.expectRevert( 97 | "Failed to resolve env var `UNDEFINED_RPC_URL_PLACEHOLDER` in `${UNDEFINED_RPC_URL_PLACEHOLDER}`: environment variable not found" 98 | ); 99 | stdChainsMock.exposed_getChain("needs_undefined_env_var"); 100 | } 101 | 102 | function test_CannotSetChain_ChainIdExists() public { 103 | // We deploy a mock to properly test the revert. 104 | StdChainsMock stdChainsMock = new StdChainsMock(); 105 | 106 | stdChainsMock.exposed_setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/")); 107 | 108 | vm.expectRevert('StdChains setChain(string,ChainData): Chain ID 123456789 already used by "custom_chain".'); 109 | 110 | stdChainsMock.exposed_setChain("another_custom_chain", ChainData("", 123456789, "")); 111 | } 112 | 113 | function test_SetChain() public { 114 | setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/")); 115 | Chain memory customChain = getChain("custom_chain"); 116 | assertEq(customChain.name, "Custom Chain"); 117 | assertEq(customChain.chainId, 123456789); 118 | assertEq(customChain.chainAlias, "custom_chain"); 119 | assertEq(customChain.rpcUrl, "https://custom.chain/"); 120 | Chain memory chainById = getChain(123456789); 121 | assertEq(chainById.name, customChain.name); 122 | assertEq(chainById.chainId, customChain.chainId); 123 | assertEq(chainById.chainAlias, customChain.chainAlias); 124 | assertEq(chainById.rpcUrl, customChain.rpcUrl); 125 | customChain.name = "Another Custom Chain"; 126 | customChain.chainId = 987654321; 127 | setChain("another_custom_chain", customChain); 128 | Chain memory anotherCustomChain = getChain("another_custom_chain"); 129 | assertEq(anotherCustomChain.name, "Another Custom Chain"); 130 | assertEq(anotherCustomChain.chainId, 987654321); 131 | assertEq(anotherCustomChain.chainAlias, "another_custom_chain"); 132 | assertEq(anotherCustomChain.rpcUrl, "https://custom.chain/"); 133 | // Verify the first chain data was not overwritten 134 | chainById = getChain(123456789); 135 | assertEq(chainById.name, "Custom Chain"); 136 | assertEq(chainById.chainId, 123456789); 137 | } 138 | 139 | function test_SetNoEmptyAlias() public { 140 | // We deploy a mock to properly test the revert. 141 | StdChainsMock stdChainsMock = new StdChainsMock(); 142 | 143 | vm.expectRevert("StdChains setChain(string,ChainData): Chain alias cannot be the empty string."); 144 | stdChainsMock.exposed_setChain("", ChainData("", 123456789, "")); 145 | } 146 | 147 | function test_SetNoChainId0() public { 148 | // We deploy a mock to properly test the revert. 149 | StdChainsMock stdChainsMock = new StdChainsMock(); 150 | 151 | vm.expectRevert("StdChains setChain(string,ChainData): Chain ID cannot be 0."); 152 | stdChainsMock.exposed_setChain("alias", ChainData("", 0, "")); 153 | } 154 | 155 | function test_GetNoChainId0() public { 156 | // We deploy a mock to properly test the revert. 157 | StdChainsMock stdChainsMock = new StdChainsMock(); 158 | 159 | vm.expectRevert("StdChains getChain(uint256): Chain ID cannot be 0."); 160 | stdChainsMock.exposed_getChain(0); 161 | } 162 | 163 | function test_GetNoEmptyAlias() public { 164 | // We deploy a mock to properly test the revert. 165 | StdChainsMock stdChainsMock = new StdChainsMock(); 166 | 167 | vm.expectRevert("StdChains getChain(string): Chain alias cannot be the empty string."); 168 | stdChainsMock.exposed_getChain(""); 169 | } 170 | 171 | function test_ChainIdNotFound() public { 172 | // We deploy a mock to properly test the revert. 173 | StdChainsMock stdChainsMock = new StdChainsMock(); 174 | 175 | vm.expectRevert("StdChains getChain(string): Chain with alias \"no_such_alias\" not found."); 176 | stdChainsMock.exposed_getChain("no_such_alias"); 177 | } 178 | 179 | function test_ChainAliasNotFound() public { 180 | // We deploy a mock to properly test the revert. 181 | StdChainsMock stdChainsMock = new StdChainsMock(); 182 | 183 | vm.expectRevert("StdChains getChain(uint256): Chain with ID 321 not found."); 184 | 185 | stdChainsMock.exposed_getChain(321); 186 | } 187 | 188 | function test_SetChain_ExistingOne() public { 189 | // We deploy a mock to properly test the revert. 190 | StdChainsMock stdChainsMock = new StdChainsMock(); 191 | 192 | setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/")); 193 | assertEq(getChain(123456789).chainId, 123456789); 194 | 195 | setChain("custom_chain", ChainData("Modified Chain", 999999999, "https://modified.chain/")); 196 | vm.expectRevert("StdChains getChain(uint256): Chain with ID 123456789 not found."); 197 | stdChainsMock.exposed_getChain(123456789); 198 | 199 | Chain memory modifiedChain = getChain(999999999); 200 | assertEq(modifiedChain.name, "Modified Chain"); 201 | assertEq(modifiedChain.chainId, 999999999); 202 | assertEq(modifiedChain.rpcUrl, "https://modified.chain/"); 203 | } 204 | 205 | function test_DontUseDefaultRpcUrl() public { 206 | // We deploy a mock to properly test the revert. 207 | StdChainsMock stdChainsMock = new StdChainsMock(); 208 | 209 | // Should error if default RPCs flag is set to false. 210 | stdChainsMock.exposed_setFallbackToDefaultRpcUrls(false); 211 | vm.expectRevert(); 212 | stdChainsMock.exposed_getChain(31337); 213 | vm.expectRevert(); 214 | stdChainsMock.exposed_getChain("sepolia"); 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /lib/forge-std/src/StdUtils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | pragma experimental ABIEncoderV2; 5 | 6 | import {IMulticall3} from "./interfaces/IMulticall3.sol"; 7 | import {MockERC20} from "./mocks/MockERC20.sol"; 8 | import {MockERC721} from "./mocks/MockERC721.sol"; 9 | import {VmSafe} from "./Vm.sol"; 10 | 11 | abstract contract StdUtils { 12 | /*////////////////////////////////////////////////////////////////////////// 13 | CONSTANTS 14 | //////////////////////////////////////////////////////////////////////////*/ 15 | 16 | IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11); 17 | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); 18 | address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; 19 | uint256 private constant INT256_MIN_ABS = 20 | 57896044618658097711785492504343953926634992332820282019728792003956564819968; 21 | uint256 private constant SECP256K1_ORDER = 22 | 115792089237316195423570985008687907852837564279074904382605163141518161494337; 23 | uint256 private constant UINT256_MAX = 24 | 115792089237316195423570985008687907853269984665640564039457584007913129639935; 25 | 26 | // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. 27 | address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; 28 | 29 | /*////////////////////////////////////////////////////////////////////////// 30 | INTERNAL FUNCTIONS 31 | //////////////////////////////////////////////////////////////////////////*/ 32 | 33 | function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { 34 | require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min."); 35 | // If x is between min and max, return x directly. This is to ensure that dictionary values 36 | // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188 37 | if (x >= min && x <= max) return x; 38 | 39 | uint256 size = max - min + 1; 40 | 41 | // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side. 42 | // This helps ensure coverage of the min/max values. 43 | if (x <= 3 && size > x) return min + x; 44 | if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x); 45 | 46 | // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive. 47 | if (x > max) { 48 | uint256 diff = x - max; 49 | uint256 rem = diff % size; 50 | if (rem == 0) return max; 51 | result = min + rem - 1; 52 | } else if (x < min) { 53 | uint256 diff = min - x; 54 | uint256 rem = diff % size; 55 | if (rem == 0) return min; 56 | result = max - rem + 1; 57 | } 58 | } 59 | 60 | function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { 61 | result = _bound(x, min, max); 62 | console2_log_StdUtils("Bound Result", result); 63 | } 64 | 65 | function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { 66 | require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min."); 67 | 68 | // Shifting all int256 values to uint256 to use _bound function. The range of two types are: 69 | // int256 : -(2**255) ~ (2**255 - 1) 70 | // uint256: 0 ~ (2**256 - 1) 71 | // So, add 2**255, INT256_MIN_ABS to the integer values. 72 | // 73 | // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow. 74 | // So, use `~uint256(x) + 1` instead. 75 | uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS); 76 | uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS); 77 | uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS); 78 | 79 | uint256 y = _bound(_x, _min, _max); 80 | 81 | // To move it back to int256 value, subtract INT256_MIN_ABS at here. 82 | result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS); 83 | } 84 | 85 | function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { 86 | result = _bound(x, min, max); 87 | console2_log_StdUtils("Bound result", vm.toString(result)); 88 | } 89 | 90 | function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) { 91 | result = _bound(privateKey, 1, SECP256K1_ORDER - 1); 92 | } 93 | 94 | function bytesToUint(bytes memory b) internal pure virtual returns (uint256) { 95 | require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32."); 96 | return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); 97 | } 98 | 99 | /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce 100 | /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol) 101 | function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) { 102 | console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead."); 103 | return vm.computeCreateAddress(deployer, nonce); 104 | } 105 | 106 | function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer) 107 | internal 108 | pure 109 | virtual 110 | returns (address) 111 | { 112 | console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); 113 | return vm.computeCreate2Address(salt, initcodeHash, deployer); 114 | } 115 | 116 | /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer 117 | function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) { 118 | console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); 119 | return vm.computeCreate2Address(salt, initCodeHash); 120 | } 121 | 122 | /// @dev returns an initialized mock ERC20 contract 123 | function deployMockERC20(string memory name, string memory symbol, uint8 decimals) 124 | internal 125 | returns (MockERC20 mock) 126 | { 127 | mock = new MockERC20(); 128 | mock.initialize(name, symbol, decimals); 129 | } 130 | 131 | /// @dev returns an initialized mock ERC721 contract 132 | function deployMockERC721(string memory name, string memory symbol) internal returns (MockERC721 mock) { 133 | mock = new MockERC721(); 134 | mock.initialize(name, symbol); 135 | } 136 | 137 | /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments 138 | /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode 139 | function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) { 140 | return hashInitCode(creationCode, ""); 141 | } 142 | 143 | /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2 144 | /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode 145 | /// @param args the ABI-encoded arguments to the constructor of C 146 | function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) { 147 | return keccak256(abi.encodePacked(creationCode, args)); 148 | } 149 | 150 | // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses. 151 | function getTokenBalances(address token, address[] memory addresses) 152 | internal 153 | virtual 154 | returns (uint256[] memory balances) 155 | { 156 | uint256 tokenCodeSize; 157 | assembly { 158 | tokenCodeSize := extcodesize(token) 159 | } 160 | require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract."); 161 | 162 | // ABI encode the aggregate call to Multicall3. 163 | uint256 length = addresses.length; 164 | IMulticall3.Call[] memory calls = new IMulticall3.Call[](length); 165 | for (uint256 i = 0; i < length; ++i) { 166 | // 0x70a08231 = bytes4("balanceOf(address)")) 167 | calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))}); 168 | } 169 | 170 | // Make the aggregate call. 171 | (, bytes[] memory returnData) = multicall.aggregate(calls); 172 | 173 | // ABI decode the return data and return the balances. 174 | balances = new uint256[](length); 175 | for (uint256 i = 0; i < length; ++i) { 176 | balances[i] = abi.decode(returnData[i], (uint256)); 177 | } 178 | } 179 | 180 | /*////////////////////////////////////////////////////////////////////////// 181 | PRIVATE FUNCTIONS 182 | //////////////////////////////////////////////////////////////////////////*/ 183 | 184 | function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) { 185 | return address(uint160(uint256(bytesValue))); 186 | } 187 | 188 | // This section is used to prevent the compilation of console, which shortens the compilation time when console is 189 | // not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid 190 | // any breaking changes to function signatures. 191 | function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn) 192 | internal 193 | pure 194 | returns (function(bytes memory) internal pure fnOut) 195 | { 196 | assembly { 197 | fnOut := fnIn 198 | } 199 | } 200 | 201 | function _sendLogPayload(bytes memory payload) internal pure { 202 | _castLogPayloadViewToPure(_sendLogPayloadView)(payload); 203 | } 204 | 205 | function _sendLogPayloadView(bytes memory payload) private view { 206 | uint256 payloadLength = payload.length; 207 | address consoleAddress = CONSOLE2_ADDRESS; 208 | /// @solidity memory-safe-assembly 209 | assembly { 210 | let payloadStart := add(payload, 32) 211 | let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) 212 | } 213 | } 214 | 215 | function console2_log_StdUtils(string memory p0) private pure { 216 | _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); 217 | } 218 | 219 | function console2_log_StdUtils(string memory p0, uint256 p1) private pure { 220 | _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); 221 | } 222 | 223 | function console2_log_StdUtils(string memory p0, string memory p1) private pure { 224 | _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /lib/forge-std/test/fixtures/broadcast.log.json: -------------------------------------------------------------------------------- 1 | { 2 | "transactions": [ 3 | { 4 | "hash": "0xc6006863c267735a11476b7f15b15bc718e117e2da114a2be815dd651e1a509f", 5 | "type": "CALL", 6 | "contractName": "Test", 7 | "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 8 | "function": "multiple_arguments(uint256,address,uint256[]):(uint256)", 9 | "arguments": ["1", "0000000000000000000000000000000000001337", "[3,4]"], 10 | "tx": { 11 | "type": "0x02", 12 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 13 | "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 14 | "gas": "0x73b9", 15 | "value": "0x0", 16 | "data": "0x23e99187000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000013370000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004", 17 | "nonce": "0x3", 18 | "accessList": [] 19 | } 20 | }, 21 | { 22 | "hash": "0xedf2b38d8d896519a947a1acf720f859bb35c0c5ecb8dd7511995b67b9853298", 23 | "type": "CALL", 24 | "contractName": "Test", 25 | "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 26 | "function": "inc():(uint256)", 27 | "arguments": [], 28 | "tx": { 29 | "type": "0x02", 30 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 31 | "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 32 | "gas": "0xdcb2", 33 | "value": "0x0", 34 | "data": "0x371303c0", 35 | "nonce": "0x4", 36 | "accessList": [] 37 | } 38 | }, 39 | { 40 | "hash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c", 41 | "type": "CALL", 42 | "contractName": "Test", 43 | "contractAddress": "0x7c6b4bbe207d642d98d5c537142d85209e585087", 44 | "function": "t(uint256):(uint256)", 45 | "arguments": ["1"], 46 | "tx": { 47 | "type": "0x02", 48 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 49 | "to": "0x7c6b4bbe207d642d98d5c537142d85209e585087", 50 | "gas": "0x8599", 51 | "value": "0x0", 52 | "data": "0xafe29f710000000000000000000000000000000000000000000000000000000000000001", 53 | "nonce": "0x5", 54 | "accessList": [] 55 | } 56 | } 57 | ], 58 | "receipts": [ 59 | { 60 | "transactionHash": "0x481dc86e40bba90403c76f8e144aa9ff04c1da2164299d0298573835f0991181", 61 | "transactionIndex": "0x0", 62 | "blockHash": "0xef0730448490304e5403be0fa8f8ce64f118e9adcca60c07a2ae1ab921d748af", 63 | "blockNumber": "0x1", 64 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 65 | "to": null, 66 | "cumulativeGasUsed": "0x13f3a", 67 | "gasUsed": "0x13f3a", 68 | "contractAddress": "0x5fbdb2315678afecb367f032d93f642f64180aa3", 69 | "logs": [], 70 | "status": "0x1", 71 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 72 | "effectiveGasPrice": "0xee6b2800" 73 | }, 74 | { 75 | "transactionHash": "0x6a187183545b8a9e7f1790e847139379bf5622baff2cb43acf3f5c79470af782", 76 | "transactionIndex": "0x0", 77 | "blockHash": "0xf3acb96a90071640c2a8c067ae4e16aad87e634ea8d8bbbb5b352fba86ba0148", 78 | "blockNumber": "0x2", 79 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 80 | "to": null, 81 | "cumulativeGasUsed": "0x45d80", 82 | "gasUsed": "0x45d80", 83 | "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 84 | "logs": [], 85 | "status": "0x1", 86 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 87 | "effectiveGasPrice": "0xee6b2800" 88 | }, 89 | { 90 | "transactionHash": "0x064ad173b4867bdef2fb60060bbdaf01735fbf10414541ea857772974e74ea9d", 91 | "transactionIndex": "0x0", 92 | "blockHash": "0x8373d02109d3ee06a0225f23da4c161c656ccc48fe0fcee931d325508ae73e58", 93 | "blockNumber": "0x3", 94 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 95 | "to": "0x4e59b44847b379578588920ca78fbf26c0b4956c", 96 | "cumulativeGasUsed": "0x45feb", 97 | "gasUsed": "0x45feb", 98 | "contractAddress": null, 99 | "logs": [], 100 | "status": "0x1", 101 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 102 | "effectiveGasPrice": "0xee6b2800" 103 | }, 104 | { 105 | "transactionHash": "0xc6006863c267735a11476b7f15b15bc718e117e2da114a2be815dd651e1a509f", 106 | "transactionIndex": "0x0", 107 | "blockHash": "0x16712fae5c0e18f75045f84363fb6b4d9a9fe25e660c4ce286833a533c97f629", 108 | "blockNumber": "0x4", 109 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 110 | "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 111 | "cumulativeGasUsed": "0x5905", 112 | "gasUsed": "0x5905", 113 | "contractAddress": null, 114 | "logs": [], 115 | "status": "0x1", 116 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 117 | "effectiveGasPrice": "0xee6b2800" 118 | }, 119 | { 120 | "transactionHash": "0xedf2b38d8d896519a947a1acf720f859bb35c0c5ecb8dd7511995b67b9853298", 121 | "transactionIndex": "0x0", 122 | "blockHash": "0x156b88c3eb9a1244ba00a1834f3f70de735b39e3e59006dd03af4fe7d5480c11", 123 | "blockNumber": "0x5", 124 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 125 | "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 126 | "cumulativeGasUsed": "0xa9c4", 127 | "gasUsed": "0xa9c4", 128 | "contractAddress": null, 129 | "logs": [], 130 | "status": "0x1", 131 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 132 | "effectiveGasPrice": "0xee6b2800" 133 | }, 134 | { 135 | "transactionHash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c", 136 | "transactionIndex": "0x0", 137 | "blockHash": "0xcf61faca67dbb2c28952b0b8a379e53b1505ae0821e84779679390cb8571cadb", 138 | "blockNumber": "0x6", 139 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 140 | "to": "0x7c6b4bbe207d642d98d5c537142d85209e585087", 141 | "cumulativeGasUsed": "0x66c5", 142 | "gasUsed": "0x66c5", 143 | "contractAddress": null, 144 | "logs": [ 145 | { 146 | "address": "0x7c6b4bbe207d642d98d5c537142d85209e585087", 147 | "topics": [ 148 | "0x0b2e13ff20ac7b474198655583edf70dedd2c1dc980e329c4fbb2fc0748b796b" 149 | ], 150 | "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000046865726500000000000000000000000000000000000000000000000000000000", 151 | "blockHash": "0xcf61faca67dbb2c28952b0b8a379e53b1505ae0821e84779679390cb8571cadb", 152 | "blockNumber": "0x6", 153 | "transactionHash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c", 154 | "transactionIndex": "0x1", 155 | "logIndex": "0x0", 156 | "transactionLogIndex": "0x0", 157 | "removed": false 158 | } 159 | ], 160 | "status": "0x1", 161 | "logsBloom": "0x00000000000800000000000000000010000000000000000000000000000180000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100", 162 | "effectiveGasPrice": "0xee6b2800" 163 | }, 164 | { 165 | "transactionHash": "0x11fbb10230c168ca1e36a7e5c69a6dbcd04fd9e64ede39d10a83e36ee8065c16", 166 | "transactionIndex": "0x0", 167 | "blockHash": "0xf1e0ed2eda4e923626ec74621006ed50b3fc27580dc7b4cf68a07ca77420e29c", 168 | "blockNumber": "0x7", 169 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 170 | "to": "0x0000000000000000000000000000000000001337", 171 | "cumulativeGasUsed": "0x5208", 172 | "gasUsed": "0x5208", 173 | "contractAddress": null, 174 | "logs": [], 175 | "status": "0x1", 176 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 177 | "effectiveGasPrice": "0xee6b2800" 178 | } 179 | ], 180 | "libraries": [ 181 | "src/Broadcast.t.sol:F:0x5fbdb2315678afecb367f032d93f642f64180aa3" 182 | ], 183 | "pending": [], 184 | "path": "broadcast/Broadcast.t.sol/31337/run-latest.json", 185 | "returns": {}, 186 | "timestamp": 1655140035 187 | } 188 | -------------------------------------------------------------------------------- /lib/forge-std/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Copyright Contributors to Forge Standard Library 2 | 3 | Apache License 4 | Version 2.0, January 2004 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, 12 | and distribution as defined by Sections 1 through 9 of this document. 13 | 14 | "Licensor" shall mean the copyright owner or entity authorized by 15 | the copyright owner that is granting the License. 16 | 17 | "Legal Entity" shall mean the union of the acting entity and all 18 | other entities that control, are controlled by, or are under common 19 | control with that entity. For the purposes of this definition, 20 | "control" means (i) the power, direct or indirect, to cause the 21 | direction or management of such entity, whether by contract or 22 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | outstanding shares, or (iii) beneficial ownership of such entity. 24 | 25 | "You" (or "Your") shall mean an individual or Legal Entity 26 | exercising permissions granted by this License. 27 | 28 | "Source" form shall mean the preferred form for making modifications, 29 | including but not limited to software source code, documentation 30 | source, and configuration files. 31 | 32 | "Object" form shall mean any form resulting from mechanical 33 | transformation or translation of a Source form, including but 34 | not limited to compiled object code, generated documentation, 35 | and conversions to other media types. 36 | 37 | "Work" shall mean the work of authorship, whether in Source or 38 | Object form, made available under the License, as indicated by a 39 | copyright notice that is included in or attached to the work 40 | (an example is provided in the Appendix below). 41 | 42 | "Derivative Works" shall mean any work, whether in Source or Object 43 | form, that is based on (or derived from) the Work and for which the 44 | editorial revisions, annotations, elaborations, or other modifications 45 | represent, as a whole, an original work of authorship. For the purposes 46 | of this License, Derivative Works shall not include works that remain 47 | separable from, or merely link (or bind by name) to the interfaces of, 48 | the Work and Derivative Works thereof. 49 | 50 | "Contribution" shall mean any work of authorship, including 51 | the original version of the Work and any modifications or additions 52 | to that Work or Derivative Works thereof, that is intentionally 53 | submitted to Licensor for inclusion in the Work by the copyright owner 54 | or by an individual or Legal Entity authorized to submit on behalf of 55 | the copyright owner. For the purposes of this definition, "submitted" 56 | means any form of electronic, verbal, or written communication sent 57 | to the Licensor or its representatives, including but not limited to 58 | communication on electronic mailing lists, source code control systems, 59 | and issue tracking systems that are managed by, or on behalf of, the 60 | Licensor for the purpose of discussing and improving the Work, but 61 | excluding communication that is conspicuously marked or otherwise 62 | designated in writing by the copyright owner as "Not a Contribution." 63 | 64 | "Contributor" shall mean Licensor and any individual or Legal Entity 65 | on behalf of whom a Contribution has been received by Licensor and 66 | subsequently incorporated within the Work. 67 | 68 | 2. Grant of Copyright License. Subject to the terms and conditions of 69 | this License, each Contributor hereby grants to You a perpetual, 70 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 71 | copyright license to reproduce, prepare Derivative Works of, 72 | publicly display, publicly perform, sublicense, and distribute the 73 | Work and such Derivative Works in Source or Object form. 74 | 75 | 3. Grant of Patent License. Subject to the terms and conditions of 76 | this License, each Contributor hereby grants to You a perpetual, 77 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | (except as stated in this section) patent license to make, have made, 79 | use, offer to sell, sell, import, and otherwise transfer the Work, 80 | where such license applies only to those patent claims licensable 81 | by such Contributor that are necessarily infringed by their 82 | Contribution(s) alone or by combination of their Contribution(s) 83 | with the Work to which such Contribution(s) was submitted. If You 84 | institute patent litigation against any entity (including a 85 | cross-claim or counterclaim in a lawsuit) alleging that the Work 86 | or a Contribution incorporated within the Work constitutes direct 87 | or contributory patent infringement, then any patent licenses 88 | granted to You under this License for that Work shall terminate 89 | as of the date such litigation is filed. 90 | 91 | 4. Redistribution. You may reproduce and distribute copies of the 92 | Work or Derivative Works thereof in any medium, with or without 93 | modifications, and in Source or Object form, provided that You 94 | meet the following conditions: 95 | 96 | (a) You must give any other recipients of the Work or 97 | Derivative Works a copy of this License; and 98 | 99 | (b) You must cause any modified files to carry prominent notices 100 | stating that You changed the files; and 101 | 102 | (c) You must retain, in the Source form of any Derivative Works 103 | that You distribute, all copyright, patent, trademark, and 104 | attribution notices from the Source form of the Work, 105 | excluding those notices that do not pertain to any part of 106 | the Derivative Works; and 107 | 108 | (d) If the Work includes a "NOTICE" text file as part of its 109 | distribution, then any Derivative Works that You distribute must 110 | include a readable copy of the attribution notices contained 111 | within such NOTICE file, excluding those notices that do not 112 | pertain to any part of the Derivative Works, in at least one 113 | of the following places: within a NOTICE text file distributed 114 | as part of the Derivative Works; within the Source form or 115 | documentation, if provided along with the Derivative Works; or, 116 | within a display generated by the Derivative Works, if and 117 | wherever such third-party notices normally appear. The contents 118 | of the NOTICE file are for informational purposes only and 119 | do not modify the License. You may add Your own attribution 120 | notices within Derivative Works that You distribute, alongside 121 | or as an addendum to the NOTICE text from the Work, provided 122 | that such additional attribution notices cannot be construed 123 | as modifying the License. 124 | 125 | You may add Your own copyright statement to Your modifications and 126 | may provide additional or different license terms and conditions 127 | for use, reproduction, or distribution of Your modifications, or 128 | for any such Derivative Works as a whole, provided Your use, 129 | reproduction, and distribution of the Work otherwise complies with 130 | the conditions stated in this License. 131 | 132 | 5. Submission of Contributions. Unless You explicitly state otherwise, 133 | any Contribution intentionally submitted for inclusion in the Work 134 | by You to the Licensor shall be under the terms and conditions of 135 | this License, without any additional terms or conditions. 136 | Notwithstanding the above, nothing herein shall supersede or modify 137 | the terms of any separate license agreement you may have executed 138 | with Licensor regarding such Contributions. 139 | 140 | 6. Trademarks. This License does not grant permission to use the trade 141 | names, trademarks, service marks, or product names of the Licensor, 142 | except as required for reasonable and customary use in describing the 143 | origin of the Work and reproducing the content of the NOTICE file. 144 | 145 | 7. Disclaimer of Warranty. Unless required by applicable law or 146 | agreed to in writing, Licensor provides the Work (and each 147 | Contributor provides its Contributions) on an "AS IS" BASIS, 148 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 149 | implied, including, without limitation, any warranties or conditions 150 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any 153 | risks associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, 156 | whether in tort (including negligence), contract, or otherwise, 157 | unless required by applicable law (such as deliberate and grossly 158 | negligent acts) or agreed to in writing, shall any Contributor be 159 | liable to You for damages, including any direct, indirect, special, 160 | incidental, or consequential damages of any character arising as a 161 | result of this License or out of the use or inability to use the 162 | Work (including but not limited to damages for loss of goodwill, 163 | work stoppage, computer failure or malfunction, or any and all 164 | other commercial damages or losses), even if such Contributor 165 | has been advised of the possibility of such damages. 166 | 167 | 9. Accepting Warranty or Additional Liability. While redistributing 168 | the Work or Derivative Works thereof, You may choose to offer, 169 | and charge a fee for, acceptance of support, warranty, indemnity, 170 | or other liability obligations and/or rights consistent with this 171 | License. However, in accepting such obligations, You may act only 172 | on Your own behalf and on Your sole responsibility, not on behalf 173 | of any other Contributor, and only if You agree to indemnify, 174 | defend, and hold each Contributor harmless for any liability 175 | incurred by, or claims asserted against, such Contributor by reason 176 | of your accepting any such warranty or additional liability. 177 | 178 | END OF TERMS AND CONDITIONS 179 | 180 | APPENDIX: How to apply the Apache License to your work. 181 | 182 | To apply the Apache License to your work, attach the following 183 | boilerplate notice, with the fields enclosed by brackets "[]" 184 | replaced with your own identifying information. (Don't include 185 | the brackets!) The text should be enclosed in the appropriate 186 | comment syntax for the file format. We also recommend that a 187 | file or class name and description of purpose be included on the 188 | same "printed page" as the copyright notice for easier 189 | identification within third-party archives. 190 | 191 | Copyright [yyyy] [name of copyright owner] 192 | 193 | Licensed under the Apache License, Version 2.0 (the "License"); 194 | you may not use this file except in compliance with the License. 195 | You may obtain a copy of the License at 196 | 197 | http://www.apache.org/licenses/LICENSE-2.0 198 | 199 | Unless required by applicable law or agreed to in writing, software 200 | distributed under the License is distributed on an "AS IS" BASIS, 201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | See the License for the specific language governing permissions and 203 | limitations under the License. 204 | -------------------------------------------------------------------------------- /lib/forge-std/src/StdStyle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | import {VmSafe} from "./Vm.sol"; 5 | 6 | library StdStyle { 7 | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); 8 | 9 | string constant RED = "\u001b[91m"; 10 | string constant GREEN = "\u001b[92m"; 11 | string constant YELLOW = "\u001b[93m"; 12 | string constant BLUE = "\u001b[94m"; 13 | string constant MAGENTA = "\u001b[95m"; 14 | string constant CYAN = "\u001b[96m"; 15 | string constant BOLD = "\u001b[1m"; 16 | string constant DIM = "\u001b[2m"; 17 | string constant ITALIC = "\u001b[3m"; 18 | string constant UNDERLINE = "\u001b[4m"; 19 | string constant INVERSE = "\u001b[7m"; 20 | string constant RESET = "\u001b[0m"; 21 | 22 | function styleConcat(string memory style, string memory self) private pure returns (string memory) { 23 | return string(abi.encodePacked(style, self, RESET)); 24 | } 25 | 26 | function red(string memory self) internal pure returns (string memory) { 27 | return styleConcat(RED, self); 28 | } 29 | 30 | function red(uint256 self) internal pure returns (string memory) { 31 | return red(vm.toString(self)); 32 | } 33 | 34 | function red(int256 self) internal pure returns (string memory) { 35 | return red(vm.toString(self)); 36 | } 37 | 38 | function red(address self) internal pure returns (string memory) { 39 | return red(vm.toString(self)); 40 | } 41 | 42 | function red(bool self) internal pure returns (string memory) { 43 | return red(vm.toString(self)); 44 | } 45 | 46 | function redBytes(bytes memory self) internal pure returns (string memory) { 47 | return red(vm.toString(self)); 48 | } 49 | 50 | function redBytes32(bytes32 self) internal pure returns (string memory) { 51 | return red(vm.toString(self)); 52 | } 53 | 54 | function green(string memory self) internal pure returns (string memory) { 55 | return styleConcat(GREEN, self); 56 | } 57 | 58 | function green(uint256 self) internal pure returns (string memory) { 59 | return green(vm.toString(self)); 60 | } 61 | 62 | function green(int256 self) internal pure returns (string memory) { 63 | return green(vm.toString(self)); 64 | } 65 | 66 | function green(address self) internal pure returns (string memory) { 67 | return green(vm.toString(self)); 68 | } 69 | 70 | function green(bool self) internal pure returns (string memory) { 71 | return green(vm.toString(self)); 72 | } 73 | 74 | function greenBytes(bytes memory self) internal pure returns (string memory) { 75 | return green(vm.toString(self)); 76 | } 77 | 78 | function greenBytes32(bytes32 self) internal pure returns (string memory) { 79 | return green(vm.toString(self)); 80 | } 81 | 82 | function yellow(string memory self) internal pure returns (string memory) { 83 | return styleConcat(YELLOW, self); 84 | } 85 | 86 | function yellow(uint256 self) internal pure returns (string memory) { 87 | return yellow(vm.toString(self)); 88 | } 89 | 90 | function yellow(int256 self) internal pure returns (string memory) { 91 | return yellow(vm.toString(self)); 92 | } 93 | 94 | function yellow(address self) internal pure returns (string memory) { 95 | return yellow(vm.toString(self)); 96 | } 97 | 98 | function yellow(bool self) internal pure returns (string memory) { 99 | return yellow(vm.toString(self)); 100 | } 101 | 102 | function yellowBytes(bytes memory self) internal pure returns (string memory) { 103 | return yellow(vm.toString(self)); 104 | } 105 | 106 | function yellowBytes32(bytes32 self) internal pure returns (string memory) { 107 | return yellow(vm.toString(self)); 108 | } 109 | 110 | function blue(string memory self) internal pure returns (string memory) { 111 | return styleConcat(BLUE, self); 112 | } 113 | 114 | function blue(uint256 self) internal pure returns (string memory) { 115 | return blue(vm.toString(self)); 116 | } 117 | 118 | function blue(int256 self) internal pure returns (string memory) { 119 | return blue(vm.toString(self)); 120 | } 121 | 122 | function blue(address self) internal pure returns (string memory) { 123 | return blue(vm.toString(self)); 124 | } 125 | 126 | function blue(bool self) internal pure returns (string memory) { 127 | return blue(vm.toString(self)); 128 | } 129 | 130 | function blueBytes(bytes memory self) internal pure returns (string memory) { 131 | return blue(vm.toString(self)); 132 | } 133 | 134 | function blueBytes32(bytes32 self) internal pure returns (string memory) { 135 | return blue(vm.toString(self)); 136 | } 137 | 138 | function magenta(string memory self) internal pure returns (string memory) { 139 | return styleConcat(MAGENTA, self); 140 | } 141 | 142 | function magenta(uint256 self) internal pure returns (string memory) { 143 | return magenta(vm.toString(self)); 144 | } 145 | 146 | function magenta(int256 self) internal pure returns (string memory) { 147 | return magenta(vm.toString(self)); 148 | } 149 | 150 | function magenta(address self) internal pure returns (string memory) { 151 | return magenta(vm.toString(self)); 152 | } 153 | 154 | function magenta(bool self) internal pure returns (string memory) { 155 | return magenta(vm.toString(self)); 156 | } 157 | 158 | function magentaBytes(bytes memory self) internal pure returns (string memory) { 159 | return magenta(vm.toString(self)); 160 | } 161 | 162 | function magentaBytes32(bytes32 self) internal pure returns (string memory) { 163 | return magenta(vm.toString(self)); 164 | } 165 | 166 | function cyan(string memory self) internal pure returns (string memory) { 167 | return styleConcat(CYAN, self); 168 | } 169 | 170 | function cyan(uint256 self) internal pure returns (string memory) { 171 | return cyan(vm.toString(self)); 172 | } 173 | 174 | function cyan(int256 self) internal pure returns (string memory) { 175 | return cyan(vm.toString(self)); 176 | } 177 | 178 | function cyan(address self) internal pure returns (string memory) { 179 | return cyan(vm.toString(self)); 180 | } 181 | 182 | function cyan(bool self) internal pure returns (string memory) { 183 | return cyan(vm.toString(self)); 184 | } 185 | 186 | function cyanBytes(bytes memory self) internal pure returns (string memory) { 187 | return cyan(vm.toString(self)); 188 | } 189 | 190 | function cyanBytes32(bytes32 self) internal pure returns (string memory) { 191 | return cyan(vm.toString(self)); 192 | } 193 | 194 | function bold(string memory self) internal pure returns (string memory) { 195 | return styleConcat(BOLD, self); 196 | } 197 | 198 | function bold(uint256 self) internal pure returns (string memory) { 199 | return bold(vm.toString(self)); 200 | } 201 | 202 | function bold(int256 self) internal pure returns (string memory) { 203 | return bold(vm.toString(self)); 204 | } 205 | 206 | function bold(address self) internal pure returns (string memory) { 207 | return bold(vm.toString(self)); 208 | } 209 | 210 | function bold(bool self) internal pure returns (string memory) { 211 | return bold(vm.toString(self)); 212 | } 213 | 214 | function boldBytes(bytes memory self) internal pure returns (string memory) { 215 | return bold(vm.toString(self)); 216 | } 217 | 218 | function boldBytes32(bytes32 self) internal pure returns (string memory) { 219 | return bold(vm.toString(self)); 220 | } 221 | 222 | function dim(string memory self) internal pure returns (string memory) { 223 | return styleConcat(DIM, self); 224 | } 225 | 226 | function dim(uint256 self) internal pure returns (string memory) { 227 | return dim(vm.toString(self)); 228 | } 229 | 230 | function dim(int256 self) internal pure returns (string memory) { 231 | return dim(vm.toString(self)); 232 | } 233 | 234 | function dim(address self) internal pure returns (string memory) { 235 | return dim(vm.toString(self)); 236 | } 237 | 238 | function dim(bool self) internal pure returns (string memory) { 239 | return dim(vm.toString(self)); 240 | } 241 | 242 | function dimBytes(bytes memory self) internal pure returns (string memory) { 243 | return dim(vm.toString(self)); 244 | } 245 | 246 | function dimBytes32(bytes32 self) internal pure returns (string memory) { 247 | return dim(vm.toString(self)); 248 | } 249 | 250 | function italic(string memory self) internal pure returns (string memory) { 251 | return styleConcat(ITALIC, self); 252 | } 253 | 254 | function italic(uint256 self) internal pure returns (string memory) { 255 | return italic(vm.toString(self)); 256 | } 257 | 258 | function italic(int256 self) internal pure returns (string memory) { 259 | return italic(vm.toString(self)); 260 | } 261 | 262 | function italic(address self) internal pure returns (string memory) { 263 | return italic(vm.toString(self)); 264 | } 265 | 266 | function italic(bool self) internal pure returns (string memory) { 267 | return italic(vm.toString(self)); 268 | } 269 | 270 | function italicBytes(bytes memory self) internal pure returns (string memory) { 271 | return italic(vm.toString(self)); 272 | } 273 | 274 | function italicBytes32(bytes32 self) internal pure returns (string memory) { 275 | return italic(vm.toString(self)); 276 | } 277 | 278 | function underline(string memory self) internal pure returns (string memory) { 279 | return styleConcat(UNDERLINE, self); 280 | } 281 | 282 | function underline(uint256 self) internal pure returns (string memory) { 283 | return underline(vm.toString(self)); 284 | } 285 | 286 | function underline(int256 self) internal pure returns (string memory) { 287 | return underline(vm.toString(self)); 288 | } 289 | 290 | function underline(address self) internal pure returns (string memory) { 291 | return underline(vm.toString(self)); 292 | } 293 | 294 | function underline(bool self) internal pure returns (string memory) { 295 | return underline(vm.toString(self)); 296 | } 297 | 298 | function underlineBytes(bytes memory self) internal pure returns (string memory) { 299 | return underline(vm.toString(self)); 300 | } 301 | 302 | function underlineBytes32(bytes32 self) internal pure returns (string memory) { 303 | return underline(vm.toString(self)); 304 | } 305 | 306 | function inverse(string memory self) internal pure returns (string memory) { 307 | return styleConcat(INVERSE, self); 308 | } 309 | 310 | function inverse(uint256 self) internal pure returns (string memory) { 311 | return inverse(vm.toString(self)); 312 | } 313 | 314 | function inverse(int256 self) internal pure returns (string memory) { 315 | return inverse(vm.toString(self)); 316 | } 317 | 318 | function inverse(address self) internal pure returns (string memory) { 319 | return inverse(vm.toString(self)); 320 | } 321 | 322 | function inverse(bool self) internal pure returns (string memory) { 323 | return inverse(vm.toString(self)); 324 | } 325 | 326 | function inverseBytes(bytes memory self) internal pure returns (string memory) { 327 | return inverse(vm.toString(self)); 328 | } 329 | 330 | function inverseBytes32(bytes32 self) internal pure returns (string memory) { 331 | return inverse(vm.toString(self)); 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /lib/forge-std/src/interfaces/IERC4626.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2; 3 | 4 | import "./IERC20.sol"; 5 | 6 | /// @dev Interface of the ERC4626 "Tokenized Vault Standard", as defined in 7 | /// https://eips.ethereum.org/EIPS/eip-4626 8 | interface IERC4626 is IERC20 { 9 | event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares); 10 | 11 | event Withdraw( 12 | address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares 13 | ); 14 | 15 | /// @notice Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing. 16 | /// @dev 17 | /// - MUST be an ERC-20 token contract. 18 | /// - MUST NOT revert. 19 | function asset() external view returns (address assetTokenAddress); 20 | 21 | /// @notice Returns the total amount of the underlying asset that is “managed” by Vault. 22 | /// @dev 23 | /// - SHOULD include any compounding that occurs from yield. 24 | /// - MUST be inclusive of any fees that are charged against assets in the Vault. 25 | /// - MUST NOT revert. 26 | function totalAssets() external view returns (uint256 totalManagedAssets); 27 | 28 | /// @notice Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal 29 | /// scenario where all the conditions are met. 30 | /// @dev 31 | /// - MUST NOT be inclusive of any fees that are charged against assets in the Vault. 32 | /// - MUST NOT show any variations depending on the caller. 33 | /// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. 34 | /// - MUST NOT revert. 35 | /// 36 | /// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the 37 | /// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and 38 | /// from. 39 | function convertToShares(uint256 assets) external view returns (uint256 shares); 40 | 41 | /// @notice Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal 42 | /// scenario where all the conditions are met. 43 | /// @dev 44 | /// - MUST NOT be inclusive of any fees that are charged against assets in the Vault. 45 | /// - MUST NOT show any variations depending on the caller. 46 | /// - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange. 47 | /// - MUST NOT revert. 48 | /// 49 | /// NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the 50 | /// “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and 51 | /// from. 52 | function convertToAssets(uint256 shares) external view returns (uint256 assets); 53 | 54 | /// @notice Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver, 55 | /// through a deposit call. 56 | /// @dev 57 | /// - MUST return a limited value if receiver is subject to some deposit limit. 58 | /// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited. 59 | /// - MUST NOT revert. 60 | function maxDeposit(address receiver) external view returns (uint256 maxAssets); 61 | 62 | /// @notice Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given 63 | /// current on-chain conditions. 64 | /// @dev 65 | /// - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit 66 | /// call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called 67 | /// in the same transaction. 68 | /// - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the 69 | /// deposit would be accepted, regardless if the user has enough tokens approved, etc. 70 | /// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. 71 | /// - MUST NOT revert. 72 | /// 73 | /// NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in 74 | /// share price or some other type of condition, meaning the depositor will lose assets by depositing. 75 | function previewDeposit(uint256 assets) external view returns (uint256 shares); 76 | 77 | /// @notice Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens. 78 | /// @dev 79 | /// - MUST emit the Deposit event. 80 | /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the 81 | /// deposit execution, and are accounted for during deposit. 82 | /// - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not 83 | /// approving enough underlying tokens to the Vault contract, etc). 84 | /// 85 | /// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. 86 | function deposit(uint256 assets, address receiver) external returns (uint256 shares); 87 | 88 | /// @notice Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call. 89 | /// @dev 90 | /// - MUST return a limited value if receiver is subject to some mint limit. 91 | /// - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted. 92 | /// - MUST NOT revert. 93 | function maxMint(address receiver) external view returns (uint256 maxShares); 94 | 95 | /// @notice Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given 96 | /// current on-chain conditions. 97 | /// @dev 98 | /// - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call 99 | /// in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the 100 | /// same transaction. 101 | /// - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint 102 | /// would be accepted, regardless if the user has enough tokens approved, etc. 103 | /// - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees. 104 | /// - MUST NOT revert. 105 | /// 106 | /// NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in 107 | /// share price or some other type of condition, meaning the depositor will lose assets by minting. 108 | function previewMint(uint256 shares) external view returns (uint256 assets); 109 | 110 | /// @notice Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens. 111 | /// @dev 112 | /// - MUST emit the Deposit event. 113 | /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint 114 | /// execution, and are accounted for during mint. 115 | /// - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not 116 | /// approving enough underlying tokens to the Vault contract, etc). 117 | /// 118 | /// NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token. 119 | function mint(uint256 shares, address receiver) external returns (uint256 assets); 120 | 121 | /// @notice Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the 122 | /// Vault, through a withdraw call. 123 | /// @dev 124 | /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock. 125 | /// - MUST NOT revert. 126 | function maxWithdraw(address owner) external view returns (uint256 maxAssets); 127 | 128 | /// @notice Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, 129 | /// given current on-chain conditions. 130 | /// @dev 131 | /// - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw 132 | /// call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if 133 | /// called 134 | /// in the same transaction. 135 | /// - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though 136 | /// the withdrawal would be accepted, regardless if the user has enough shares, etc. 137 | /// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. 138 | /// - MUST NOT revert. 139 | /// 140 | /// NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in 141 | /// share price or some other type of condition, meaning the depositor will lose assets by depositing. 142 | function previewWithdraw(uint256 assets) external view returns (uint256 shares); 143 | 144 | /// @notice Burns shares from owner and sends exactly assets of underlying tokens to receiver. 145 | /// @dev 146 | /// - MUST emit the Withdraw event. 147 | /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the 148 | /// withdraw execution, and are accounted for during withdraw. 149 | /// - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner 150 | /// not having enough shares, etc). 151 | /// 152 | /// Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed. 153 | /// Those methods should be performed separately. 154 | function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares); 155 | 156 | /// @notice Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault, 157 | /// through a redeem call. 158 | /// @dev 159 | /// - MUST return a limited value if owner is subject to some withdrawal limit or timelock. 160 | /// - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock. 161 | /// - MUST NOT revert. 162 | function maxRedeem(address owner) external view returns (uint256 maxShares); 163 | 164 | /// @notice Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block, 165 | /// given current on-chain conditions. 166 | /// @dev 167 | /// - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call 168 | /// in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the 169 | /// same transaction. 170 | /// - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the 171 | /// redemption would be accepted, regardless if the user has enough shares, etc. 172 | /// - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees. 173 | /// - MUST NOT revert. 174 | /// 175 | /// NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in 176 | /// share price or some other type of condition, meaning the depositor will lose assets by redeeming. 177 | function previewRedeem(uint256 shares) external view returns (uint256 assets); 178 | 179 | /// @notice Burns exactly shares from owner and sends assets of underlying tokens to receiver. 180 | /// @dev 181 | /// - MUST emit the Withdraw event. 182 | /// - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the 183 | /// redeem execution, and are accounted for during redeem. 184 | /// - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner 185 | /// not having enough shares, etc). 186 | /// 187 | /// NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed. 188 | /// Those methods should be performed separately. 189 | function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); 190 | } 191 | -------------------------------------------------------------------------------- /lib/forge-std/src/StdChains.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | import {VmSafe} from "./Vm.sol"; 5 | 6 | /** 7 | * StdChains provides information about EVM compatible chains that can be used in scripts/tests. 8 | * For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are 9 | * identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of 10 | * the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the 11 | * alias used in this contract, which can be found as the first argument to the 12 | * `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function. 13 | * 14 | * There are two main ways to use this contract: 15 | * 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or 16 | * `setChain(string memory chainAlias, Chain memory chain)` 17 | * 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`. 18 | * 19 | * The first time either of those are used, chains are initialized with the default set of RPC URLs. 20 | * This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in 21 | * `defaultRpcUrls`. 22 | * 23 | * The `setChain` function is straightforward, and it simply saves off the given chain data. 24 | * 25 | * The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say 26 | * we want to retrieve the RPC URL for `mainnet`: 27 | * - If you have specified data with `setChain`, it will return that. 28 | * - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it 29 | * is valid (e.g. a URL is specified, or an environment variable is given and exists). 30 | * - If neither of the above conditions is met, the default data is returned. 31 | * 32 | * Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults. 33 | */ 34 | abstract contract StdChains { 35 | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); 36 | 37 | bool private stdChainsInitialized; 38 | 39 | struct ChainData { 40 | string name; 41 | uint256 chainId; 42 | string rpcUrl; 43 | } 44 | 45 | struct Chain { 46 | // The chain name. 47 | string name; 48 | // The chain's Chain ID. 49 | uint256 chainId; 50 | // The chain's alias. (i.e. what gets specified in `foundry.toml`). 51 | string chainAlias; 52 | // A default RPC endpoint for this chain. 53 | // NOTE: This default RPC URL is included for convenience to facilitate quick tests and 54 | // experimentation. Do not use this RPC URL for production test suites, CI, or other heavy 55 | // usage as you will be throttled and this is a disservice to others who need this endpoint. 56 | string rpcUrl; 57 | } 58 | 59 | // Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data. 60 | mapping(string => Chain) private chains; 61 | // Maps from the chain's alias to it's default RPC URL. 62 | mapping(string => string) private defaultRpcUrls; 63 | // Maps from a chain ID to it's alias. 64 | mapping(uint256 => string) private idToAlias; 65 | 66 | bool private fallbackToDefaultRpcUrls = true; 67 | 68 | // The RPC URL will be fetched from config or defaultRpcUrls if possible. 69 | function getChain(string memory chainAlias) internal virtual returns (Chain memory chain) { 70 | require(bytes(chainAlias).length != 0, "StdChains getChain(string): Chain alias cannot be the empty string."); 71 | 72 | initializeStdChains(); 73 | chain = chains[chainAlias]; 74 | require( 75 | chain.chainId != 0, 76 | string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found.")) 77 | ); 78 | 79 | chain = getChainWithUpdatedRpcUrl(chainAlias, chain); 80 | } 81 | 82 | function getChain(uint256 chainId) internal virtual returns (Chain memory chain) { 83 | require(chainId != 0, "StdChains getChain(uint256): Chain ID cannot be 0."); 84 | initializeStdChains(); 85 | string memory chainAlias = idToAlias[chainId]; 86 | 87 | chain = chains[chainAlias]; 88 | 89 | require( 90 | chain.chainId != 0, 91 | string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found.")) 92 | ); 93 | 94 | chain = getChainWithUpdatedRpcUrl(chainAlias, chain); 95 | } 96 | 97 | // set chain info, with priority to argument's rpcUrl field. 98 | function setChain(string memory chainAlias, ChainData memory chain) internal virtual { 99 | require( 100 | bytes(chainAlias).length != 0, 101 | "StdChains setChain(string,ChainData): Chain alias cannot be the empty string." 102 | ); 103 | 104 | require(chain.chainId != 0, "StdChains setChain(string,ChainData): Chain ID cannot be 0."); 105 | 106 | initializeStdChains(); 107 | string memory foundAlias = idToAlias[chain.chainId]; 108 | 109 | require( 110 | bytes(foundAlias).length == 0 || keccak256(bytes(foundAlias)) == keccak256(bytes(chainAlias)), 111 | string( 112 | abi.encodePacked( 113 | "StdChains setChain(string,ChainData): Chain ID ", 114 | vm.toString(chain.chainId), 115 | " already used by \"", 116 | foundAlias, 117 | "\"." 118 | ) 119 | ) 120 | ); 121 | 122 | uint256 oldChainId = chains[chainAlias].chainId; 123 | delete idToAlias[oldChainId]; 124 | 125 | chains[chainAlias] = 126 | Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl}); 127 | idToAlias[chain.chainId] = chainAlias; 128 | } 129 | 130 | // set chain info, with priority to argument's rpcUrl field. 131 | function setChain(string memory chainAlias, Chain memory chain) internal virtual { 132 | setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl})); 133 | } 134 | 135 | function _toUpper(string memory str) private pure returns (string memory) { 136 | bytes memory strb = bytes(str); 137 | bytes memory copy = new bytes(strb.length); 138 | for (uint256 i = 0; i < strb.length; i++) { 139 | bytes1 b = strb[i]; 140 | if (b >= 0x61 && b <= 0x7A) { 141 | copy[i] = bytes1(uint8(b) - 32); 142 | } else { 143 | copy[i] = b; 144 | } 145 | } 146 | return string(copy); 147 | } 148 | 149 | // lookup rpcUrl, in descending order of priority: 150 | // current -> config (foundry.toml) -> environment variable -> default 151 | function getChainWithUpdatedRpcUrl(string memory chainAlias, Chain memory chain) 152 | private 153 | view 154 | returns (Chain memory) 155 | { 156 | if (bytes(chain.rpcUrl).length == 0) { 157 | try vm.rpcUrl(chainAlias) returns (string memory configRpcUrl) { 158 | chain.rpcUrl = configRpcUrl; 159 | } catch (bytes memory err) { 160 | string memory envName = string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL")); 161 | if (fallbackToDefaultRpcUrls) { 162 | chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]); 163 | } else { 164 | chain.rpcUrl = vm.envString(envName); 165 | } 166 | // Distinguish 'not found' from 'cannot read' 167 | // The upstream error thrown by forge for failing cheats changed so we check both the old and new versions 168 | bytes memory oldNotFoundError = 169 | abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias))); 170 | bytes memory newNotFoundError = abi.encodeWithSignature( 171 | "CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias)) 172 | ); 173 | bytes32 errHash = keccak256(err); 174 | if ( 175 | (errHash != keccak256(oldNotFoundError) && errHash != keccak256(newNotFoundError)) 176 | || bytes(chain.rpcUrl).length == 0 177 | ) { 178 | /// @solidity memory-safe-assembly 179 | assembly { 180 | revert(add(32, err), mload(err)) 181 | } 182 | } 183 | } 184 | } 185 | return chain; 186 | } 187 | 188 | function setFallbackToDefaultRpcUrls(bool useDefault) internal { 189 | fallbackToDefaultRpcUrls = useDefault; 190 | } 191 | 192 | function initializeStdChains() private { 193 | if (stdChainsInitialized) return; 194 | 195 | stdChainsInitialized = true; 196 | 197 | // If adding an RPC here, make sure to test the default RPC URL in `testRpcs` 198 | setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545")); 199 | setChainWithDefaultRpcUrl( 200 | "mainnet", ChainData("Mainnet", 1, "https://mainnet.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001") 201 | ); 202 | setChainWithDefaultRpcUrl( 203 | "goerli", ChainData("Goerli", 5, "https://goerli.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001") 204 | ); 205 | setChainWithDefaultRpcUrl( 206 | "sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001") 207 | ); 208 | setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io")); 209 | setChainWithDefaultRpcUrl("optimism_goerli", ChainData("Optimism Goerli", 420, "https://goerli.optimism.io")); 210 | setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc")); 211 | setChainWithDefaultRpcUrl( 212 | "arbitrum_one_goerli", ChainData("Arbitrum One Goerli", 421613, "https://goerli-rollup.arbitrum.io/rpc") 213 | ); 214 | setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc")); 215 | setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com")); 216 | setChainWithDefaultRpcUrl( 217 | "polygon_mumbai", ChainData("Polygon Mumbai", 80001, "https://rpc-mumbai.maticvigil.com") 218 | ); 219 | setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc")); 220 | setChainWithDefaultRpcUrl( 221 | "avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc") 222 | ); 223 | setChainWithDefaultRpcUrl( 224 | "bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org") 225 | ); 226 | setChainWithDefaultRpcUrl( 227 | "bnb_smart_chain_testnet", 228 | ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel") 229 | ); 230 | setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com")); 231 | setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network")); 232 | setChainWithDefaultRpcUrl( 233 | "moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network") 234 | ); 235 | setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network")); 236 | setChainWithDefaultRpcUrl("base_goerli", ChainData("Base Goerli", 84531, "https://goerli.base.org")); 237 | setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org")); 238 | } 239 | 240 | // set chain info, with priority to chainAlias' rpc url in foundry.toml 241 | function setChainWithDefaultRpcUrl(string memory chainAlias, ChainData memory chain) private { 242 | string memory rpcUrl = chain.rpcUrl; 243 | defaultRpcUrls[chainAlias] = rpcUrl; 244 | chain.rpcUrl = ""; 245 | setChain(chainAlias, chain); 246 | chain.rpcUrl = rpcUrl; // restore argument 247 | } 248 | } 249 | -------------------------------------------------------------------------------- /src/ERC404.sol: -------------------------------------------------------------------------------- 1 | //SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.0; 3 | 4 | abstract contract Ownable { 5 | event OwnershipTransferred(address indexed user, address indexed newOwner); 6 | 7 | error Unauthorized(); 8 | error InvalidOwner(); 9 | 10 | address public owner; 11 | 12 | modifier onlyOwner() virtual { 13 | if (msg.sender != owner) revert Unauthorized(); 14 | 15 | _; 16 | } 17 | 18 | constructor(address _owner) { 19 | if (_owner == address(0)) revert InvalidOwner(); 20 | 21 | owner = _owner; 22 | 23 | emit OwnershipTransferred(address(0), _owner); 24 | } 25 | 26 | function transferOwnership(address _owner) public virtual onlyOwner { 27 | if (_owner == address(0)) revert InvalidOwner(); 28 | 29 | owner = _owner; 30 | 31 | emit OwnershipTransferred(msg.sender, _owner); 32 | } 33 | 34 | function revokeOwnership() public virtual onlyOwner { 35 | owner = address(0); 36 | 37 | emit OwnershipTransferred(msg.sender, address(0)); 38 | } 39 | } 40 | 41 | abstract contract ERC721Receiver { 42 | function onERC721Received( 43 | address, 44 | address, 45 | uint256, 46 | bytes calldata 47 | ) external virtual returns (bytes4) { 48 | return ERC721Receiver.onERC721Received.selector; 49 | } 50 | } 51 | 52 | /// @notice ERC404 53 | /// A gas-efficient, mixed ERC20 / ERC721 implementation 54 | /// with native liquidity and fractionalization. 55 | /// 56 | /// This is an experimental standard designed to integrate 57 | /// with pre-existing ERC20 / ERC721 support as smoothly as 58 | /// possible. 59 | /// 60 | /// @dev In order to support full functionality of ERC20 and ERC721 61 | /// supply assumptions are made that slightly constraint usage. 62 | /// Ensure decimals are sufficiently large (standard 18 recommended) 63 | /// as ids are effectively encoded in the lowest range of amounts. 64 | /// 65 | /// NFTs are spent on ERC20 functions in a FILO queue, this is by 66 | /// design. 67 | /// 68 | abstract contract ERC404 is Ownable { 69 | // Events 70 | event ERC20Transfer( 71 | address indexed from, 72 | address indexed to, 73 | uint256 amount 74 | ); 75 | event Approval( 76 | address indexed owner, 77 | address indexed spender, 78 | uint256 amount 79 | ); 80 | event Transfer( 81 | address indexed from, 82 | address indexed to, 83 | uint256 indexed id 84 | ); 85 | event ERC721Approval( 86 | address indexed owner, 87 | address indexed spender, 88 | uint256 indexed id 89 | ); 90 | event ApprovalForAll( 91 | address indexed owner, 92 | address indexed operator, 93 | bool approved 94 | ); 95 | 96 | // Errors 97 | error NotFound(); 98 | error AlreadyExists(); 99 | error InvalidRecipient(); 100 | error InvalidSender(); 101 | error UnsafeRecipient(); 102 | 103 | // Metadata 104 | /// @dev Token name 105 | string public name; 106 | 107 | /// @dev Token symbol 108 | string public symbol; 109 | 110 | /// @dev Decimals for fractional representation 111 | uint8 public immutable decimals; 112 | 113 | /// @dev Total supply in fractionalized representation 114 | uint256 public immutable totalSupply; 115 | 116 | /// @dev Current mint counter, monotonically increasing to ensure accurate ownership 117 | uint256 public minted; 118 | 119 | // Mappings 120 | /// @dev Balance of user in fractional representation 121 | mapping(address => uint256) public balanceOf; 122 | 123 | /// @dev Allowance of user in fractional representation 124 | mapping(address => mapping(address => uint256)) public allowance; 125 | 126 | /// @dev Approval in native representaion 127 | mapping(uint256 => address) public getApproved; 128 | 129 | /// @dev Approval for all in native representation 130 | mapping(address => mapping(address => bool)) public isApprovedForAll; 131 | 132 | /// @dev Owner of id in native representation 133 | mapping(uint256 => address) internal _ownerOf; 134 | 135 | /// @dev Array of owned ids in native representation 136 | mapping(address => uint256[]) internal _owned; 137 | 138 | /// @dev Tracks indices for the _owned mapping 139 | mapping(uint256 => uint256) internal _ownedIndex; 140 | 141 | /// @dev Addresses whitelisted from minting / burning for gas savings (pairs, routers, etc) 142 | mapping(address => bool) public whitelist; 143 | 144 | // Constructor 145 | constructor( 146 | string memory _name, 147 | string memory _symbol, 148 | uint8 _decimals, 149 | uint256 _totalNativeSupply, 150 | address _owner 151 | ) Ownable(_owner) { 152 | name = _name; 153 | symbol = _symbol; 154 | decimals = _decimals; 155 | totalSupply = _totalNativeSupply * (10 ** decimals); 156 | } 157 | 158 | /// @notice Initialization function to set pairs / etc 159 | /// saving gas by avoiding mint / burn on unnecessary targets 160 | function setWhitelist(address target, bool state) public onlyOwner { 161 | whitelist[target] = state; 162 | } 163 | 164 | /// @notice Function to find owner of a given native token 165 | function ownerOf(uint256 id) public view virtual returns (address owner) { 166 | owner = _ownerOf[id]; 167 | 168 | if (owner == address(0)) { 169 | revert NotFound(); 170 | } 171 | } 172 | 173 | /// @notice tokenURI must be implemented by child contract 174 | function tokenURI(uint256 id) public view virtual returns (string memory); 175 | 176 | /// @notice Function for token approvals 177 | /// @dev This function assumes id / native if amount less than or equal to current max id 178 | function approve( 179 | address spender, 180 | uint256 amountOrId 181 | ) public virtual returns (bool) { 182 | if (amountOrId <= minted && amountOrId > 0) { 183 | address owner = _ownerOf[amountOrId]; 184 | 185 | if (msg.sender != owner && !isApprovedForAll[owner][msg.sender]) { 186 | revert Unauthorized(); 187 | } 188 | 189 | getApproved[amountOrId] = spender; 190 | 191 | emit Approval(owner, spender, amountOrId); 192 | } else { 193 | allowance[msg.sender][spender] = amountOrId; 194 | 195 | emit Approval(msg.sender, spender, amountOrId); 196 | } 197 | 198 | return true; 199 | } 200 | 201 | /// @notice Function native approvals 202 | function setApprovalForAll(address operator, bool approved) public virtual { 203 | isApprovedForAll[msg.sender][operator] = approved; 204 | 205 | emit ApprovalForAll(msg.sender, operator, approved); 206 | } 207 | 208 | /// @notice Function for mixed transfers 209 | /// @dev This function assumes id / native if amount less than or equal to current max id 210 | function transferFrom( 211 | address from, 212 | address to, 213 | uint256 amountOrId 214 | ) public virtual { 215 | if (amountOrId <= minted) { 216 | if (from != _ownerOf[amountOrId]) { 217 | revert InvalidSender(); 218 | } 219 | 220 | if (to == address(0)) { 221 | revert InvalidRecipient(); 222 | } 223 | 224 | if ( 225 | msg.sender != from && 226 | !isApprovedForAll[from][msg.sender] && 227 | msg.sender != getApproved[amountOrId] 228 | ) { 229 | revert Unauthorized(); 230 | } 231 | 232 | balanceOf[from] -= _getUnit(); 233 | 234 | unchecked { 235 | balanceOf[to] += _getUnit(); 236 | } 237 | 238 | _ownerOf[amountOrId] = to; 239 | delete getApproved[amountOrId]; 240 | 241 | // update _owned for sender 242 | uint256 updatedId = _owned[from][_owned[from].length - 1]; 243 | _owned[from][_ownedIndex[amountOrId]] = updatedId; 244 | // pop 245 | _owned[from].pop(); 246 | // update index for the moved id 247 | _ownedIndex[updatedId] = _ownedIndex[amountOrId]; 248 | // push token to to owned 249 | _owned[to].push(amountOrId); 250 | // update index for to owned 251 | _ownedIndex[amountOrId] = _owned[to].length - 1; 252 | 253 | emit Transfer(from, to, amountOrId); 254 | emit ERC20Transfer(from, to, _getUnit()); 255 | } else { 256 | uint256 allowed = allowance[from][msg.sender]; 257 | 258 | if (allowed != type(uint256).max) 259 | allowance[from][msg.sender] = allowed - amountOrId; 260 | 261 | _transfer(from, to, amountOrId); 262 | } 263 | } 264 | 265 | /// @notice Function for fractional transfers 266 | function transfer( 267 | address to, 268 | uint256 amount 269 | ) public virtual returns (bool) { 270 | return _transfer(msg.sender, to, amount); 271 | } 272 | 273 | /// @notice Function for native transfers with contract support 274 | function safeTransferFrom( 275 | address from, 276 | address to, 277 | uint256 id 278 | ) public virtual { 279 | transferFrom(from, to, id); 280 | 281 | if ( 282 | to.code.length != 0 && 283 | ERC721Receiver(to).onERC721Received(msg.sender, from, id, "") != 284 | ERC721Receiver.onERC721Received.selector 285 | ) { 286 | revert UnsafeRecipient(); 287 | } 288 | } 289 | 290 | /// @notice Function for native transfers with contract support and callback data 291 | function safeTransferFrom( 292 | address from, 293 | address to, 294 | uint256 id, 295 | bytes calldata data 296 | ) public virtual { 297 | transferFrom(from, to, id); 298 | 299 | if ( 300 | to.code.length != 0 && 301 | ERC721Receiver(to).onERC721Received(msg.sender, from, id, data) != 302 | ERC721Receiver.onERC721Received.selector 303 | ) { 304 | revert UnsafeRecipient(); 305 | } 306 | } 307 | 308 | /// @notice Internal function for fractional transfers 309 | function _transfer( 310 | address from, 311 | address to, 312 | uint256 amount 313 | ) internal returns (bool) { 314 | uint256 unit = _getUnit(); 315 | uint256 balanceBeforeSender = balanceOf[from]; 316 | uint256 balanceBeforeReceiver = balanceOf[to]; 317 | 318 | balanceOf[from] -= amount; 319 | 320 | unchecked { 321 | balanceOf[to] += amount; 322 | } 323 | 324 | // Skip burn for certain addresses to save gas 325 | if (!whitelist[from]) { 326 | uint256 tokens_to_burn = (balanceBeforeSender / unit) - 327 | (balanceOf[from] / unit); 328 | for (uint256 i = 0; i < tokens_to_burn; i++) { 329 | _burn(from); 330 | } 331 | } 332 | 333 | // Skip minting for certain addresses to save gas 334 | if (!whitelist[to]) { 335 | uint256 tokens_to_mint = (balanceOf[to] / unit) - 336 | (balanceBeforeReceiver / unit); 337 | for (uint256 i = 0; i < tokens_to_mint; i++) { 338 | _mint(to); 339 | } 340 | } 341 | 342 | emit ERC20Transfer(from, to, amount); 343 | return true; 344 | } 345 | 346 | // Internal utility logic 347 | function _getUnit() internal view returns (uint256) { 348 | return 10 ** decimals; 349 | } 350 | 351 | function _mint(address to) internal virtual { 352 | if (to == address(0)) { 353 | revert InvalidRecipient(); 354 | } 355 | 356 | unchecked { 357 | minted++; 358 | } 359 | 360 | uint256 id = minted; 361 | 362 | if (_ownerOf[id] != address(0)) { 363 | revert AlreadyExists(); 364 | } 365 | 366 | _ownerOf[id] = to; 367 | _owned[to].push(id); 368 | _ownedIndex[id] = _owned[to].length - 1; 369 | 370 | emit Transfer(address(0), to, id); 371 | } 372 | 373 | function _burn(address from) internal virtual { 374 | if (from == address(0)) { 375 | revert InvalidSender(); 376 | } 377 | 378 | uint256 id = _owned[from][_owned[from].length - 1]; 379 | _owned[from].pop(); 380 | delete _ownedIndex[id]; 381 | delete _ownerOf[id]; 382 | delete getApproved[id]; 383 | 384 | emit Transfer(from, address(0), id); 385 | } 386 | 387 | function _setNameSymbol( 388 | string memory _name, 389 | string memory _symbol 390 | ) internal { 391 | name = _name; 392 | symbol = _symbol; 393 | } 394 | } 395 | -------------------------------------------------------------------------------- /lib/forge-std/test/StdStorage.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.7.0 <0.9.0; 3 | 4 | import "../src/StdStorage.sol"; 5 | import "../src/Test.sol"; 6 | 7 | contract StdStorageTest is Test { 8 | using stdStorage for StdStorage; 9 | 10 | StorageTest internal test; 11 | 12 | function setUp() public { 13 | test = new StorageTest(); 14 | } 15 | 16 | function test_StorageHidden() public { 17 | assertEq(uint256(keccak256("my.random.var")), stdstore.target(address(test)).sig("hidden()").find()); 18 | } 19 | 20 | function test_StorageObvious() public { 21 | assertEq(uint256(0), stdstore.target(address(test)).sig("exists()").find()); 22 | } 23 | 24 | function test_StorageExtraSload() public { 25 | assertEq(16, stdstore.target(address(test)).sig(test.extra_sload.selector).find()); 26 | } 27 | 28 | function test_StorageCheckedWriteHidden() public { 29 | stdstore.target(address(test)).sig(test.hidden.selector).checked_write(100); 30 | assertEq(uint256(test.hidden()), 100); 31 | } 32 | 33 | function test_StorageCheckedWriteObvious() public { 34 | stdstore.target(address(test)).sig(test.exists.selector).checked_write(100); 35 | assertEq(test.exists(), 100); 36 | } 37 | 38 | function test_StorageCheckedWriteSignedIntegerHidden() public { 39 | stdstore.target(address(test)).sig(test.hidden.selector).checked_write_int(-100); 40 | assertEq(int256(uint256(test.hidden())), -100); 41 | } 42 | 43 | function test_StorageCheckedWriteSignedIntegerObvious() public { 44 | stdstore.target(address(test)).sig(test.tG.selector).checked_write_int(-100); 45 | assertEq(test.tG(), -100); 46 | } 47 | 48 | function test_StorageMapStructA() public { 49 | uint256 slot = 50 | stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(0).find(); 51 | assertEq(uint256(keccak256(abi.encode(address(this), 4))), slot); 52 | } 53 | 54 | function test_StorageMapStructB() public { 55 | uint256 slot = 56 | stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(1).find(); 57 | assertEq(uint256(keccak256(abi.encode(address(this), 4))) + 1, slot); 58 | } 59 | 60 | function test_StorageDeepMap() public { 61 | uint256 slot = stdstore.target(address(test)).sig(test.deep_map.selector).with_key(address(this)).with_key( 62 | address(this) 63 | ).find(); 64 | assertEq(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(5)))))), slot); 65 | } 66 | 67 | function test_StorageCheckedWriteDeepMap() public { 68 | stdstore.target(address(test)).sig(test.deep_map.selector).with_key(address(this)).with_key(address(this)) 69 | .checked_write(100); 70 | assertEq(100, test.deep_map(address(this), address(this))); 71 | } 72 | 73 | function test_StorageDeepMapStructA() public { 74 | uint256 slot = stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)) 75 | .with_key(address(this)).depth(0).find(); 76 | assertEq( 77 | bytes32(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 0), 78 | bytes32(slot) 79 | ); 80 | } 81 | 82 | function test_StorageDeepMapStructB() public { 83 | uint256 slot = stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)) 84 | .with_key(address(this)).depth(1).find(); 85 | assertEq( 86 | bytes32(uint256(keccak256(abi.encode(address(this), keccak256(abi.encode(address(this), uint256(6)))))) + 1), 87 | bytes32(slot) 88 | ); 89 | } 90 | 91 | function test_StorageCheckedWriteDeepMapStructA() public { 92 | stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)).with_key( 93 | address(this) 94 | ).depth(0).checked_write(100); 95 | (uint256 a, uint256 b) = test.deep_map_struct(address(this), address(this)); 96 | assertEq(100, a); 97 | assertEq(0, b); 98 | } 99 | 100 | function test_StorageCheckedWriteDeepMapStructB() public { 101 | stdstore.target(address(test)).sig(test.deep_map_struct.selector).with_key(address(this)).with_key( 102 | address(this) 103 | ).depth(1).checked_write(100); 104 | (uint256 a, uint256 b) = test.deep_map_struct(address(this), address(this)); 105 | assertEq(0, a); 106 | assertEq(100, b); 107 | } 108 | 109 | function test_StorageCheckedWriteMapStructA() public { 110 | stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(0).checked_write(100); 111 | (uint256 a, uint256 b) = test.map_struct(address(this)); 112 | assertEq(a, 100); 113 | assertEq(b, 0); 114 | } 115 | 116 | function test_StorageCheckedWriteMapStructB() public { 117 | stdstore.target(address(test)).sig(test.map_struct.selector).with_key(address(this)).depth(1).checked_write(100); 118 | (uint256 a, uint256 b) = test.map_struct(address(this)); 119 | assertEq(a, 0); 120 | assertEq(b, 100); 121 | } 122 | 123 | function test_StorageStructA() public { 124 | uint256 slot = stdstore.target(address(test)).sig(test.basic.selector).depth(0).find(); 125 | assertEq(uint256(7), slot); 126 | } 127 | 128 | function test_StorageStructB() public { 129 | uint256 slot = stdstore.target(address(test)).sig(test.basic.selector).depth(1).find(); 130 | assertEq(uint256(7) + 1, slot); 131 | } 132 | 133 | function test_StorageCheckedWriteStructA() public { 134 | stdstore.target(address(test)).sig(test.basic.selector).depth(0).checked_write(100); 135 | (uint256 a, uint256 b) = test.basic(); 136 | assertEq(a, 100); 137 | assertEq(b, 1337); 138 | } 139 | 140 | function test_StorageCheckedWriteStructB() public { 141 | stdstore.target(address(test)).sig(test.basic.selector).depth(1).checked_write(100); 142 | (uint256 a, uint256 b) = test.basic(); 143 | assertEq(a, 1337); 144 | assertEq(b, 100); 145 | } 146 | 147 | function test_StorageMapAddrFound() public { 148 | uint256 slot = stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).find(); 149 | assertEq(uint256(keccak256(abi.encode(address(this), uint256(1)))), slot); 150 | } 151 | 152 | function test_StorageMapAddrRoot() public { 153 | (uint256 slot, bytes32 key) = 154 | stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).parent(); 155 | assertEq(address(uint160(uint256(key))), address(this)); 156 | assertEq(uint256(1), slot); 157 | slot = stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).root(); 158 | assertEq(uint256(1), slot); 159 | } 160 | 161 | function test_StorageMapUintFound() public { 162 | uint256 slot = stdstore.target(address(test)).sig(test.map_uint.selector).with_key(100).find(); 163 | assertEq(uint256(keccak256(abi.encode(100, uint256(2)))), slot); 164 | } 165 | 166 | function test_StorageCheckedWriteMapUint() public { 167 | stdstore.target(address(test)).sig(test.map_uint.selector).with_key(100).checked_write(100); 168 | assertEq(100, test.map_uint(100)); 169 | } 170 | 171 | function test_StorageCheckedWriteMapAddr() public { 172 | stdstore.target(address(test)).sig(test.map_addr.selector).with_key(address(this)).checked_write(100); 173 | assertEq(100, test.map_addr(address(this))); 174 | } 175 | 176 | function test_StorageCheckedWriteMapBool() public { 177 | stdstore.target(address(test)).sig(test.map_bool.selector).with_key(address(this)).checked_write(true); 178 | assertTrue(test.map_bool(address(this))); 179 | } 180 | 181 | function testFail_StorageCheckedWriteMapPacked() public { 182 | // expect PackedSlot error but not external call so cant expectRevert 183 | stdstore.target(address(test)).sig(test.read_struct_lower.selector).with_key(address(uint160(1337))) 184 | .checked_write(100); 185 | } 186 | 187 | function test_StorageCheckedWriteMapPackedSuccess() public { 188 | uint256 full = test.map_packed(address(1337)); 189 | // keep upper 128, set lower 128 to 1337 190 | full = (full & (uint256((1 << 128) - 1) << 128)) | 1337; 191 | stdstore.target(address(test)).sig(test.map_packed.selector).with_key(address(uint160(1337))).checked_write( 192 | full 193 | ); 194 | assertEq(1337, test.read_struct_lower(address(1337))); 195 | } 196 | 197 | function testFail_StorageConst() public { 198 | // vm.expectRevert(abi.encodeWithSignature("NotStorage(bytes4)", bytes4(keccak256("const()")))); 199 | stdstore.target(address(test)).sig("const()").find(); 200 | } 201 | 202 | function testFail_StorageNativePack() public { 203 | stdstore.target(address(test)).sig(test.tA.selector).find(); 204 | stdstore.target(address(test)).sig(test.tB.selector).find(); 205 | 206 | // these both would fail 207 | stdstore.target(address(test)).sig(test.tC.selector).find(); 208 | stdstore.target(address(test)).sig(test.tD.selector).find(); 209 | } 210 | 211 | function test_StorageReadBytes32() public { 212 | bytes32 val = stdstore.target(address(test)).sig(test.tE.selector).read_bytes32(); 213 | assertEq(val, hex"1337"); 214 | } 215 | 216 | function test_StorageReadBool_False() public { 217 | bool val = stdstore.target(address(test)).sig(test.tB.selector).read_bool(); 218 | assertEq(val, false); 219 | } 220 | 221 | function test_StorageReadBool_True() public { 222 | bool val = stdstore.target(address(test)).sig(test.tH.selector).read_bool(); 223 | assertEq(val, true); 224 | } 225 | 226 | function test_StorageReadBool_Revert() public { 227 | vm.expectRevert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool."); 228 | this.readNonBoolValue(); 229 | } 230 | 231 | function readNonBoolValue() public { 232 | stdstore.target(address(test)).sig(test.tE.selector).read_bool(); 233 | } 234 | 235 | function test_StorageReadAddress() public { 236 | address val = stdstore.target(address(test)).sig(test.tF.selector).read_address(); 237 | assertEq(val, address(1337)); 238 | } 239 | 240 | function test_StorageReadUint() public { 241 | uint256 val = stdstore.target(address(test)).sig(test.exists.selector).read_uint(); 242 | assertEq(val, 1); 243 | } 244 | 245 | function test_StorageReadInt() public { 246 | int256 val = stdstore.target(address(test)).sig(test.tG.selector).read_int(); 247 | assertEq(val, type(int256).min); 248 | } 249 | } 250 | 251 | contract StorageTest { 252 | uint256 public exists = 1; 253 | mapping(address => uint256) public map_addr; 254 | mapping(uint256 => uint256) public map_uint; 255 | mapping(address => uint256) public map_packed; 256 | mapping(address => UnpackedStruct) public map_struct; 257 | mapping(address => mapping(address => uint256)) public deep_map; 258 | mapping(address => mapping(address => UnpackedStruct)) public deep_map_struct; 259 | UnpackedStruct public basic; 260 | 261 | uint248 public tA; 262 | bool public tB; 263 | 264 | bool public tC = false; 265 | uint248 public tD = 1; 266 | 267 | struct UnpackedStruct { 268 | uint256 a; 269 | uint256 b; 270 | } 271 | 272 | mapping(address => bool) public map_bool; 273 | 274 | bytes32 public tE = hex"1337"; 275 | address public tF = address(1337); 276 | int256 public tG = type(int256).min; 277 | bool public tH = true; 278 | bytes32 private tI = ~bytes32(hex"1337"); 279 | 280 | constructor() { 281 | basic = UnpackedStruct({a: 1337, b: 1337}); 282 | 283 | uint256 two = (1 << 128) | 1; 284 | map_packed[msg.sender] = two; 285 | map_packed[address(uint160(1337))] = 1 << 128; 286 | } 287 | 288 | function read_struct_upper(address who) public view returns (uint256) { 289 | return map_packed[who] >> 128; 290 | } 291 | 292 | function read_struct_lower(address who) public view returns (uint256) { 293 | return map_packed[who] & ((1 << 128) - 1); 294 | } 295 | 296 | function hidden() public view returns (bytes32 t) { 297 | bytes32 slot = keccak256("my.random.var"); 298 | /// @solidity memory-safe-assembly 299 | assembly { 300 | t := sload(slot) 301 | } 302 | } 303 | 304 | function const() public pure returns (bytes32 t) { 305 | t = bytes32(hex"1337"); 306 | } 307 | 308 | function extra_sload() public view returns (bytes32 t) { 309 | // trigger read on slot `tE`, and make a staticcall to make sure compiler doesn't optimize this SLOAD away 310 | assembly { 311 | pop(staticcall(gas(), sload(tE.slot), 0, 0, 0, 0)) 312 | } 313 | t = tI; 314 | } 315 | } 316 | --------------------------------------------------------------------------------