├── .env.example ├── .github └── workflows │ ├── ci.yml │ └── pr.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .solhint.json ├── .solhintignore ├── LICENSE.md ├── README.md ├── assets └── trilemma.png ├── foundry.toml ├── lib ├── forge-std │ ├── .github │ │ └── workflows │ │ │ ├── ci.yml │ │ │ └── sync.yml │ ├── .gitignore │ ├── .gitmodules │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── foundry.toml │ ├── lib │ │ └── ds-test │ │ │ ├── .github │ │ │ └── workflows │ │ │ │ └── build.yml │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── Makefile │ │ │ ├── default.nix │ │ │ ├── demo │ │ │ └── demo.sol │ │ │ ├── package.json │ │ │ └── src │ │ │ ├── test.sol │ │ │ └── test.t.sol │ ├── package.json │ ├── src │ │ ├── Base.sol │ │ ├── Script.sol │ │ ├── StdAssertions.sol │ │ ├── StdChains.sol │ │ ├── StdCheats.sol │ │ ├── StdError.sol │ │ ├── StdInvariant.sol │ │ ├── StdJson.sol │ │ ├── StdMath.sol │ │ ├── StdStorage.sol │ │ ├── StdStyle.sol │ │ ├── StdUtils.sol │ │ ├── Test.sol │ │ ├── Vm.sol │ │ ├── console.sol │ │ ├── console2.sol │ │ ├── interfaces │ │ │ ├── IERC1155.sol │ │ │ ├── IERC165.sol │ │ │ ├── IERC20.sol │ │ │ ├── IERC4626.sol │ │ │ ├── IERC721.sol │ │ │ └── IMulticall3.sol │ │ └── safeconsole.sol │ └── test │ │ ├── StdAssertions.t.sol │ │ ├── StdChains.t.sol │ │ ├── StdCheats.t.sol │ │ ├── StdError.t.sol │ │ ├── StdMath.t.sol │ │ ├── StdStorage.t.sol │ │ ├── StdStyle.t.sol │ │ ├── StdUtils.t.sol │ │ ├── Vm.t.sol │ │ ├── compilation │ │ ├── CompilationScript.sol │ │ ├── CompilationScriptBase.sol │ │ ├── CompilationTest.sol │ │ └── CompilationTestBase.sol │ │ └── fixtures │ │ └── broadcast.log.json └── solmate │ ├── .gas-snapshot │ ├── .gitattributes │ ├── .github │ ├── pull_request_template.md │ └── workflows │ │ └── tests.yml │ ├── .gitignore │ ├── .gitmodules │ ├── .prettierignore │ ├── .prettierrc │ ├── LICENSE │ ├── README.md │ ├── audits │ └── v6-Fixed-Point-Solutions.pdf │ ├── foundry.toml │ ├── lib │ └── ds-test │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── default.nix │ │ ├── demo │ │ └── demo.sol │ │ ├── package.json │ │ └── src │ │ └── test.sol │ ├── package-lock.json │ ├── package.json │ └── src │ ├── auth │ ├── Auth.sol │ ├── Owned.sol │ └── authorities │ │ ├── MultiRolesAuthority.sol │ │ └── RolesAuthority.sol │ ├── mixins │ └── ERC4626.sol │ ├── test │ ├── Auth.t.sol │ ├── Bytes32AddressLib.t.sol │ ├── CREATE3.t.sol │ ├── DSTestPlus.t.sol │ ├── ERC1155.t.sol │ ├── ERC20.t.sol │ ├── ERC4626.t.sol │ ├── ERC6909.t.sol │ ├── ERC721.t.sol │ ├── FixedPointMathLib.t.sol │ ├── LibString.t.sol │ ├── MerkleProofLib.t.sol │ ├── MultiRolesAuthority.t.sol │ ├── Owned.t.sol │ ├── ReentrancyGuard.t.sol │ ├── RolesAuthority.t.sol │ ├── SSTORE2.t.sol │ ├── SafeCastLib.t.sol │ ├── SafeTransferLib.t.sol │ ├── SignedWadMath.t.sol │ ├── WETH.t.sol │ └── utils │ │ ├── DSInvariantTest.sol │ │ ├── DSTestPlus.sol │ │ ├── Hevm.sol │ │ ├── mocks │ │ ├── MockAuthChild.sol │ │ ├── MockAuthority.sol │ │ ├── MockERC1155.sol │ │ ├── MockERC20.sol │ │ ├── MockERC4626.sol │ │ ├── MockERC6909.sol │ │ ├── MockERC721.sol │ │ └── MockOwned.sol │ │ └── weird-tokens │ │ ├── MissingReturnToken.sol │ │ ├── ReturnsFalseToken.sol │ │ ├── ReturnsGarbageToken.sol │ │ ├── ReturnsTooLittleToken.sol │ │ ├── ReturnsTooMuchToken.sol │ │ ├── ReturnsTwoToken.sol │ │ └── RevertingToken.sol │ ├── tokens │ ├── ERC1155.sol │ ├── ERC20.sol │ ├── ERC6909.sol │ ├── ERC721.sol │ └── WETH.sol │ └── utils │ ├── Bytes32AddressLib.sol │ ├── CREATE3.sol │ ├── FixedPointMathLib.sol │ ├── LibString.sol │ ├── MerkleProofLib.sol │ ├── ReentrancyGuard.sol │ ├── SSTORE2.sol │ ├── SafeCastLib.sol │ ├── SafeTransferLib.sol │ └── SignedWadMath.sol ├── package-lock.json ├── package.json ├── pyproject.toml ├── remappings.txt ├── src ├── create2 │ ├── Create2Factory.sol │ └── interfaces │ │ ├── ICreate2Factory.sol │ │ └── ICreate2FactoryAdmin.sol ├── create3 │ ├── Create3Factory.sol │ └── interfaces │ │ ├── ICreate3Factory.sol │ │ └── ICreate3FactoryAdmin.sol └── dependencies │ ├── access │ ├── Context.sol │ └── Ownable.sol │ ├── cryptography │ └── ECDSA.sol │ ├── libraries │ ├── Address.sol │ ├── StorageSlot.sol │ └── Strings.sol │ ├── proxy │ ├── ERC1967Proxy.sol │ ├── ERC1967Utils.sol │ ├── Proxy.sol │ ├── interfaces │ │ ├── IBeacon.sol │ │ └── IERC1822.sol │ └── utils │ │ ├── Initializable.sol │ │ └── UUPSUpgradeable.sol │ └── token │ └── interfaces │ └── IERC20.sol └── test ├── create2 ├── Create2Factory.admin.t.sol ├── Create2Factory.t.sol ├── common │ ├── Constants.t.sol │ ├── contracts │ │ ├── Child.args.t.sol │ │ ├── Child.noargs.t.sol │ │ └── TestSetup.t.sol │ ├── interfaces │ │ └── IChild.t.sol │ └── libraries │ │ └── AddressLib.t.sol └── helpers │ └── DeploymentHelper.t.sol ├── create3 ├── Create3Factory.admin.t.sol ├── Create3Factory.t.sol ├── common │ ├── Constants.t.sol │ ├── contracts │ │ ├── Child.args.t.sol │ │ ├── Child.noargs.t.sol │ │ ├── Children.args.t.sol │ │ └── TestSetup.t.sol │ ├── interfaces │ │ └── IChild.t.sol │ └── libraries │ │ └── AddressLib.t.sol └── helpers │ └── DeploymentHelper.t.sol └── proxy └── ERC1967Proxy.t.sol /.env.example: -------------------------------------------------------------------------------- 1 | ETHEREUM_RPC=your_rpc_url -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | 8 | env: 9 | ETHEREUM_RPC: ${{ secrets.ETHEREUM_RPC }} 10 | 11 | jobs: 12 | run-ci: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | with: 17 | submodules: recursive 18 | 19 | - uses: actions/setup-node@v3 20 | 21 | - name: Install node dependencies 22 | run: npm install 23 | 24 | - name: Set up python 25 | id: setup-python 26 | uses: actions/setup-python@v3 27 | with: 28 | python-version: 3.9 29 | 30 | - name: Install Poetry 31 | uses: snok/install-poetry@v1 32 | 33 | - name: Load cached venv 34 | id: cached-poetry-dependencies 35 | uses: actions/cache@v3 36 | with: 37 | path: .venv 38 | key: venv-${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }} 39 | 40 | - name: Install python dependencies 41 | run: poetry install --no-interaction 42 | 43 | - name: Install Foundry 44 | uses: onbjerg/foundry-toolchain@v1 45 | with: 46 | version: nightly 47 | 48 | - name: Pull Submodules 49 | run: forge update 50 | 51 | - name: Check formatting 52 | run: npm run format:check 53 | 54 | - name: Check linting 55 | run: npm run lint:check 56 | 57 | - name: Run tests 58 | run: forge test --optimize --fork-url ${{ env.ETHEREUM_RPC }} 59 | 60 | - name: Coverage 61 | run: | 62 | sudo apt update && sudo apt install -y lcov 63 | npm run coverage 64 | id: coverage 65 | 66 | - uses: codecov/codecov-action@v2 67 | 68 | # Too slow to run regularly 69 | #- name: Run audit 70 | # run: poetry run slither --solc-remaps @openzeppelin=lib/openzeppelin-contracts --solc-args optimize src/ 71 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: pr 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | 10 | permissions: 11 | contents: read 12 | pull-requests: read 13 | 14 | jobs: 15 | check-title: 16 | runs-on: ubuntu-latest 17 | 18 | name: Validate PR title 19 | steps: 20 | - uses: amannn/action-semantic-pull-request@v5 21 | env: 22 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # misc 2 | .DS_Store 3 | *.pem 4 | cache/ 5 | broadcast/ 6 | 7 | # production 8 | out/ 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # testing 14 | lcov.info 15 | .gas-snapshot 16 | 17 | # local env files 18 | .env 19 | 20 | # editor 21 | .vscode 22 | .idea -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no -- commitlint --edit ${1} 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npm run format && npm run lint:check && npm run test 5 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:recommended", 3 | "rules": { 4 | "compiler-version": ["error",">=0.8.0"], 5 | "no-inline-assembly": ["off", ">=0.8.0"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.solhintignore: -------------------------------------------------------------------------------- 1 | src/dependencies -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Chain Rule, LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xSafe Contracts 2 | 3 | ## Deterministic Multi-Chain Deployment 4 | 5 | 🏆 Introducing xSafe, the new gold standard for intent-based CREATE3 contract deployments. Deploy your contracts to the same address on many chains–no nonces, no salts. 6 | 7 | ## The Multi-Chain Deployment Trilemma 8 | 9 | ![Multi-chain Deployment Trilemma](assets/trilemma.png) 10 | 11 | ### The Problem with EOA Deployments 12 | 13 | Traditionally, achieving the same address on many chains requires careful (manual) EOA nonce management. Mess up the nonce once, start all over. 14 | 15 | ### The Problem with CREATE2 16 | 17 | The `CREATE2` opcode can generate identical addresses, but when constructor arguments vary across chains, differing contract bytecode results in distinct addresses. An intent-based solution, [like this](src/create2/Create2Factory.sol), obviates salt storage, but addresses still depend on contract bytecode. 18 | 19 | ### The Problem with CREATE3 20 | 21 | A `CREATE3` approach offers an elegant solution, irrespective of contract bytecode, but still requires users to memorize salts. 22 | 23 | ## The Solution 24 | 25 | [xSafe](src/create3/Create3Factory.sol) achieves same-address deployment with no bytecode dependence, no nonce tracking, and no salt storage. Under the hood, salts are derived from principals' signatures, thereby allowing agents to deploy contracts on behalf of signers. 26 | 27 | ## Testing 28 | 29 | ### 1. Environment Variables 30 | 31 | Create a `.env` file in the project root directory and add your RPC URL. 32 | 33 | ```dotenv 34 | RPC_URL="your_rpc_url_here" 35 | ``` 36 | 37 | ### 2. Install Dependencies 38 | 39 | Install npm dependencies: 40 | 41 | ```bash 42 | npm install 43 | ``` 44 | 45 | Install Foundry dependencies: 46 | 47 | ```bash 48 | forge install 49 | ``` 50 | 51 | ### 3. Run Tests 52 | 53 | Execute the tests using Foundry: 54 | 55 | ```bash 56 | forge test 57 | ``` 58 | -------------------------------------------------------------------------------- /assets/trilemma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chainrule-labs/xsafe-contracts/5d7b42ea7890988ac4732243e505ee9f5b56b6ee/assets/trilemma.png -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = "src" 3 | out = "out" 4 | libs = ["lib"] 5 | solc = "0.8.21" 6 | gas_reports = ["*"] 7 | fuzz_max_global_rejects = 100000 8 | 9 | [fmt] 10 | line_length = 120 11 | tab_width = 4 12 | bracket_spacing = true 13 | int_types = "long" 14 | multiline_func_header = "attributes_first" 15 | quote_style = "double" 16 | number_underscore = "preserve" 17 | override_spacing = true 18 | wrap_comments = false 19 | ignore = [".github/"] 20 | 21 | # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options -------------------------------------------------------------------------------- /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/.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/.gitignore: -------------------------------------------------------------------------------- 1 | cache/ 2 | out/ 3 | .vscode 4 | .idea 5 | -------------------------------------------------------------------------------- /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/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/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/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/lib/ds-test/.gitignore: -------------------------------------------------------------------------------- 1 | /.dapple 2 | /build 3 | /out 4 | /cache/ 5 | -------------------------------------------------------------------------------- /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/default.nix: -------------------------------------------------------------------------------- 1 | { solidityPackage, dappsys }: solidityPackage { 2 | name = "ds-test"; 3 | src = ./src; 4 | } 5 | -------------------------------------------------------------------------------- /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/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "forge-std", 3 | "version": "1.7.1", 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/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/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/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/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/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/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/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 | -------------------------------------------------------------------------------- /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 {T1} 67 | 68 | uint256[] public someArr; 69 | bytes someBytes; 70 | 71 | function assertionError() public pure { 72 | assert(false); 73 | } 74 | 75 | function arithmeticError(uint256 a) public pure { 76 | a -= 100; 77 | } 78 | 79 | function divError(uint256 a) public pure { 80 | 100 / a; 81 | } 82 | 83 | function modError(uint256 a) public pure { 84 | 100 % a; 85 | } 86 | 87 | function enumConversion(uint256 a) public pure { 88 | T(a); 89 | } 90 | 91 | function encodeStgError() public { 92 | /// @solidity memory-safe-assembly 93 | assembly { 94 | sstore(someBytes.slot, 1) 95 | } 96 | keccak256(someBytes); 97 | } 98 | 99 | function pop() public { 100 | someArr.pop(); 101 | } 102 | 103 | function indexOOBError(uint256 a) public pure { 104 | uint256[] memory t = new uint256[](0); 105 | t[a]; 106 | } 107 | 108 | function mem() public pure { 109 | uint256 l = 2 ** 256 / 32; 110 | new uint256[](l); 111 | } 112 | 113 | function intern() public returns (uint256) { 114 | function(uint256) internal returns (uint256) x; 115 | x(2); 116 | return 7; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /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/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(0x329f5e71), "VmSafe"); 13 | assertEq(type(Vm).interfaceId, bytes4(0x82ccbb14), "Vm"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /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/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/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/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/solmate/.gitattributes: -------------------------------------------------------------------------------- 1 | .gas-snapshot linguist-language=Julia -------------------------------------------------------------------------------- /lib/solmate/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Describe the changes made in your pull request here. 4 | 5 | ## Checklist 6 | 7 | Ensure you completed **all of the steps** below before submitting your pull request: 8 | 9 | - [ ] Ran `forge snapshot`? 10 | - [ ] Ran `npm run lint`? 11 | - [ ] Ran `forge test`? 12 | 13 | _Pull requests with an incomplete checklist will be thrown out._ 14 | -------------------------------------------------------------------------------- /lib/solmate/.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | tests: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | 11 | - name: Install Foundry 12 | uses: onbjerg/foundry-toolchain@v1 13 | with: 14 | version: nightly 15 | 16 | - name: Install dependencies 17 | run: forge install 18 | 19 | - name: Check contract sizes 20 | run: forge build --sizes 21 | 22 | - name: Check gas snapshots 23 | run: forge snapshot --check 24 | 25 | - name: Run tests 26 | run: forge test 27 | env: 28 | # Only fuzz intensely if we're running this action on a push to main or for a PR going into main: 29 | FOUNDRY_PROFILE: ${{ (github.ref == 'refs/heads/main' || github.base_ref == 'main') && 'intense' }} 30 | -------------------------------------------------------------------------------- /lib/solmate/.gitignore: -------------------------------------------------------------------------------- 1 | /cache 2 | /node_modules 3 | /out -------------------------------------------------------------------------------- /lib/solmate/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/ds-test"] 2 | path = lib/ds-test 3 | url = https://github.com/dapphub/ds-test 4 | -------------------------------------------------------------------------------- /lib/solmate/.prettierignore: -------------------------------------------------------------------------------- 1 | lib -------------------------------------------------------------------------------- /lib/solmate/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "printWidth": 100, 4 | 5 | "overrides": [ 6 | { 7 | "files": "*.sol", 8 | "options": { 9 | "tabWidth": 4, 10 | "printWidth": 120 11 | } 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /lib/solmate/README.md: -------------------------------------------------------------------------------- 1 | # solmate 2 | 3 | **Modern**, **opinionated**, and **gas optimized** building blocks for **smart contract development**. 4 | 5 | ## Contracts 6 | 7 | ```ml 8 | auth 9 | ├─ Owned — "Simple single owner authorization" 10 | ├─ Auth — "Flexible and updatable auth pattern" 11 | ├─ authorities 12 | │ ├─ RolesAuthority — "Role based Authority that supports up to 256 roles" 13 | │ ├─ MultiRolesAuthority — "Flexible and target agnostic role based Authority" 14 | mixins 15 | ├─ ERC4626 — "Minimal ERC4626 tokenized Vault implementation" 16 | tokens 17 | ├─ WETH — "Minimalist and modern Wrapped Ether implementation" 18 | ├─ ERC20 — "Modern and gas efficient ERC20 + EIP-2612 implementation" 19 | ├─ ERC721 — "Modern, minimalist, and gas efficient ERC721 implementation" 20 | ├─ ERC1155 — "Minimalist and gas efficient standard ERC1155 implementation" 21 | ├─ ERC6909 — "Minimalist and gas efficient standard ERC6909 implementation" 22 | utils 23 | ├─ SSTORE2 — "Library for cheaper reads and writes to persistent storage" 24 | ├─ CREATE3 — "Deploy to deterministic addresses without an initcode factor" 25 | ├─ LibString — "Library for creating string representations of uint values" 26 | ├─ SafeCastLib — "Safe unsigned integer casting lib that reverts on overflow" 27 | ├─ SignedWadMath — "Signed integer 18 decimal fixed point arithmetic library" 28 | ├─ MerkleProofLib — "Efficient merkle tree inclusion proof verification library" 29 | ├─ ReentrancyGuard — "Gas optimized reentrancy protection for smart contracts" 30 | ├─ FixedPointMathLib — "Arithmetic library with operations for fixed-point numbers" 31 | ├─ Bytes32AddressLib — "Library for converting between addresses and bytes32 values" 32 | ├─ SafeTransferLib — "Safe ERC20/ETH transfer lib that handles missing return values" 33 | ``` 34 | 35 | ## Safety 36 | 37 | This is **experimental software** and is provided on an "as is" and "as available" basis. 38 | 39 | While each [major release has been audited](audits), these contracts are **not designed with user safety** in mind: 40 | 41 | - There are implicit invariants these contracts expect to hold. 42 | - **You can easily shoot yourself in the foot if you're not careful.** 43 | - You should thoroughly read each contract you plan to use top to bottom. 44 | 45 | We **do not give any warranties** and **will not be liable for any loss** incurred through any use of this codebase. 46 | 47 | ## Installation 48 | 49 | To install with [**Foundry**](https://github.com/gakonst/foundry): 50 | 51 | ```sh 52 | forge install transmissions11/solmate 53 | ``` 54 | 55 | To install with [**Hardhat**](https://github.com/nomiclabs/hardhat) or [**Truffle**](https://github.com/trufflesuite/truffle): 56 | 57 | ```sh 58 | npm install solmate 59 | ``` 60 | 61 | ## Acknowledgements 62 | 63 | These contracts were inspired by or directly modified from many sources, primarily: 64 | 65 | - [Gnosis](https://github.com/gnosis/gp-v2-contracts) 66 | - [Uniswap](https://github.com/Uniswap/uniswap-lib) 67 | - [Dappsys](https://github.com/dapphub/dappsys) 68 | - [Dappsys V2](https://github.com/dapp-org/dappsys-v2) 69 | - [0xSequence](https://github.com/0xSequence) 70 | - [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts) 71 | -------------------------------------------------------------------------------- /lib/solmate/audits/v6-Fixed-Point-Solutions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chainrule-labs/xsafe-contracts/5d7b42ea7890988ac4732243e505ee9f5b56b6ee/lib/solmate/audits/v6-Fixed-Point-Solutions.pdf -------------------------------------------------------------------------------- /lib/solmate/foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | solc = "0.8.15" 3 | bytecode_hash = "none" 4 | optimizer_runs = 1000000 5 | 6 | [profile.intense.fuzz] 7 | runs = 10000 8 | -------------------------------------------------------------------------------- /lib/solmate/lib/ds-test/.gitignore: -------------------------------------------------------------------------------- 1 | /.dapple 2 | /build 3 | /out 4 | -------------------------------------------------------------------------------- /lib/solmate/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/solmate/lib/ds-test/default.nix: -------------------------------------------------------------------------------- 1 | { solidityPackage, dappsys }: solidityPackage { 2 | name = "ds-test"; 3 | src = ./src; 4 | } 5 | -------------------------------------------------------------------------------- /lib/solmate/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/solmate/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solmate", 3 | "version": "6.2.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@solidity-parser/parser": { 8 | "version": "0.13.2", 9 | "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.13.2.tgz", 10 | "integrity": "sha512-RwHnpRnfrnD2MSPveYoPh8nhofEvX7fgjHk1Oq+NNvCcLx4r1js91CO9o+F/F3fBzOCyvm8kKRTriFICX/odWw==", 11 | "dev": true, 12 | "requires": { 13 | "antlr4ts": "^0.5.0-alpha.4" 14 | } 15 | }, 16 | "ansi-regex": { 17 | "version": "5.0.0", 18 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 19 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 20 | "dev": true 21 | }, 22 | "antlr4ts": { 23 | "version": "0.5.0-alpha.4", 24 | "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", 25 | "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", 26 | "dev": true 27 | }, 28 | "emoji-regex": { 29 | "version": "9.2.2", 30 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 31 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", 32 | "dev": true 33 | }, 34 | "escape-string-regexp": { 35 | "version": "4.0.0", 36 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 37 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 38 | "dev": true 39 | }, 40 | "is-fullwidth-code-point": { 41 | "version": "3.0.0", 42 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 43 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 44 | "dev": true 45 | }, 46 | "lru-cache": { 47 | "version": "6.0.0", 48 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 49 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 50 | "dev": true, 51 | "requires": { 52 | "yallist": "^4.0.0" 53 | } 54 | }, 55 | "prettier": { 56 | "version": "2.3.2", 57 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", 58 | "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", 59 | "dev": true 60 | }, 61 | "prettier-plugin-solidity": { 62 | "version": "1.0.0-beta.16", 63 | "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.16.tgz", 64 | "integrity": "sha512-xVBcnoWpe52dNnCCbqPHC9ZrTWXcNfldf852ZD0DBcHDqVMwjHTAPEdfBVy6FczbFpVa8bmxQil+G5XkEz5WHA==", 65 | "dev": true, 66 | "requires": { 67 | "@solidity-parser/parser": "^0.13.2", 68 | "emoji-regex": "^9.2.2", 69 | "escape-string-regexp": "^4.0.0", 70 | "semver": "^7.3.5", 71 | "solidity-comments-extractor": "^0.0.7", 72 | "string-width": "^4.2.2" 73 | } 74 | }, 75 | "semver": { 76 | "version": "7.3.5", 77 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 78 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 79 | "dev": true, 80 | "requires": { 81 | "lru-cache": "^6.0.0" 82 | } 83 | }, 84 | "solidity-comments-extractor": { 85 | "version": "0.0.7", 86 | "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz", 87 | "integrity": "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==", 88 | "dev": true 89 | }, 90 | "string-width": { 91 | "version": "4.2.2", 92 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 93 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 94 | "dev": true, 95 | "requires": { 96 | "emoji-regex": "^8.0.0", 97 | "is-fullwidth-code-point": "^3.0.0", 98 | "strip-ansi": "^6.0.0" 99 | }, 100 | "dependencies": { 101 | "emoji-regex": { 102 | "version": "8.0.0", 103 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 104 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 105 | "dev": true 106 | } 107 | } 108 | }, 109 | "strip-ansi": { 110 | "version": "6.0.0", 111 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 112 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 113 | "dev": true, 114 | "requires": { 115 | "ansi-regex": "^5.0.0" 116 | } 117 | }, 118 | "yallist": { 119 | "version": "4.0.0", 120 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 121 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 122 | "dev": true 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /lib/solmate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solmate", 3 | "license": "AGPL-3.0-only", 4 | "version": "6.2.0", 5 | "description": "Modern, opinionated and gas optimized building blocks for smart contract development.", 6 | "files": [ 7 | "src/**/*.sol" 8 | ], 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/transmissions11/solmate.git" 12 | }, 13 | "devDependencies": { 14 | "prettier": "^2.3.1", 15 | "prettier-plugin-solidity": "^1.0.0-beta.13" 16 | }, 17 | "scripts": { 18 | "lint": "prettier --write **.sol" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/solmate/src/auth/Auth.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Provides a flexible and updatable auth pattern which is completely separate from application logic. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol) 6 | /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) 7 | abstract contract Auth { 8 | event OwnershipTransferred(address indexed user, address indexed newOwner); 9 | 10 | event AuthorityUpdated(address indexed user, Authority indexed newAuthority); 11 | 12 | address public owner; 13 | 14 | Authority public authority; 15 | 16 | constructor(address _owner, Authority _authority) { 17 | owner = _owner; 18 | authority = _authority; 19 | 20 | emit OwnershipTransferred(msg.sender, _owner); 21 | emit AuthorityUpdated(msg.sender, _authority); 22 | } 23 | 24 | modifier requiresAuth() virtual { 25 | require(isAuthorized(msg.sender, msg.sig), "UNAUTHORIZED"); 26 | 27 | _; 28 | } 29 | 30 | function isAuthorized(address user, bytes4 functionSig) internal view virtual returns (bool) { 31 | Authority auth = authority; // Memoizing authority saves us a warm SLOAD, around 100 gas. 32 | 33 | // Checking if the caller is the owner only after calling the authority saves gas in most cases, but be 34 | // aware that this makes protected functions uncallable even to the owner if the authority is out of order. 35 | return (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) || user == owner; 36 | } 37 | 38 | function setAuthority(Authority newAuthority) public virtual { 39 | // We check if the caller is the owner first because we want to ensure they can 40 | // always swap out the authority even if it's reverting or using up a lot of gas. 41 | require(msg.sender == owner || authority.canCall(msg.sender, address(this), msg.sig)); 42 | 43 | authority = newAuthority; 44 | 45 | emit AuthorityUpdated(msg.sender, newAuthority); 46 | } 47 | 48 | function transferOwnership(address newOwner) public virtual requiresAuth { 49 | owner = newOwner; 50 | 51 | emit OwnershipTransferred(msg.sender, newOwner); 52 | } 53 | } 54 | 55 | /// @notice A generic interface for a contract which provides authorization data to an Auth instance. 56 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol) 57 | /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) 58 | interface Authority { 59 | function canCall( 60 | address user, 61 | address target, 62 | bytes4 functionSig 63 | ) external view returns (bool); 64 | } 65 | -------------------------------------------------------------------------------- /lib/solmate/src/auth/Owned.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Simple single owner authorization mixin. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) 6 | abstract contract Owned { 7 | /*////////////////////////////////////////////////////////////// 8 | EVENTS 9 | //////////////////////////////////////////////////////////////*/ 10 | 11 | event OwnershipTransferred(address indexed user, address indexed newOwner); 12 | 13 | /*////////////////////////////////////////////////////////////// 14 | OWNERSHIP STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | address public owner; 18 | 19 | modifier onlyOwner() virtual { 20 | require(msg.sender == owner, "UNAUTHORIZED"); 21 | 22 | _; 23 | } 24 | 25 | /*////////////////////////////////////////////////////////////// 26 | CONSTRUCTOR 27 | //////////////////////////////////////////////////////////////*/ 28 | 29 | constructor(address _owner) { 30 | owner = _owner; 31 | 32 | emit OwnershipTransferred(address(0), _owner); 33 | } 34 | 35 | /*////////////////////////////////////////////////////////////// 36 | OWNERSHIP LOGIC 37 | //////////////////////////////////////////////////////////////*/ 38 | 39 | function transferOwnership(address newOwner) public virtual onlyOwner { 40 | owner = newOwner; 41 | 42 | emit OwnershipTransferred(msg.sender, newOwner); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/solmate/src/auth/authorities/MultiRolesAuthority.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {Auth, Authority} from "../Auth.sol"; 5 | 6 | /// @notice Flexible and target agnostic role based Authority that supports up to 256 roles. 7 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/authorities/MultiRolesAuthority.sol) 8 | contract MultiRolesAuthority is Auth, Authority { 9 | /*////////////////////////////////////////////////////////////// 10 | EVENTS 11 | //////////////////////////////////////////////////////////////*/ 12 | 13 | event UserRoleUpdated(address indexed user, uint8 indexed role, bool enabled); 14 | 15 | event PublicCapabilityUpdated(bytes4 indexed functionSig, bool enabled); 16 | 17 | event RoleCapabilityUpdated(uint8 indexed role, bytes4 indexed functionSig, bool enabled); 18 | 19 | event TargetCustomAuthorityUpdated(address indexed target, Authority indexed authority); 20 | 21 | /*////////////////////////////////////////////////////////////// 22 | CONSTRUCTOR 23 | //////////////////////////////////////////////////////////////*/ 24 | 25 | constructor(address _owner, Authority _authority) Auth(_owner, _authority) {} 26 | 27 | /*////////////////////////////////////////////////////////////// 28 | CUSTOM TARGET AUTHORITY STORAGE 29 | //////////////////////////////////////////////////////////////*/ 30 | 31 | mapping(address => Authority) public getTargetCustomAuthority; 32 | 33 | /*////////////////////////////////////////////////////////////// 34 | ROLE/USER STORAGE 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | mapping(address => bytes32) public getUserRoles; 38 | 39 | mapping(bytes4 => bool) public isCapabilityPublic; 40 | 41 | mapping(bytes4 => bytes32) public getRolesWithCapability; 42 | 43 | function doesUserHaveRole(address user, uint8 role) public view virtual returns (bool) { 44 | return (uint256(getUserRoles[user]) >> role) & 1 != 0; 45 | } 46 | 47 | function doesRoleHaveCapability(uint8 role, bytes4 functionSig) public view virtual returns (bool) { 48 | return (uint256(getRolesWithCapability[functionSig]) >> role) & 1 != 0; 49 | } 50 | 51 | /*////////////////////////////////////////////////////////////// 52 | AUTHORIZATION LOGIC 53 | //////////////////////////////////////////////////////////////*/ 54 | 55 | function canCall( 56 | address user, 57 | address target, 58 | bytes4 functionSig 59 | ) public view virtual override returns (bool) { 60 | Authority customAuthority = getTargetCustomAuthority[target]; 61 | 62 | if (address(customAuthority) != address(0)) return customAuthority.canCall(user, target, functionSig); 63 | 64 | return 65 | isCapabilityPublic[functionSig] || bytes32(0) != getUserRoles[user] & getRolesWithCapability[functionSig]; 66 | } 67 | 68 | /*/////////////////////////////////////////////////////////////// 69 | CUSTOM TARGET AUTHORITY CONFIGURATION LOGIC 70 | //////////////////////////////////////////////////////////////*/ 71 | 72 | function setTargetCustomAuthority(address target, Authority customAuthority) public virtual requiresAuth { 73 | getTargetCustomAuthority[target] = customAuthority; 74 | 75 | emit TargetCustomAuthorityUpdated(target, customAuthority); 76 | } 77 | 78 | /*////////////////////////////////////////////////////////////// 79 | PUBLIC CAPABILITY CONFIGURATION LOGIC 80 | //////////////////////////////////////////////////////////////*/ 81 | 82 | function setPublicCapability(bytes4 functionSig, bool enabled) public virtual requiresAuth { 83 | isCapabilityPublic[functionSig] = enabled; 84 | 85 | emit PublicCapabilityUpdated(functionSig, enabled); 86 | } 87 | 88 | /*////////////////////////////////////////////////////////////// 89 | USER ROLE ASSIGNMENT LOGIC 90 | //////////////////////////////////////////////////////////////*/ 91 | 92 | function setUserRole( 93 | address user, 94 | uint8 role, 95 | bool enabled 96 | ) public virtual requiresAuth { 97 | if (enabled) { 98 | getUserRoles[user] |= bytes32(1 << role); 99 | } else { 100 | getUserRoles[user] &= ~bytes32(1 << role); 101 | } 102 | 103 | emit UserRoleUpdated(user, role, enabled); 104 | } 105 | 106 | /*////////////////////////////////////////////////////////////// 107 | ROLE CAPABILITY CONFIGURATION LOGIC 108 | //////////////////////////////////////////////////////////////*/ 109 | 110 | function setRoleCapability( 111 | uint8 role, 112 | bytes4 functionSig, 113 | bool enabled 114 | ) public virtual requiresAuth { 115 | if (enabled) { 116 | getRolesWithCapability[functionSig] |= bytes32(1 << role); 117 | } else { 118 | getRolesWithCapability[functionSig] &= ~bytes32(1 << role); 119 | } 120 | 121 | emit RoleCapabilityUpdated(role, functionSig, enabled); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /lib/solmate/src/auth/authorities/RolesAuthority.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {Auth, Authority} from "../Auth.sol"; 5 | 6 | /// @notice Role based Authority that supports up to 256 roles. 7 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/authorities/RolesAuthority.sol) 8 | /// @author Modified from Dappsys (https://github.com/dapphub/ds-roles/blob/master/src/roles.sol) 9 | contract RolesAuthority is Auth, Authority { 10 | /*////////////////////////////////////////////////////////////// 11 | EVENTS 12 | //////////////////////////////////////////////////////////////*/ 13 | 14 | event UserRoleUpdated(address indexed user, uint8 indexed role, bool enabled); 15 | 16 | event PublicCapabilityUpdated(address indexed target, bytes4 indexed functionSig, bool enabled); 17 | 18 | event RoleCapabilityUpdated(uint8 indexed role, address indexed target, bytes4 indexed functionSig, bool enabled); 19 | 20 | /*////////////////////////////////////////////////////////////// 21 | CONSTRUCTOR 22 | //////////////////////////////////////////////////////////////*/ 23 | 24 | constructor(address _owner, Authority _authority) Auth(_owner, _authority) {} 25 | 26 | /*////////////////////////////////////////////////////////////// 27 | ROLE/USER STORAGE 28 | //////////////////////////////////////////////////////////////*/ 29 | 30 | mapping(address => bytes32) public getUserRoles; 31 | 32 | mapping(address => mapping(bytes4 => bool)) public isCapabilityPublic; 33 | 34 | mapping(address => mapping(bytes4 => bytes32)) public getRolesWithCapability; 35 | 36 | function doesUserHaveRole(address user, uint8 role) public view virtual returns (bool) { 37 | return (uint256(getUserRoles[user]) >> role) & 1 != 0; 38 | } 39 | 40 | function doesRoleHaveCapability( 41 | uint8 role, 42 | address target, 43 | bytes4 functionSig 44 | ) public view virtual returns (bool) { 45 | return (uint256(getRolesWithCapability[target][functionSig]) >> role) & 1 != 0; 46 | } 47 | 48 | /*////////////////////////////////////////////////////////////// 49 | AUTHORIZATION LOGIC 50 | //////////////////////////////////////////////////////////////*/ 51 | 52 | function canCall( 53 | address user, 54 | address target, 55 | bytes4 functionSig 56 | ) public view virtual override returns (bool) { 57 | return 58 | isCapabilityPublic[target][functionSig] || 59 | bytes32(0) != getUserRoles[user] & getRolesWithCapability[target][functionSig]; 60 | } 61 | 62 | /*////////////////////////////////////////////////////////////// 63 | ROLE CAPABILITY CONFIGURATION LOGIC 64 | //////////////////////////////////////////////////////////////*/ 65 | 66 | function setPublicCapability( 67 | address target, 68 | bytes4 functionSig, 69 | bool enabled 70 | ) public virtual requiresAuth { 71 | isCapabilityPublic[target][functionSig] = enabled; 72 | 73 | emit PublicCapabilityUpdated(target, functionSig, enabled); 74 | } 75 | 76 | function setRoleCapability( 77 | uint8 role, 78 | address target, 79 | bytes4 functionSig, 80 | bool enabled 81 | ) public virtual requiresAuth { 82 | if (enabled) { 83 | getRolesWithCapability[target][functionSig] |= bytes32(1 << role); 84 | } else { 85 | getRolesWithCapability[target][functionSig] &= ~bytes32(1 << role); 86 | } 87 | 88 | emit RoleCapabilityUpdated(role, target, functionSig, enabled); 89 | } 90 | 91 | /*////////////////////////////////////////////////////////////// 92 | USER ROLE ASSIGNMENT LOGIC 93 | //////////////////////////////////////////////////////////////*/ 94 | 95 | function setUserRole( 96 | address user, 97 | uint8 role, 98 | bool enabled 99 | ) public virtual requiresAuth { 100 | if (enabled) { 101 | getUserRoles[user] |= bytes32(1 << role); 102 | } else { 103 | getUserRoles[user] &= ~bytes32(1 << role); 104 | } 105 | 106 | emit UserRoleUpdated(user, role, enabled); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /lib/solmate/src/test/Bytes32AddressLib.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | 6 | import {Bytes32AddressLib} from "../utils/Bytes32AddressLib.sol"; 7 | 8 | contract Bytes32AddressLibTest is DSTestPlus { 9 | function testFillLast12Bytes() public { 10 | assertEq( 11 | Bytes32AddressLib.fillLast12Bytes(0xfEEDFaCEcaFeBEEFfEEDFACecaFEBeeFfeEdfAce), 12 | 0xfeedfacecafebeeffeedfacecafebeeffeedface000000000000000000000000 13 | ); 14 | } 15 | 16 | function testFromLast20Bytes() public { 17 | assertEq( 18 | Bytes32AddressLib.fromLast20Bytes(0xfeedfacecafebeeffeedfacecafebeeffeedfacecafebeeffeedfacecafebeef), 19 | 0xCAfeBeefFeedfAceCAFeBEEffEEDfaCecafEBeeF 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/solmate/src/test/CREATE3.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {WETH} from "../tokens/WETH.sol"; 5 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 6 | import {MockERC20} from "./utils/mocks/MockERC20.sol"; 7 | import {MockAuthChild} from "./utils/mocks/MockAuthChild.sol"; 8 | 9 | import {CREATE3} from "../utils/CREATE3.sol"; 10 | 11 | contract CREATE3Test is DSTestPlus { 12 | function testDeployERC20() public { 13 | bytes32 salt = keccak256(bytes("A salt!")); 14 | 15 | MockERC20 deployed = MockERC20( 16 | CREATE3.deploy( 17 | salt, 18 | abi.encodePacked(type(MockERC20).creationCode, abi.encode("Mock Token", "MOCK", 18)), 19 | 0 20 | ) 21 | ); 22 | 23 | assertEq(address(deployed), CREATE3.getDeployed(salt)); 24 | 25 | assertEq(deployed.name(), "Mock Token"); 26 | assertEq(deployed.symbol(), "MOCK"); 27 | assertEq(deployed.decimals(), 18); 28 | } 29 | 30 | function testFailDoubleDeploySameBytecode() public { 31 | bytes32 salt = keccak256(bytes("Salty...")); 32 | 33 | CREATE3.deploy(salt, type(MockAuthChild).creationCode, 0); 34 | CREATE3.deploy(salt, type(MockAuthChild).creationCode, 0); 35 | } 36 | 37 | function testFailDoubleDeployDifferentBytecode() public { 38 | bytes32 salt = keccak256(bytes("and sweet!")); 39 | 40 | CREATE3.deploy(salt, type(WETH).creationCode, 0); 41 | CREATE3.deploy(salt, type(MockAuthChild).creationCode, 0); 42 | } 43 | 44 | function testDeployERC20( 45 | bytes32 salt, 46 | string calldata name, 47 | string calldata symbol, 48 | uint8 decimals 49 | ) public { 50 | MockERC20 deployed = MockERC20( 51 | CREATE3.deploy(salt, abi.encodePacked(type(MockERC20).creationCode, abi.encode(name, symbol, decimals)), 0) 52 | ); 53 | 54 | assertEq(address(deployed), CREATE3.getDeployed(salt)); 55 | 56 | assertEq(deployed.name(), name); 57 | assertEq(deployed.symbol(), symbol); 58 | assertEq(deployed.decimals(), decimals); 59 | } 60 | 61 | function testFailDoubleDeploySameBytecode(bytes32 salt, bytes calldata bytecode) public { 62 | CREATE3.deploy(salt, bytecode, 0); 63 | CREATE3.deploy(salt, bytecode, 0); 64 | } 65 | 66 | function testFailDoubleDeployDifferentBytecode( 67 | bytes32 salt, 68 | bytes calldata bytecode1, 69 | bytes calldata bytecode2 70 | ) public { 71 | CREATE3.deploy(salt, bytecode1, 0); 72 | CREATE3.deploy(salt, bytecode2, 0); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/solmate/src/test/DSTestPlus.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | 6 | contract DSTestPlusTest is DSTestPlus { 7 | function testBound() public { 8 | assertEq(bound(0, 69, 69), 69); 9 | assertEq(bound(0, 68, 69), 68); 10 | assertEq(bound(5, 0, 4), 0); 11 | assertEq(bound(9999, 1337, 6666), 6006); 12 | assertEq(bound(0, type(uint256).max - 6, type(uint256).max), type(uint256).max - 6); 13 | assertEq(bound(6, type(uint256).max - 6, type(uint256).max), type(uint256).max); 14 | } 15 | 16 | function testFailBoundMinBiggerThanMax() public { 17 | bound(5, 100, 10); 18 | } 19 | 20 | function testRelApproxEqBothZeroesPasses() public { 21 | assertRelApproxEq(0, 0, 1e18); 22 | assertRelApproxEq(0, 0, 0); 23 | } 24 | 25 | function testBound( 26 | uint256 num, 27 | uint256 min, 28 | uint256 max 29 | ) public { 30 | if (min > max) (min, max) = (max, min); 31 | 32 | uint256 bounded = bound(num, min, max); 33 | 34 | assertGe(bounded, min); 35 | assertLe(bounded, max); 36 | } 37 | 38 | function testFailBoundMinBiggerThanMax( 39 | uint256 num, 40 | uint256 min, 41 | uint256 max 42 | ) public { 43 | if (max == min) { 44 | unchecked { 45 | min++; // Overflow is handled below. 46 | } 47 | } 48 | 49 | if (max > min) (min, max) = (max, min); 50 | 51 | bound(num, min, max); 52 | } 53 | 54 | function testBrutalizeMemory() public brutalizeMemory("FEEDFACECAFEBEEFFEEDFACECAFEBEEF") { 55 | bytes32 scratchSpace1; 56 | bytes32 scratchSpace2; 57 | bytes32 freeMem1; 58 | bytes32 freeMem2; 59 | 60 | assembly { 61 | scratchSpace1 := mload(0) 62 | scratchSpace2 := mload(32) 63 | freeMem1 := mload(mload(0x40)) 64 | freeMem2 := mload(add(mload(0x40), 32)) 65 | } 66 | 67 | assertGt(uint256(freeMem1), 0); 68 | assertGt(uint256(freeMem2), 0); 69 | assertGt(uint256(scratchSpace1), 0); 70 | assertGt(uint256(scratchSpace2), 0); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /lib/solmate/src/test/LibString.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | 6 | import {LibString} from "../utils/LibString.sol"; 7 | 8 | contract LibStringTest is DSTestPlus { 9 | function testToString() public { 10 | assertEq(LibString.toString(uint256(0)), "0"); 11 | assertEq(LibString.toString(uint256(1)), "1"); 12 | assertEq(LibString.toString(uint256(17)), "17"); 13 | assertEq(LibString.toString(uint256(99999999)), "99999999"); 14 | assertEq(LibString.toString(uint256(99999999999)), "99999999999"); 15 | assertEq(LibString.toString(uint256(2342343923423)), "2342343923423"); 16 | assertEq(LibString.toString(uint256(98765685434567)), "98765685434567"); 17 | } 18 | 19 | function testToStringIntPositive() public { 20 | assertEq(LibString.toString(int256(0)), "0"); 21 | assertEq(LibString.toString(int256(1)), "1"); 22 | assertEq(LibString.toString(int256(17)), "17"); 23 | assertEq(LibString.toString(int256(99999999)), "99999999"); 24 | assertEq(LibString.toString(int256(99999999999)), "99999999999"); 25 | assertEq(LibString.toString(int256(2342343923423)), "2342343923423"); 26 | assertEq(LibString.toString(int256(98765685434567)), "98765685434567"); 27 | } 28 | 29 | function testToStringIntNegative() public { 30 | assertEq(LibString.toString(int256(-0)), "0"); 31 | assertEq(LibString.toString(int256(-17)), "-17"); 32 | assertEq(LibString.toString(int256(-99999999)), "-99999999"); 33 | assertEq(LibString.toString(int256(-99999999999)), "-99999999999"); 34 | assertEq(LibString.toString(int256(-2342343923423)), "-2342343923423"); 35 | assertEq(LibString.toString(int256(-98765685434567)), "-98765685434567"); 36 | } 37 | 38 | function testDifferentiallyFuzzToString(uint256 value, bytes calldata brutalizeWith) 39 | public 40 | brutalizeMemory(brutalizeWith) 41 | { 42 | string memory libString = LibString.toString(value); 43 | string memory oz = toStringOZ(value); 44 | 45 | assertEq(bytes(libString).length, bytes(oz).length); 46 | assertEq(libString, oz); 47 | } 48 | 49 | function testDifferentiallyFuzzToStringInt(int256 value, bytes calldata brutalizeWith) 50 | public 51 | brutalizeMemory(brutalizeWith) 52 | { 53 | string memory libString = LibString.toString(value); 54 | string memory oz = toStringOZ(value); 55 | 56 | assertEq(bytes(libString).length, bytes(oz).length); 57 | assertEq(libString, oz); 58 | } 59 | 60 | function testToStringOverwrite() public { 61 | string memory str = LibString.toString(uint256(1)); 62 | 63 | bytes32 data; 64 | bytes32 expected; 65 | 66 | assembly { 67 | // Imagine a high level allocation writing something to the current free memory. 68 | // Should have sufficient higher order bits for this to be visible 69 | mstore(mload(0x40), not(0)) 70 | // Correctly allocate 32 more bytes, to avoid more interference 71 | mstore(0x40, add(mload(0x40), 32)) 72 | data := mload(add(str, 32)) 73 | 74 | // the expected value should be the uft-8 encoding of 1 (49), 75 | // followed by clean bits. We achieve this by taking the value and 76 | // shifting left to the end of the 32 byte word 77 | expected := shl(248, 49) 78 | } 79 | 80 | assertEq(data, expected); 81 | } 82 | 83 | function testToStringDirty() public { 84 | uint256 freememptr; 85 | // Make the next 4 bytes of the free memory dirty 86 | assembly { 87 | let dirty := not(0) 88 | freememptr := mload(0x40) 89 | mstore(freememptr, dirty) 90 | mstore(add(freememptr, 32), dirty) 91 | mstore(add(freememptr, 64), dirty) 92 | mstore(add(freememptr, 96), dirty) 93 | mstore(add(freememptr, 128), dirty) 94 | } 95 | string memory str = LibString.toString(uint256(1)); 96 | uint256 len; 97 | bytes32 data; 98 | bytes32 expected; 99 | assembly { 100 | freememptr := str 101 | len := mload(str) 102 | data := mload(add(str, 32)) 103 | // the expected value should be the uft-8 encoding of 1 (49), 104 | // followed by clean bits. We achieve this by taking the value and 105 | // shifting left to the end of the 32 byte word 106 | expected := shl(248, 49) 107 | } 108 | emit log_named_uint("str: ", freememptr); 109 | emit log_named_uint("len: ", len); 110 | emit log_named_bytes32("data: ", data); 111 | assembly { 112 | freememptr := mload(0x40) 113 | } 114 | emit log_named_uint("memptr: ", freememptr); 115 | 116 | assertEq(data, expected); 117 | } 118 | } 119 | 120 | function toStringOZ(int256 value) pure returns (string memory) { 121 | return string(abi.encodePacked(value < 0 ? "-" : "", toStringOZ(absOZ(value)))); 122 | } 123 | 124 | function toStringOZ(uint256 value) pure returns (string memory) { 125 | if (value == 0) { 126 | return "0"; 127 | } 128 | uint256 temp = value; 129 | uint256 digits; 130 | while (temp != 0) { 131 | digits++; 132 | temp /= 10; 133 | } 134 | bytes memory buffer = new bytes(digits); 135 | while (value != 0) { 136 | digits -= 1; 137 | buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); 138 | value /= 10; 139 | } 140 | return string(buffer); 141 | } 142 | 143 | function absOZ(int256 n) pure returns (uint256) { 144 | unchecked { 145 | // must be unchecked in order to support `n = type(int256).min` 146 | return uint256(n >= 0 ? n : -n); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /lib/solmate/src/test/MerkleProofLib.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | 6 | import {MerkleProofLib} from "../utils/MerkleProofLib.sol"; 7 | 8 | contract MerkleProofLibTest is DSTestPlus { 9 | function testVerifyEmptyMerkleProofSuppliedLeafAndRootSame() public { 10 | bytes32[] memory proof; 11 | assertBoolEq(this.verify(proof, 0x00, 0x00), true); 12 | } 13 | 14 | function testVerifyEmptyMerkleProofSuppliedLeafAndRootDifferent() public { 15 | bytes32[] memory proof; 16 | bytes32 leaf = "a"; 17 | assertBoolEq(this.verify(proof, 0x00, leaf), false); 18 | } 19 | 20 | function testValidProofSupplied() public { 21 | // Merkle tree created from leaves ['a', 'b', 'c']. 22 | // Leaf is 'a'. 23 | bytes32[] memory proof = new bytes32[](2); 24 | proof[0] = 0xb5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5510; 25 | proof[1] = 0x0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2; 26 | bytes32 root = 0x5842148bc6ebeb52af882a317c765fccd3ae80589b21a9b8cbf21abb630e46a7; 27 | bytes32 leaf = 0x3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb; 28 | assertBoolEq(this.verify(proof, root, leaf), true); 29 | } 30 | 31 | function testVerifyInvalidProofSupplied() public { 32 | // Merkle tree created from leaves ['a', 'b', 'c']. 33 | // Leaf is 'a'. 34 | // Proof is same as testValidProofSupplied but last byte of first element is modified. 35 | bytes32[] memory proof = new bytes32[](2); 36 | proof[0] = 0xb5553de315e0edf504d9150af82dafa5c4667fa618ed0a6f19c69b41166c5511; 37 | proof[1] = 0x0b42b6393c1f53060fe3ddbfcd7aadcca894465a5a438f69c87d790b2299b9b2; 38 | bytes32 root = 0x5842148bc6ebeb52af882a317c765fccd3ae80589b21a9b8cbf21abb630e46a7; 39 | bytes32 leaf = 0x3ac225168df54212a25c1c01fd35bebfea408fdac2e31ddd6f80a4bbf9a5f1cb; 40 | assertBoolEq(this.verify(proof, root, leaf), false); 41 | } 42 | 43 | function verify( 44 | bytes32[] calldata proof, 45 | bytes32 root, 46 | bytes32 leaf 47 | ) external pure returns (bool) { 48 | return MerkleProofLib.verify(proof, root, leaf); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/solmate/src/test/Owned.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | import {MockOwned} from "./utils/mocks/MockOwned.sol"; 6 | 7 | contract OwnedTest is DSTestPlus { 8 | MockOwned mockOwned; 9 | 10 | function setUp() public { 11 | mockOwned = new MockOwned(); 12 | } 13 | 14 | function testTransferOwnership() public { 15 | testTransferOwnership(address(0xBEEF)); 16 | } 17 | 18 | function testCallFunctionAsNonOwner() public { 19 | testCallFunctionAsNonOwner(address(0)); 20 | } 21 | 22 | function testCallFunctionAsOwner() public { 23 | mockOwned.updateFlag(); 24 | } 25 | 26 | function testTransferOwnership(address newOwner) public { 27 | mockOwned.transferOwnership(newOwner); 28 | 29 | assertEq(mockOwned.owner(), newOwner); 30 | } 31 | 32 | function testCallFunctionAsNonOwner(address owner) public { 33 | hevm.assume(owner != address(this)); 34 | 35 | mockOwned.transferOwnership(owner); 36 | 37 | hevm.expectRevert("UNAUTHORIZED"); 38 | mockOwned.updateFlag(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/solmate/src/test/ReentrancyGuard.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | 6 | import {ReentrancyGuard} from "../utils/ReentrancyGuard.sol"; 7 | 8 | contract RiskyContract is ReentrancyGuard { 9 | uint256 public enterTimes; 10 | 11 | function unprotectedCall() public { 12 | enterTimes++; 13 | 14 | if (enterTimes > 1) return; 15 | 16 | this.protectedCall(); 17 | } 18 | 19 | function protectedCall() public nonReentrant { 20 | enterTimes++; 21 | 22 | if (enterTimes > 1) return; 23 | 24 | this.protectedCall(); 25 | } 26 | 27 | function overprotectedCall() public nonReentrant {} 28 | } 29 | 30 | contract ReentrancyGuardTest is DSTestPlus { 31 | RiskyContract riskyContract; 32 | 33 | function setUp() public { 34 | riskyContract = new RiskyContract(); 35 | } 36 | 37 | function invariantReentrancyStatusAlways1() public { 38 | assertEq(uint256(hevm.load(address(riskyContract), 0)), 1); 39 | } 40 | 41 | function testFailUnprotectedCall() public { 42 | riskyContract.unprotectedCall(); 43 | 44 | assertEq(riskyContract.enterTimes(), 1); 45 | } 46 | 47 | function testProtectedCall() public { 48 | try riskyContract.protectedCall() { 49 | fail("Reentrancy Guard Failed To Stop Attacker"); 50 | } catch {} 51 | } 52 | 53 | function testNoReentrancy() public { 54 | riskyContract.overprotectedCall(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/solmate/src/test/SSTORE2.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | 6 | import {SSTORE2} from "../utils/SSTORE2.sol"; 7 | 8 | contract SSTORE2Test is DSTestPlus { 9 | function testWriteRead() public { 10 | bytes memory testBytes = abi.encode("this is a test"); 11 | 12 | address pointer = SSTORE2.write(testBytes); 13 | 14 | assertBytesEq(SSTORE2.read(pointer), testBytes); 15 | } 16 | 17 | function testWriteReadFullStartBound() public { 18 | assertBytesEq(SSTORE2.read(SSTORE2.write(hex"11223344"), 0), hex"11223344"); 19 | } 20 | 21 | function testWriteReadCustomStartBound() public { 22 | assertBytesEq(SSTORE2.read(SSTORE2.write(hex"11223344"), 1), hex"223344"); 23 | } 24 | 25 | function testWriteReadFullBoundedRead() public { 26 | bytes memory testBytes = abi.encode("this is a test"); 27 | 28 | assertBytesEq(SSTORE2.read(SSTORE2.write(testBytes), 0, testBytes.length), testBytes); 29 | } 30 | 31 | function testWriteReadCustomBounds() public { 32 | assertBytesEq(SSTORE2.read(SSTORE2.write(hex"11223344"), 1, 3), hex"2233"); 33 | } 34 | 35 | function testWriteReadEmptyBound() public { 36 | SSTORE2.read(SSTORE2.write(hex"11223344"), 3, 3); 37 | } 38 | 39 | function testFailReadInvalidPointer() public view { 40 | SSTORE2.read(DEAD_ADDRESS); 41 | } 42 | 43 | function testFailReadInvalidPointerCustomStartBound() public view { 44 | SSTORE2.read(DEAD_ADDRESS, 1); 45 | } 46 | 47 | function testFailReadInvalidPointerCustomBounds() public view { 48 | SSTORE2.read(DEAD_ADDRESS, 2, 4); 49 | } 50 | 51 | function testFailWriteReadOutOfStartBound() public { 52 | SSTORE2.read(SSTORE2.write(hex"11223344"), 41000); 53 | } 54 | 55 | function testFailWriteReadEmptyOutOfBounds() public { 56 | SSTORE2.read(SSTORE2.write(hex"11223344"), 42000, 42000); 57 | } 58 | 59 | function testFailWriteReadOutOfBounds() public { 60 | SSTORE2.read(SSTORE2.write(hex"11223344"), 41000, 42000); 61 | } 62 | 63 | function testWriteRead(bytes calldata testBytes, bytes calldata brutalizeWith) 64 | public 65 | brutalizeMemory(brutalizeWith) 66 | { 67 | assertBytesEq(SSTORE2.read(SSTORE2.write(testBytes)), testBytes); 68 | } 69 | 70 | function testWriteReadCustomStartBound( 71 | bytes calldata testBytes, 72 | uint256 startIndex, 73 | bytes calldata brutalizeWith 74 | ) public brutalizeMemory(brutalizeWith) { 75 | if (testBytes.length == 0) return; 76 | 77 | startIndex = bound(startIndex, 0, testBytes.length); 78 | 79 | assertBytesEq(SSTORE2.read(SSTORE2.write(testBytes), startIndex), bytes(testBytes[startIndex:])); 80 | } 81 | 82 | function testWriteReadCustomBounds( 83 | bytes calldata testBytes, 84 | uint256 startIndex, 85 | uint256 endIndex, 86 | bytes calldata brutalizeWith 87 | ) public brutalizeMemory(brutalizeWith) { 88 | if (testBytes.length == 0) return; 89 | 90 | endIndex = bound(endIndex, 0, testBytes.length); 91 | startIndex = bound(startIndex, 0, testBytes.length); 92 | 93 | if (startIndex > endIndex) return; 94 | 95 | assertBytesEq( 96 | SSTORE2.read(SSTORE2.write(testBytes), startIndex, endIndex), 97 | bytes(testBytes[startIndex:endIndex]) 98 | ); 99 | } 100 | 101 | function testFailReadInvalidPointer(address pointer, bytes calldata brutalizeWith) 102 | public 103 | view 104 | brutalizeMemory(brutalizeWith) 105 | { 106 | if (pointer.code.length > 0) revert(); 107 | 108 | SSTORE2.read(pointer); 109 | } 110 | 111 | function testFailReadInvalidPointerCustomStartBound( 112 | address pointer, 113 | uint256 startIndex, 114 | bytes calldata brutalizeWith 115 | ) public view brutalizeMemory(brutalizeWith) { 116 | if (pointer.code.length > 0) revert(); 117 | 118 | SSTORE2.read(pointer, startIndex); 119 | } 120 | 121 | function testFailReadInvalidPointerCustomBounds( 122 | address pointer, 123 | uint256 startIndex, 124 | uint256 endIndex, 125 | bytes calldata brutalizeWith 126 | ) public view brutalizeMemory(brutalizeWith) { 127 | if (pointer.code.length > 0) revert(); 128 | 129 | SSTORE2.read(pointer, startIndex, endIndex); 130 | } 131 | 132 | function testFailWriteReadCustomStartBoundOutOfRange( 133 | bytes calldata testBytes, 134 | uint256 startIndex, 135 | bytes calldata brutalizeWith 136 | ) public brutalizeMemory(brutalizeWith) { 137 | startIndex = bound(startIndex, testBytes.length + 1, type(uint256).max); 138 | 139 | SSTORE2.read(SSTORE2.write(testBytes), startIndex); 140 | } 141 | 142 | function testFailWriteReadCustomBoundsOutOfRange( 143 | bytes calldata testBytes, 144 | uint256 startIndex, 145 | uint256 endIndex, 146 | bytes calldata brutalizeWith 147 | ) public brutalizeMemory(brutalizeWith) { 148 | endIndex = bound(endIndex, testBytes.length + 1, type(uint256).max); 149 | 150 | SSTORE2.read(SSTORE2.write(testBytes), startIndex, endIndex); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /lib/solmate/src/test/SignedWadMath.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | 6 | import {wadMul, wadDiv} from "../utils/SignedWadMath.sol"; 7 | 8 | contract SignedWadMathTest is DSTestPlus { 9 | function testWadMul( 10 | uint256 x, 11 | uint256 y, 12 | bool negX, 13 | bool negY 14 | ) public { 15 | x = bound(x, 0, 99999999999999e18); 16 | y = bound(x, 0, 99999999999999e18); 17 | 18 | int256 xPrime = negX ? -int256(x) : int256(x); 19 | int256 yPrime = negY ? -int256(y) : int256(y); 20 | 21 | assertEq(wadMul(xPrime, yPrime), (xPrime * yPrime) / 1e18); 22 | } 23 | 24 | function testFailWadMulEdgeCase() public pure { 25 | int256 x = -1; 26 | int256 y = type(int256).min; 27 | 28 | wadMul(x, y); 29 | } 30 | 31 | function testFailWadMulEdgeCase2() public pure { 32 | int256 x = type(int256).min; 33 | int256 y = -1; 34 | 35 | wadMul(x, y); 36 | } 37 | 38 | function testFailWadMulOverflow(int256 x, int256 y) public pure { 39 | // Ignore cases where x * y does not overflow. 40 | unchecked { 41 | if ((x * y) / x == y) revert(); 42 | } 43 | 44 | wadMul(x, y); 45 | } 46 | 47 | function testWadDiv( 48 | uint256 x, 49 | uint256 y, 50 | bool negX, 51 | bool negY 52 | ) public { 53 | x = bound(x, 0, 99999999e18); 54 | y = bound(x, 1, 99999999e18); 55 | 56 | int256 xPrime = negX ? -int256(x) : int256(x); 57 | int256 yPrime = negY ? -int256(y) : int256(y); 58 | 59 | assertEq(wadDiv(xPrime, yPrime), (xPrime * 1e18) / yPrime); 60 | } 61 | 62 | function testFailWadDivOverflow(int256 x, int256 y) public pure { 63 | // Ignore cases where x * WAD does not overflow or y is 0. 64 | unchecked { 65 | if (y == 0 || (x * 1e18) / 1e18 == x) revert(); 66 | } 67 | 68 | wadDiv(x, y); 69 | } 70 | 71 | function testFailWadDivZeroDenominator(int256 x) public pure { 72 | wadDiv(x, 0); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/solmate/src/test/WETH.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | import {DSInvariantTest} from "./utils/DSInvariantTest.sol"; 6 | 7 | import {SafeTransferLib} from "../utils/SafeTransferLib.sol"; 8 | 9 | import {WETH} from "../tokens/WETH.sol"; 10 | 11 | contract WETHTest is DSTestPlus { 12 | WETH weth; 13 | 14 | function setUp() public { 15 | weth = new WETH(); 16 | } 17 | 18 | function testFallbackDeposit() public { 19 | assertEq(weth.balanceOf(address(this)), 0); 20 | assertEq(weth.totalSupply(), 0); 21 | 22 | SafeTransferLib.safeTransferETH(address(weth), 1 ether); 23 | 24 | assertEq(weth.balanceOf(address(this)), 1 ether); 25 | assertEq(weth.totalSupply(), 1 ether); 26 | } 27 | 28 | function testDeposit() public { 29 | assertEq(weth.balanceOf(address(this)), 0); 30 | assertEq(weth.totalSupply(), 0); 31 | 32 | weth.deposit{value: 1 ether}(); 33 | 34 | assertEq(weth.balanceOf(address(this)), 1 ether); 35 | assertEq(weth.totalSupply(), 1 ether); 36 | } 37 | 38 | function testWithdraw() public { 39 | uint256 startingBalance = address(this).balance; 40 | 41 | weth.deposit{value: 1 ether}(); 42 | 43 | weth.withdraw(1 ether); 44 | 45 | uint256 balanceAfterWithdraw = address(this).balance; 46 | 47 | assertEq(balanceAfterWithdraw, startingBalance); 48 | assertEq(weth.balanceOf(address(this)), 0); 49 | assertEq(weth.totalSupply(), 0); 50 | } 51 | 52 | function testPartialWithdraw() public { 53 | weth.deposit{value: 1 ether}(); 54 | 55 | uint256 balanceBeforeWithdraw = address(this).balance; 56 | 57 | weth.withdraw(0.5 ether); 58 | 59 | uint256 balanceAfterWithdraw = address(this).balance; 60 | 61 | assertEq(balanceAfterWithdraw, balanceBeforeWithdraw + 0.5 ether); 62 | assertEq(weth.balanceOf(address(this)), 0.5 ether); 63 | assertEq(weth.totalSupply(), 0.5 ether); 64 | } 65 | 66 | function testFallbackDeposit(uint256 amount) public { 67 | amount = bound(amount, 0, address(this).balance); 68 | 69 | assertEq(weth.balanceOf(address(this)), 0); 70 | assertEq(weth.totalSupply(), 0); 71 | 72 | SafeTransferLib.safeTransferETH(address(weth), amount); 73 | 74 | assertEq(weth.balanceOf(address(this)), amount); 75 | assertEq(weth.totalSupply(), amount); 76 | } 77 | 78 | function testDeposit(uint256 amount) public { 79 | amount = bound(amount, 0, address(this).balance); 80 | 81 | assertEq(weth.balanceOf(address(this)), 0); 82 | assertEq(weth.totalSupply(), 0); 83 | 84 | weth.deposit{value: amount}(); 85 | 86 | assertEq(weth.balanceOf(address(this)), amount); 87 | assertEq(weth.totalSupply(), amount); 88 | } 89 | 90 | function testWithdraw(uint256 depositAmount, uint256 withdrawAmount) public { 91 | depositAmount = bound(depositAmount, 0, address(this).balance); 92 | withdrawAmount = bound(withdrawAmount, 0, depositAmount); 93 | 94 | weth.deposit{value: depositAmount}(); 95 | 96 | uint256 balanceBeforeWithdraw = address(this).balance; 97 | 98 | weth.withdraw(withdrawAmount); 99 | 100 | uint256 balanceAfterWithdraw = address(this).balance; 101 | 102 | assertEq(balanceAfterWithdraw, balanceBeforeWithdraw + withdrawAmount); 103 | assertEq(weth.balanceOf(address(this)), depositAmount - withdrawAmount); 104 | assertEq(weth.totalSupply(), depositAmount - withdrawAmount); 105 | } 106 | 107 | receive() external payable {} 108 | } 109 | 110 | contract WETHInvariants is DSTestPlus, DSInvariantTest { 111 | WETHTester wethTester; 112 | WETH weth; 113 | 114 | function setUp() public { 115 | weth = new WETH(); 116 | wethTester = new WETHTester{value: address(this).balance}(weth); 117 | 118 | addTargetContract(address(wethTester)); 119 | } 120 | 121 | function invariantTotalSupplyEqualsBalance() public { 122 | assertEq(address(weth).balance, weth.totalSupply()); 123 | } 124 | } 125 | 126 | contract WETHTester { 127 | WETH weth; 128 | 129 | constructor(WETH _weth) payable { 130 | weth = _weth; 131 | } 132 | 133 | function deposit(uint256 amount) public { 134 | weth.deposit{value: amount}(); 135 | } 136 | 137 | function fallbackDeposit(uint256 amount) public { 138 | SafeTransferLib.safeTransferETH(address(weth), amount); 139 | } 140 | 141 | function withdraw(uint256 amount) public { 142 | weth.withdraw(amount); 143 | } 144 | 145 | receive() external payable {} 146 | } 147 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/DSInvariantTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract DSInvariantTest { 5 | address[] private targets; 6 | 7 | function targetContracts() public view virtual returns (address[] memory) { 8 | require(targets.length > 0, "NO_TARGET_CONTRACTS"); 9 | 10 | return targets; 11 | } 12 | 13 | function addTargetContract(address newTargetContract) internal virtual { 14 | targets.push(newTargetContract); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/Hevm.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | interface Hevm { 5 | /// @notice Sets the block timestamp. 6 | function warp(uint256) external; 7 | 8 | /// @notice Sets the block height. 9 | function roll(uint256) external; 10 | 11 | /// @notice Sets the block base fee. 12 | function fee(uint256) external; 13 | 14 | /// @notice Loads a storage slot from an address. 15 | function load(address, bytes32) external returns (bytes32); 16 | 17 | /// @notice Stores a value to an address' storage slot. 18 | function store( 19 | address, 20 | bytes32, 21 | bytes32 22 | ) external; 23 | 24 | /// @notice Signs a digest with a private key, returns v r s. 25 | function sign(uint256, bytes32) 26 | external 27 | returns ( 28 | uint8, 29 | bytes32, 30 | bytes32 31 | ); 32 | 33 | /// @notice Gets address for a given private key. 34 | function addr(uint256) external returns (address); 35 | 36 | /// @notice Performs a foreign function call via a terminal call. 37 | function ffi(string[] calldata) external returns (bytes memory); 38 | 39 | /// @notice Sets the next call's msg.sender to be the input address. 40 | function prank(address) external; 41 | 42 | /// @notice Sets all subsequent calls' msg.sender to be the input address until stopPrank is called. 43 | function startPrank(address) external; 44 | 45 | /// @notice Sets the next call's msg.sender to be the input address and the tx.origin to be the second input. 46 | function prank(address, address) external; 47 | 48 | /// @notice Sets all subsequent calls' msg.sender to be the input address and 49 | /// sets tx.origin to be the second address inputted until stopPrank is called. 50 | function startPrank(address, address) external; 51 | 52 | /// @notice Resets msg.sender to its original value before a prank. 53 | function stopPrank() external; 54 | 55 | /// @notice Sets an address' balance. 56 | function deal(address, uint256) external; 57 | 58 | /// @notice Sets an address' code. 59 | function etch(address, bytes calldata) external; 60 | 61 | /// @notice Expects an error from the next call. 62 | function expectRevert(bytes calldata) external; 63 | 64 | /// @notice Expects a revert from the next call. 65 | function expectRevert(bytes4) external; 66 | 67 | /// @notice Record all storage reads and writes. 68 | function record() external; 69 | 70 | /// @notice Gets all accessed reads and write slots from a recording session, for a given address. 71 | function accesses(address) external returns (bytes32[] memory reads, bytes32[] memory writes); 72 | 73 | /// @notice Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData). 74 | /// @notice Call this function, then emit an event, then call a function. Internally after the call, we check 75 | /// if logs were emitted in the expected order with the expected topics and data as specified by the booleans. 76 | function expectEmit( 77 | bool, 78 | bool, 79 | bool, 80 | bool 81 | ) external; 82 | 83 | /// @notice Mocks the behavior of a contract call, setting the input and output for a function. 84 | /// @notice Calldata can either be strict or a partial match, e.g. if only passed 85 | /// a selector to the expected calldata, then the entire function will be mocked. 86 | function mockCall( 87 | address, 88 | bytes calldata, 89 | bytes calldata 90 | ) external; 91 | 92 | /// @notice Clears all mocked calls. 93 | function clearMockedCalls() external; 94 | 95 | /// @notice Expect a call to an address with the specified calldata. 96 | /// @notice Calldata can either be strict or a partial match. 97 | function expectCall(address, bytes calldata) external; 98 | 99 | /// @notice Fetches the contract bytecode from its artifact file. 100 | function getCode(string calldata) external returns (bytes memory); 101 | 102 | /// @notice Label an address in test traces. 103 | function label(address addr, string calldata label) external; 104 | 105 | /// @notice When fuzzing, generate new inputs if the input conditional is not met. 106 | function assume(bool) external; 107 | } 108 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockAuthChild.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {Auth, Authority} from "../../../auth/Auth.sol"; 5 | 6 | contract MockAuthChild is Auth(msg.sender, Authority(address(0))) { 7 | bool public flag; 8 | 9 | function updateFlag() public virtual requiresAuth { 10 | flag = true; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockAuthority.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {Authority} from "../../../auth/Auth.sol"; 5 | 6 | contract MockAuthority is Authority { 7 | bool immutable allowCalls; 8 | 9 | constructor(bool _allowCalls) { 10 | allowCalls = _allowCalls; 11 | } 12 | 13 | function canCall( 14 | address, 15 | address, 16 | bytes4 17 | ) public view override returns (bool) { 18 | return allowCalls; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockERC1155.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC1155} from "../../../tokens/ERC1155.sol"; 5 | 6 | contract MockERC1155 is ERC1155 { 7 | function uri(uint256) public pure virtual override returns (string memory) {} 8 | 9 | function mint( 10 | address to, 11 | uint256 id, 12 | uint256 amount, 13 | bytes memory data 14 | ) public virtual { 15 | _mint(to, id, amount, data); 16 | } 17 | 18 | function batchMint( 19 | address to, 20 | uint256[] memory ids, 21 | uint256[] memory amounts, 22 | bytes memory data 23 | ) public virtual { 24 | _batchMint(to, ids, amounts, data); 25 | } 26 | 27 | function burn( 28 | address from, 29 | uint256 id, 30 | uint256 amount 31 | ) public virtual { 32 | _burn(from, id, amount); 33 | } 34 | 35 | function batchBurn( 36 | address from, 37 | uint256[] memory ids, 38 | uint256[] memory amounts 39 | ) public virtual { 40 | _batchBurn(from, ids, amounts); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC20} from "../../../tokens/ERC20.sol"; 5 | 6 | contract MockERC20 is ERC20 { 7 | constructor( 8 | string memory _name, 9 | string memory _symbol, 10 | uint8 _decimals 11 | ) ERC20(_name, _symbol, _decimals) {} 12 | 13 | function mint(address to, uint256 value) public virtual { 14 | _mint(to, value); 15 | } 16 | 17 | function burn(address from, uint256 value) public virtual { 18 | _burn(from, value); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockERC4626.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC20} from "../../../tokens/ERC20.sol"; 5 | import {ERC4626} from "../../../mixins/ERC4626.sol"; 6 | 7 | contract MockERC4626 is ERC4626 { 8 | uint256 public beforeWithdrawHookCalledCounter = 0; 9 | uint256 public afterDepositHookCalledCounter = 0; 10 | 11 | constructor( 12 | ERC20 _underlying, 13 | string memory _name, 14 | string memory _symbol 15 | ) ERC4626(_underlying, _name, _symbol) {} 16 | 17 | function totalAssets() public view override returns (uint256) { 18 | return asset.balanceOf(address(this)); 19 | } 20 | 21 | function beforeWithdraw(uint256, uint256) internal override { 22 | beforeWithdrawHookCalledCounter++; 23 | } 24 | 25 | function afterDeposit(uint256, uint256) internal override { 26 | afterDepositHookCalledCounter++; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockERC6909.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC6909} from "../../../tokens/ERC6909.sol"; 5 | 6 | contract MockERC6909 is ERC6909 { 7 | function mint( 8 | address receiver, 9 | uint256 id, 10 | uint256 amount 11 | ) public virtual { 12 | _mint(receiver, id, amount); 13 | } 14 | 15 | function burn( 16 | address sender, 17 | uint256 id, 18 | uint256 amount 19 | ) public virtual { 20 | _burn(sender, id, amount); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC721} from "../../../tokens/ERC721.sol"; 5 | 6 | contract MockERC721 is ERC721 { 7 | constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {} 8 | 9 | function tokenURI(uint256) public pure virtual override returns (string memory) {} 10 | 11 | function mint(address to, uint256 tokenId) public virtual { 12 | _mint(to, tokenId); 13 | } 14 | 15 | function burn(uint256 tokenId) public virtual { 16 | _burn(tokenId); 17 | } 18 | 19 | function safeMint(address to, uint256 tokenId) public virtual { 20 | _safeMint(to, tokenId); 21 | } 22 | 23 | function safeMint( 24 | address to, 25 | uint256 tokenId, 26 | bytes memory data 27 | ) public virtual { 28 | _safeMint(to, tokenId, data); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockOwned.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {Owned} from "../../../auth/Owned.sol"; 5 | 6 | contract MockOwned is Owned(msg.sender) { 7 | bool public flag; 8 | 9 | function updateFlag() public virtual onlyOwner { 10 | flag = true; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/MissingReturnToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract MissingReturnToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "MissingReturnToken"; 18 | 19 | string public constant symbol = "MRT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | CONSTRUCTOR 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | constructor() { 38 | totalSupply = type(uint256).max; 39 | balanceOf[msg.sender] = type(uint256).max; 40 | } 41 | 42 | /*/////////////////////////////////////////////////////////////// 43 | ERC20 LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function approve(address spender, uint256 amount) public virtual { 47 | allowance[msg.sender][spender] = amount; 48 | 49 | emit Approval(msg.sender, spender, amount); 50 | } 51 | 52 | function transfer(address to, uint256 amount) public virtual { 53 | balanceOf[msg.sender] -= amount; 54 | 55 | // Cannot overflow because the sum of all user 56 | // balances can't exceed the max uint256 value. 57 | unchecked { 58 | balanceOf[to] += amount; 59 | } 60 | 61 | emit Transfer(msg.sender, to, amount); 62 | } 63 | 64 | function transferFrom( 65 | address from, 66 | address to, 67 | uint256 amount 68 | ) public virtual { 69 | uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. 70 | 71 | if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; 72 | 73 | balanceOf[from] -= amount; 74 | 75 | // Cannot overflow because the sum of all user 76 | // balances can't exceed the max uint256 value. 77 | unchecked { 78 | balanceOf[to] += amount; 79 | } 80 | 81 | emit Transfer(from, to, amount); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/ReturnsFalseToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract ReturnsFalseToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "ReturnsFalseToken"; 18 | 19 | string public constant symbol = "RFT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | CONSTRUCTOR 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | constructor() { 38 | totalSupply = type(uint256).max; 39 | balanceOf[msg.sender] = type(uint256).max; 40 | } 41 | 42 | /*/////////////////////////////////////////////////////////////// 43 | ERC20 LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function approve(address, uint256) public virtual returns (bool) { 47 | return false; 48 | } 49 | 50 | function transfer(address, uint256) public virtual returns (bool) { 51 | return false; 52 | } 53 | 54 | function transferFrom( 55 | address, 56 | address, 57 | uint256 58 | ) public virtual returns (bool) { 59 | return false; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/ReturnsGarbageToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract ReturnsGarbageToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "ReturnsGarbageToken"; 18 | 19 | string public constant symbol = "RGT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | MOCK STORAGE 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | bytes garbage; 38 | 39 | /*/////////////////////////////////////////////////////////////// 40 | CONSTRUCTOR 41 | //////////////////////////////////////////////////////////////*/ 42 | 43 | constructor() { 44 | totalSupply = type(uint256).max; 45 | balanceOf[msg.sender] = type(uint256).max; 46 | } 47 | 48 | /*/////////////////////////////////////////////////////////////// 49 | ERC20 LOGIC 50 | //////////////////////////////////////////////////////////////*/ 51 | 52 | function approve(address spender, uint256 amount) public virtual { 53 | allowance[msg.sender][spender] = amount; 54 | 55 | emit Approval(msg.sender, spender, amount); 56 | 57 | bytes memory _garbage = garbage; 58 | 59 | assembly { 60 | return(add(_garbage, 32), mload(_garbage)) 61 | } 62 | } 63 | 64 | function transfer(address to, uint256 amount) public virtual { 65 | balanceOf[msg.sender] -= amount; 66 | 67 | // Cannot overflow because the sum of all user 68 | // balances can't exceed the max uint256 value. 69 | unchecked { 70 | balanceOf[to] += amount; 71 | } 72 | 73 | emit Transfer(msg.sender, to, amount); 74 | 75 | bytes memory _garbage = garbage; 76 | 77 | assembly { 78 | return(add(_garbage, 32), mload(_garbage)) 79 | } 80 | } 81 | 82 | function transferFrom( 83 | address from, 84 | address to, 85 | uint256 amount 86 | ) public virtual { 87 | uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. 88 | 89 | if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; 90 | 91 | balanceOf[from] -= amount; 92 | 93 | // Cannot overflow because the sum of all user 94 | // balances can't exceed the max uint256 value. 95 | unchecked { 96 | balanceOf[to] += amount; 97 | } 98 | 99 | emit Transfer(from, to, amount); 100 | 101 | bytes memory _garbage = garbage; 102 | 103 | assembly { 104 | return(add(_garbage, 32), mload(_garbage)) 105 | } 106 | } 107 | 108 | /*/////////////////////////////////////////////////////////////// 109 | MOCK LOGIC 110 | //////////////////////////////////////////////////////////////*/ 111 | 112 | function setGarbage(bytes memory _garbage) public virtual { 113 | garbage = _garbage; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/ReturnsTooLittleToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract ReturnsTooLittleToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "ReturnsTooLittleToken"; 18 | 19 | string public constant symbol = "RTLT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | CONSTRUCTOR 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | constructor() { 38 | totalSupply = type(uint256).max; 39 | balanceOf[msg.sender] = type(uint256).max; 40 | } 41 | 42 | /*/////////////////////////////////////////////////////////////// 43 | ERC20 LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function approve(address, uint256) public virtual { 47 | assembly { 48 | mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) 49 | return(0, 8) 50 | } 51 | } 52 | 53 | function transfer(address, uint256) public virtual { 54 | assembly { 55 | mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) 56 | return(0, 8) 57 | } 58 | } 59 | 60 | function transferFrom( 61 | address, 62 | address, 63 | uint256 64 | ) public virtual { 65 | assembly { 66 | mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) 67 | return(0, 8) 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/ReturnsTooMuchToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract ReturnsTooMuchToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "ReturnsTooMuchToken"; 18 | 19 | string public constant symbol = "RTMT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | CONSTRUCTOR 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | constructor() { 38 | totalSupply = type(uint256).max; 39 | balanceOf[msg.sender] = type(uint256).max; 40 | } 41 | 42 | /*/////////////////////////////////////////////////////////////// 43 | ERC20 LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function approve(address spender, uint256 amount) public virtual { 47 | allowance[msg.sender][spender] = amount; 48 | 49 | emit Approval(msg.sender, spender, amount); 50 | 51 | assembly { 52 | mstore(0, 1) 53 | return(0, 4096) 54 | } 55 | } 56 | 57 | function transfer(address to, uint256 amount) public virtual { 58 | balanceOf[msg.sender] -= amount; 59 | 60 | // Cannot overflow because the sum of all user 61 | // balances can't exceed the max uint256 value. 62 | unchecked { 63 | balanceOf[to] += amount; 64 | } 65 | 66 | emit Transfer(msg.sender, to, amount); 67 | 68 | assembly { 69 | mstore(0, 1) 70 | return(0, 4096) 71 | } 72 | } 73 | 74 | function transferFrom( 75 | address from, 76 | address to, 77 | uint256 amount 78 | ) public virtual { 79 | uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. 80 | 81 | if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; 82 | 83 | balanceOf[from] -= amount; 84 | 85 | // Cannot overflow because the sum of all user 86 | // balances can't exceed the max uint256 value. 87 | unchecked { 88 | balanceOf[to] += amount; 89 | } 90 | 91 | emit Transfer(from, to, amount); 92 | 93 | assembly { 94 | mstore(0, 1) 95 | return(0, 4096) 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/ReturnsTwoToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract ReturnsTwoToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "ReturnsFalseToken"; 18 | 19 | string public constant symbol = "RTT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | CONSTRUCTOR 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | constructor() { 38 | totalSupply = type(uint256).max; 39 | balanceOf[msg.sender] = type(uint256).max; 40 | } 41 | 42 | /*/////////////////////////////////////////////////////////////// 43 | ERC20 LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function approve(address, uint256) public virtual returns (uint256) { 47 | return 2; 48 | } 49 | 50 | function transfer(address, uint256) public virtual returns (uint256) { 51 | return 2; 52 | } 53 | 54 | function transferFrom( 55 | address, 56 | address, 57 | uint256 58 | ) public virtual returns (uint256) { 59 | return 2; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/RevertingToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract RevertingToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "RevertingToken"; 18 | 19 | string public constant symbol = "RT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | CONSTRUCTOR 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | constructor() { 38 | totalSupply = type(uint256).max; 39 | balanceOf[msg.sender] = type(uint256).max; 40 | } 41 | 42 | /*/////////////////////////////////////////////////////////////// 43 | ERC20 LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function approve(address, uint256) public virtual { 47 | revert(); 48 | } 49 | 50 | function transfer(address, uint256) public virtual { 51 | revert(); 52 | } 53 | 54 | function transferFrom( 55 | address, 56 | address, 57 | uint256 58 | ) public virtual { 59 | revert(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/solmate/src/tokens/ERC6909.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Minimalist and gas efficient standard ERC6909 implementation. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC6909.sol) 6 | abstract contract ERC6909 { 7 | /*////////////////////////////////////////////////////////////// 8 | EVENTS 9 | //////////////////////////////////////////////////////////////*/ 10 | 11 | event OperatorSet(address indexed owner, address indexed operator, bool approved); 12 | 13 | event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount); 14 | 15 | event Transfer(address caller, address indexed from, address indexed to, uint256 indexed id, uint256 amount); 16 | 17 | /*////////////////////////////////////////////////////////////// 18 | ERC6909 STORAGE 19 | //////////////////////////////////////////////////////////////*/ 20 | 21 | mapping(uint256 => uint256) public totalSupply; 22 | 23 | mapping(address => mapping(address => bool)) public isOperator; 24 | 25 | mapping(address => mapping(uint256 => uint256)) public balanceOf; 26 | 27 | mapping(address => mapping(address => mapping(uint256 => uint256))) public allowance; 28 | 29 | /*////////////////////////////////////////////////////////////// 30 | ERC6909 LOGIC 31 | //////////////////////////////////////////////////////////////*/ 32 | 33 | function transfer( 34 | address receiver, 35 | uint256 id, 36 | uint256 amount 37 | ) public virtual returns (bool) { 38 | balanceOf[msg.sender][id] -= amount; 39 | 40 | // Cannot overflow because the sum of all user 41 | // balances can't exceed the max uint256 value. 42 | unchecked { 43 | balanceOf[receiver][id] += amount; 44 | } 45 | 46 | emit Transfer(msg.sender, msg.sender, receiver, id, amount); 47 | 48 | return true; 49 | } 50 | 51 | function transferFrom( 52 | address sender, 53 | address receiver, 54 | uint256 id, 55 | uint256 amount 56 | ) public virtual returns (bool) { 57 | if (msg.sender != sender && !isOperator[sender][msg.sender]) { 58 | uint256 allowed = allowance[sender][msg.sender][id]; 59 | if (allowed != type(uint256).max) allowance[sender][msg.sender][id] = allowed - amount; 60 | } 61 | 62 | balanceOf[sender][id] -= amount; 63 | 64 | // Cannot overflow because the sum of all user 65 | // balances can't exceed the max uint256 value. 66 | unchecked { 67 | balanceOf[receiver][id] += amount; 68 | } 69 | 70 | emit Transfer(msg.sender, sender, receiver, id, amount); 71 | 72 | return true; 73 | } 74 | 75 | function approve( 76 | address spender, 77 | uint256 id, 78 | uint256 amount 79 | ) public virtual returns (bool) { 80 | allowance[msg.sender][spender][id] = amount; 81 | 82 | emit Approval(msg.sender, spender, id, amount); 83 | 84 | return true; 85 | } 86 | 87 | function setOperator(address operator, bool approved) public virtual returns (bool) { 88 | isOperator[msg.sender][operator] = approved; 89 | 90 | emit OperatorSet(msg.sender, operator, approved); 91 | 92 | return true; 93 | } 94 | 95 | /*////////////////////////////////////////////////////////////// 96 | ERC165 LOGIC 97 | //////////////////////////////////////////////////////////////*/ 98 | 99 | function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { 100 | return 101 | interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 102 | interfaceId == 0xb2e69f8a; // ERC165 Interface ID for ERC6909 103 | } 104 | 105 | /*////////////////////////////////////////////////////////////// 106 | INTERNAL MINT/BURN LOGIC 107 | //////////////////////////////////////////////////////////////*/ 108 | 109 | function _mint( 110 | address receiver, 111 | uint256 id, 112 | uint256 amount 113 | ) internal virtual { 114 | totalSupply[id] += amount; 115 | 116 | // Cannot overflow because the sum of all user 117 | // balances can't exceed the max uint256 value. 118 | unchecked { 119 | balanceOf[receiver][id] += amount; 120 | } 121 | 122 | emit Transfer(msg.sender, address(0), receiver, id, amount); 123 | } 124 | 125 | function _burn( 126 | address sender, 127 | uint256 id, 128 | uint256 amount 129 | ) internal virtual { 130 | balanceOf[sender][id] -= amount; 131 | 132 | // Cannot underflow because a user's balance 133 | // will never be larger than the total supply. 134 | unchecked { 135 | totalSupply[id] -= amount; 136 | } 137 | 138 | emit Transfer(msg.sender, sender, address(0), id, amount); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /lib/solmate/src/tokens/WETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC20} from "./ERC20.sol"; 5 | 6 | import {SafeTransferLib} from "../utils/SafeTransferLib.sol"; 7 | 8 | /// @notice Minimalist and modern Wrapped Ether implementation. 9 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/WETH.sol) 10 | /// @author Inspired by WETH9 (https://github.com/dapphub/ds-weth/blob/master/src/weth9.sol) 11 | contract WETH is ERC20("Wrapped Ether", "WETH", 18) { 12 | using SafeTransferLib for address; 13 | 14 | event Deposit(address indexed from, uint256 amount); 15 | 16 | event Withdrawal(address indexed to, uint256 amount); 17 | 18 | function deposit() public payable virtual { 19 | _mint(msg.sender, msg.value); 20 | 21 | emit Deposit(msg.sender, msg.value); 22 | } 23 | 24 | function withdraw(uint256 amount) public virtual { 25 | _burn(msg.sender, amount); 26 | 27 | emit Withdrawal(msg.sender, amount); 28 | 29 | msg.sender.safeTransferETH(amount); 30 | } 31 | 32 | receive() external payable virtual { 33 | deposit(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/Bytes32AddressLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Library for converting between addresses and bytes32 values. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Bytes32AddressLib.sol) 6 | library Bytes32AddressLib { 7 | function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) { 8 | return address(uint160(uint256(bytesValue))); 9 | } 10 | 11 | function fillLast12Bytes(address addressValue) internal pure returns (bytes32) { 12 | return bytes32(bytes20(addressValue)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/CREATE3.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {Bytes32AddressLib} from "./Bytes32AddressLib.sol"; 5 | 6 | /// @notice Deploy to deterministic addresses without an initcode factor. 7 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/CREATE3.sol) 8 | /// @author Modified from 0xSequence (https://github.com/0xSequence/create3/blob/master/contracts/Create3.sol) 9 | library CREATE3 { 10 | using Bytes32AddressLib for bytes32; 11 | 12 | //--------------------------------------------------------------------------------// 13 | // Opcode | Opcode + Arguments | Description | Stack View // 14 | //--------------------------------------------------------------------------------// 15 | // 0x36 | 0x36 | CALLDATASIZE | size // 16 | // 0x3d | 0x3d | RETURNDATASIZE | 0 size // 17 | // 0x3d | 0x3d | RETURNDATASIZE | 0 0 size // 18 | // 0x37 | 0x37 | CALLDATACOPY | // 19 | // 0x36 | 0x36 | CALLDATASIZE | size // 20 | // 0x3d | 0x3d | RETURNDATASIZE | 0 size // 21 | // 0x34 | 0x34 | CALLVALUE | value 0 size // 22 | // 0xf0 | 0xf0 | CREATE | newContract // 23 | //--------------------------------------------------------------------------------// 24 | // Opcode | Opcode + Arguments | Description | Stack View // 25 | //--------------------------------------------------------------------------------// 26 | // 0x67 | 0x67XXXXXXXXXXXXXXXX | PUSH8 bytecode | bytecode // 27 | // 0x3d | 0x3d | RETURNDATASIZE | 0 bytecode // 28 | // 0x52 | 0x52 | MSTORE | // 29 | // 0x60 | 0x6008 | PUSH1 08 | 8 // 30 | // 0x60 | 0x6018 | PUSH1 18 | 24 8 // 31 | // 0xf3 | 0xf3 | RETURN | // 32 | //--------------------------------------------------------------------------------// 33 | bytes internal constant PROXY_BYTECODE = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3"; 34 | 35 | bytes32 internal constant PROXY_BYTECODE_HASH = keccak256(PROXY_BYTECODE); 36 | 37 | function deploy( 38 | bytes32 salt, 39 | bytes memory creationCode, 40 | uint256 value 41 | ) internal returns (address deployed) { 42 | bytes memory proxyChildBytecode = PROXY_BYTECODE; 43 | 44 | address proxy; 45 | /// @solidity memory-safe-assembly 46 | assembly { 47 | // Deploy a new contract with our pre-made bytecode via CREATE2. 48 | // We start 32 bytes into the code to avoid copying the byte length. 49 | proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), salt) 50 | } 51 | require(proxy != address(0), "DEPLOYMENT_FAILED"); 52 | 53 | deployed = getDeployed(salt); 54 | (bool success, ) = proxy.call{value: value}(creationCode); 55 | require(success && deployed.code.length != 0, "INITIALIZATION_FAILED"); 56 | } 57 | 58 | function getDeployed(bytes32 salt) internal view returns (address) { 59 | address proxy = keccak256( 60 | abi.encodePacked( 61 | // Prefix: 62 | bytes1(0xFF), 63 | // Creator: 64 | address(this), 65 | // Salt: 66 | salt, 67 | // Bytecode hash: 68 | PROXY_BYTECODE_HASH 69 | ) 70 | ).fromLast20Bytes(); 71 | 72 | return 73 | keccak256( 74 | abi.encodePacked( 75 | // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01) 76 | // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex) 77 | hex"d6_94", 78 | proxy, 79 | hex"01" // Nonce of the proxy contract (1) 80 | ) 81 | ).fromLast20Bytes(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/LibString.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Efficient library for creating string representations of integers. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) 6 | /// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/LibString.sol) 7 | library LibString { 8 | function toString(int256 value) internal pure returns (string memory str) { 9 | if (value >= 0) return toString(uint256(value)); 10 | 11 | unchecked { 12 | str = toString(uint256(-value)); 13 | 14 | /// @solidity memory-safe-assembly 15 | assembly { 16 | // Note: This is only safe because we over-allocate memory 17 | // and write the string from right to left in toString(uint256), 18 | // and thus can be sure that sub(str, 1) is an unused memory location. 19 | 20 | let length := mload(str) // Load the string length. 21 | // Put the - character at the start of the string contents. 22 | mstore(str, 45) // 45 is the ASCII code for the - character. 23 | str := sub(str, 1) // Move back the string pointer by a byte. 24 | mstore(str, add(length, 1)) // Update the string length. 25 | } 26 | } 27 | } 28 | 29 | function toString(uint256 value) internal pure returns (string memory str) { 30 | /// @solidity memory-safe-assembly 31 | assembly { 32 | // The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes 33 | // to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the 34 | // trailing zeros padding, and 3 other words for a max of 78 digits. In total: 5 * 32 = 160 bytes. 35 | let newFreeMemoryPointer := add(mload(0x40), 160) 36 | 37 | // Update the free memory pointer to avoid overriding our string. 38 | mstore(0x40, newFreeMemoryPointer) 39 | 40 | // Assign str to the end of the zone of newly allocated memory. 41 | str := sub(newFreeMemoryPointer, 32) 42 | 43 | // Clean the last word of memory it may not be overwritten. 44 | mstore(str, 0) 45 | 46 | // Cache the end of the memory to calculate the length later. 47 | let end := str 48 | 49 | // We write the string from rightmost digit to leftmost digit. 50 | // The following is essentially a do-while loop that also handles the zero case. 51 | // prettier-ignore 52 | for { let temp := value } 1 {} { 53 | // Move the pointer 1 byte to the left. 54 | str := sub(str, 1) 55 | 56 | // Write the character to the pointer. 57 | // The ASCII index of the '0' character is 48. 58 | mstore8(str, add(48, mod(temp, 10))) 59 | 60 | // Keep dividing temp until zero. 61 | temp := div(temp, 10) 62 | 63 | // prettier-ignore 64 | if iszero(temp) { break } 65 | } 66 | 67 | // Compute and cache the final total length of the string. 68 | let length := sub(end, str) 69 | 70 | // Move the pointer 32 bytes leftwards to make room for the length. 71 | str := sub(str, 32) 72 | 73 | // Store the string's length at the start of memory allocated for our string. 74 | mstore(str, length) 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/MerkleProofLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Gas optimized merkle proof verification library. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol) 6 | /// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/MerkleProofLib.sol) 7 | library MerkleProofLib { 8 | function verify( 9 | bytes32[] calldata proof, 10 | bytes32 root, 11 | bytes32 leaf 12 | ) internal pure returns (bool isValid) { 13 | /// @solidity memory-safe-assembly 14 | assembly { 15 | if proof.length { 16 | // Left shifting by 5 is like multiplying by 32. 17 | let end := add(proof.offset, shl(5, proof.length)) 18 | 19 | // Initialize offset to the offset of the proof in calldata. 20 | let offset := proof.offset 21 | 22 | // Iterate over proof elements to compute root hash. 23 | // prettier-ignore 24 | for {} 1 {} { 25 | // Slot where the leaf should be put in scratch space. If 26 | // leaf > calldataload(offset): slot 32, otherwise: slot 0. 27 | let leafSlot := shl(5, gt(leaf, calldataload(offset))) 28 | 29 | // Store elements to hash contiguously in scratch space. 30 | // The xor puts calldataload(offset) in whichever slot leaf 31 | // is not occupying, so 0 if leafSlot is 32, and 32 otherwise. 32 | mstore(leafSlot, leaf) 33 | mstore(xor(leafSlot, 32), calldataload(offset)) 34 | 35 | // Reuse leaf to store the hash to reduce stack operations. 36 | leaf := keccak256(0, 64) // Hash both slots of scratch space. 37 | 38 | offset := add(offset, 32) // Shift 1 word per cycle. 39 | 40 | // prettier-ignore 41 | if iszero(lt(offset, end)) { break } 42 | } 43 | } 44 | 45 | isValid := eq(leaf, root) // The proof is valid if the roots match. 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/ReentrancyGuard.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Gas optimized reentrancy protection for smart contracts. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol) 6 | /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol) 7 | abstract contract ReentrancyGuard { 8 | uint256 private locked = 1; 9 | 10 | modifier nonReentrant() virtual { 11 | require(locked == 1, "REENTRANCY"); 12 | 13 | locked = 2; 14 | 15 | _; 16 | 17 | locked = 1; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/SSTORE2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Read and write to persistent storage at a fraction of the cost. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SSTORE2.sol) 6 | /// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol) 7 | library SSTORE2 { 8 | uint256 internal constant DATA_OFFSET = 1; // We skip the first byte as it's a STOP opcode to ensure the contract can't be called. 9 | 10 | /*////////////////////////////////////////////////////////////// 11 | WRITE LOGIC 12 | //////////////////////////////////////////////////////////////*/ 13 | 14 | function write(bytes memory data) internal returns (address pointer) { 15 | // Prefix the bytecode with a STOP opcode to ensure it cannot be called. 16 | bytes memory runtimeCode = abi.encodePacked(hex"00", data); 17 | 18 | bytes memory creationCode = abi.encodePacked( 19 | //---------------------------------------------------------------------------------------------------------------// 20 | // Opcode | Opcode + Arguments | Description | Stack View // 21 | //---------------------------------------------------------------------------------------------------------------// 22 | // 0x60 | 0x600B | PUSH1 11 | codeOffset // 23 | // 0x59 | 0x59 | MSIZE | 0 codeOffset // 24 | // 0x81 | 0x81 | DUP2 | codeOffset 0 codeOffset // 25 | // 0x38 | 0x38 | CODESIZE | codeSize codeOffset 0 codeOffset // 26 | // 0x03 | 0x03 | SUB | (codeSize - codeOffset) 0 codeOffset // 27 | // 0x80 | 0x80 | DUP | (codeSize - codeOffset) (codeSize - codeOffset) 0 codeOffset // 28 | // 0x92 | 0x92 | SWAP3 | codeOffset (codeSize - codeOffset) 0 (codeSize - codeOffset) // 29 | // 0x59 | 0x59 | MSIZE | 0 codeOffset (codeSize - codeOffset) 0 (codeSize - codeOffset) // 30 | // 0x39 | 0x39 | CODECOPY | 0 (codeSize - codeOffset) // 31 | // 0xf3 | 0xf3 | RETURN | // 32 | //---------------------------------------------------------------------------------------------------------------// 33 | hex"60_0B_59_81_38_03_80_92_59_39_F3", // Returns all code in the contract except for the first 11 (0B in hex) bytes. 34 | runtimeCode // The bytecode we want the contract to have after deployment. Capped at 1 byte less than the code size limit. 35 | ); 36 | 37 | /// @solidity memory-safe-assembly 38 | assembly { 39 | // Deploy a new contract with the generated creation code. 40 | // We start 32 bytes into the code to avoid copying the byte length. 41 | pointer := create(0, add(creationCode, 32), mload(creationCode)) 42 | } 43 | 44 | require(pointer != address(0), "DEPLOYMENT_FAILED"); 45 | } 46 | 47 | /*////////////////////////////////////////////////////////////// 48 | READ LOGIC 49 | //////////////////////////////////////////////////////////////*/ 50 | 51 | function read(address pointer) internal view returns (bytes memory) { 52 | return readBytecode(pointer, DATA_OFFSET, pointer.code.length - DATA_OFFSET); 53 | } 54 | 55 | function read(address pointer, uint256 start) internal view returns (bytes memory) { 56 | start += DATA_OFFSET; 57 | 58 | return readBytecode(pointer, start, pointer.code.length - start); 59 | } 60 | 61 | function read( 62 | address pointer, 63 | uint256 start, 64 | uint256 end 65 | ) internal view returns (bytes memory) { 66 | start += DATA_OFFSET; 67 | end += DATA_OFFSET; 68 | 69 | require(pointer.code.length >= end, "OUT_OF_BOUNDS"); 70 | 71 | return readBytecode(pointer, start, end - start); 72 | } 73 | 74 | /*////////////////////////////////////////////////////////////// 75 | INTERNAL HELPER LOGIC 76 | //////////////////////////////////////////////////////////////*/ 77 | 78 | function readBytecode( 79 | address pointer, 80 | uint256 start, 81 | uint256 size 82 | ) private view returns (bytes memory data) { 83 | /// @solidity memory-safe-assembly 84 | assembly { 85 | // Get a pointer to some free memory. 86 | data := mload(0x40) 87 | 88 | // Update the free memory pointer to prevent overriding our data. 89 | // We use and(x, not(31)) as a cheaper equivalent to sub(x, mod(x, 32)). 90 | // Adding 31 to size and running the result through the logic above ensures 91 | // the memory pointer remains word-aligned, following the Solidity convention. 92 | mstore(0x40, add(data, and(add(add(size, 32), 31), not(31)))) 93 | 94 | // Store the size of the data in the first 32 byte chunk of free memory. 95 | mstore(data, size) 96 | 97 | // Copy the code into memory right after the 32 bytes we used to store the size. 98 | extcodecopy(pointer, add(data, 32), start, size) 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/SafeCastLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Safe unsigned integer casting library that reverts on overflow. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeCastLib.sol) 6 | /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol) 7 | library SafeCastLib { 8 | function safeCastTo248(uint256 x) internal pure returns (uint248 y) { 9 | require(x < 1 << 248); 10 | 11 | y = uint248(x); 12 | } 13 | 14 | function safeCastTo240(uint256 x) internal pure returns (uint240 y) { 15 | require(x < 1 << 240); 16 | 17 | y = uint240(x); 18 | } 19 | 20 | function safeCastTo232(uint256 x) internal pure returns (uint232 y) { 21 | require(x < 1 << 232); 22 | 23 | y = uint232(x); 24 | } 25 | 26 | function safeCastTo224(uint256 x) internal pure returns (uint224 y) { 27 | require(x < 1 << 224); 28 | 29 | y = uint224(x); 30 | } 31 | 32 | function safeCastTo216(uint256 x) internal pure returns (uint216 y) { 33 | require(x < 1 << 216); 34 | 35 | y = uint216(x); 36 | } 37 | 38 | function safeCastTo208(uint256 x) internal pure returns (uint208 y) { 39 | require(x < 1 << 208); 40 | 41 | y = uint208(x); 42 | } 43 | 44 | function safeCastTo200(uint256 x) internal pure returns (uint200 y) { 45 | require(x < 1 << 200); 46 | 47 | y = uint200(x); 48 | } 49 | 50 | function safeCastTo192(uint256 x) internal pure returns (uint192 y) { 51 | require(x < 1 << 192); 52 | 53 | y = uint192(x); 54 | } 55 | 56 | function safeCastTo184(uint256 x) internal pure returns (uint184 y) { 57 | require(x < 1 << 184); 58 | 59 | y = uint184(x); 60 | } 61 | 62 | function safeCastTo176(uint256 x) internal pure returns (uint176 y) { 63 | require(x < 1 << 176); 64 | 65 | y = uint176(x); 66 | } 67 | 68 | function safeCastTo168(uint256 x) internal pure returns (uint168 y) { 69 | require(x < 1 << 168); 70 | 71 | y = uint168(x); 72 | } 73 | 74 | function safeCastTo160(uint256 x) internal pure returns (uint160 y) { 75 | require(x < 1 << 160); 76 | 77 | y = uint160(x); 78 | } 79 | 80 | function safeCastTo152(uint256 x) internal pure returns (uint152 y) { 81 | require(x < 1 << 152); 82 | 83 | y = uint152(x); 84 | } 85 | 86 | function safeCastTo144(uint256 x) internal pure returns (uint144 y) { 87 | require(x < 1 << 144); 88 | 89 | y = uint144(x); 90 | } 91 | 92 | function safeCastTo136(uint256 x) internal pure returns (uint136 y) { 93 | require(x < 1 << 136); 94 | 95 | y = uint136(x); 96 | } 97 | 98 | function safeCastTo128(uint256 x) internal pure returns (uint128 y) { 99 | require(x < 1 << 128); 100 | 101 | y = uint128(x); 102 | } 103 | 104 | function safeCastTo120(uint256 x) internal pure returns (uint120 y) { 105 | require(x < 1 << 120); 106 | 107 | y = uint120(x); 108 | } 109 | 110 | function safeCastTo112(uint256 x) internal pure returns (uint112 y) { 111 | require(x < 1 << 112); 112 | 113 | y = uint112(x); 114 | } 115 | 116 | function safeCastTo104(uint256 x) internal pure returns (uint104 y) { 117 | require(x < 1 << 104); 118 | 119 | y = uint104(x); 120 | } 121 | 122 | function safeCastTo96(uint256 x) internal pure returns (uint96 y) { 123 | require(x < 1 << 96); 124 | 125 | y = uint96(x); 126 | } 127 | 128 | function safeCastTo88(uint256 x) internal pure returns (uint88 y) { 129 | require(x < 1 << 88); 130 | 131 | y = uint88(x); 132 | } 133 | 134 | function safeCastTo80(uint256 x) internal pure returns (uint80 y) { 135 | require(x < 1 << 80); 136 | 137 | y = uint80(x); 138 | } 139 | 140 | function safeCastTo72(uint256 x) internal pure returns (uint72 y) { 141 | require(x < 1 << 72); 142 | 143 | y = uint72(x); 144 | } 145 | 146 | function safeCastTo64(uint256 x) internal pure returns (uint64 y) { 147 | require(x < 1 << 64); 148 | 149 | y = uint64(x); 150 | } 151 | 152 | function safeCastTo56(uint256 x) internal pure returns (uint56 y) { 153 | require(x < 1 << 56); 154 | 155 | y = uint56(x); 156 | } 157 | 158 | function safeCastTo48(uint256 x) internal pure returns (uint48 y) { 159 | require(x < 1 << 48); 160 | 161 | y = uint48(x); 162 | } 163 | 164 | function safeCastTo40(uint256 x) internal pure returns (uint40 y) { 165 | require(x < 1 << 40); 166 | 167 | y = uint40(x); 168 | } 169 | 170 | function safeCastTo32(uint256 x) internal pure returns (uint32 y) { 171 | require(x < 1 << 32); 172 | 173 | y = uint32(x); 174 | } 175 | 176 | function safeCastTo24(uint256 x) internal pure returns (uint24 y) { 177 | require(x < 1 << 24); 178 | 179 | y = uint24(x); 180 | } 181 | 182 | function safeCastTo16(uint256 x) internal pure returns (uint16 y) { 183 | require(x < 1 << 16); 184 | 185 | y = uint16(x); 186 | } 187 | 188 | function safeCastTo8(uint256 x) internal pure returns (uint8 y) { 189 | require(x < 1 << 8); 190 | 191 | y = uint8(x); 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xsafe-contracts", 3 | "description": "Deterministic Multi-Chain Deployment", 4 | "author": "Chain Rule, LLC", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+https://github.com/chainrule-labs/xsafe-contracts.git" 9 | }, 10 | "scripts": { 11 | "commit": "cz", 12 | "coverage": "forge coverage --report lcov && npm run coverage:filter && npx lcov-summary lcov.info", 13 | "coverage:filter": "lcov -r lcov.info 'test/*' 'src/dependencies/*' -o lcov.info", 14 | "format": "forge fmt", 15 | "format:check": "forge fmt --check", 16 | "lint:check": "solhint --config ./.solhint.json 'src/**/*.sol'", 17 | "prepare": "husky install", 18 | "test": "forge test --optimize && npm run coverage" 19 | }, 20 | "commitlint": { 21 | "extends": [ 22 | "@commitlint/config-conventional" 23 | ] 24 | }, 25 | "config": { 26 | "commitizen": { 27 | "path": "cz-conventional-changelog" 28 | } 29 | }, 30 | "devDependencies": { 31 | "@commitlint/cli": "^17.8.0", 32 | "@commitlint/config-conventional": "^17.8.0", 33 | "commitizen": "^4.3.0", 34 | "cz-conventional-changelog": "^3.3.0", 35 | "husky": "^8.0.0", 36 | "lcov-summary": "^1.0.1", 37 | "solhint": "^3.6.2" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "xsafe-contracts" 3 | version = "0.1.0" 4 | description = "" 5 | authors = [ 6 | "0xernesto <78889960+0xernesto@users.noreply.github.com>", 7 | "cucupac <46691282+cucupac@users.noreply.github.com>", 8 | "rahul0eth <63620041+rahul0eth@users.noreply.github.com>", 9 | ] 10 | 11 | [tool.poetry.dependencies] 12 | python = "^3.9" 13 | slither-analyzer = "^0.8.2" 14 | 15 | [tool.poetry.dev-dependencies] 16 | 17 | [build-system] 18 | requires = ["poetry-core>=1.0.0"] 19 | build-backend = "poetry.core.masonry.api" -------------------------------------------------------------------------------- /remappings.txt: -------------------------------------------------------------------------------- 1 | ds-test/=lib/forge-std/lib/ds-test/src/ 2 | forge-std/=lib/forge-std/src/ 3 | solmate/=lib/solmate/src/ 4 | -------------------------------------------------------------------------------- /src/create2/interfaces/ICreate2Factory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | interface ICreate2Factory { 5 | function userNonces(address _principal, bytes32 _hashedBytecode) external returns (uint256); 6 | function getTransactionHash(address _principal, bytes memory _bytecode, uint256 _nonce) 7 | external 8 | returns (bytes32); 9 | function getAddress(address _principal, bytes memory _bytecode) external returns (address); 10 | function getBytecodeHash(bytes memory _bytecode) external pure returns (bytes32); 11 | function getDeploymentHistory(address _principal) external returns (address[] memory); 12 | function deploy(address _principal, bytes memory _signature, bytes memory _bytecode) external returns (address); 13 | } 14 | -------------------------------------------------------------------------------- /src/create2/interfaces/ICreate2FactoryAdmin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { ICreate2Factory } from "./ICreate2Factory.sol"; 5 | 6 | interface ICreate2FactoryAdmin is ICreate2Factory { 7 | error UUPSUnauthorizedCallContext(); 8 | 9 | function upgradeToAndCall(address newImplementation, bytes memory data) external; 10 | function extractNative() external; 11 | function extractERC20(address _token) external; 12 | } 13 | -------------------------------------------------------------------------------- /src/create3/interfaces/ICreate3Factory.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | interface ICreate3Factory { 5 | function userNonces(address _principal, bytes32 hashedCreationCode) external returns (uint256); 6 | function getTransactionHash(address _principal, bytes memory _creationCode) external returns (bytes32); 7 | function getAddress(address _principal, bytes memory _creationCode) external returns (address); 8 | function getBytecodeHash(bytes memory _creationCode) external pure returns (bytes32); 9 | function getDeploymentHistory(address _principal) external returns (address[] memory); 10 | function deploy( 11 | address _principal, 12 | bytes memory _signature, 13 | bytes memory _creationCode, 14 | bytes memory _constructorArgsCode 15 | ) external payable; 16 | } 17 | -------------------------------------------------------------------------------- /src/create3/interfaces/ICreate3FactoryAdmin.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { ICreate3Factory } from "./ICreate3Factory.sol"; 5 | 6 | interface ICreate3FactoryAdmin is ICreate3Factory { 7 | error UUPSUnauthorizedCallContext(); 8 | 9 | function upgradeToAndCall(address newImplementation, bytes memory data) external; 10 | function extractNative() external; 11 | function extractERC20(address _token) external; 12 | } 13 | -------------------------------------------------------------------------------- /src/dependencies/access/Context.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | /** 7 | * @dev Provides information about the current execution context, including the 8 | * sender of the transaction and its data. While these are generally available 9 | * via msg.sender and msg.data, they should not be accessed in such a direct 10 | * manner, since when dealing with meta-transactions the account sending and 11 | * paying for execution may not be the actual sender (as far as an application 12 | * is concerned). 13 | * 14 | * This contract is only required for intermediate, library-like contracts. 15 | */ 16 | abstract contract Context { 17 | function _msgSender() internal view virtual returns (address) { 18 | return msg.sender; 19 | } 20 | 21 | function _msgData() internal view virtual returns (bytes calldata) { 22 | return msg.data; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/dependencies/access/Ownable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | import { Context } from "./Context.sol"; 7 | import { Initializable } from "../proxy/utils/Initializable.sol"; 8 | 9 | /** 10 | * @dev Contract module which provides a basic access control mechanism, where 11 | * there is an account (an owner) that can be granted exclusive access to 12 | * specific functions. 13 | * 14 | * The initial owner is set to the address provided by the deployer. This can 15 | * later be changed with {transferOwnership}. 16 | * 17 | * This module is used through inheritance. It will make available the modifier 18 | * `onlyOwner`, which can be applied to your functions to restrict their use to 19 | * the owner. 20 | */ 21 | abstract contract Ownable is Initializable, Context { 22 | address private _owner; 23 | 24 | /** 25 | * @dev The caller account is not authorized to perform an operation. 26 | */ 27 | error OwnableUnauthorizedAccount(address account); 28 | 29 | /** 30 | * @dev The owner is not a valid owner account. (eg. `address(0)`) 31 | */ 32 | error OwnableInvalidOwner(address owner); 33 | 34 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 35 | 36 | /** 37 | * @dev Initializes the contract setting the deployer as the initial owner. 38 | */ 39 | function __Ownable_init() internal onlyInitializing { 40 | __Ownable_init_unchained(); 41 | } 42 | 43 | function __Ownable_init_unchained() internal onlyInitializing { 44 | _transferOwnership(_msgSender()); 45 | } 46 | 47 | /** 48 | * @dev Throws if called by any account other than the owner. 49 | */ 50 | modifier onlyOwner() { 51 | _checkOwner(); 52 | _; 53 | } 54 | 55 | /** 56 | * @dev Returns the address of the current owner. 57 | */ 58 | function owner() public view virtual returns (address) { 59 | return _owner; 60 | } 61 | 62 | /** 63 | * @dev Throws if the sender is not the owner. 64 | */ 65 | function _checkOwner() internal view virtual { 66 | if (owner() != _msgSender()) { 67 | revert OwnableUnauthorizedAccount(_msgSender()); 68 | } 69 | } 70 | 71 | /** 72 | * @dev Leaves the contract without owner. It will not be possible to call 73 | * `onlyOwner` functions. Can only be called by the current owner. 74 | * 75 | * NOTE: Renouncing ownership will leave the contract without an owner, 76 | * thereby disabling any functionality that is only available to the owner. 77 | */ 78 | function renounceOwnership() public virtual onlyOwner { 79 | _transferOwnership(address(0)); 80 | } 81 | 82 | /** 83 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 84 | * Can only be called by the current owner. 85 | */ 86 | function transferOwnership(address newOwner) public virtual onlyOwner { 87 | if (newOwner == address(0)) { 88 | revert OwnableInvalidOwner(address(0)); 89 | } 90 | _transferOwnership(newOwner); 91 | } 92 | 93 | /** 94 | * @dev Transfers ownership of the contract to a new account (`newOwner`). 95 | * Internal function without access restriction. 96 | */ 97 | function _transferOwnership(address newOwner) internal virtual { 98 | address oldOwner = _owner; 99 | _owner = newOwner; 100 | emit OwnershipTransferred(oldOwner, newOwner); 101 | } 102 | 103 | /** 104 | * @dev This empty reserved space is put in place to allow future versions to add new 105 | * variables without shifting down storage slots in the inheritance chain. 106 | * Storage slot management is necessary, as we're using an upgradable proxy contract. 107 | * For details, see: https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps 108 | */ 109 | uint256[50] private __gap; 110 | } 111 | -------------------------------------------------------------------------------- /src/dependencies/libraries/StorageSlot.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) 3 | // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. 4 | 5 | pragma solidity ^0.8.20; 6 | 7 | /** 8 | * @dev Library for reading and writing primitive types to specific storage slots. 9 | * 10 | * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. 11 | * This library helps with reading and writing to such slots without the need for inline assembly. 12 | * 13 | * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. 14 | * 15 | * Example usage to set ERC1967 implementation slot: 16 | * ```solidity 17 | * contract ERC1967 { 18 | * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; 19 | * 20 | * function __getImplementation() internal view returns (address) { 21 | * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; 22 | * } 23 | * 24 | * function __setImplementation(address newImplementation) internal { 25 | * require(newImplementation.code.length > 0); 26 | * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; 27 | * } 28 | * } 29 | * ``` 30 | */ 31 | library StorageSlot { 32 | struct AddressSlot { 33 | address value; 34 | } 35 | 36 | struct BooleanSlot { 37 | bool value; 38 | } 39 | 40 | struct Bytes32Slot { 41 | bytes32 value; 42 | } 43 | 44 | struct Uint256Slot { 45 | uint256 value; 46 | } 47 | 48 | struct StringSlot { 49 | string value; 50 | } 51 | 52 | struct BytesSlot { 53 | bytes value; 54 | } 55 | 56 | /** 57 | * @dev Returns an `AddressSlot` with member `value` located at `slot`. 58 | */ 59 | function _getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { 60 | /// @solidity memory-safe-assembly 61 | assembly { 62 | r.slot := slot 63 | } 64 | } 65 | 66 | /** 67 | * @dev Returns an `BooleanSlot` with member `value` located at `slot`. 68 | */ 69 | function _getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { 70 | /// @solidity memory-safe-assembly 71 | assembly { 72 | r.slot := slot 73 | } 74 | } 75 | 76 | /** 77 | * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. 78 | */ 79 | function _getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { 80 | /// @solidity memory-safe-assembly 81 | assembly { 82 | r.slot := slot 83 | } 84 | } 85 | 86 | /** 87 | * @dev Returns an `Uint256Slot` with member `value` located at `slot`. 88 | */ 89 | function _getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { 90 | /// @solidity memory-safe-assembly 91 | assembly { 92 | r.slot := slot 93 | } 94 | } 95 | 96 | /** 97 | * @dev Returns an `StringSlot` with member `value` located at `slot`. 98 | */ 99 | function _getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { 100 | /// @solidity memory-safe-assembly 101 | assembly { 102 | r.slot := slot 103 | } 104 | } 105 | 106 | /** 107 | * @dev Returns an `StringSlot` representation of the string storage pointer `store`. 108 | */ 109 | function _getStringSlot(string storage store) internal pure returns (StringSlot storage r) { 110 | /// @solidity memory-safe-assembly 111 | assembly { 112 | r.slot := store.slot 113 | } 114 | } 115 | 116 | /** 117 | * @dev Returns an `BytesSlot` with member `value` located at `slot`. 118 | */ 119 | function _getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { 120 | /// @solidity memory-safe-assembly 121 | assembly { 122 | r.slot := slot 123 | } 124 | } 125 | 126 | /** 127 | * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. 128 | */ 129 | function _getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { 130 | /// @solidity memory-safe-assembly 131 | assembly { 132 | r.slot := store.slot 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /src/dependencies/libraries/Strings.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev String operations. 8 | */ 9 | library Strings { 10 | bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; 11 | uint8 private constant _ADDRESS_LENGTH = 20; 12 | 13 | /** 14 | * @dev Converts a `uint256` to its ASCII `string` decimal representation. 15 | */ 16 | function _toString(uint256 value) internal pure returns (string memory) { 17 | // Inspired by OraclizeAPI's implementation - MIT licence 18 | // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol 19 | 20 | if (value == 0) { 21 | return "0"; 22 | } 23 | uint256 temp = value; 24 | uint256 digits; 25 | while (temp != 0) { 26 | digits++; 27 | temp /= 10; 28 | } 29 | bytes memory buffer = new bytes(digits); 30 | while (value != 0) { 31 | digits -= 1; 32 | buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); 33 | value /= 10; 34 | } 35 | return string(buffer); 36 | } 37 | 38 | /** 39 | * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. 40 | */ 41 | function _toHexString(uint256 value) internal pure returns (string memory) { 42 | if (value == 0) { 43 | return "0x00"; 44 | } 45 | uint256 temp = value; 46 | uint256 length = 0; 47 | while (temp != 0) { 48 | length++; 49 | temp >>= 8; 50 | } 51 | return _toHexString(value, length); 52 | } 53 | 54 | /** 55 | * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. 56 | */ 57 | function _toHexString(uint256 value, uint256 length) internal pure returns (string memory) { 58 | bytes memory buffer = new bytes(2 * length + 2); 59 | buffer[0] = "0"; 60 | buffer[1] = "x"; 61 | for (uint256 i = 2 * length + 1; i > 1; --i) { 62 | buffer[i] = _HEX_SYMBOLS[value & 0xf]; 63 | value >>= 4; 64 | } 65 | require(value == 0, "Strings: hex length insufficient"); 66 | return string(buffer); 67 | } 68 | 69 | /** 70 | * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. 71 | */ 72 | function _toHexString(address addr) internal pure returns (string memory) { 73 | return _toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/dependencies/proxy/ERC1967Proxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Proxy.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | import { Proxy } from "./Proxy.sol"; 7 | import { ERC1967Utils } from "./ERC1967Utils.sol"; 8 | 9 | /** 10 | * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an 11 | * implementation address that can be changed. This address is stored in storage in the location specified by 12 | * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the 13 | * implementation behind the proxy. 14 | */ 15 | contract ERC1967Proxy is Proxy { 16 | /** 17 | * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation`. 18 | * 19 | * If `_data` is nonempty, it's used as data in a delegate call to `implementation`. This will typically be an 20 | * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor. 21 | * 22 | * Requirements: 23 | * 24 | * - If `data` is empty, `msg.value` must be zero. 25 | */ 26 | constructor(address implementation, bytes memory _data) payable { 27 | ERC1967Utils._upgradeToAndCall(implementation, _data); 28 | } 29 | 30 | /** 31 | * @dev Returns the current implementation address. 32 | * 33 | * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using 34 | * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. 35 | * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc` 36 | */ 37 | function _implementation() internal view virtual override returns (address) { 38 | return ERC1967Utils._getImplementation(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/dependencies/proxy/Proxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (proxy/Proxy.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | /** 7 | * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM 8 | * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to 9 | * be specified by overriding the virtual {_implementation} function. 10 | * 11 | * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a 12 | * different contract through the {_delegate} function. 13 | * 14 | * The success and return data of the delegated call will be returned back to the caller of the proxy. 15 | */ 16 | abstract contract Proxy { 17 | /** 18 | * @dev Delegates the current call to `implementation`. 19 | * 20 | * This function does not return to its internal call site, it will return directly to the external caller. 21 | */ 22 | function _delegate(address implementation) internal virtual { 23 | assembly { 24 | // Copy msg.data. We take full control of memory in this inline assembly 25 | // block because it will not return to Solidity code. We overwrite the 26 | // Solidity scratch pad at memory position 0. 27 | calldatacopy(0, 0, calldatasize()) 28 | 29 | // Call the implementation. 30 | // out and outsize are 0 because we don't know the size yet. 31 | let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) 32 | 33 | // Copy the returned data. 34 | returndatacopy(0, 0, returndatasize()) 35 | 36 | switch result 37 | // delegatecall returns 0 on error. 38 | case 0 { revert(0, returndatasize()) } 39 | default { return(0, returndatasize()) } 40 | } 41 | } 42 | 43 | /** 44 | * @dev This is a virtual function that should be overridden so it returns the address to which the fallback 45 | * function and {_fallback} should delegate. 46 | */ 47 | function _implementation() internal view virtual returns (address); 48 | 49 | /** 50 | * @dev Delegates the current call to the address returned by `_implementation()`. 51 | * 52 | * This function does not return to its internal call site, it will return directly to the external caller. 53 | */ 54 | function _fallback() internal virtual { 55 | _delegate(_implementation()); 56 | } 57 | 58 | /** 59 | * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other 60 | * function in the contract matches the call data. 61 | */ 62 | fallback() external payable virtual { 63 | _fallback(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/dependencies/proxy/interfaces/IBeacon.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | pragma solidity >=0.8.0; 4 | 5 | /** 6 | * @dev This is the interface that {BeaconProxy} expects of its beacon. 7 | */ 8 | interface IBeacon { 9 | /** 10 | * @dev Must return an address that can be used as a delegate call target. 11 | * 12 | * {BeaconProxy} will check that this address is a contract. 13 | */ 14 | function implementation() external view returns (address); 15 | } 16 | -------------------------------------------------------------------------------- /src/dependencies/proxy/interfaces/IERC1822.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC1822.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | /** 7 | * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified 8 | * proxy whose upgrades are fully controlled by the current implementation. 9 | */ 10 | interface IERC1822Proxiable { 11 | /** 12 | * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation 13 | * address. 14 | * 15 | * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks 16 | * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this 17 | * function revert if invoked through a proxy. 18 | */ 19 | function proxiableUUID() external view returns (bytes32); 20 | } 21 | -------------------------------------------------------------------------------- /src/dependencies/token/interfaces/IERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) 3 | 4 | pragma solidity ^0.8.20; 5 | 6 | /** 7 | * @dev Interface of the ERC20 standard as defined in the EIP. 8 | */ 9 | interface IERC20 { 10 | /** 11 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 12 | * another (`to`). 13 | * 14 | * Note that `value` may be zero. 15 | */ 16 | event Transfer(address indexed from, address indexed to, uint256 value); 17 | 18 | /** 19 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 20 | * a call to {approve}. `value` is the new allowance. 21 | */ 22 | event Approval(address indexed owner, address indexed spender, uint256 value); 23 | 24 | /** 25 | * @dev Returns the value of tokens in existence. 26 | */ 27 | function totalSupply() external view returns (uint256); 28 | 29 | /** 30 | * @dev Returns the value of tokens owned by `account`. 31 | */ 32 | function balanceOf(address account) external view returns (uint256); 33 | 34 | /** 35 | * @dev Moves a `value` amount of tokens from the caller's account to `to`. 36 | * 37 | * Returns a boolean value indicating whether the operation succeeded. 38 | * 39 | * Emits a {Transfer} event. 40 | */ 41 | function transfer(address to, uint256 value) external returns (bool); 42 | 43 | /** 44 | * @dev Returns the remaining number of tokens that `spender` will be 45 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 46 | * zero by default. 47 | * 48 | * This value changes when {approve} or {transferFrom} are called. 49 | */ 50 | function allowance(address owner, address spender) external view returns (uint256); 51 | 52 | /** 53 | * @dev Sets a `value` amount of tokens as the allowance of `spender` over the 54 | * caller's tokens. 55 | * 56 | * Returns a boolean value indicating whether the operation succeeded. 57 | * 58 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 59 | * that someone may use both the old and the new allowance by unfortunate 60 | * transaction ordering. One possible solution to mitigate this race 61 | * condition is to first reduce the spender's allowance to 0 and set the 62 | * desired value afterwards: 63 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 64 | * 65 | * Emits an {Approval} event. 66 | */ 67 | function approve(address spender, uint256 value) external returns (bool); 68 | 69 | /** 70 | * @dev Moves a `value` amount of tokens from `from` to `to` using the 71 | * allowance mechanism. `value` is then deducted from the caller's 72 | * allowance. 73 | * 74 | * Returns a boolean value indicating whether the operation succeeded. 75 | * 76 | * Emits a {Transfer} event. 77 | */ 78 | function transferFrom(address from, address to, uint256 value) external returns (bool); 79 | } 80 | -------------------------------------------------------------------------------- /test/create2/Create2Factory.admin.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { Test } from "forge-std/Test.sol"; 5 | import { Create2Factory } from "../../src/create2/Create2Factory.sol"; 6 | import { ERC1967Proxy } from "../../src/dependencies/proxy/ERC1967Proxy.sol"; 7 | import { IERC20 } from "../../src/dependencies/token/interfaces/IERC20.sol"; 8 | import { ICreate2FactoryAdmin } from "../../src/create2/interfaces/ICreate2FactoryAdmin.sol"; 9 | import { TestSetup } from "./common/contracts/TestSetup.t.sol"; 10 | import { CONTRACT_DEPLOYER, TEST_ERC20_TOKEN } from "./common/Constants.t.sol"; 11 | 12 | contract Create2FactoryTest is TestSetup { 13 | /* solhint-disable func-name-mixedcase */ 14 | 15 | function test_ExtractNative(uint256 amount) public { 16 | // Setup 17 | vm.assume(amount > 0 && amount < 1e22); 18 | vm.deal(address(proxy), amount); 19 | 20 | assertEq(address(proxy).balance, amount); 21 | 22 | uint256 preLocalBalance = CONTRACT_DEPLOYER.balance; 23 | 24 | // Act 25 | vm.prank(CONTRACT_DEPLOYER); 26 | ICreate2FactoryAdmin(address(proxy)).extractNative(); 27 | 28 | assertEq(CONTRACT_DEPLOYER.balance, preLocalBalance + amount); 29 | } 30 | 31 | function testFail_ExtractNativeUnauthorized(uint256 amount, address invalidExtractor) public { 32 | // Setup 33 | vm.assume(amount > 0 && amount < 1e22); 34 | vm.assume(invalidExtractor != CONTRACT_DEPLOYER); 35 | vm.deal(address(proxy), amount); 36 | 37 | // Act 38 | vm.prank(invalidExtractor); 39 | ICreate2FactoryAdmin(address(proxy)).extractNative(); 40 | } 41 | } 42 | 43 | contract Create2FactoryForkTest is Test { 44 | /* solhint-disable func-name-mixedcase */ 45 | 46 | Create2Factory public implementation; 47 | ERC1967Proxy public proxy; 48 | uint256 public mainnetFork; 49 | 50 | function setUp() public { 51 | // Setup: use mainnet fork 52 | mainnetFork = vm.createFork(vm.envString("ETHEREUM_RPC")); 53 | vm.selectFork(mainnetFork); 54 | 55 | // Instantiate contracts 56 | implementation = new Create2Factory(); 57 | vm.prank(CONTRACT_DEPLOYER); 58 | proxy = new ERC1967Proxy(address(implementation), abi.encodeWithSignature("initialize()")); 59 | } 60 | 61 | function test_ActiveFork() public { 62 | assertEq(vm.activeFork(), mainnetFork); 63 | } 64 | 65 | function test_ExtractERC20(uint256 amount) public { 66 | // Assumptions 67 | vm.assume(amount > 0 && amount <= 1e6 * 1e5); 68 | 69 | // Setup: give the contract ERC20 tokens 70 | deal(TEST_ERC20_TOKEN, address(proxy), amount); 71 | 72 | // Pre-action assertions 73 | assertEq(IERC20(TEST_ERC20_TOKEN).balanceOf(address(proxy)), amount); 74 | 75 | // Act 76 | vm.prank(CONTRACT_DEPLOYER); 77 | ICreate2FactoryAdmin(address(proxy)).extractERC20(TEST_ERC20_TOKEN); 78 | 79 | // Post-action assertions 80 | assertEq(IERC20(TEST_ERC20_TOKEN).balanceOf(address(proxy)), 0); 81 | assertEq(IERC20(TEST_ERC20_TOKEN).balanceOf(CONTRACT_DEPLOYER), amount); 82 | } 83 | 84 | function testFail_ExtractERC20Unauthorized(uint256 amount, address invalidExtractor) public { 85 | // Assumptions 86 | vm.assume(amount > 0 && amount <= 1e6 * 1e5); 87 | vm.assume(invalidExtractor != CONTRACT_DEPLOYER); 88 | 89 | // Setup: give the contract ERC20 tokens 90 | deal(TEST_ERC20_TOKEN, address(proxy), amount); 91 | 92 | // Act 93 | vm.prank(invalidExtractor); 94 | ICreate2FactoryAdmin(address(proxy)).extractERC20(TEST_ERC20_TOKEN); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /test/create2/common/Constants.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | address constant CONTRACT_DEPLOYER = 0x0a5B347509621337cDDf44CBCf6B6E7C9C908CD2; 5 | 6 | address constant TEST_ERC20_TOKEN = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; // USDC on Ethereum 7 | -------------------------------------------------------------------------------- /test/create2/common/contracts/Child.args.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { IChild } from "../interfaces/IChild.t.sol"; 5 | 6 | contract ChildArgs is IChild { 7 | address public arg; 8 | 9 | constructor(address _arg) { 10 | arg = _arg; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/create2/common/contracts/Child.noargs.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { IChild } from "../interfaces/IChild.t.sol"; 5 | 6 | contract ChildNoArgs is IChild { } 7 | -------------------------------------------------------------------------------- /test/create2/common/contracts/TestSetup.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { Test } from "forge-std/Test.sol"; 5 | import { ICreate2Factory } from "../../../../src/create2/interfaces/ICreate2Factory.sol"; 6 | import { Create2Factory } from "../../../../src/create2/Create2Factory.sol"; 7 | import { ERC1967Proxy } from "../../../../src/dependencies/proxy/ERC1967Proxy.sol"; 8 | import { ChildArgs } from "./Child.args.t.sol"; 9 | import { ChildNoArgs } from "./Child.noargs.t.sol"; 10 | import { CONTRACT_DEPLOYER } from "../../common/Constants.t.sol"; 11 | 12 | abstract contract TestSetup is Test { 13 | Create2Factory public implementation; 14 | ERC1967Proxy public proxy; 15 | ChildArgs public childWithArgs; 16 | ChildNoArgs public childNoArgs; 17 | bytes public bytecodeChildWithArgs; 18 | bytes public bytecodeChildNoArgs; 19 | bytes32 public hashedBytecodeChildWithArgs; 20 | bytes32 public hashedBytecodeChildNoArgs; 21 | 22 | // Events 23 | event Deploy(address indexed sender, address indexed childA, bytes32 hashedBytecode, uint256 nonce); 24 | 25 | function setUp() public { 26 | implementation = new Create2Factory(); 27 | vm.prank(CONTRACT_DEPLOYER); 28 | proxy = new ERC1967Proxy(address(implementation), abi.encodeWithSignature("initialize()")); 29 | 30 | // Get Bytecode 31 | bytecodeChildWithArgs = abi.encodePacked(type(ChildArgs).creationCode, abi.encode(address(this))); 32 | hashedBytecodeChildWithArgs = keccak256(bytecodeChildWithArgs); 33 | bytecodeChildNoArgs = abi.encodePacked(type(ChildNoArgs).creationCode, ""); 34 | hashedBytecodeChildNoArgs = keccak256(bytecodeChildNoArgs); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/create2/common/interfaces/IChild.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | interface IChild { } 5 | -------------------------------------------------------------------------------- /test/create2/common/libraries/AddressLib.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | library AddressLib { 5 | function includes(address[] memory _array, address _address) internal pure returns (bool) { 6 | for (uint256 i; i < _array.length; i++) { 7 | if (_array[i] == _address) { 8 | return true; 9 | } 10 | } 11 | return false; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/create2/helpers/DeploymentHelper.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { Test } from "forge-std/Test.sol"; 5 | import { VmSafe } from "forge-std/Vm.sol"; 6 | import { ICreate2Factory } from "../../../src/create2/interfaces/ICreate2Factory.sol"; 7 | 8 | abstract contract DeploymentHelper is Test { 9 | /** 10 | * @dev Reusable function for deploying childA contracts. 11 | * @param _contract The address of the PredictveDeployer proxy contract. 12 | * @param _wallet The principal's evm account that signs off on a childA contract deployment. 13 | * @param _bytecode The to-be-deployed contract bytecode. 14 | */ 15 | function deployChild(address _contract, VmSafe.Wallet memory _wallet, bytes memory _bytecode) 16 | internal 17 | returns (address) 18 | { 19 | uint256 currentNonce = ICreate2Factory(_contract).userNonces(_wallet.addr, keccak256(_bytecode)); 20 | bytes32 txHash = ICreate2Factory(_contract).getTransactionHash(_wallet.addr, _bytecode, currentNonce); 21 | bytes32 messageHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", txHash)); 22 | (uint8 v, bytes32 r, bytes32 s) = vm.sign(_wallet.privateKey, messageHash); 23 | bytes memory signature = abi.encodePacked(r, s, v); 24 | return ICreate2Factory(_contract).deploy(_wallet.addr, signature, _bytecode); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/create3/Create3Factory.admin.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { Test } from "forge-std/Test.sol"; 5 | import { Create3Factory } from "../../src/create3/Create3Factory.sol"; 6 | import { ERC1967Proxy } from "../../src/dependencies/proxy/ERC1967Proxy.sol"; 7 | import { IERC20 } from "../../src/dependencies/token/interfaces/IERC20.sol"; 8 | import { ICreate3FactoryAdmin } from "../../src/create3/interfaces/ICreate3FactoryAdmin.sol"; 9 | import { TestSetup } from "./common/contracts/TestSetup.t.sol"; 10 | import { CONTRACT_DEPLOYER, TEST_ERC20_TOKEN } from "./common/Constants.t.sol"; 11 | 12 | contract Create3FactoryAdminTest is TestSetup { 13 | /* solhint-disable func-name-mixedcase */ 14 | 15 | function test_ExtractNative(uint256 amount) public { 16 | // Setup 17 | vm.assume(amount > 0 && amount < 1e22); 18 | vm.deal(address(proxy), amount); 19 | 20 | assertEq(address(proxy).balance, amount, "Equivalence Violation: native balance != amount"); 21 | 22 | uint256 preLocalBalance = CONTRACT_DEPLOYER.balance; 23 | 24 | // Act 25 | vm.prank(CONTRACT_DEPLOYER); 26 | ICreate3FactoryAdmin(address(proxy)).extractNative(); 27 | 28 | assertEq( 29 | CONTRACT_DEPLOYER.balance, 30 | preLocalBalance + amount, 31 | "Equivalence Violation: native balance != preLocalBalance + amount." 32 | ); 33 | } 34 | 35 | function testFail_ExtractNativeUnauthorized(uint256 amount, address invalidExtractor) public { 36 | // Setup 37 | vm.assume(amount > 0 && amount < 1e22); 38 | vm.assume(invalidExtractor != CONTRACT_DEPLOYER); 39 | vm.deal(address(proxy), amount); 40 | 41 | // Act 42 | vm.prank(invalidExtractor); 43 | ICreate3FactoryAdmin(address(proxy)).extractNative(); 44 | } 45 | } 46 | 47 | contract Create3FactoryForkTest is Test { 48 | /* solhint-disable func-name-mixedcase */ 49 | 50 | Create3Factory public implementation; 51 | ERC1967Proxy public proxy; 52 | uint256 public mainnetFork; 53 | 54 | function setUp() public { 55 | // Setup: use mainnet fork 56 | mainnetFork = vm.createFork(vm.envString("ETHEREUM_RPC")); 57 | vm.selectFork(mainnetFork); 58 | 59 | // Instantiate contracts 60 | implementation = new Create3Factory(); 61 | vm.prank(CONTRACT_DEPLOYER); 62 | proxy = new ERC1967Proxy(address(implementation), abi.encodeWithSignature("initialize()")); 63 | } 64 | 65 | function test_ActiveFork() public { 66 | assertEq(vm.activeFork(), mainnetFork, "Equivalence Violation: vm.activeFork() != mainnetFork"); 67 | } 68 | 69 | function test_ExtractERC20(uint256 amount) public { 70 | // Assumptions 71 | vm.assume(amount > 0 && amount <= 1e6 * 1e5); 72 | 73 | // Setup: give the contract ERC20 tokens 74 | deal(TEST_ERC20_TOKEN, address(proxy), amount); 75 | 76 | // Pre-action assertions 77 | assertEq( 78 | IERC20(TEST_ERC20_TOKEN).balanceOf(address(proxy)), amount, "Equivalence Violation: ERC20 balance != amount" 79 | ); 80 | 81 | // Act 82 | vm.prank(CONTRACT_DEPLOYER); 83 | ICreate3FactoryAdmin(address(proxy)).extractERC20(TEST_ERC20_TOKEN); 84 | 85 | // Post-action assertions 86 | assertEq(IERC20(TEST_ERC20_TOKEN).balanceOf(address(proxy)), 0, "Equivalence Violation: ERC20 balance != 0"); 87 | assertEq( 88 | IERC20(TEST_ERC20_TOKEN).balanceOf(CONTRACT_DEPLOYER), 89 | amount, 90 | "Equivalence Violation: ERC20 balance != amount" 91 | ); 92 | } 93 | 94 | function testFail_ExtractERC20Unauthorized(uint256 amount, address invalidExtractor) public { 95 | // Assumptions 96 | vm.assume(amount > 0 && amount <= 1e6 * 1e5); 97 | vm.assume(invalidExtractor != CONTRACT_DEPLOYER); 98 | 99 | // Setup: give the contract ERC20 tokens 100 | deal(TEST_ERC20_TOKEN, address(proxy), amount); 101 | 102 | // Act 103 | vm.prank(invalidExtractor); 104 | ICreate3FactoryAdmin(address(proxy)).extractERC20(TEST_ERC20_TOKEN); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /test/create3/common/Constants.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | address constant CONTRACT_DEPLOYER = 0x0a5B347509621337cDDf44CBCf6B6E7C9C908CD2; 5 | 6 | address constant TEST_ERC20_TOKEN = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48; // USDC on Ethereum 7 | -------------------------------------------------------------------------------- /test/create3/common/contracts/Child.args.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { IChild } from "../interfaces/IChild.t.sol"; 5 | 6 | // Value types 7 | contract AddressChild is IChild { 8 | address public arg; 9 | 10 | constructor(address _arg) { 11 | arg = _arg; 12 | } 13 | } 14 | 15 | contract UintChild is IChild { 16 | uint256 public arg; 17 | 18 | constructor(uint256 _arg) { 19 | arg = _arg; 20 | } 21 | } 22 | 23 | contract IntChild is IChild { 24 | int256 public arg; 25 | 26 | constructor(int256 _arg) { 27 | arg = _arg; 28 | } 29 | } 30 | 31 | contract StringChild is IChild { 32 | string public arg; 33 | 34 | constructor(string memory _arg) { 35 | arg = _arg; 36 | } 37 | } 38 | 39 | contract BytesChild is IChild { 40 | bytes public arg; 41 | 42 | constructor(bytes memory _arg) { 43 | arg = _arg; 44 | } 45 | } 46 | 47 | contract Bytes32Child is IChild { 48 | bytes32 public arg; 49 | 50 | constructor(bytes32 _arg) { 51 | arg = _arg; 52 | } 53 | } 54 | 55 | contract BoolChild is IChild { 56 | bool public arg; 57 | 58 | constructor(bool _arg) { 59 | arg = _arg; 60 | } 61 | } 62 | 63 | // Referrence types 64 | contract AddressArrayChild is IChild { 65 | address[] public arg; 66 | 67 | constructor(address[] memory _arg) { 68 | arg = _arg; 69 | } 70 | } 71 | 72 | contract UintArrayChild is IChild { 73 | uint256[] public arg; 74 | 75 | constructor(uint256[] memory _arg) { 76 | arg = _arg; 77 | } 78 | } 79 | 80 | contract IntArrayChild is IChild { 81 | int256[] public arg; 82 | 83 | constructor(int256[] memory _arg) { 84 | arg = _arg; 85 | } 86 | } 87 | 88 | contract StringArrayChild is IChild { 89 | string[] public arg; 90 | 91 | constructor(string[] memory _arg) { 92 | arg = _arg; 93 | } 94 | } 95 | 96 | contract BytesArrayChild is IChild { 97 | bytes[] public arg; 98 | 99 | constructor(bytes[] memory _arg) { 100 | arg = _arg; 101 | } 102 | } 103 | 104 | contract Bytes32ArrayChild is IChild { 105 | bytes32[] public arg; 106 | 107 | constructor(bytes32[] memory _arg) { 108 | arg = _arg; 109 | } 110 | } 111 | 112 | contract BoolArrayChild is IChild { 113 | bool[] public arg; 114 | 115 | constructor(bool[] memory _arg) { 116 | arg = _arg; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /test/create3/common/contracts/Child.noargs.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { IChild } from "../interfaces/IChild.t.sol"; 5 | 6 | contract ChildNoArgs is IChild { } 7 | -------------------------------------------------------------------------------- /test/create3/common/contracts/Children.args.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { 5 | AddressChild, 6 | UintChild, 7 | IntChild, 8 | StringChild, 9 | BytesChild, 10 | Bytes32Child, 11 | BoolChild, 12 | AddressArrayChild, 13 | UintArrayChild, 14 | IntArrayChild, 15 | StringArrayChild, 16 | BytesArrayChild, 17 | Bytes32ArrayChild, 18 | BoolArrayChild 19 | } from "./Child.args.t.sol"; 20 | import { IChild } from "../interfaces/IChild.t.sol"; 21 | import { CONTRACT_DEPLOYER } from "../Constants.t.sol"; 22 | 23 | /** 24 | * @title ChildrenWithConstructorArgs 25 | * @dev Constructs arrays of children with different types and different construct args for each type. 26 | */ 27 | contract ChildrenWithConstructorArgs { 28 | struct ChildContractData { 29 | bytes creationCode; 30 | bytes constructorArgsCode1; 31 | bytes constructorArgsCode2; 32 | } 33 | 34 | ChildContractData[] public childrenData; 35 | 36 | constructor() { 37 | __constructChildren(); 38 | } 39 | 40 | /// @dev Constructs children with different constructor arguments for testing. 41 | function __constructChildren() private { 42 | address defaultAddress = address(this); 43 | address variantAddress = address(uint160(uint256(keccak256(abi.encodePacked("variant"))))); 44 | 45 | // value types 46 | __addChildData(type(AddressChild).creationCode, abi.encode(defaultAddress), abi.encode(variantAddress)); 47 | __addChildData(type(UintChild).creationCode, abi.encode(uint256(1)), abi.encode(uint256(2))); 48 | __addChildData(type(IntChild).creationCode, abi.encode(int256(-1)), abi.encode(int256(-2))); 49 | __addChildData(type(StringChild).creationCode, abi.encode("hello world"), abi.encode("variant")); 50 | __addChildData(type(BytesChild).creationCode, abi.encode(hex"01"), abi.encode(hex"02")); 51 | __addChildData( 52 | type(Bytes32Child).creationCode, abi.encode(bytes32(uint256(1))), abi.encode(bytes32(uint256(2))) 53 | ); 54 | __addChildData(type(BoolChild).creationCode, abi.encode(true), abi.encode(false)); 55 | 56 | // reference types 57 | // Address Arrays 58 | address[] memory defaultAddresses = new address[](1); 59 | defaultAddresses[0] = defaultAddress; 60 | address[] memory variantAddresses = new address[](1); 61 | variantAddresses[0] = variantAddress; 62 | __addChildData(type(AddressArrayChild).creationCode, abi.encode(defaultAddresses), abi.encode(variantAddresses)); 63 | 64 | // Uints Arrays 65 | uint256[] memory defaultUints = new uint256[](1); 66 | defaultUints[0] = 1; 67 | uint256[] memory variantUints = new uint256[](1); 68 | variantUints[0] = 2; 69 | __addChildData(type(UintArrayChild).creationCode, abi.encode(defaultUints), abi.encode(variantUints)); 70 | 71 | // Ints Arrays 72 | int256[] memory defaultInts = new int256[](1); 73 | defaultInts[0] = -1; 74 | int256[] memory variantInts = new int256[](1); 75 | variantInts[0] = -2; 76 | __addChildData(type(IntArrayChild).creationCode, abi.encode(defaultInts), abi.encode(variantInts)); 77 | 78 | // Strings Arrays 79 | string[] memory defaultStrings = new string[](1); 80 | defaultStrings[0] = "hello world"; 81 | string[] memory variantStrings = new string[](1); 82 | variantStrings[0] = "variant"; 83 | __addChildData(type(StringArrayChild).creationCode, abi.encode(defaultStrings), abi.encode(variantStrings)); 84 | 85 | // Bytes Arrays 86 | bytes[] memory defaultBytes = new bytes[](1); 87 | defaultBytes[0] = hex"01"; 88 | bytes[] memory variantBytes = new bytes[](1); 89 | variantBytes[0] = hex"02"; 90 | __addChildData(type(BytesArrayChild).creationCode, abi.encode(defaultBytes), abi.encode(variantBytes)); 91 | 92 | // Bytes32 Arrays 93 | bytes32[] memory defaultBytes32 = new bytes32[](1); 94 | defaultBytes32[0] = bytes32(uint256(1)); 95 | bytes32[] memory variantBytes32 = new bytes32[](1); 96 | variantBytes32[0] = bytes32(uint256(2)); 97 | __addChildData(type(Bytes32ArrayChild).creationCode, abi.encode(defaultBytes32), abi.encode(variantBytes32)); 98 | 99 | // Bools Arrays 100 | bool[] memory defaultBools = new bool[](1); 101 | defaultBools[0] = true; 102 | bool[] memory variantBools = new bool[](1); 103 | variantBools[0] = false; 104 | __addChildData(type(BoolArrayChild).creationCode, abi.encode(defaultBools), abi.encode(variantBools)); 105 | } 106 | 107 | /// @dev Helper function to add child data to the array. 108 | function __addChildData( 109 | bytes memory creationCode, 110 | bytes memory constructorArgsCode1, 111 | bytes memory constructorArgsCode2 112 | ) private { 113 | childrenData.push( 114 | ChildContractData({ 115 | creationCode: creationCode, 116 | constructorArgsCode1: constructorArgsCode1, 117 | constructorArgsCode2: constructorArgsCode2 118 | }) 119 | ); 120 | } 121 | 122 | function getChildrenData() public view returns (ChildContractData[] memory) { 123 | return childrenData; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /test/create3/common/contracts/TestSetup.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { Test } from "forge-std/Test.sol"; 5 | import { ICreate3Factory } from "../../../../src/create3/interfaces/ICreate3Factory.sol"; 6 | import { Create3Factory } from "../../../../src/create3/Create3Factory.sol"; 7 | import { ERC1967Proxy } from "../../../../src/dependencies/proxy/ERC1967Proxy.sol"; 8 | import { ChildNoArgs } from "./Child.noargs.t.sol"; 9 | import { ChildrenWithConstructorArgs } from "./Children.args.t.sol"; 10 | 11 | import { CONTRACT_DEPLOYER } from "../Constants.t.sol"; 12 | 13 | abstract contract TestSetup is Test { 14 | Create3Factory public implementation; 15 | ERC1967Proxy public proxy; 16 | 17 | ChildrenWithConstructorArgs public childrenWithConstructorArgs; 18 | bytes public noArgsChildCreationCode; 19 | 20 | // Events 21 | event Deploy( 22 | address indexed principal, 23 | address indexed child, 24 | bytes32 indexed hashedCreationCode, 25 | bytes constructorArgsCode, 26 | uint256 nonce 27 | ); 28 | 29 | function setUp() public { 30 | implementation = new Create3Factory(); 31 | vm.prank(CONTRACT_DEPLOYER); 32 | proxy = new ERC1967Proxy(address(implementation), abi.encodeWithSignature("initialize()")); 33 | 34 | noArgsChildCreationCode = type(ChildNoArgs).creationCode; 35 | childrenWithConstructorArgs = new ChildrenWithConstructorArgs(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test/create3/common/interfaces/IChild.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | interface IChild { } 5 | -------------------------------------------------------------------------------- /test/create3/common/libraries/AddressLib.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | library AddressLib { 5 | function includes(address[] memory _array, address _address) internal pure returns (bool) { 6 | for (uint256 i; i < _array.length; i++) { 7 | if (_array[i] == _address) { 8 | return true; 9 | } 10 | } 11 | return false; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/create3/helpers/DeploymentHelper.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { Test } from "forge-std/Test.sol"; 5 | import { VmSafe } from "forge-std/Vm.sol"; 6 | import { ChildrenWithConstructorArgs } from "../common/contracts/Children.args.t.sol"; 7 | import { TestSetup } from "../common/contracts/TestSetup.t.sol"; 8 | import { ICreate3Factory } from "../../../src/create3/interfaces/ICreate3Factory.sol"; 9 | 10 | abstract contract DeploymentHelper is Test, TestSetup { 11 | /** 12 | * @dev Reusable function for deploying childA contracts. 13 | * @param _contract The address of the PredictveDeployer proxy contract. 14 | * @param _wallet The principal's evm account that signs off on a childA contract deployment. 15 | * @param _creationCode The to-be-deployed contract bytecode. 16 | */ 17 | function deployChild( 18 | address _contract, 19 | VmSafe.Wallet memory _wallet, 20 | bytes memory _creationCode, 21 | bytes memory _constructorArgsCode 22 | ) internal { 23 | bytes memory signature = getSignature(_contract, _wallet, _creationCode); 24 | ICreate3Factory(_contract).deploy(_wallet.addr, signature, _creationCode, _constructorArgsCode); 25 | } 26 | 27 | /** 28 | * @dev Reusable function for returning generic bytcode contract creation code and constructor args code. 29 | */ 30 | function getDeploymentBytecode() internal view returns (bytes memory, bytes memory) { 31 | ChildrenWithConstructorArgs.ChildContractData[] memory childrenData = 32 | childrenWithConstructorArgs.getChildrenData(); 33 | ChildrenWithConstructorArgs.ChildContractData memory child = childrenData[0]; 34 | return (child.creationCode, child.constructorArgsCode1); 35 | } 36 | 37 | /** 38 | * @dev Reusable function for returning a signature to be used for deployment. 39 | * @param _contract The address of the PredictveDeployer proxy contract. 40 | * @param _wallet The principal's evm account that signs off on a childA contract deployment. 41 | * @param _creationCode The to-be-deployed contract bytecode. 42 | * @return signature The signature to be used for deployment. 43 | */ 44 | function getSignature(address _contract, VmSafe.Wallet memory _wallet, bytes memory _creationCode) 45 | internal 46 | returns (bytes memory) 47 | { 48 | bytes32 txHash = ICreate3Factory(_contract).getTransactionHash(_wallet.addr, _creationCode); 49 | 50 | bytes32 messageHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", txHash)); 51 | 52 | (uint8 v, bytes32 r, bytes32 s) = vm.sign(_wallet.privateKey, messageHash); 53 | 54 | return abi.encodePacked(r, s, v); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /test/proxy/ERC1967Proxy.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.21; 3 | 4 | import { Create2Factory } from "../../src/create2/Create2Factory.sol"; 5 | import { ERC1967Proxy } from "../../src/dependencies/proxy/ERC1967Proxy.sol"; 6 | import { ICreate2FactoryAdmin } from "../../src/create2/interfaces/ICreate2FactoryAdmin.sol"; 7 | import { TestSetup } from "../create2/common/contracts/TestSetup.t.sol"; 8 | import { CONTRACT_DEPLOYER } from "../create2/common/Constants.t.sol"; 9 | 10 | contract ERC1967ProxyTest is TestSetup { 11 | /* solhint-disable func-name-mixedcase */ 12 | 13 | function test_upgradeToAndCall() public { 14 | // Setup 15 | bytes32 implentationStorageSlot = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; 16 | address implementationAddressV1 = address(uint160(uint256(vm.load(address(proxy), implentationStorageSlot)))); 17 | 18 | // Pre-action assertions 19 | assertEq(implementationAddressV1, address(implementation)); 20 | 21 | // Act 22 | Create2Factory implementationV2 = new Create2Factory(); 23 | vm.prank(CONTRACT_DEPLOYER); 24 | ICreate2FactoryAdmin(address(proxy)).upgradeToAndCall(address(implementationV2), ""); 25 | 26 | // Post-action assertions 27 | address implementationAddressV2 = address(uint160(uint256(vm.load(address(proxy), implentationStorageSlot)))); 28 | assertEq(implementationAddressV2, address(implementationV2)); 29 | } 30 | 31 | function testFail_UpgradeToAndCallUnauthorized(address invalidDeployer) public { 32 | // Assumptions 33 | vm.assume(invalidDeployer != CONTRACT_DEPLOYER); 34 | 35 | // Setup 36 | Create2Factory implementationV2 = new Create2Factory(); 37 | 38 | // Act 39 | vm.prank(invalidDeployer); 40 | ICreate2FactoryAdmin(address(proxy)).upgradeToAndCall(address(implementationV2), ""); 41 | } 42 | } 43 | --------------------------------------------------------------------------------