├── .gitmodules ├── README.md ├── foundry ├── .env.example ├── .github │ └── workflows │ │ └── test.yml ├── .gitignore ├── .gitmodules ├── README.md ├── broadcast │ └── DeployAndCall.s.sol │ │ └── 11155111 │ │ ├── run-1708178412.json │ │ ├── run-1708179023.json │ │ ├── run-1708179042.json │ │ ├── run-1708179310.json │ │ ├── run-1708179329.json │ │ ├── run-1709115917.json │ │ ├── run-1709115930.json │ │ └── run-latest.json ├── foundry.toml ├── lib │ └── forge-std │ │ ├── .gitattributes │ │ ├── .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 │ │ ├── scripts │ │ └── vm.py │ │ ├── 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 │ │ ├── mocks │ │ │ ├── MockERC20.sol │ │ │ └── MockERC721.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 │ │ └── mocks │ │ ├── MockERC20.t.sol │ │ └── MockERC721.t.sol ├── remappings.txt ├── script │ └── DeployAndCall.s.sol ├── src │ └── MockERC20.sol └── test │ ├── MockERC20.ForgeGasMetering.t.sol │ └── MockERC20.Foundry.t.sol ├── hardhat ├── .gitignore ├── README.md ├── contracts │ └── MockERC20.sol ├── hardhat.config.ts ├── package.json ├── pnpm-lock.yaml ├── test │ └── MockERC20.ts └── tsconfig.json └── tevm ├── .gitignore ├── constants.ts ├── index.ts ├── package.json ├── pnpm-lock.yaml └── tsconfig.json /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "foundry/lib/solady"] 2 | path = foundry/lib/solady 3 | url = https://github.com/vectorized/solady 4 | [submodule "foundry/lib/forge-gas-metering"] 5 | path = foundry/lib/forge-gas-metering 6 | url = https://github.com/emo-eth/forge-gas-metering 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gas measurements comparison 2 | 3 | Comparing the way Forge, Tevm, Hardhat and forge-gas-metering will report gas usage against Sepolia testnet transactions. 4 | 5 | There are two subsequent mint transactions on a newly deployed mock ERC20 contract, for each of the two scenarios. There are 50 `0` bytes from the transaction's data in the first scenario that are turned into `1` bytes in the second one, which explains the expected 600 gas overhead (`600 = 50 * (16 - 4)`). 6 | 7 | The idea is to figure out which of these tools will report different gas usage based on the amount of zero and non-zero bytes that need to be read/written. 8 | 9 | ## Results 10 | 11 | > The process is the following: 12 | > 13 | > 1. deploy the contract; 14 | > 2. mint the same amount of tokens to the same address twice. 15 | > 16 | > `recipient = 0x0000000000000000000000000000000000000001 | 0x1111111111111111111111111111111111111111` 17 | > 18 | > `amount = 0x0000000000000000000000000000000000000000000000000000000000000001 | 0x1111111111111111111111111111111111111111111111111111111111111111` 19 | 20 | | Medium | Zero bytes (1st) | Non-zero bytes (1st) | Zero bytes (2nd) | Non-zero bytes (2nd) | Bytes cost diff included | Exact match | 21 | | ---------------------- | ---------------- | -------------------- | ---------------- | -------------------- | ------------------------ | ----------- | 22 | | Reference (Sepolia tx) | 67,839 | 68,439 | 33,639 | 34,239 | ✅ | ✅ | 23 | | Forge (isolated) | 67,839 | 68,439 | 33,639 | 34,239 | ✅ | ✅ | 24 | | Hardhat | 67,839 | 68,439 | 33,639 | 34,239 | ✅ | ✅ | 25 | | forge-gas-metering | 63,879 | 64,479 | 21,579 | 22,179 | ✅ | ❌ | 26 | | Forge | 46,495 | 46,495 | 2,695 | 2,695 | ❌ | ❌ | 27 | | Tevm | 46,495 | 46,495 | 2,695 | 2,695 | ❌ | ❌ | 28 | 29 | ## How to reproduce 30 | 31 | ### Clone and install 32 | 33 | ```bash 34 | git clone git@github.com:0xpolarzero/gas-metering-comparison.git 35 | cd gas-metering-comparison 36 | 37 | # From the root: 38 | # Foundry 39 | cd foundry 40 | forge install 41 | 42 | # Hardhat 43 | cd hardhat 44 | pnpm install 45 | 46 | # Tevm 47 | cd tevm 48 | pnpm install 49 | ``` 50 | 51 | ### Sepolia 52 | 53 | This will deploy the contract and mint the tokens twice. Which will provide both the reference Sepolia txs and the measurements from the script. 54 | 55 | **In `/foundry`**: 56 | 57 | 1. Create `.env` and fill it with the content in `.env.example`; 58 | 59 | 2. run `source .env`; 60 | 61 | 3. deploy the contract and mint the tokens: 62 | 63 | ```bash 64 | forge script script/DeployAndCall.s.sol:DeployAndCall --rpc-url $RPC_URL_SEPOLIA --broadcast -vvvv --sig "run(address, uint256)" 0x0000000000000000000000000000000000000001 0x0000000000000000000000000000000000000000000000000000000000000001 65 | # or 66 | forge script script/DeployAndCall.s.sol:DeployAndCall --rpc-url $RPC_URL_SEPOLIA --broadcast -vvvv --sig "run(address, uint256)" 0x1111111111111111111111111111111111111111 0x1111111111111111111111111111111111111111111111111111111111111111 67 | ``` 68 | 69 | ### Foundry (Forge) 70 | 71 | **In `/foundry`**: run `forge test --mc MockERC20Foundry -vvvv --isolate`. 72 | 73 | ### Hardhat 74 | 75 | **In `/hardhat`**: run `pnpm hardhat test`. 76 | 77 | ### forge-gas-metering 78 | 79 | **In `/foundry`**: run `forge test --mc MockERC20ForgeGasMetering -vv`. 80 | 81 | ### Tevm 82 | 83 | **In `/tevm`**: run `pnpm ts-node index.ts`. 84 | -------------------------------------------------------------------------------- /foundry/.env.example: -------------------------------------------------------------------------------- 1 | PRIVATE_KEY= 2 | RPC_URL_SEPOLIA= -------------------------------------------------------------------------------- /foundry/.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: workflow_dispatch 4 | 5 | env: 6 | FOUNDRY_PROFILE: ci 7 | 8 | jobs: 9 | check: 10 | strategy: 11 | fail-fast: true 12 | 13 | name: Foundry project 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | with: 18 | submodules: recursive 19 | 20 | - name: Install Foundry 21 | uses: foundry-rs/foundry-toolchain@v1 22 | with: 23 | version: nightly 24 | 25 | - name: Run Forge build 26 | run: | 27 | forge --version 28 | forge build --sizes 29 | id: build 30 | 31 | - name: Run Forge tests 32 | run: | 33 | forge test -vvv 34 | id: test 35 | -------------------------------------------------------------------------------- /foundry/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiler files 2 | cache/ 3 | out/ 4 | 5 | # Ignores development broadcast logs 6 | !/broadcast 7 | /broadcast/*/31337/ 8 | /broadcast/**/dry-run/ 9 | 10 | # Docs 11 | docs/ 12 | 13 | # Dotenv file 14 | .env 15 | -------------------------------------------------------------------------------- /foundry/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/forge-std"] 2 | path = lib/forge-std 3 | url = https://github.com/foundry-rs/forge-std 4 | -------------------------------------------------------------------------------- /foundry/README.md: -------------------------------------------------------------------------------- 1 | ## Foundry 2 | 3 | **Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** 4 | 5 | Foundry consists of: 6 | 7 | - **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). 8 | - **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. 9 | - **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. 10 | - **Chisel**: Fast, utilitarian, and verbose solidity REPL. 11 | 12 | ## Documentation 13 | 14 | https://book.getfoundry.sh/ 15 | 16 | ## Usage 17 | 18 | ### Build 19 | 20 | ```shell 21 | $ forge build 22 | ``` 23 | 24 | ### Test 25 | 26 | ```shell 27 | $ forge test 28 | ``` 29 | 30 | ### Format 31 | 32 | ```shell 33 | $ forge fmt 34 | ``` 35 | 36 | ### Gas Snapshots 37 | 38 | ```shell 39 | $ forge snapshot 40 | ``` 41 | 42 | ### Anvil 43 | 44 | ```shell 45 | $ anvil 46 | ``` 47 | 48 | ### Deploy 49 | 50 | ```shell 51 | $ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key 52 | ``` 53 | 54 | ### Cast 55 | 56 | ```shell 57 | $ cast 58 | ``` 59 | 60 | ### Help 61 | 62 | ```shell 63 | $ forge --help 64 | $ anvil --help 65 | $ cast --help 66 | ``` 67 | -------------------------------------------------------------------------------- /foundry/broadcast/DeployAndCall.s.sol/11155111/run-1708179023.json: -------------------------------------------------------------------------------- 1 | { 2 | "transactions": [ 3 | { 4 | "hash": "0xc434aba381833890ecd9468e7743359659799db6a5fb68a3440822356185a3f0", 5 | "transactionType": "CREATE", 6 | "contractName": null, 7 | "contractAddress": "0x325B64349f9e4806D59CAf8fAD6891563DD7Dd39", 8 | "function": null, 9 | "arguments": null, 10 | "transaction": { 11 | "type": "0x02", 12 | "from": "0xad285b5df24bde77a8391924569af2ad2d4ee4a7", 13 | "gas": "0xa117d", 14 | "value": "0x0", 15 | "data": "0x608060405234801561001057600080fd5b50610838806100206000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c806340c10f191161008c57806395d89b411161006657806395d89b41146101ba578063a9059cbb146101d9578063d505accf146101ec578063dd62ed3e146101ff57600080fd5b806340c10f191461015957806370a082311461016e5780637ecebe001461019457600080fd5b806306fdde03146100d4578063095ea7b3146100f257806318160ddd1461011557806323b872dd1461012f578063313ce567146101425780633644e51514610151575b600080fd5b6100dc610228565b6040516100e9919061066a565b60405180910390f35b6101056101003660046106d4565b61024b565b60405190151581526020016100e9565b6805345cdf77eb68f44c545b6040519081526020016100e9565b61010561013d3660046106fe565b61029e565b604051601281526020016100e9565b61012161035c565b61016c6101673660046106d4565b6103d9565b005b61012161017c36600461073a565b6387a211a2600c908152600091909152602090205490565b6101216101a236600461073a565b6338377508600c908152600091909152602090205490565b60408051808201909152600381526204d32360ec1b60208201526100dc565b6101056101e73660046106d4565b6103e7565b61016c6101fa36600461075c565b610462565b61012161020d3660046107cf565b602052637f5e9f20600c908152600091909152603490205490565b60408051808201909152600981526804d6f636b45524332360bc1b602082015290565b600082602052637f5e9f20600c5233600052816034600c205581600052602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560206000a350600192915050565b60008360601b33602052637f5e9f208117600c526034600c20805460018101156102de57808511156102d8576313be252b6000526004601cfd5b84810382555b50506387a211a28117600c526020600c208054808511156103075763f4d678b86000526004601cfd5b84810382555050836000526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3505060019392505050565b600080610367610228565b8051906020012090506040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81528160208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015260a081209250505090565b6103e382826105eb565b5050565b60006387a211a2600c52336000526020600c208054808411156104125763f4d678b86000526004601cfd5b83810382555050826000526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350600192915050565b600061046c610228565b8051906020012090508442111561048b57631a15a3cc6000526004601cfd5b6040518860601b60601c98508760601b60601c975065383775081901600e52886000526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83528360208401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528a60208401528960408401528860608401528060808401528760a084015260c08320604e526042602c206000528660ff1660205285604052846060526020806080600060015afa8b3d51146105975763ddafbaef6000526004601cfd5b0190556303faf4f960a51b88176040526034602c2087905587897f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a360405250506000606052505050505050565b6805345cdf77eb68f44c548181018181101561060f5763e5cfe9576000526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52816000526020600c208181540181555080602052600c5160601c60007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a35050565b600060208083528351808285015260005b818110156106975785810183015185820160400152820161067b565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b03811681146106cf57600080fd5b919050565b600080604083850312156106e757600080fd5b6106f0836106b8565b946020939093013593505050565b60008060006060848603121561071357600080fd5b61071c846106b8565b925061072a602085016106b8565b9150604084013590509250925092565b60006020828403121561074c57600080fd5b610755826106b8565b9392505050565b600080600080600080600060e0888a03121561077757600080fd5b610780886106b8565b965061078e602089016106b8565b95506040880135945060608801359350608088013560ff811681146107b257600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156107e257600080fd5b6107eb836106b8565b91506107f9602084016106b8565b9050925092905056fea264697066735822122082f1cd64bc183a33615a26a4776bafe321950e36815c3c095ff40b5e18c1fc3464736f6c63430008140033", 16 | "nonce": "0x6b", 17 | "accessList": [] 18 | }, 19 | "additionalContracts": [], 20 | "isFixedGasLimit": false 21 | }, 22 | { 23 | "hash": "0x886c7e6d86a3a06d0d6c5cba40579551f0bb83c646f0247da9e326a4291183b2", 24 | "transactionType": "CALL", 25 | "contractName": "src/MockERC20.sol:MockERC20", 26 | "contractAddress": "0x325B64349f9e4806D59CAf8fAD6891563DD7Dd39", 27 | "function": "mint(address,uint256)", 28 | "arguments": [ 29 | "0x0000000000000000000000000000000000000001", 30 | "1" 31 | ], 32 | "transaction": { 33 | "type": "0x02", 34 | "from": "0xad285b5df24bde77a8391924569af2ad2d4ee4a7", 35 | "to": "0x325b64349f9e4806d59caf8fad6891563dd7dd39", 36 | "gas": "0x16e05", 37 | "value": "0x0", 38 | "data": "0x40c10f1900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", 39 | "nonce": "0x6c", 40 | "accessList": [] 41 | }, 42 | "additionalContracts": [], 43 | "isFixedGasLimit": false 44 | }, 45 | { 46 | "hash": "0xa30ca53c4856957f95fdbf4885e0e5001892af742335301125d5ef65df867586", 47 | "transactionType": "CALL", 48 | "contractName": "src/MockERC20.sol:MockERC20", 49 | "contractAddress": "0x325B64349f9e4806D59CAf8fAD6891563DD7Dd39", 50 | "function": "mint(address,uint256)", 51 | "arguments": [ 52 | "0x0000000000000000000000000000000000000001", 53 | "1" 54 | ], 55 | "transaction": { 56 | "type": "0x02", 57 | "from": "0xad285b5df24bde77a8391924569af2ad2d4ee4a7", 58 | "to": "0x325b64349f9e4806d59caf8fad6891563dd7dd39", 59 | "gas": "0xb57f", 60 | "value": "0x0", 61 | "data": "0x40c10f1900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", 62 | "nonce": "0x6d", 63 | "accessList": [] 64 | }, 65 | "additionalContracts": [], 66 | "isFixedGasLimit": false 67 | } 68 | ], 69 | "receipts": [], 70 | "libraries": [], 71 | "pending": [ 72 | "0xc434aba381833890ecd9468e7743359659799db6a5fb68a3440822356185a3f0", 73 | "0x886c7e6d86a3a06d0d6c5cba40579551f0bb83c646f0247da9e326a4291183b2", 74 | "0xa30ca53c4856957f95fdbf4885e0e5001892af742335301125d5ef65df867586" 75 | ], 76 | "returns": {}, 77 | "timestamp": 1708179023, 78 | "chain": 11155111, 79 | "multi": false, 80 | "commit": "f52f324" 81 | } -------------------------------------------------------------------------------- /foundry/broadcast/DeployAndCall.s.sol/11155111/run-1708179310.json: -------------------------------------------------------------------------------- 1 | { 2 | "transactions": [ 3 | { 4 | "hash": "0x4df5034ca1fe456a2f3eac54d38055a9a2a68e1abc5c18cfabd23dc2d33ca255", 5 | "transactionType": "CREATE", 6 | "contractName": null, 7 | "contractAddress": "0x839aC9F8e36215Ada5346700f6cAF6C943E42119", 8 | "function": null, 9 | "arguments": null, 10 | "transaction": { 11 | "type": "0x02", 12 | "from": "0xad285b5df24bde77a8391924569af2ad2d4ee4a7", 13 | "gas": "0xa117d", 14 | "value": "0x0", 15 | "data": "0x608060405234801561001057600080fd5b50610838806100206000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c806340c10f191161008c57806395d89b411161006657806395d89b41146101ba578063a9059cbb146101d9578063d505accf146101ec578063dd62ed3e146101ff57600080fd5b806340c10f191461015957806370a082311461016e5780637ecebe001461019457600080fd5b806306fdde03146100d4578063095ea7b3146100f257806318160ddd1461011557806323b872dd1461012f578063313ce567146101425780633644e51514610151575b600080fd5b6100dc610228565b6040516100e9919061066a565b60405180910390f35b6101056101003660046106d4565b61024b565b60405190151581526020016100e9565b6805345cdf77eb68f44c545b6040519081526020016100e9565b61010561013d3660046106fe565b61029e565b604051601281526020016100e9565b61012161035c565b61016c6101673660046106d4565b6103d9565b005b61012161017c36600461073a565b6387a211a2600c908152600091909152602090205490565b6101216101a236600461073a565b6338377508600c908152600091909152602090205490565b60408051808201909152600381526204d32360ec1b60208201526100dc565b6101056101e73660046106d4565b6103e7565b61016c6101fa36600461075c565b610462565b61012161020d3660046107cf565b602052637f5e9f20600c908152600091909152603490205490565b60408051808201909152600981526804d6f636b45524332360bc1b602082015290565b600082602052637f5e9f20600c5233600052816034600c205581600052602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560206000a350600192915050565b60008360601b33602052637f5e9f208117600c526034600c20805460018101156102de57808511156102d8576313be252b6000526004601cfd5b84810382555b50506387a211a28117600c526020600c208054808511156103075763f4d678b86000526004601cfd5b84810382555050836000526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3505060019392505050565b600080610367610228565b8051906020012090506040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81528160208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015260a081209250505090565b6103e382826105eb565b5050565b60006387a211a2600c52336000526020600c208054808411156104125763f4d678b86000526004601cfd5b83810382555050826000526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350600192915050565b600061046c610228565b8051906020012090508442111561048b57631a15a3cc6000526004601cfd5b6040518860601b60601c98508760601b60601c975065383775081901600e52886000526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83528360208401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528a60208401528960408401528860608401528060808401528760a084015260c08320604e526042602c206000528660ff1660205285604052846060526020806080600060015afa8b3d51146105975763ddafbaef6000526004601cfd5b0190556303faf4f960a51b88176040526034602c2087905587897f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a360405250506000606052505050505050565b6805345cdf77eb68f44c548181018181101561060f5763e5cfe9576000526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52816000526020600c208181540181555080602052600c5160601c60007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a35050565b600060208083528351808285015260005b818110156106975785810183015185820160400152820161067b565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b03811681146106cf57600080fd5b919050565b600080604083850312156106e757600080fd5b6106f0836106b8565b946020939093013593505050565b60008060006060848603121561071357600080fd5b61071c846106b8565b925061072a602085016106b8565b9150604084013590509250925092565b60006020828403121561074c57600080fd5b610755826106b8565b9392505050565b600080600080600080600060e0888a03121561077757600080fd5b610780886106b8565b965061078e602089016106b8565b95506040880135945060608801359350608088013560ff811681146107b257600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156107e257600080fd5b6107eb836106b8565b91506107f9602084016106b8565b9050925092905056fea264697066735822122082f1cd64bc183a33615a26a4776bafe321950e36815c3c095ff40b5e18c1fc3464736f6c63430008140033", 16 | "nonce": "0x71", 17 | "accessList": [] 18 | }, 19 | "additionalContracts": [], 20 | "isFixedGasLimit": false 21 | }, 22 | { 23 | "hash": "0x6a985f8e7556af5cc90c0c9ef4af90d0b031f090732ea4e9c5e77debe056cd39", 24 | "transactionType": "CALL", 25 | "contractName": "src/MockERC20.sol:MockERC20", 26 | "contractAddress": "0x839aC9F8e36215Ada5346700f6cAF6C943E42119", 27 | "function": "mint(address,uint256)", 28 | "arguments": [ 29 | "0x1111111111111111111111111111111111111111", 30 | "7719472615821079694904732333912527190217998977709370935963838933860875309329" 31 | ], 32 | "transaction": { 33 | "type": "0x02", 34 | "from": "0xad285b5df24bde77a8391924569af2ad2d4ee4a7", 35 | "to": "0x839ac9f8e36215ada5346700f6caf6c943e42119", 36 | "gas": "0x17142", 37 | "value": "0x0", 38 | "data": "0x40c10f1900000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", 39 | "nonce": "0x72", 40 | "accessList": [] 41 | }, 42 | "additionalContracts": [], 43 | "isFixedGasLimit": false 44 | }, 45 | { 46 | "hash": "0x91cc033349873f65cf69e1b967b17ea983eb266a929c044c74ef8de52697f25e", 47 | "transactionType": "CALL", 48 | "contractName": "src/MockERC20.sol:MockERC20", 49 | "contractAddress": "0x839aC9F8e36215Ada5346700f6cAF6C943E42119", 50 | "function": "mint(address,uint256)", 51 | "arguments": [ 52 | "0x1111111111111111111111111111111111111111", 53 | "7719472615821079694904732333912527190217998977709370935963838933860875309329" 54 | ], 55 | "transaction": { 56 | "type": "0x02", 57 | "from": "0xad285b5df24bde77a8391924569af2ad2d4ee4a7", 58 | "to": "0x839ac9f8e36215ada5346700f6caf6c943e42119", 59 | "gas": "0xb8bb", 60 | "value": "0x0", 61 | "data": "0x40c10f1900000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", 62 | "nonce": "0x73", 63 | "accessList": [] 64 | }, 65 | "additionalContracts": [], 66 | "isFixedGasLimit": false 67 | } 68 | ], 69 | "receipts": [], 70 | "libraries": [], 71 | "pending": [ 72 | "0x4df5034ca1fe456a2f3eac54d38055a9a2a68e1abc5c18cfabd23dc2d33ca255", 73 | "0x6a985f8e7556af5cc90c0c9ef4af90d0b031f090732ea4e9c5e77debe056cd39", 74 | "0x91cc033349873f65cf69e1b967b17ea983eb266a929c044c74ef8de52697f25e" 75 | ], 76 | "returns": {}, 77 | "timestamp": 1708179310, 78 | "chain": 11155111, 79 | "multi": false, 80 | "commit": "f52f324" 81 | } -------------------------------------------------------------------------------- /foundry/broadcast/DeployAndCall.s.sol/11155111/run-1709115917.json: -------------------------------------------------------------------------------- 1 | { 2 | "transactions": [ 3 | { 4 | "hash": "0x41297143b41cc1ddb4a46836f78f5e7c574edaceda0f115005ea6494a2640be2", 5 | "transactionType": "CREATE", 6 | "contractName": null, 7 | "contractAddress": "0x1e0e0fc4936Ad1E4C362E73B3e71D7d7B925cB93", 8 | "function": null, 9 | "arguments": null, 10 | "transaction": { 11 | "type": "0x02", 12 | "from": "0xad285b5df24bde77a8391924569af2ad2d4ee4a7", 13 | "gas": "0xa117d", 14 | "value": "0x0", 15 | "data": "0x608060405234801561001057600080fd5b50610838806100206000396000f3fe608060405234801561001057600080fd5b50600436106100cf5760003560e01c806340c10f191161008c57806395d89b411161006657806395d89b41146101ba578063a9059cbb146101d9578063d505accf146101ec578063dd62ed3e146101ff57600080fd5b806340c10f191461015957806370a082311461016e5780637ecebe001461019457600080fd5b806306fdde03146100d4578063095ea7b3146100f257806318160ddd1461011557806323b872dd1461012f578063313ce567146101425780633644e51514610151575b600080fd5b6100dc610228565b6040516100e9919061066a565b60405180910390f35b6101056101003660046106d4565b61024b565b60405190151581526020016100e9565b6805345cdf77eb68f44c545b6040519081526020016100e9565b61010561013d3660046106fe565b61029e565b604051601281526020016100e9565b61012161035c565b61016c6101673660046106d4565b6103d9565b005b61012161017c36600461073a565b6387a211a2600c908152600091909152602090205490565b6101216101a236600461073a565b6338377508600c908152600091909152602090205490565b60408051808201909152600381526204d32360ec1b60208201526100dc565b6101056101e73660046106d4565b6103e7565b61016c6101fa36600461075c565b610462565b61012161020d3660046107cf565b602052637f5e9f20600c908152600091909152603490205490565b60408051808201909152600981526804d6f636b45524332360bc1b602082015290565b600082602052637f5e9f20600c5233600052816034600c205581600052602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560206000a350600192915050565b60008360601b33602052637f5e9f208117600c526034600c20805460018101156102de57808511156102d8576313be252b6000526004601cfd5b84810382555b50506387a211a28117600c526020600c208054808511156103075763f4d678b86000526004601cfd5b84810382555050836000526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3505060019392505050565b600080610367610228565b8051906020012090506040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81528160208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015260a081209250505090565b6103e382826105eb565b5050565b60006387a211a2600c52336000526020600c208054808411156104125763f4d678b86000526004601cfd5b83810382555050826000526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350600192915050565b600061046c610228565b8051906020012090508442111561048b57631a15a3cc6000526004601cfd5b6040518860601b60601c98508760601b60601c975065383775081901600e52886000526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83528360208401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528a60208401528960408401528860608401528060808401528760a084015260c08320604e526042602c206000528660ff1660205285604052846060526020806080600060015afa8b3d51146105975763ddafbaef6000526004601cfd5b0190556303faf4f960a51b88176040526034602c2087905587897f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a360405250506000606052505050505050565b6805345cdf77eb68f44c548181018181101561060f5763e5cfe9576000526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52816000526020600c208181540181555080602052600c5160601c60007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a35050565b600060208083528351808285015260005b818110156106975785810183015185820160400152820161067b565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b03811681146106cf57600080fd5b919050565b600080604083850312156106e757600080fd5b6106f0836106b8565b946020939093013593505050565b60008060006060848603121561071357600080fd5b61071c846106b8565b925061072a602085016106b8565b9150604084013590509250925092565b60006020828403121561074c57600080fd5b610755826106b8565b9392505050565b600080600080600080600060e0888a03121561077757600080fd5b610780886106b8565b965061078e602089016106b8565b95506040880135945060608801359350608088013560ff811681146107b257600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156107e257600080fd5b6107eb836106b8565b91506107f9602084016106b8565b9050925092905056fea264697066735822122082f1cd64bc183a33615a26a4776bafe321950e36815c3c095ff40b5e18c1fc3464736f6c63430008140033", 16 | "nonce": "0x75", 17 | "accessList": [] 18 | }, 19 | "additionalContracts": [], 20 | "isFixedGasLimit": false 21 | }, 22 | { 23 | "hash": "0x21b1f013b5b6840842efb8ee32d63048225cbcd3eecc60e91f8995348a61ac1d", 24 | "transactionType": "CALL", 25 | "contractName": "src/MockERC20.sol:MockERC20", 26 | "contractAddress": "0x1e0e0fc4936Ad1E4C362E73B3e71D7d7B925cB93", 27 | "function": "mint(address,uint256)", 28 | "arguments": [ 29 | "0x0000000000000000000000000000000000000001", 30 | "1" 31 | ], 32 | "transaction": { 33 | "type": "0x02", 34 | "from": "0xad285b5df24bde77a8391924569af2ad2d4ee4a7", 35 | "to": "0x1e0e0fc4936ad1e4c362e73b3e71d7d7b925cb93", 36 | "gas": "0x16e05", 37 | "value": "0x0", 38 | "data": "0x40c10f1900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", 39 | "nonce": "0x76", 40 | "accessList": [] 41 | }, 42 | "additionalContracts": [], 43 | "isFixedGasLimit": false 44 | }, 45 | { 46 | "hash": "0x1281b07779cfc1a5ab489012332867afca9ab2f1f27881086bc40fed63131343", 47 | "transactionType": "CALL", 48 | "contractName": "src/MockERC20.sol:MockERC20", 49 | "contractAddress": "0x1e0e0fc4936Ad1E4C362E73B3e71D7d7B925cB93", 50 | "function": "mint(address,uint256)", 51 | "arguments": [ 52 | "0x0000000000000000000000000000000000000001", 53 | "1" 54 | ], 55 | "transaction": { 56 | "type": "0x02", 57 | "from": "0xad285b5df24bde77a8391924569af2ad2d4ee4a7", 58 | "to": "0x1e0e0fc4936ad1e4c362e73b3e71d7d7b925cb93", 59 | "gas": "0xb57f", 60 | "value": "0x0", 61 | "data": "0x40c10f1900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001", 62 | "nonce": "0x77", 63 | "accessList": [] 64 | }, 65 | "additionalContracts": [], 66 | "isFixedGasLimit": false 67 | } 68 | ], 69 | "receipts": [], 70 | "libraries": [], 71 | "pending": [ 72 | "0x41297143b41cc1ddb4a46836f78f5e7c574edaceda0f115005ea6494a2640be2", 73 | "0x21b1f013b5b6840842efb8ee32d63048225cbcd3eecc60e91f8995348a61ac1d", 74 | "0x1281b07779cfc1a5ab489012332867afca9ab2f1f27881086bc40fed63131343" 75 | ], 76 | "returns": {}, 77 | "timestamp": 1709115917, 78 | "chain": 11155111, 79 | "multi": false, 80 | "commit": "3d9b6d9" 81 | } -------------------------------------------------------------------------------- /foundry/foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = "src" 3 | out = "out" 4 | libs = ["lib"] 5 | 6 | # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options 7 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/.gitattributes: -------------------------------------------------------------------------------- 1 | src/Vm.sol linguist-generated 2 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/.gitignore: -------------------------------------------------------------------------------- 1 | cache/ 2 | out/ 3 | .vscode 4 | .idea 5 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/ds-test"] 2 | path = lib/ds-test 3 | url = https://github.com/dapphub/ds-test 4 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Copyright Contributors to Forge Standard Library 2 | 3 | Apache License 4 | Version 2.0, January 2004 5 | http://www.apache.org/licenses/ 6 | 7 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 8 | 9 | 1. Definitions. 10 | 11 | "License" shall mean the terms and conditions for use, reproduction, 12 | and distribution as defined by Sections 1 through 9 of this document. 13 | 14 | "Licensor" shall mean the copyright owner or entity authorized by 15 | the copyright owner that is granting the License. 16 | 17 | "Legal Entity" shall mean the union of the acting entity and all 18 | other entities that control, are controlled by, or are under common 19 | control with that entity. For the purposes of this definition, 20 | "control" means (i) the power, direct or indirect, to cause the 21 | direction or management of such entity, whether by contract or 22 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 23 | outstanding shares, or (iii) beneficial ownership of such entity. 24 | 25 | "You" (or "Your") shall mean an individual or Legal Entity 26 | exercising permissions granted by this License. 27 | 28 | "Source" form shall mean the preferred form for making modifications, 29 | including but not limited to software source code, documentation 30 | source, and configuration files. 31 | 32 | "Object" form shall mean any form resulting from mechanical 33 | transformation or translation of a Source form, including but 34 | not limited to compiled object code, generated documentation, 35 | and conversions to other media types. 36 | 37 | "Work" shall mean the work of authorship, whether in Source or 38 | Object form, made available under the License, as indicated by a 39 | copyright notice that is included in or attached to the work 40 | (an example is provided in the Appendix below). 41 | 42 | "Derivative Works" shall mean any work, whether in Source or Object 43 | form, that is based on (or derived from) the Work and for which the 44 | editorial revisions, annotations, elaborations, or other modifications 45 | represent, as a whole, an original work of authorship. For the purposes 46 | of this License, Derivative Works shall not include works that remain 47 | separable from, or merely link (or bind by name) to the interfaces of, 48 | the Work and Derivative Works thereof. 49 | 50 | "Contribution" shall mean any work of authorship, including 51 | the original version of the Work and any modifications or additions 52 | to that Work or Derivative Works thereof, that is intentionally 53 | submitted to Licensor for inclusion in the Work by the copyright owner 54 | or by an individual or Legal Entity authorized to submit on behalf of 55 | the copyright owner. For the purposes of this definition, "submitted" 56 | means any form of electronic, verbal, or written communication sent 57 | to the Licensor or its representatives, including but not limited to 58 | communication on electronic mailing lists, source code control systems, 59 | and issue tracking systems that are managed by, or on behalf of, the 60 | Licensor for the purpose of discussing and improving the Work, but 61 | excluding communication that is conspicuously marked or otherwise 62 | designated in writing by the copyright owner as "Not a Contribution." 63 | 64 | "Contributor" shall mean Licensor and any individual or Legal Entity 65 | on behalf of whom a Contribution has been received by Licensor and 66 | subsequently incorporated within the Work. 67 | 68 | 2. Grant of Copyright License. Subject to the terms and conditions of 69 | this License, each Contributor hereby grants to You a perpetual, 70 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 71 | copyright license to reproduce, prepare Derivative Works of, 72 | publicly display, publicly perform, sublicense, and distribute the 73 | Work and such Derivative Works in Source or Object form. 74 | 75 | 3. Grant of Patent License. Subject to the terms and conditions of 76 | this License, each Contributor hereby grants to You a perpetual, 77 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 78 | (except as stated in this section) patent license to make, have made, 79 | use, offer to sell, sell, import, and otherwise transfer the Work, 80 | where such license applies only to those patent claims licensable 81 | by such Contributor that are necessarily infringed by their 82 | Contribution(s) alone or by combination of their Contribution(s) 83 | with the Work to which such Contribution(s) was submitted. If You 84 | institute patent litigation against any entity (including a 85 | cross-claim or counterclaim in a lawsuit) alleging that the Work 86 | or a Contribution incorporated within the Work constitutes direct 87 | or contributory patent infringement, then any patent licenses 88 | granted to You under this License for that Work shall terminate 89 | as of the date such litigation is filed. 90 | 91 | 4. Redistribution. You may reproduce and distribute copies of the 92 | Work or Derivative Works thereof in any medium, with or without 93 | modifications, and in Source or Object form, provided that You 94 | meet the following conditions: 95 | 96 | (a) You must give any other recipients of the Work or 97 | Derivative Works a copy of this License; and 98 | 99 | (b) You must cause any modified files to carry prominent notices 100 | stating that You changed the files; and 101 | 102 | (c) You must retain, in the Source form of any Derivative Works 103 | that You distribute, all copyright, patent, trademark, and 104 | attribution notices from the Source form of the Work, 105 | excluding those notices that do not pertain to any part of 106 | the Derivative Works; and 107 | 108 | (d) If the Work includes a "NOTICE" text file as part of its 109 | distribution, then any Derivative Works that You distribute must 110 | include a readable copy of the attribution notices contained 111 | within such NOTICE file, excluding those notices that do not 112 | pertain to any part of the Derivative Works, in at least one 113 | of the following places: within a NOTICE text file distributed 114 | as part of the Derivative Works; within the Source form or 115 | documentation, if provided along with the Derivative Works; or, 116 | within a display generated by the Derivative Works, if and 117 | wherever such third-party notices normally appear. The contents 118 | of the NOTICE file are for informational purposes only and 119 | do not modify the License. You may add Your own attribution 120 | notices within Derivative Works that You distribute, alongside 121 | or as an addendum to the NOTICE text from the Work, provided 122 | that such additional attribution notices cannot be construed 123 | as modifying the License. 124 | 125 | You may add Your own copyright statement to Your modifications and 126 | may provide additional or different license terms and conditions 127 | for use, reproduction, or distribution of Your modifications, or 128 | for any such Derivative Works as a whole, provided Your use, 129 | reproduction, and distribution of the Work otherwise complies with 130 | the conditions stated in this License. 131 | 132 | 5. Submission of Contributions. Unless You explicitly state otherwise, 133 | any Contribution intentionally submitted for inclusion in the Work 134 | by You to the Licensor shall be under the terms and conditions of 135 | this License, without any additional terms or conditions. 136 | Notwithstanding the above, nothing herein shall supersede or modify 137 | the terms of any separate license agreement you may have executed 138 | with Licensor regarding such Contributions. 139 | 140 | 6. Trademarks. This License does not grant permission to use the trade 141 | names, trademarks, service marks, or product names of the Licensor, 142 | except as required for reasonable and customary use in describing the 143 | origin of the Work and reproducing the content of the NOTICE file. 144 | 145 | 7. Disclaimer of Warranty. Unless required by applicable law or 146 | agreed to in writing, Licensor provides the Work (and each 147 | Contributor provides its Contributions) on an "AS IS" BASIS, 148 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 149 | implied, including, without limitation, any warranties or conditions 150 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any 153 | risks associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, 156 | whether in tort (including negligence), contract, or otherwise, 157 | unless required by applicable law (such as deliberate and grossly 158 | negligent acts) or agreed to in writing, shall any Contributor be 159 | liable to You for damages, including any direct, indirect, special, 160 | incidental, or consequential damages of any character arising as a 161 | result of this License or out of the use or inability to use the 162 | Work (including but not limited to damages for loss of goodwill, 163 | work stoppage, computer failure or malfunction, or any and all 164 | other commercial damages or losses), even if such Contributor 165 | has been advised of the possibility of such damages. 166 | 167 | 9. Accepting Warranty or Additional Liability. While redistributing 168 | the Work or Derivative Works thereof, You may choose to offer, 169 | and charge a fee for, acceptance of support, warranty, indemnity, 170 | or other liability obligations and/or rights consistent with this 171 | License. However, in accepting such obligations, You may act only 172 | on Your own behalf and on Your sole responsibility, not on behalf 173 | of any other Contributor, and only if You agree to indemnify, 174 | defend, and hold each Contributor harmless for any liability 175 | incurred by, or claims asserted against, such Contributor by reason 176 | of your accepting any such warranty or additional liability. 177 | 178 | END OF TERMS AND CONDITIONS 179 | 180 | APPENDIX: How to apply the Apache License to your work. 181 | 182 | To apply the Apache License to your work, attach the following 183 | boilerplate notice, with the fields enclosed by brackets "[]" 184 | replaced with your own identifying information. (Don't include 185 | the brackets!) The text should be enclosed in the appropriate 186 | comment syntax for the file format. We also recommend that a 187 | file or class name and description of purpose be included on the 188 | same "printed page" as the copyright notice for easier 189 | identification within third-party archives. 190 | 191 | Copyright [yyyy] [name of copyright owner] 192 | 193 | Licensed under the Apache License, Version 2.0 (the "License"); 194 | you may not use this file except in compliance with the License. 195 | You may obtain a copy of the License at 196 | 197 | http://www.apache.org/licenses/LICENSE-2.0 198 | 199 | Unless required by applicable law or agreed to in writing, software 200 | distributed under the License is distributed on an "AS IS" BASIS, 201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | See the License for the specific language governing permissions and 203 | limitations under the License. 204 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/README.md: -------------------------------------------------------------------------------- 1 | # Forge Standard Library • [![CI status](https://github.com/foundry-rs/forge-std/actions/workflows/ci.yml/badge.svg)](https://github.com/foundry-rs/forge-std/actions/workflows/ci.yml) 2 | 3 | Forge Standard Library is a collection of helpful contracts and libraries for use with [Forge and Foundry](https://github.com/foundry-rs/foundry). It leverages Forge's cheatcodes to make writing tests easier and faster, while improving the UX of cheatcodes. 4 | 5 | **Learn how to use Forge-Std with the [📖 Foundry Book (Forge-Std Guide)](https://book.getfoundry.sh/forge/forge-std.html).** 6 | 7 | ## Install 8 | 9 | ```bash 10 | forge install foundry-rs/forge-std 11 | ``` 12 | 13 | ## Contracts 14 | ### stdError 15 | 16 | This is a helper contract for errors and reverts. In Forge, this contract is particularly helpful for the `expectRevert` cheatcode, as it provides all compiler builtin errors. 17 | 18 | See the contract itself for all error codes. 19 | 20 | #### Example usage 21 | 22 | ```solidity 23 | 24 | import "forge-std/Test.sol"; 25 | 26 | contract TestContract is Test { 27 | ErrorsTest test; 28 | 29 | function setUp() public { 30 | test = new ErrorsTest(); 31 | } 32 | 33 | function testExpectArithmetic() public { 34 | vm.expectRevert(stdError.arithmeticError); 35 | test.arithmeticError(10); 36 | } 37 | } 38 | 39 | contract ErrorsTest { 40 | function arithmeticError(uint256 a) public { 41 | uint256 a = a - 100; 42 | } 43 | } 44 | ``` 45 | 46 | ### stdStorage 47 | 48 | This is a rather large contract due to all of the overloading to make the UX decent. Primarily, it is a wrapper around the `record` and `accesses` cheatcodes. It can *always* find and write the storage slot(s) associated with a particular variable without knowing the storage layout. The one _major_ caveat to this is while a slot can be found for packed storage variables, we can't write to that variable safely. If a user tries to write to a packed slot, the execution throws an error, unless it is uninitialized (`bytes32(0)`). 49 | 50 | This works by recording all `SLOAD`s and `SSTORE`s during a function call. If there is a single slot read or written to, it immediately returns the slot. Otherwise, behind the scenes, we iterate through and check each one (assuming the user passed in a `depth` parameter). If the variable is a struct, you can pass in a `depth` parameter which is basically the field depth. 51 | 52 | I.e.: 53 | ```solidity 54 | struct T { 55 | // depth 0 56 | uint256 a; 57 | // depth 1 58 | uint256 b; 59 | } 60 | ``` 61 | 62 | #### Example usage 63 | 64 | ```solidity 65 | import "forge-std/Test.sol"; 66 | 67 | contract TestContract is Test { 68 | using stdStorage for StdStorage; 69 | 70 | Storage test; 71 | 72 | function setUp() public { 73 | test = new Storage(); 74 | } 75 | 76 | function testFindExists() public { 77 | // Lets say we want to find the slot for the public 78 | // variable `exists`. We just pass in the function selector 79 | // to the `find` command 80 | uint256 slot = stdstore.target(address(test)).sig("exists()").find(); 81 | assertEq(slot, 0); 82 | } 83 | 84 | function testWriteExists() public { 85 | // Lets say we want to write to the slot for the public 86 | // variable `exists`. We just pass in the function selector 87 | // to the `checked_write` command 88 | stdstore.target(address(test)).sig("exists()").checked_write(100); 89 | assertEq(test.exists(), 100); 90 | } 91 | 92 | // It supports arbitrary storage layouts, like assembly based storage locations 93 | function testFindHidden() public { 94 | // `hidden` is a random hash of a bytes, iteration through slots would 95 | // not find it. Our mechanism does 96 | // Also, you can use the selector instead of a string 97 | uint256 slot = stdstore.target(address(test)).sig(test.hidden.selector).find(); 98 | assertEq(slot, uint256(keccak256("my.random.var"))); 99 | } 100 | 101 | // If targeting a mapping, you have to pass in the keys necessary to perform the find 102 | // i.e.: 103 | function testFindMapping() public { 104 | uint256 slot = stdstore 105 | .target(address(test)) 106 | .sig(test.map_addr.selector) 107 | .with_key(address(this)) 108 | .find(); 109 | // in the `Storage` constructor, we wrote that this address' value was 1 in the map 110 | // so when we load the slot, we expect it to be 1 111 | assertEq(uint(vm.load(address(test), bytes32(slot))), 1); 112 | } 113 | 114 | // If the target is a struct, you can specify the field depth: 115 | function testFindStruct() public { 116 | // NOTE: see the depth parameter - 0 means 0th field, 1 means 1st field, etc. 117 | uint256 slot_for_a_field = stdstore 118 | .target(address(test)) 119 | .sig(test.basicStruct.selector) 120 | .depth(0) 121 | .find(); 122 | 123 | uint256 slot_for_b_field = stdstore 124 | .target(address(test)) 125 | .sig(test.basicStruct.selector) 126 | .depth(1) 127 | .find(); 128 | 129 | assertEq(uint(vm.load(address(test), bytes32(slot_for_a_field))), 1); 130 | assertEq(uint(vm.load(address(test), bytes32(slot_for_b_field))), 2); 131 | } 132 | } 133 | 134 | // A complex storage contract 135 | contract Storage { 136 | struct UnpackedStruct { 137 | uint256 a; 138 | uint256 b; 139 | } 140 | 141 | constructor() { 142 | map_addr[msg.sender] = 1; 143 | } 144 | 145 | uint256 public exists = 1; 146 | mapping(address => uint256) public map_addr; 147 | // mapping(address => Packed) public map_packed; 148 | mapping(address => UnpackedStruct) public map_struct; 149 | mapping(address => mapping(address => uint256)) public deep_map; 150 | mapping(address => mapping(address => UnpackedStruct)) public deep_map_struct; 151 | UnpackedStruct public basicStruct = UnpackedStruct({ 152 | a: 1, 153 | b: 2 154 | }); 155 | 156 | function hidden() public view returns (bytes32 t) { 157 | // an extremely hidden storage slot 158 | bytes32 slot = keccak256("my.random.var"); 159 | assembly { 160 | t := sload(slot) 161 | } 162 | } 163 | } 164 | ``` 165 | 166 | ### stdCheats 167 | 168 | This is a wrapper over miscellaneous cheatcodes that need wrappers to be more dev friendly. Currently there are only functions related to `prank`. In general, users may expect ETH to be put into an address on `prank`, but this is not the case for safety reasons. Explicitly this `hoax` function should only be used for address that have expected balances as it will get overwritten. If an address already has ETH, you should just use `prank`. If you want to change that balance explicitly, just use `deal`. If you want to do both, `hoax` is also right for you. 169 | 170 | 171 | #### Example usage: 172 | ```solidity 173 | 174 | // SPDX-License-Identifier: MIT 175 | pragma solidity ^0.8.0; 176 | 177 | import "forge-std/Test.sol"; 178 | 179 | // Inherit the stdCheats 180 | contract StdCheatsTest is Test { 181 | Bar test; 182 | function setUp() public { 183 | test = new Bar(); 184 | } 185 | 186 | function testHoax() public { 187 | // we call `hoax`, which gives the target address 188 | // eth and then calls `prank` 189 | hoax(address(1337)); 190 | test.bar{value: 100}(address(1337)); 191 | 192 | // overloaded to allow you to specify how much eth to 193 | // initialize the address with 194 | hoax(address(1337), 1); 195 | test.bar{value: 1}(address(1337)); 196 | } 197 | 198 | function testStartHoax() public { 199 | // we call `startHoax`, which gives the target address 200 | // eth and then calls `startPrank` 201 | // 202 | // it is also overloaded so that you can specify an eth amount 203 | startHoax(address(1337)); 204 | test.bar{value: 100}(address(1337)); 205 | test.bar{value: 100}(address(1337)); 206 | vm.stopPrank(); 207 | test.bar(address(this)); 208 | } 209 | } 210 | 211 | contract Bar { 212 | function bar(address expectedSender) public payable { 213 | require(msg.sender == expectedSender, "!prank"); 214 | } 215 | } 216 | ``` 217 | 218 | ### Std Assertions 219 | 220 | Expand upon the assertion functions from the `DSTest` library. 221 | 222 | ### `console.log` 223 | 224 | Usage follows the same format as [Hardhat](https://hardhat.org/hardhat-network/reference/#console-log). 225 | It's recommended to use `console2.sol` as shown below, as this will show the decoded logs in Forge traces. 226 | 227 | ```solidity 228 | // import it indirectly via Test.sol 229 | import "forge-std/Test.sol"; 230 | // or directly import it 231 | import "forge-std/console2.sol"; 232 | ... 233 | console2.log(someValue); 234 | ``` 235 | 236 | If you need compatibility with Hardhat, you must use the standard `console.sol` instead. 237 | Due to a bug in `console.sol`, logs that use `uint256` or `int256` types will not be properly decoded in Forge traces. 238 | 239 | ```solidity 240 | // import it indirectly via Test.sol 241 | import "forge-std/Test.sol"; 242 | // or directly import it 243 | import "forge-std/console.sol"; 244 | ... 245 | console.log(someValue); 246 | ``` 247 | 248 | ## License 249 | 250 | Forge Standard Library is offered under either [MIT](LICENSE-MIT) or [Apache 2.0](LICENSE-APACHE) license. 251 | -------------------------------------------------------------------------------- /foundry/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"] -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/lib/ds-test/.gitignore: -------------------------------------------------------------------------------- 1 | /.dapple 2 | /build 3 | /out 4 | /cache/ 5 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/lib/ds-test/default.nix: -------------------------------------------------------------------------------- 1 | { solidityPackage, dappsys }: solidityPackage { 2 | name = "ds-test"; 3 | src = ./src; 4 | } 5 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/lib/ds-test/demo/demo.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import "../src/test.sol"; 5 | 6 | contract DemoTest is DSTest { 7 | function test_this() public pure { 8 | require(true); 9 | } 10 | function test_logs() public { 11 | emit log("-- log(string)"); 12 | emit log("a string"); 13 | 14 | emit log("-- log_named_uint(string, uint)"); 15 | emit log_named_uint("uint", 512); 16 | 17 | emit log("-- log_named_int(string, int)"); 18 | emit log_named_int("int", -512); 19 | 20 | emit log("-- log_named_address(string, address)"); 21 | emit log_named_address("address", address(this)); 22 | 23 | emit log("-- log_named_bytes32(string, bytes32)"); 24 | emit log_named_bytes32("bytes32", "a string"); 25 | 26 | emit log("-- log_named_bytes(string, bytes)"); 27 | emit log_named_bytes("bytes", hex"cafefe"); 28 | 29 | emit log("-- log_named_string(string, string)"); 30 | emit log_named_string("string", "a string"); 31 | 32 | emit log("-- log_named_decimal_uint(string, uint, uint)"); 33 | emit log_named_decimal_uint("decimal uint", 1.0e18, 18); 34 | 35 | emit log("-- log_named_decimal_int(string, int, uint)"); 36 | emit log_named_decimal_int("decimal int", -1.0e18, 18); 37 | } 38 | event log_old_named_uint(bytes32,uint); 39 | function test_old_logs() public { 40 | emit log_old_named_uint("key", 500); 41 | emit log_named_bytes32("bkey", "val"); 42 | } 43 | function test_trace() public view { 44 | this.echo("string 1", "string 2"); 45 | } 46 | function test_multiline() public { 47 | emit log("a multiline\\nstring"); 48 | emit log("a multiline string"); 49 | emit log_bytes("a string"); 50 | emit log_bytes("a multiline\nstring"); 51 | emit log_bytes("a multiline\\nstring"); 52 | emit logs(hex"0000"); 53 | emit log_named_bytes("0x0000", hex"0000"); 54 | emit logs(hex"ff"); 55 | } 56 | function echo(string memory s1, string memory s2) public pure 57 | returns (string memory, string memory) 58 | { 59 | return (s1, s2); 60 | } 61 | 62 | function prove_this(uint x) public { 63 | emit log_named_uint("sym x", x); 64 | assertGt(x + 1, 0); 65 | } 66 | 67 | function test_logn() public { 68 | assembly { 69 | log0(0x01, 0x02) 70 | log1(0x01, 0x02, 0x03) 71 | log2(0x01, 0x02, 0x03, 0x04) 72 | log3(0x01, 0x02, 0x03, 0x04, 0x05) 73 | } 74 | } 75 | 76 | event MyEvent(uint, uint indexed, uint, uint indexed); 77 | function test_events() public { 78 | emit MyEvent(1, 2, 3, 4); 79 | } 80 | 81 | function test_asserts() public { 82 | string memory err = "this test has failed!"; 83 | emit log("## assertTrue(bool)\n"); 84 | assertTrue(false); 85 | emit log("\n"); 86 | assertTrue(false, err); 87 | 88 | emit log("\n## assertEq(address,address)\n"); 89 | assertEq(address(this), msg.sender); 90 | emit log("\n"); 91 | assertEq(address(this), msg.sender, err); 92 | 93 | emit log("\n## assertEq32(bytes32,bytes32)\n"); 94 | assertEq32("bytes 1", "bytes 2"); 95 | emit log("\n"); 96 | assertEq32("bytes 1", "bytes 2", err); 97 | 98 | emit log("\n## assertEq(bytes32,bytes32)\n"); 99 | assertEq32("bytes 1", "bytes 2"); 100 | emit log("\n"); 101 | assertEq32("bytes 1", "bytes 2", err); 102 | 103 | emit log("\n## assertEq(uint,uint)\n"); 104 | assertEq(uint(0), 1); 105 | emit log("\n"); 106 | assertEq(uint(0), 1, err); 107 | 108 | emit log("\n## assertEq(int,int)\n"); 109 | assertEq(-1, -2); 110 | emit log("\n"); 111 | assertEq(-1, -2, err); 112 | 113 | emit log("\n## assertEqDecimal(int,int,uint)\n"); 114 | assertEqDecimal(-1.0e18, -1.1e18, 18); 115 | emit log("\n"); 116 | assertEqDecimal(-1.0e18, -1.1e18, 18, err); 117 | 118 | emit log("\n## assertEqDecimal(uint,uint,uint)\n"); 119 | assertEqDecimal(uint(1.0e18), 1.1e18, 18); 120 | emit log("\n"); 121 | assertEqDecimal(uint(1.0e18), 1.1e18, 18, err); 122 | 123 | emit log("\n## assertGt(uint,uint)\n"); 124 | assertGt(uint(0), 0); 125 | emit log("\n"); 126 | assertGt(uint(0), 0, err); 127 | 128 | emit log("\n## assertGt(int,int)\n"); 129 | assertGt(-1, -1); 130 | emit log("\n"); 131 | assertGt(-1, -1, err); 132 | 133 | emit log("\n## assertGtDecimal(int,int,uint)\n"); 134 | assertGtDecimal(-2.0e18, -1.1e18, 18); 135 | emit log("\n"); 136 | assertGtDecimal(-2.0e18, -1.1e18, 18, err); 137 | 138 | emit log("\n## assertGtDecimal(uint,uint,uint)\n"); 139 | assertGtDecimal(uint(1.0e18), 1.1e18, 18); 140 | emit log("\n"); 141 | assertGtDecimal(uint(1.0e18), 1.1e18, 18, err); 142 | 143 | emit log("\n## assertGe(uint,uint)\n"); 144 | assertGe(uint(0), 1); 145 | emit log("\n"); 146 | assertGe(uint(0), 1, err); 147 | 148 | emit log("\n## assertGe(int,int)\n"); 149 | assertGe(-1, 0); 150 | emit log("\n"); 151 | assertGe(-1, 0, err); 152 | 153 | emit log("\n## assertGeDecimal(int,int,uint)\n"); 154 | assertGeDecimal(-2.0e18, -1.1e18, 18); 155 | emit log("\n"); 156 | assertGeDecimal(-2.0e18, -1.1e18, 18, err); 157 | 158 | emit log("\n## assertGeDecimal(uint,uint,uint)\n"); 159 | assertGeDecimal(uint(1.0e18), 1.1e18, 18); 160 | emit log("\n"); 161 | assertGeDecimal(uint(1.0e18), 1.1e18, 18, err); 162 | 163 | emit log("\n## assertLt(uint,uint)\n"); 164 | assertLt(uint(0), 0); 165 | emit log("\n"); 166 | assertLt(uint(0), 0, err); 167 | 168 | emit log("\n## assertLt(int,int)\n"); 169 | assertLt(-1, -1); 170 | emit log("\n"); 171 | assertLt(-1, -1, err); 172 | 173 | emit log("\n## assertLtDecimal(int,int,uint)\n"); 174 | assertLtDecimal(-1.0e18, -1.1e18, 18); 175 | emit log("\n"); 176 | assertLtDecimal(-1.0e18, -1.1e18, 18, err); 177 | 178 | emit log("\n## assertLtDecimal(uint,uint,uint)\n"); 179 | assertLtDecimal(uint(2.0e18), 1.1e18, 18); 180 | emit log("\n"); 181 | assertLtDecimal(uint(2.0e18), 1.1e18, 18, err); 182 | 183 | emit log("\n## assertLe(uint,uint)\n"); 184 | assertLe(uint(1), 0); 185 | emit log("\n"); 186 | assertLe(uint(1), 0, err); 187 | 188 | emit log("\n## assertLe(int,int)\n"); 189 | assertLe(0, -1); 190 | emit log("\n"); 191 | assertLe(0, -1, err); 192 | 193 | emit log("\n## assertLeDecimal(int,int,uint)\n"); 194 | assertLeDecimal(-1.0e18, -1.1e18, 18); 195 | emit log("\n"); 196 | assertLeDecimal(-1.0e18, -1.1e18, 18, err); 197 | 198 | emit log("\n## assertLeDecimal(uint,uint,uint)\n"); 199 | assertLeDecimal(uint(2.0e18), 1.1e18, 18); 200 | emit log("\n"); 201 | assertLeDecimal(uint(2.0e18), 1.1e18, 18, err); 202 | 203 | emit log("\n## assertEq(string,string)\n"); 204 | string memory s1 = "string 1"; 205 | string memory s2 = "string 2"; 206 | assertEq(s1, s2); 207 | emit log("\n"); 208 | assertEq(s1, s2, err); 209 | 210 | emit log("\n## assertEq0(bytes,bytes)\n"); 211 | assertEq0(hex"abcdef01", hex"abcdef02"); 212 | emit log("\n"); 213 | assertEq0(hex"abcdef01", hex"abcdef02", err); 214 | } 215 | } 216 | 217 | contract DemoTestWithSetUp { 218 | function setUp() public { 219 | } 220 | function test_pass() public pure { 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "forge-std", 3 | "version": "1.7.6", 4 | "description": "Forge Standard Library is a collection of helpful contracts and libraries for use with Forge and Foundry.", 5 | "homepage": "https://book.getfoundry.sh/forge/forge-std", 6 | "bugs": "https://github.com/foundry-rs/forge-std/issues", 7 | "license": "(Apache-2.0 OR MIT)", 8 | "author": "Contributors to Forge Standard Library", 9 | "files": [ 10 | "src/**/*" 11 | ], 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/foundry-rs/forge-std.git" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/src/StdJson.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.0 <0.9.0; 3 | 4 | pragma experimental ABIEncoderV2; 5 | 6 | import {VmSafe} from "./Vm.sol"; 7 | 8 | // Helpers for parsing and writing JSON files 9 | // To parse: 10 | // ``` 11 | // using stdJson for string; 12 | // string memory json = vm.readFile("some_peth"); 13 | // json.parseUint(""); 14 | // ``` 15 | // To write: 16 | // ``` 17 | // using stdJson for string; 18 | // string memory json = "deploymentArtifact"; 19 | // Contract contract = new Contract(); 20 | // json.serialize("contractAddress", address(contract)); 21 | // json = json.serialize("deploymentTimes", uint(1)); 22 | // // store the stringified JSON to the 'json' variable we have been using as a key 23 | // // as we won't need it any longer 24 | // string memory json2 = "finalArtifact"; 25 | // string memory final = json2.serialize("depArtifact", json); 26 | // final.write(""); 27 | // ``` 28 | 29 | library stdJson { 30 | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); 31 | 32 | function parseRaw(string memory json, string memory key) internal pure returns (bytes memory) { 33 | return vm.parseJson(json, key); 34 | } 35 | 36 | function readUint(string memory json, string memory key) internal pure returns (uint256) { 37 | return vm.parseJsonUint(json, key); 38 | } 39 | 40 | function readUintArray(string memory json, string memory key) internal pure returns (uint256[] memory) { 41 | return vm.parseJsonUintArray(json, key); 42 | } 43 | 44 | function readInt(string memory json, string memory key) internal pure returns (int256) { 45 | return vm.parseJsonInt(json, key); 46 | } 47 | 48 | function readIntArray(string memory json, string memory key) internal pure returns (int256[] memory) { 49 | return vm.parseJsonIntArray(json, key); 50 | } 51 | 52 | function readBytes32(string memory json, string memory key) internal pure returns (bytes32) { 53 | return vm.parseJsonBytes32(json, key); 54 | } 55 | 56 | function readBytes32Array(string memory json, string memory key) internal pure returns (bytes32[] memory) { 57 | return vm.parseJsonBytes32Array(json, key); 58 | } 59 | 60 | function readString(string memory json, string memory key) internal pure returns (string memory) { 61 | return vm.parseJsonString(json, key); 62 | } 63 | 64 | function readStringArray(string memory json, string memory key) internal pure returns (string[] memory) { 65 | return vm.parseJsonStringArray(json, key); 66 | } 67 | 68 | function readAddress(string memory json, string memory key) internal pure returns (address) { 69 | return vm.parseJsonAddress(json, key); 70 | } 71 | 72 | function readAddressArray(string memory json, string memory key) internal pure returns (address[] memory) { 73 | return vm.parseJsonAddressArray(json, key); 74 | } 75 | 76 | function readBool(string memory json, string memory key) internal pure returns (bool) { 77 | return vm.parseJsonBool(json, key); 78 | } 79 | 80 | function readBoolArray(string memory json, string memory key) internal pure returns (bool[] memory) { 81 | return vm.parseJsonBoolArray(json, key); 82 | } 83 | 84 | function readBytes(string memory json, string memory key) internal pure returns (bytes memory) { 85 | return vm.parseJsonBytes(json, key); 86 | } 87 | 88 | function readBytesArray(string memory json, string memory key) internal pure returns (bytes[] memory) { 89 | return vm.parseJsonBytesArray(json, key); 90 | } 91 | 92 | function serialize(string memory jsonKey, string memory rootObject) internal returns (string memory) { 93 | return vm.serializeJson(jsonKey, rootObject); 94 | } 95 | 96 | function serialize(string memory jsonKey, string memory key, bool value) internal returns (string memory) { 97 | return vm.serializeBool(jsonKey, key, value); 98 | } 99 | 100 | function serialize(string memory jsonKey, string memory key, bool[] memory value) 101 | internal 102 | returns (string memory) 103 | { 104 | return vm.serializeBool(jsonKey, key, value); 105 | } 106 | 107 | function serialize(string memory jsonKey, string memory key, uint256 value) internal returns (string memory) { 108 | return vm.serializeUint(jsonKey, key, value); 109 | } 110 | 111 | function serialize(string memory jsonKey, string memory key, uint256[] memory value) 112 | internal 113 | returns (string memory) 114 | { 115 | return vm.serializeUint(jsonKey, key, value); 116 | } 117 | 118 | function serialize(string memory jsonKey, string memory key, int256 value) internal returns (string memory) { 119 | return vm.serializeInt(jsonKey, key, value); 120 | } 121 | 122 | function serialize(string memory jsonKey, string memory key, int256[] memory value) 123 | internal 124 | returns (string memory) 125 | { 126 | return vm.serializeInt(jsonKey, key, value); 127 | } 128 | 129 | function serialize(string memory jsonKey, string memory key, address value) internal returns (string memory) { 130 | return vm.serializeAddress(jsonKey, key, value); 131 | } 132 | 133 | function serialize(string memory jsonKey, string memory key, address[] memory value) 134 | internal 135 | returns (string memory) 136 | { 137 | return vm.serializeAddress(jsonKey, key, value); 138 | } 139 | 140 | function serialize(string memory jsonKey, string memory key, bytes32 value) internal returns (string memory) { 141 | return vm.serializeBytes32(jsonKey, key, value); 142 | } 143 | 144 | function serialize(string memory jsonKey, string memory key, bytes32[] memory value) 145 | internal 146 | returns (string memory) 147 | { 148 | return vm.serializeBytes32(jsonKey, key, value); 149 | } 150 | 151 | function serialize(string memory jsonKey, string memory key, bytes memory value) internal returns (string memory) { 152 | return vm.serializeBytes(jsonKey, key, value); 153 | } 154 | 155 | function serialize(string memory jsonKey, string memory key, bytes[] memory value) 156 | internal 157 | returns (string memory) 158 | { 159 | return vm.serializeBytes(jsonKey, key, value); 160 | } 161 | 162 | function serialize(string memory jsonKey, string memory key, string memory value) 163 | internal 164 | returns (string memory) 165 | { 166 | return vm.serializeString(jsonKey, key, value); 167 | } 168 | 169 | function serialize(string memory jsonKey, string memory key, string[] memory value) 170 | internal 171 | returns (string memory) 172 | { 173 | return vm.serializeString(jsonKey, key, value); 174 | } 175 | 176 | function write(string memory jsonKey, string memory path) internal { 177 | vm.writeJson(jsonKey, path); 178 | } 179 | 180 | function write(string memory jsonKey, string memory path, string memory valueKey) internal { 181 | vm.writeJson(jsonKey, path, valueKey); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/src/StdStyle.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.4.22 <0.9.0; 3 | 4 | import {VmSafe} from "./Vm.sol"; 5 | 6 | library StdStyle { 7 | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); 8 | 9 | string constant RED = "\u001b[91m"; 10 | string constant GREEN = "\u001b[92m"; 11 | string constant YELLOW = "\u001b[93m"; 12 | string constant BLUE = "\u001b[94m"; 13 | string constant MAGENTA = "\u001b[95m"; 14 | string constant CYAN = "\u001b[96m"; 15 | string constant BOLD = "\u001b[1m"; 16 | string constant DIM = "\u001b[2m"; 17 | string constant ITALIC = "\u001b[3m"; 18 | string constant UNDERLINE = "\u001b[4m"; 19 | string constant INVERSE = "\u001b[7m"; 20 | string constant RESET = "\u001b[0m"; 21 | 22 | function styleConcat(string memory style, string memory self) private pure returns (string memory) { 23 | return string(abi.encodePacked(style, self, RESET)); 24 | } 25 | 26 | function red(string memory self) internal pure returns (string memory) { 27 | return styleConcat(RED, self); 28 | } 29 | 30 | function red(uint256 self) internal pure returns (string memory) { 31 | return red(vm.toString(self)); 32 | } 33 | 34 | function red(int256 self) internal pure returns (string memory) { 35 | return red(vm.toString(self)); 36 | } 37 | 38 | function red(address self) internal pure returns (string memory) { 39 | return red(vm.toString(self)); 40 | } 41 | 42 | function red(bool self) internal pure returns (string memory) { 43 | return red(vm.toString(self)); 44 | } 45 | 46 | function redBytes(bytes memory self) internal pure returns (string memory) { 47 | return red(vm.toString(self)); 48 | } 49 | 50 | function redBytes32(bytes32 self) internal pure returns (string memory) { 51 | return red(vm.toString(self)); 52 | } 53 | 54 | function green(string memory self) internal pure returns (string memory) { 55 | return styleConcat(GREEN, self); 56 | } 57 | 58 | function green(uint256 self) internal pure returns (string memory) { 59 | return green(vm.toString(self)); 60 | } 61 | 62 | function green(int256 self) internal pure returns (string memory) { 63 | return green(vm.toString(self)); 64 | } 65 | 66 | function green(address self) internal pure returns (string memory) { 67 | return green(vm.toString(self)); 68 | } 69 | 70 | function green(bool self) internal pure returns (string memory) { 71 | return green(vm.toString(self)); 72 | } 73 | 74 | function greenBytes(bytes memory self) internal pure returns (string memory) { 75 | return green(vm.toString(self)); 76 | } 77 | 78 | function greenBytes32(bytes32 self) internal pure returns (string memory) { 79 | return green(vm.toString(self)); 80 | } 81 | 82 | function yellow(string memory self) internal pure returns (string memory) { 83 | return styleConcat(YELLOW, self); 84 | } 85 | 86 | function yellow(uint256 self) internal pure returns (string memory) { 87 | return yellow(vm.toString(self)); 88 | } 89 | 90 | function yellow(int256 self) internal pure returns (string memory) { 91 | return yellow(vm.toString(self)); 92 | } 93 | 94 | function yellow(address self) internal pure returns (string memory) { 95 | return yellow(vm.toString(self)); 96 | } 97 | 98 | function yellow(bool self) internal pure returns (string memory) { 99 | return yellow(vm.toString(self)); 100 | } 101 | 102 | function yellowBytes(bytes memory self) internal pure returns (string memory) { 103 | return yellow(vm.toString(self)); 104 | } 105 | 106 | function yellowBytes32(bytes32 self) internal pure returns (string memory) { 107 | return yellow(vm.toString(self)); 108 | } 109 | 110 | function blue(string memory self) internal pure returns (string memory) { 111 | return styleConcat(BLUE, self); 112 | } 113 | 114 | function blue(uint256 self) internal pure returns (string memory) { 115 | return blue(vm.toString(self)); 116 | } 117 | 118 | function blue(int256 self) internal pure returns (string memory) { 119 | return blue(vm.toString(self)); 120 | } 121 | 122 | function blue(address self) internal pure returns (string memory) { 123 | return blue(vm.toString(self)); 124 | } 125 | 126 | function blue(bool self) internal pure returns (string memory) { 127 | return blue(vm.toString(self)); 128 | } 129 | 130 | function blueBytes(bytes memory self) internal pure returns (string memory) { 131 | return blue(vm.toString(self)); 132 | } 133 | 134 | function blueBytes32(bytes32 self) internal pure returns (string memory) { 135 | return blue(vm.toString(self)); 136 | } 137 | 138 | function magenta(string memory self) internal pure returns (string memory) { 139 | return styleConcat(MAGENTA, self); 140 | } 141 | 142 | function magenta(uint256 self) internal pure returns (string memory) { 143 | return magenta(vm.toString(self)); 144 | } 145 | 146 | function magenta(int256 self) internal pure returns (string memory) { 147 | return magenta(vm.toString(self)); 148 | } 149 | 150 | function magenta(address self) internal pure returns (string memory) { 151 | return magenta(vm.toString(self)); 152 | } 153 | 154 | function magenta(bool self) internal pure returns (string memory) { 155 | return magenta(vm.toString(self)); 156 | } 157 | 158 | function magentaBytes(bytes memory self) internal pure returns (string memory) { 159 | return magenta(vm.toString(self)); 160 | } 161 | 162 | function magentaBytes32(bytes32 self) internal pure returns (string memory) { 163 | return magenta(vm.toString(self)); 164 | } 165 | 166 | function cyan(string memory self) internal pure returns (string memory) { 167 | return styleConcat(CYAN, self); 168 | } 169 | 170 | function cyan(uint256 self) internal pure returns (string memory) { 171 | return cyan(vm.toString(self)); 172 | } 173 | 174 | function cyan(int256 self) internal pure returns (string memory) { 175 | return cyan(vm.toString(self)); 176 | } 177 | 178 | function cyan(address self) internal pure returns (string memory) { 179 | return cyan(vm.toString(self)); 180 | } 181 | 182 | function cyan(bool self) internal pure returns (string memory) { 183 | return cyan(vm.toString(self)); 184 | } 185 | 186 | function cyanBytes(bytes memory self) internal pure returns (string memory) { 187 | return cyan(vm.toString(self)); 188 | } 189 | 190 | function cyanBytes32(bytes32 self) internal pure returns (string memory) { 191 | return cyan(vm.toString(self)); 192 | } 193 | 194 | function bold(string memory self) internal pure returns (string memory) { 195 | return styleConcat(BOLD, self); 196 | } 197 | 198 | function bold(uint256 self) internal pure returns (string memory) { 199 | return bold(vm.toString(self)); 200 | } 201 | 202 | function bold(int256 self) internal pure returns (string memory) { 203 | return bold(vm.toString(self)); 204 | } 205 | 206 | function bold(address self) internal pure returns (string memory) { 207 | return bold(vm.toString(self)); 208 | } 209 | 210 | function bold(bool self) internal pure returns (string memory) { 211 | return bold(vm.toString(self)); 212 | } 213 | 214 | function boldBytes(bytes memory self) internal pure returns (string memory) { 215 | return bold(vm.toString(self)); 216 | } 217 | 218 | function boldBytes32(bytes32 self) internal pure returns (string memory) { 219 | return bold(vm.toString(self)); 220 | } 221 | 222 | function dim(string memory self) internal pure returns (string memory) { 223 | return styleConcat(DIM, self); 224 | } 225 | 226 | function dim(uint256 self) internal pure returns (string memory) { 227 | return dim(vm.toString(self)); 228 | } 229 | 230 | function dim(int256 self) internal pure returns (string memory) { 231 | return dim(vm.toString(self)); 232 | } 233 | 234 | function dim(address self) internal pure returns (string memory) { 235 | return dim(vm.toString(self)); 236 | } 237 | 238 | function dim(bool self) internal pure returns (string memory) { 239 | return dim(vm.toString(self)); 240 | } 241 | 242 | function dimBytes(bytes memory self) internal pure returns (string memory) { 243 | return dim(vm.toString(self)); 244 | } 245 | 246 | function dimBytes32(bytes32 self) internal pure returns (string memory) { 247 | return dim(vm.toString(self)); 248 | } 249 | 250 | function italic(string memory self) internal pure returns (string memory) { 251 | return styleConcat(ITALIC, self); 252 | } 253 | 254 | function italic(uint256 self) internal pure returns (string memory) { 255 | return italic(vm.toString(self)); 256 | } 257 | 258 | function italic(int256 self) internal pure returns (string memory) { 259 | return italic(vm.toString(self)); 260 | } 261 | 262 | function italic(address self) internal pure returns (string memory) { 263 | return italic(vm.toString(self)); 264 | } 265 | 266 | function italic(bool self) internal pure returns (string memory) { 267 | return italic(vm.toString(self)); 268 | } 269 | 270 | function italicBytes(bytes memory self) internal pure returns (string memory) { 271 | return italic(vm.toString(self)); 272 | } 273 | 274 | function italicBytes32(bytes32 self) internal pure returns (string memory) { 275 | return italic(vm.toString(self)); 276 | } 277 | 278 | function underline(string memory self) internal pure returns (string memory) { 279 | return styleConcat(UNDERLINE, self); 280 | } 281 | 282 | function underline(uint256 self) internal pure returns (string memory) { 283 | return underline(vm.toString(self)); 284 | } 285 | 286 | function underline(int256 self) internal pure returns (string memory) { 287 | return underline(vm.toString(self)); 288 | } 289 | 290 | function underline(address self) internal pure returns (string memory) { 291 | return underline(vm.toString(self)); 292 | } 293 | 294 | function underline(bool self) internal pure returns (string memory) { 295 | return underline(vm.toString(self)); 296 | } 297 | 298 | function underlineBytes(bytes memory self) internal pure returns (string memory) { 299 | return underline(vm.toString(self)); 300 | } 301 | 302 | function underlineBytes32(bytes32 self) internal pure returns (string memory) { 303 | return underline(vm.toString(self)); 304 | } 305 | 306 | function inverse(string memory self) internal pure returns (string memory) { 307 | return styleConcat(INVERSE, self); 308 | } 309 | 310 | function inverse(uint256 self) internal pure returns (string memory) { 311 | return inverse(vm.toString(self)); 312 | } 313 | 314 | function inverse(int256 self) internal pure returns (string memory) { 315 | return inverse(vm.toString(self)); 316 | } 317 | 318 | function inverse(address self) internal pure returns (string memory) { 319 | return inverse(vm.toString(self)); 320 | } 321 | 322 | function inverse(bool self) internal pure returns (string memory) { 323 | return inverse(vm.toString(self)); 324 | } 325 | 326 | function inverseBytes(bytes memory self) internal pure returns (string memory) { 327 | return inverse(vm.toString(self)); 328 | } 329 | 330 | function inverseBytes32(bytes32 self) internal pure returns (string memory) { 331 | return inverse(vm.toString(self)); 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/src/StdUtils.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | pragma experimental ABIEncoderV2; 5 | 6 | import {IMulticall3} from "./interfaces/IMulticall3.sol"; 7 | import {MockERC20} from "./mocks/MockERC20.sol"; 8 | import {MockERC721} from "./mocks/MockERC721.sol"; 9 | import {VmSafe} from "./Vm.sol"; 10 | 11 | abstract contract StdUtils { 12 | /*////////////////////////////////////////////////////////////////////////// 13 | CONSTANTS 14 | //////////////////////////////////////////////////////////////////////////*/ 15 | 16 | IMulticall3 private constant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11); 17 | VmSafe private constant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code"))))); 18 | address private constant CONSOLE2_ADDRESS = 0x000000000000000000636F6e736F6c652e6c6f67; 19 | uint256 private constant INT256_MIN_ABS = 20 | 57896044618658097711785492504343953926634992332820282019728792003956564819968; 21 | uint256 private constant SECP256K1_ORDER = 22 | 115792089237316195423570985008687907852837564279074904382605163141518161494337; 23 | uint256 private constant UINT256_MAX = 24 | 115792089237316195423570985008687907853269984665640564039457584007913129639935; 25 | 26 | // Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy. 27 | address private constant CREATE2_FACTORY = 0x4e59b44847b379578588920cA78FbF26c0B4956C; 28 | 29 | /*////////////////////////////////////////////////////////////////////////// 30 | INTERNAL FUNCTIONS 31 | //////////////////////////////////////////////////////////////////////////*/ 32 | 33 | function _bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { 34 | require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min."); 35 | // If x is between min and max, return x directly. This is to ensure that dictionary values 36 | // do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188 37 | if (x >= min && x <= max) return x; 38 | 39 | uint256 size = max - min + 1; 40 | 41 | // If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side. 42 | // This helps ensure coverage of the min/max values. 43 | if (x <= 3 && size > x) return min + x; 44 | if (x >= UINT256_MAX - 3 && size > UINT256_MAX - x) return max - (UINT256_MAX - x); 45 | 46 | // Otherwise, wrap x into the range [min, max], i.e. the range is inclusive. 47 | if (x > max) { 48 | uint256 diff = x - max; 49 | uint256 rem = diff % size; 50 | if (rem == 0) return max; 51 | result = min + rem - 1; 52 | } else if (x < min) { 53 | uint256 diff = min - x; 54 | uint256 rem = diff % size; 55 | if (rem == 0) return min; 56 | result = max - rem + 1; 57 | } 58 | } 59 | 60 | function bound(uint256 x, uint256 min, uint256 max) internal pure virtual returns (uint256 result) { 61 | result = _bound(x, min, max); 62 | console2_log_StdUtils("Bound Result", result); 63 | } 64 | 65 | function _bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { 66 | require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min."); 67 | 68 | // Shifting all int256 values to uint256 to use _bound function. The range of two types are: 69 | // int256 : -(2**255) ~ (2**255 - 1) 70 | // uint256: 0 ~ (2**256 - 1) 71 | // So, add 2**255, INT256_MIN_ABS to the integer values. 72 | // 73 | // If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow. 74 | // So, use `~uint256(x) + 1` instead. 75 | uint256 _x = x < 0 ? (INT256_MIN_ABS - ~uint256(x) - 1) : (uint256(x) + INT256_MIN_ABS); 76 | uint256 _min = min < 0 ? (INT256_MIN_ABS - ~uint256(min) - 1) : (uint256(min) + INT256_MIN_ABS); 77 | uint256 _max = max < 0 ? (INT256_MIN_ABS - ~uint256(max) - 1) : (uint256(max) + INT256_MIN_ABS); 78 | 79 | uint256 y = _bound(_x, _min, _max); 80 | 81 | // To move it back to int256 value, subtract INT256_MIN_ABS at here. 82 | result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) + 1) : int256(y - INT256_MIN_ABS); 83 | } 84 | 85 | function bound(int256 x, int256 min, int256 max) internal pure virtual returns (int256 result) { 86 | result = _bound(x, min, max); 87 | console2_log_StdUtils("Bound result", vm.toString(result)); 88 | } 89 | 90 | function boundPrivateKey(uint256 privateKey) internal pure virtual returns (uint256 result) { 91 | result = _bound(privateKey, 1, SECP256K1_ORDER - 1); 92 | } 93 | 94 | function bytesToUint(bytes memory b) internal pure virtual returns (uint256) { 95 | require(b.length <= 32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32."); 96 | return abi.decode(abi.encodePacked(new bytes(32 - b.length), b), (uint256)); 97 | } 98 | 99 | /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce 100 | /// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol) 101 | function computeCreateAddress(address deployer, uint256 nonce) internal pure virtual returns (address) { 102 | console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead."); 103 | return vm.computeCreateAddress(deployer, nonce); 104 | } 105 | 106 | function computeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer) 107 | internal 108 | pure 109 | virtual 110 | returns (address) 111 | { 112 | console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); 113 | return vm.computeCreate2Address(salt, initcodeHash, deployer); 114 | } 115 | 116 | /// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployer 117 | function computeCreate2Address(bytes32 salt, bytes32 initCodeHash) internal pure returns (address) { 118 | console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead."); 119 | return vm.computeCreate2Address(salt, initCodeHash); 120 | } 121 | 122 | /// @dev returns an initialized mock ERC20 contract 123 | function deployMockERC20(string memory name, string memory symbol, uint8 decimals) 124 | internal 125 | returns (MockERC20 mock) 126 | { 127 | mock = new MockERC20(); 128 | mock.initialize(name, symbol, decimals); 129 | } 130 | 131 | /// @dev returns an initialized mock ERC721 contract 132 | function deployMockERC721(string memory name, string memory symbol) internal returns (MockERC721 mock) { 133 | mock = new MockERC721(); 134 | mock.initialize(name, symbol); 135 | } 136 | 137 | /// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments 138 | /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode 139 | function hashInitCode(bytes memory creationCode) internal pure returns (bytes32) { 140 | return hashInitCode(creationCode, ""); 141 | } 142 | 143 | /// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2 144 | /// @param creationCode the creation code of a contract C, as returned by type(C).creationCode 145 | /// @param args the ABI-encoded arguments to the constructor of C 146 | function hashInitCode(bytes memory creationCode, bytes memory args) internal pure returns (bytes32) { 147 | return keccak256(abi.encodePacked(creationCode, args)); 148 | } 149 | 150 | // Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses. 151 | function getTokenBalances(address token, address[] memory addresses) 152 | internal 153 | virtual 154 | returns (uint256[] memory balances) 155 | { 156 | uint256 tokenCodeSize; 157 | assembly { 158 | tokenCodeSize := extcodesize(token) 159 | } 160 | require(tokenCodeSize > 0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract."); 161 | 162 | // ABI encode the aggregate call to Multicall3. 163 | uint256 length = addresses.length; 164 | IMulticall3.Call[] memory calls = new IMulticall3.Call[](length); 165 | for (uint256 i = 0; i < length; ++i) { 166 | // 0x70a08231 = bytes4("balanceOf(address)")) 167 | calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))}); 168 | } 169 | 170 | // Make the aggregate call. 171 | (, bytes[] memory returnData) = multicall.aggregate(calls); 172 | 173 | // ABI decode the return data and return the balances. 174 | balances = new uint256[](length); 175 | for (uint256 i = 0; i < length; ++i) { 176 | balances[i] = abi.decode(returnData[i], (uint256)); 177 | } 178 | } 179 | 180 | /*////////////////////////////////////////////////////////////////////////// 181 | PRIVATE FUNCTIONS 182 | //////////////////////////////////////////////////////////////////////////*/ 183 | 184 | function addressFromLast20Bytes(bytes32 bytesValue) private pure returns (address) { 185 | return address(uint160(uint256(bytesValue))); 186 | } 187 | 188 | // This section is used to prevent the compilation of console, which shortens the compilation time when console is 189 | // not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid 190 | // any breaking changes to function signatures. 191 | function _castLogPayloadViewToPure(function(bytes memory) internal view fnIn) 192 | internal 193 | pure 194 | returns (function(bytes memory) internal pure fnOut) 195 | { 196 | assembly { 197 | fnOut := fnIn 198 | } 199 | } 200 | 201 | function _sendLogPayload(bytes memory payload) internal pure { 202 | _castLogPayloadViewToPure(_sendLogPayloadView)(payload); 203 | } 204 | 205 | function _sendLogPayloadView(bytes memory payload) private view { 206 | uint256 payloadLength = payload.length; 207 | address consoleAddress = CONSOLE2_ADDRESS; 208 | /// @solidity memory-safe-assembly 209 | assembly { 210 | let payloadStart := add(payload, 32) 211 | let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) 212 | } 213 | } 214 | 215 | function console2_log_StdUtils(string memory p0) private pure { 216 | _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); 217 | } 218 | 219 | function console2_log_StdUtils(string memory p0, uint256 p1) private pure { 220 | _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); 221 | } 222 | 223 | function console2_log_StdUtils(string memory p0, string memory p1) private pure { 224 | _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/src/interfaces/IERC1155.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2; 3 | 4 | import "./IERC165.sol"; 5 | 6 | /// @title ERC-1155 Multi Token Standard 7 | /// @dev See https://eips.ethereum.org/EIPS/eip-1155 8 | /// Note: The ERC-165 identifier for this interface is 0xd9b67a26. 9 | interface IERC1155 is IERC165 { 10 | /// @dev 11 | /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). 12 | /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender). 13 | /// - The `_from` argument MUST be the address of the holder whose balance is decreased. 14 | /// - The `_to` argument MUST be the address of the recipient whose balance is increased. 15 | /// - The `_id` argument MUST be the token type being transferred. 16 | /// - The `_value` argument MUST be the number of tokens the holder balance is decreased by and match what the recipient balance is increased by. 17 | /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). 18 | /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). 19 | event TransferSingle( 20 | address indexed _operator, address indexed _from, address indexed _to, uint256 _id, uint256 _value 21 | ); 22 | 23 | /// @dev 24 | /// - Either `TransferSingle` or `TransferBatch` MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see "Safe Transfer Rules" section of the standard). 25 | /// - The `_operator` argument MUST be the address of an account/contract that is approved to make the transfer (SHOULD be msg.sender). 26 | /// - The `_from` argument MUST be the address of the holder whose balance is decreased. 27 | /// - The `_to` argument MUST be the address of the recipient whose balance is increased. 28 | /// - The `_ids` argument MUST be the list of tokens being transferred. 29 | /// - The `_values` argument MUST be the list of number of tokens (matching the list and order of tokens specified in _ids) the holder balance is decreased by and match what the recipient balance is increased by. 30 | /// - When minting/creating tokens, the `_from` argument MUST be set to `0x0` (i.e. zero address). 31 | /// - When burning/destroying tokens, the `_to` argument MUST be set to `0x0` (i.e. zero address). 32 | event TransferBatch( 33 | address indexed _operator, address indexed _from, address indexed _to, uint256[] _ids, uint256[] _values 34 | ); 35 | 36 | /// @dev MUST emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absence of an event assumes disabled). 37 | event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); 38 | 39 | /// @dev MUST emit when the URI is updated for a token ID. URIs are defined in RFC 3986. 40 | /// The URI MUST point to a JSON file that conforms to the "ERC-1155 Metadata URI JSON Schema". 41 | event URI(string _value, uint256 indexed _id); 42 | 43 | /// @notice Transfers `_value` amount of an `_id` from the `_from` address to the `_to` address specified (with safety call). 44 | /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard). 45 | /// - MUST revert if `_to` is the zero address. 46 | /// - MUST revert if balance of holder for token `_id` is lower than the `_value` sent. 47 | /// - MUST revert on any other error. 48 | /// - MUST emit the `TransferSingle` event to reflect the balance change (see "Safe Transfer Rules" section of the standard). 49 | /// - After the above conditions are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call `onERC1155Received` on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). 50 | /// @param _from Source address 51 | /// @param _to Target address 52 | /// @param _id ID of the token type 53 | /// @param _value Transfer amount 54 | /// @param _data Additional data with no specified format, MUST be sent unaltered in call to `onERC1155Received` on `_to` 55 | function safeTransferFrom(address _from, address _to, uint256 _id, uint256 _value, bytes calldata _data) external; 56 | 57 | /// @notice Transfers `_values` amount(s) of `_ids` from the `_from` address to the `_to` address specified (with safety call). 58 | /// @dev Caller must be approved to manage the tokens being transferred out of the `_from` account (see "Approval" section of the standard). 59 | /// - MUST revert if `_to` is the zero address. 60 | /// - MUST revert if length of `_ids` is not the same as length of `_values`. 61 | /// - MUST revert if any of the balance(s) of the holder(s) for token(s) in `_ids` is lower than the respective amount(s) in `_values` sent to the recipient. 62 | /// - MUST revert on any other error. 63 | /// - MUST emit `TransferSingle` or `TransferBatch` event(s) such that all the balance changes are reflected (see "Safe Transfer Rules" section of the standard). 64 | /// - Balance changes and events MUST follow the ordering of the arrays (_ids[0]/_values[0] before _ids[1]/_values[1], etc). 65 | /// - After the above conditions for the transfer(s) in the batch are met, this function MUST check if `_to` is a smart contract (e.g. code size > 0). If so, it MUST call the relevant `ERC1155TokenReceiver` hook(s) on `_to` and act appropriately (see "Safe Transfer Rules" section of the standard). 66 | /// @param _from Source address 67 | /// @param _to Target address 68 | /// @param _ids IDs of each token type (order and length must match _values array) 69 | /// @param _values Transfer amounts per token type (order and length must match _ids array) 70 | /// @param _data Additional data with no specified format, MUST be sent unaltered in call to the `ERC1155TokenReceiver` hook(s) on `_to` 71 | function safeBatchTransferFrom( 72 | address _from, 73 | address _to, 74 | uint256[] calldata _ids, 75 | uint256[] calldata _values, 76 | bytes calldata _data 77 | ) external; 78 | 79 | /// @notice Get the balance of an account's tokens. 80 | /// @param _owner The address of the token holder 81 | /// @param _id ID of the token 82 | /// @return The _owner's balance of the token type requested 83 | function balanceOf(address _owner, uint256 _id) external view returns (uint256); 84 | 85 | /// @notice Get the balance of multiple account/token pairs 86 | /// @param _owners The addresses of the token holders 87 | /// @param _ids ID of the tokens 88 | /// @return The _owner's balance of the token types requested (i.e. balance for each (owner, id) pair) 89 | function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) 90 | external 91 | view 92 | returns (uint256[] memory); 93 | 94 | /// @notice Enable or disable approval for a third party ("operator") to manage all of the caller's tokens. 95 | /// @dev MUST emit the ApprovalForAll event on success. 96 | /// @param _operator Address to add to the set of authorized operators 97 | /// @param _approved True if the operator is approved, false to revoke approval 98 | function setApprovalForAll(address _operator, bool _approved) external; 99 | 100 | /// @notice Queries the approval status of an operator for a given owner. 101 | /// @param _owner The owner of the tokens 102 | /// @param _operator Address of authorized operator 103 | /// @return True if the operator is approved, false if not 104 | function isApprovedForAll(address _owner, address _operator) external view returns (bool); 105 | } 106 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/src/interfaces/IERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2; 3 | 4 | import "./IERC165.sol"; 5 | 6 | /// @title ERC-721 Non-Fungible Token Standard 7 | /// @dev See https://eips.ethereum.org/EIPS/eip-721 8 | /// Note: the ERC-165 identifier for this interface is 0x80ac58cd. 9 | interface IERC721 is IERC165 { 10 | /// @dev This emits when ownership of any NFT changes by any mechanism. 11 | /// This event emits when NFTs are created (`from` == 0) and destroyed 12 | /// (`to` == 0). Exception: during contract creation, any number of NFTs 13 | /// may be created and assigned without emitting Transfer. At the time of 14 | /// any transfer, the approved address for that NFT (if any) is reset to none. 15 | event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); 16 | 17 | /// @dev This emits when the approved address for an NFT is changed or 18 | /// reaffirmed. The zero address indicates there is no approved address. 19 | /// When a Transfer event emits, this also indicates that the approved 20 | /// address for that NFT (if any) is reset to none. 21 | event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId); 22 | 23 | /// @dev This emits when an operator is enabled or disabled for an owner. 24 | /// The operator can manage all NFTs of the owner. 25 | event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); 26 | 27 | /// @notice Count all NFTs assigned to an owner 28 | /// @dev NFTs assigned to the zero address are considered invalid, and this 29 | /// function throws for queries about the zero address. 30 | /// @param _owner An address for whom to query the balance 31 | /// @return The number of NFTs owned by `_owner`, possibly zero 32 | function balanceOf(address _owner) external view returns (uint256); 33 | 34 | /// @notice Find the owner of an NFT 35 | /// @dev NFTs assigned to zero address are considered invalid, and queries 36 | /// about them do throw. 37 | /// @param _tokenId The identifier for an NFT 38 | /// @return The address of the owner of the NFT 39 | function ownerOf(uint256 _tokenId) external view returns (address); 40 | 41 | /// @notice Transfers the ownership of an NFT from one address to another address 42 | /// @dev Throws unless `msg.sender` is the current owner, an authorized 43 | /// operator, or the approved address for this NFT. Throws if `_from` is 44 | /// not the current owner. Throws if `_to` is the zero address. Throws if 45 | /// `_tokenId` is not a valid NFT. When transfer is complete, this function 46 | /// checks if `_to` is a smart contract (code size > 0). If so, it calls 47 | /// `onERC721Received` on `_to` and throws if the return value is not 48 | /// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`. 49 | /// @param _from The current owner of the NFT 50 | /// @param _to The new owner 51 | /// @param _tokenId The NFT to transfer 52 | /// @param data Additional data with no specified format, sent in call to `_to` 53 | function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes calldata data) external payable; 54 | 55 | /// @notice Transfers the ownership of an NFT from one address to another address 56 | /// @dev This works identically to the other function with an extra data parameter, 57 | /// except this function just sets data to "". 58 | /// @param _from The current owner of the NFT 59 | /// @param _to The new owner 60 | /// @param _tokenId The NFT to transfer 61 | function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; 62 | 63 | /// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE 64 | /// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE 65 | /// THEY MAY BE PERMANENTLY LOST 66 | /// @dev Throws unless `msg.sender` is the current owner, an authorized 67 | /// operator, or the approved address for this NFT. Throws if `_from` is 68 | /// not the current owner. Throws if `_to` is the zero address. Throws if 69 | /// `_tokenId` is not a valid NFT. 70 | /// @param _from The current owner of the NFT 71 | /// @param _to The new owner 72 | /// @param _tokenId The NFT to transfer 73 | function transferFrom(address _from, address _to, uint256 _tokenId) external payable; 74 | 75 | /// @notice Change or reaffirm the approved address for an NFT 76 | /// @dev The zero address indicates there is no approved address. 77 | /// Throws unless `msg.sender` is the current NFT owner, or an authorized 78 | /// operator of the current owner. 79 | /// @param _approved The new approved NFT controller 80 | /// @param _tokenId The NFT to approve 81 | function approve(address _approved, uint256 _tokenId) external payable; 82 | 83 | /// @notice Enable or disable approval for a third party ("operator") to manage 84 | /// all of `msg.sender`'s assets 85 | /// @dev Emits the ApprovalForAll event. The contract MUST allow 86 | /// multiple operators per owner. 87 | /// @param _operator Address to add to the set of authorized operators 88 | /// @param _approved True if the operator is approved, false to revoke approval 89 | function setApprovalForAll(address _operator, bool _approved) external; 90 | 91 | /// @notice Get the approved address for a single NFT 92 | /// @dev Throws if `_tokenId` is not a valid NFT. 93 | /// @param _tokenId The NFT to find the approved address for 94 | /// @return The approved address for this NFT, or the zero address if there is none 95 | function getApproved(uint256 _tokenId) external view returns (address); 96 | 97 | /// @notice Query if an address is an authorized operator for another address 98 | /// @param _owner The address that owns the NFTs 99 | /// @param _operator The address that acts on behalf of the owner 100 | /// @return True if `_operator` is an approved operator for `_owner`, false otherwise 101 | function isApprovedForAll(address _owner, address _operator) external view returns (bool); 102 | } 103 | 104 | /// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02. 105 | interface IERC721TokenReceiver { 106 | /// @notice Handle the receipt of an NFT 107 | /// @dev The ERC721 smart contract calls this function on the recipient 108 | /// after a `transfer`. This function MAY throw to revert and reject the 109 | /// transfer. Return of other than the magic value MUST result in the 110 | /// transaction being reverted. 111 | /// Note: the contract address is always the message sender. 112 | /// @param _operator The address which called `safeTransferFrom` function 113 | /// @param _from The address which previously owned the token 114 | /// @param _tokenId The NFT identifier which is being transferred 115 | /// @param _data Additional data with no specified format 116 | /// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` 117 | /// unless throwing 118 | function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) 119 | external 120 | returns (bytes4); 121 | } 122 | 123 | /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension 124 | /// @dev See https://eips.ethereum.org/EIPS/eip-721 125 | /// Note: the ERC-165 identifier for this interface is 0x5b5e139f. 126 | interface IERC721Metadata is IERC721 { 127 | /// @notice A descriptive name for a collection of NFTs in this contract 128 | function name() external view returns (string memory _name); 129 | 130 | /// @notice An abbreviated name for NFTs in this contract 131 | function symbol() external view returns (string memory _symbol); 132 | 133 | /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. 134 | /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC 135 | /// 3986. The URI may point to a JSON file that conforms to the "ERC721 136 | /// Metadata JSON Schema". 137 | function tokenURI(uint256 _tokenId) external view returns (string memory); 138 | } 139 | 140 | /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension 141 | /// @dev See https://eips.ethereum.org/EIPS/eip-721 142 | /// Note: the ERC-165 identifier for this interface is 0x780e9d63. 143 | interface IERC721Enumerable is IERC721 { 144 | /// @notice Count NFTs tracked by this contract 145 | /// @return A count of valid NFTs tracked by this contract, where each one of 146 | /// them has an assigned and queryable owner not equal to the zero address 147 | function totalSupply() external view returns (uint256); 148 | 149 | /// @notice Enumerate valid NFTs 150 | /// @dev Throws if `_index` >= `totalSupply()`. 151 | /// @param _index A counter less than `totalSupply()` 152 | /// @return The token identifier for the `_index`th NFT, 153 | /// (sort order not specified) 154 | function tokenByIndex(uint256 _index) external view returns (uint256); 155 | 156 | /// @notice Enumerate NFTs assigned to an owner 157 | /// @dev Throws if `_index` >= `balanceOf(_owner)` or if 158 | /// `_owner` is the zero address, representing invalid NFTs. 159 | /// @param _owner An address where we are interested in NFTs owned by them 160 | /// @param _index A counter less than `balanceOf(_owner)` 161 | /// @return The token identifier for the `_index`th NFT assigned to `_owner`, 162 | /// (sort order not specified) 163 | function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); 164 | } 165 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/src/mocks/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | /// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production. 5 | /// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.sol 6 | contract MockERC20 { 7 | /*////////////////////////////////////////////////////////////// 8 | EVENTS 9 | //////////////////////////////////////////////////////////////*/ 10 | 11 | event Transfer(address indexed from, address indexed to, uint256 amount); 12 | 13 | event Approval(address indexed owner, address indexed spender, uint256 amount); 14 | 15 | /*////////////////////////////////////////////////////////////// 16 | METADATA STORAGE 17 | //////////////////////////////////////////////////////////////*/ 18 | 19 | string public name; 20 | 21 | string public symbol; 22 | 23 | uint8 public decimals; 24 | 25 | /*////////////////////////////////////////////////////////////// 26 | ERC20 STORAGE 27 | //////////////////////////////////////////////////////////////*/ 28 | 29 | uint256 public totalSupply; 30 | 31 | mapping(address => uint256) public balanceOf; 32 | 33 | mapping(address => mapping(address => uint256)) public allowance; 34 | 35 | /*////////////////////////////////////////////////////////////// 36 | EIP-2612 STORAGE 37 | //////////////////////////////////////////////////////////////*/ 38 | 39 | uint256 internal INITIAL_CHAIN_ID; 40 | 41 | bytes32 internal INITIAL_DOMAIN_SEPARATOR; 42 | 43 | mapping(address => uint256) public nonces; 44 | 45 | /*////////////////////////////////////////////////////////////// 46 | INITIALIZE 47 | //////////////////////////////////////////////////////////////*/ 48 | 49 | /// @dev A bool to track whether the contract has been initialized. 50 | bool private initialized; 51 | 52 | /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and 53 | /// syntaxes, we add an initialization function that can be called only once. 54 | function initialize(string memory _name, string memory _symbol, uint8 _decimals) public { 55 | require(!initialized, "ALREADY_INITIALIZED"); 56 | 57 | name = _name; 58 | symbol = _symbol; 59 | decimals = _decimals; 60 | 61 | INITIAL_CHAIN_ID = _pureChainId(); 62 | INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); 63 | 64 | initialized = true; 65 | } 66 | 67 | /*////////////////////////////////////////////////////////////// 68 | ERC20 LOGIC 69 | //////////////////////////////////////////////////////////////*/ 70 | 71 | function approve(address spender, uint256 amount) public virtual returns (bool) { 72 | allowance[msg.sender][spender] = amount; 73 | 74 | emit Approval(msg.sender, spender, amount); 75 | 76 | return true; 77 | } 78 | 79 | function transfer(address to, uint256 amount) public virtual returns (bool) { 80 | balanceOf[msg.sender] = _sub(balanceOf[msg.sender], amount); 81 | balanceOf[to] = _add(balanceOf[to], amount); 82 | 83 | emit Transfer(msg.sender, to, amount); 84 | 85 | return true; 86 | } 87 | 88 | function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) { 89 | uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. 90 | 91 | if (allowed != ~uint256(0)) allowance[from][msg.sender] = _sub(allowed, amount); 92 | 93 | balanceOf[from] = _sub(balanceOf[from], amount); 94 | balanceOf[to] = _add(balanceOf[to], amount); 95 | 96 | emit Transfer(from, to, amount); 97 | 98 | return true; 99 | } 100 | 101 | /*////////////////////////////////////////////////////////////// 102 | EIP-2612 LOGIC 103 | //////////////////////////////////////////////////////////////*/ 104 | 105 | function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) 106 | public 107 | virtual 108 | { 109 | require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); 110 | 111 | address recoveredAddress = ecrecover( 112 | keccak256( 113 | abi.encodePacked( 114 | "\x19\x01", 115 | DOMAIN_SEPARATOR(), 116 | keccak256( 117 | abi.encode( 118 | keccak256( 119 | "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" 120 | ), 121 | owner, 122 | spender, 123 | value, 124 | nonces[owner]++, 125 | deadline 126 | ) 127 | ) 128 | ) 129 | ), 130 | v, 131 | r, 132 | s 133 | ); 134 | 135 | require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); 136 | 137 | allowance[recoveredAddress][spender] = value; 138 | 139 | emit Approval(owner, spender, value); 140 | } 141 | 142 | function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { 143 | return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); 144 | } 145 | 146 | function computeDomainSeparator() internal view virtual returns (bytes32) { 147 | return keccak256( 148 | abi.encode( 149 | keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), 150 | keccak256(bytes(name)), 151 | keccak256("1"), 152 | _pureChainId(), 153 | address(this) 154 | ) 155 | ); 156 | } 157 | 158 | /*////////////////////////////////////////////////////////////// 159 | INTERNAL MINT/BURN LOGIC 160 | //////////////////////////////////////////////////////////////*/ 161 | 162 | function _mint(address to, uint256 amount) internal virtual { 163 | totalSupply = _add(totalSupply, amount); 164 | balanceOf[to] = _add(balanceOf[to], amount); 165 | 166 | emit Transfer(address(0), to, amount); 167 | } 168 | 169 | function _burn(address from, uint256 amount) internal virtual { 170 | balanceOf[from] = _sub(balanceOf[from], amount); 171 | totalSupply = _sub(totalSupply, amount); 172 | 173 | emit Transfer(from, address(0), amount); 174 | } 175 | 176 | /*////////////////////////////////////////////////////////////// 177 | INTERNAL SAFE MATH LOGIC 178 | //////////////////////////////////////////////////////////////*/ 179 | 180 | function _add(uint256 a, uint256 b) internal pure returns (uint256) { 181 | uint256 c = a + b; 182 | require(c >= a, "ERC20: addition overflow"); 183 | return c; 184 | } 185 | 186 | function _sub(uint256 a, uint256 b) internal pure returns (uint256) { 187 | require(a >= b, "ERC20: subtraction underflow"); 188 | return a - b; 189 | } 190 | 191 | /*////////////////////////////////////////////////////////////// 192 | HELPERS 193 | //////////////////////////////////////////////////////////////*/ 194 | 195 | // We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no 196 | // compiler warnings when accessing chain ID in any solidity version supported by forge-std. We 197 | // can't simply access the chain ID in a normal view or pure function because the solc View Pure 198 | // Checker changed `chainid` from pure to view in 0.8.0. 199 | function _viewChainId() private view returns (uint256 chainId) { 200 | // Assembly required since `block.chainid` was introduced in 0.8.0. 201 | assembly { 202 | chainId := chainid() 203 | } 204 | 205 | address(this); // Silence warnings in older Solc versions. 206 | } 207 | 208 | function _pureChainId() private pure returns (uint256 chainId) { 209 | function() internal view returns (uint256) fnIn = _viewChainId; 210 | function() internal pure returns (uint256) pureChainId; 211 | assembly { 212 | pureChainId := fnIn 213 | } 214 | chainId = pureChainId(); 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/src/mocks/MockERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.2 <0.9.0; 3 | 4 | /// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production. 5 | /// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.sol 6 | contract MockERC721 { 7 | /*////////////////////////////////////////////////////////////// 8 | EVENTS 9 | //////////////////////////////////////////////////////////////*/ 10 | 11 | event Transfer(address indexed from, address indexed to, uint256 indexed id); 12 | 13 | event Approval(address indexed owner, address indexed spender, uint256 indexed id); 14 | 15 | event ApprovalForAll(address indexed owner, address indexed operator, bool approved); 16 | 17 | /*////////////////////////////////////////////////////////////// 18 | METADATA STORAGE/LOGIC 19 | //////////////////////////////////////////////////////////////*/ 20 | 21 | string public name; 22 | 23 | string public symbol; 24 | 25 | function tokenURI(uint256 id) public view virtual returns (string memory) {} 26 | 27 | /*////////////////////////////////////////////////////////////// 28 | ERC721 BALANCE/OWNER STORAGE 29 | //////////////////////////////////////////////////////////////*/ 30 | 31 | mapping(uint256 => address) internal _ownerOf; 32 | 33 | mapping(address => uint256) internal _balanceOf; 34 | 35 | function ownerOf(uint256 id) public view virtual returns (address owner) { 36 | require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); 37 | } 38 | 39 | function balanceOf(address owner) public view virtual returns (uint256) { 40 | require(owner != address(0), "ZERO_ADDRESS"); 41 | 42 | return _balanceOf[owner]; 43 | } 44 | 45 | /*////////////////////////////////////////////////////////////// 46 | ERC721 APPROVAL STORAGE 47 | //////////////////////////////////////////////////////////////*/ 48 | 49 | mapping(uint256 => address) public getApproved; 50 | 51 | mapping(address => mapping(address => bool)) public isApprovedForAll; 52 | 53 | /*////////////////////////////////////////////////////////////// 54 | INITIALIZE 55 | //////////////////////////////////////////////////////////////*/ 56 | 57 | /// @dev A bool to track whether the contract has been initialized. 58 | bool private initialized; 59 | 60 | /// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and 61 | /// syntaxes, we add an initialization function that can be called only once. 62 | function initialize(string memory _name, string memory _symbol) public { 63 | require(!initialized, "ALREADY_INITIALIZED"); 64 | 65 | name = _name; 66 | symbol = _symbol; 67 | 68 | initialized = true; 69 | } 70 | 71 | /*////////////////////////////////////////////////////////////// 72 | ERC721 LOGIC 73 | //////////////////////////////////////////////////////////////*/ 74 | 75 | function approve(address spender, uint256 id) public virtual { 76 | address owner = _ownerOf[id]; 77 | 78 | require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); 79 | 80 | getApproved[id] = spender; 81 | 82 | emit Approval(owner, spender, id); 83 | } 84 | 85 | function setApprovalForAll(address operator, bool approved) public virtual { 86 | isApprovedForAll[msg.sender][operator] = approved; 87 | 88 | emit ApprovalForAll(msg.sender, operator, approved); 89 | } 90 | 91 | function transferFrom(address from, address to, uint256 id) public virtual { 92 | require(from == _ownerOf[id], "WRONG_FROM"); 93 | 94 | require(to != address(0), "INVALID_RECIPIENT"); 95 | 96 | require( 97 | msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" 98 | ); 99 | 100 | // Underflow of the sender's balance is impossible because we check for 101 | // ownership above and the recipient's balance can't realistically overflow. 102 | _balanceOf[from]--; 103 | 104 | _balanceOf[to]++; 105 | 106 | _ownerOf[id] = to; 107 | 108 | delete getApproved[id]; 109 | 110 | emit Transfer(from, to, id); 111 | } 112 | 113 | function safeTransferFrom(address from, address to, uint256 id) public virtual { 114 | transferFrom(from, to, id); 115 | 116 | require( 117 | !_isContract(to) 118 | || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") 119 | == IERC721TokenReceiver.onERC721Received.selector, 120 | "UNSAFE_RECIPIENT" 121 | ); 122 | } 123 | 124 | function safeTransferFrom(address from, address to, uint256 id, bytes memory data) public virtual { 125 | transferFrom(from, to, id); 126 | 127 | require( 128 | !_isContract(to) 129 | || IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) 130 | == IERC721TokenReceiver.onERC721Received.selector, 131 | "UNSAFE_RECIPIENT" 132 | ); 133 | } 134 | 135 | /*////////////////////////////////////////////////////////////// 136 | ERC165 LOGIC 137 | //////////////////////////////////////////////////////////////*/ 138 | 139 | function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) { 140 | return interfaceId == 0x01ffc9a7 // ERC165 Interface ID for ERC165 141 | || interfaceId == 0x80ac58cd // ERC165 Interface ID for ERC721 142 | || interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata 143 | } 144 | 145 | /*////////////////////////////////////////////////////////////// 146 | INTERNAL MINT/BURN LOGIC 147 | //////////////////////////////////////////////////////////////*/ 148 | 149 | function _mint(address to, uint256 id) internal virtual { 150 | require(to != address(0), "INVALID_RECIPIENT"); 151 | 152 | require(_ownerOf[id] == address(0), "ALREADY_MINTED"); 153 | 154 | // Counter overflow is incredibly unrealistic. 155 | 156 | _balanceOf[to]++; 157 | 158 | _ownerOf[id] = to; 159 | 160 | emit Transfer(address(0), to, id); 161 | } 162 | 163 | function _burn(uint256 id) internal virtual { 164 | address owner = _ownerOf[id]; 165 | 166 | require(owner != address(0), "NOT_MINTED"); 167 | 168 | _balanceOf[owner]--; 169 | 170 | delete _ownerOf[id]; 171 | 172 | delete getApproved[id]; 173 | 174 | emit Transfer(owner, address(0), id); 175 | } 176 | 177 | /*////////////////////////////////////////////////////////////// 178 | INTERNAL SAFE MINT LOGIC 179 | //////////////////////////////////////////////////////////////*/ 180 | 181 | function _safeMint(address to, uint256 id) internal virtual { 182 | _mint(to, id); 183 | 184 | require( 185 | !_isContract(to) 186 | || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") 187 | == IERC721TokenReceiver.onERC721Received.selector, 188 | "UNSAFE_RECIPIENT" 189 | ); 190 | } 191 | 192 | function _safeMint(address to, uint256 id, bytes memory data) internal virtual { 193 | _mint(to, id); 194 | 195 | require( 196 | !_isContract(to) 197 | || IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) 198 | == IERC721TokenReceiver.onERC721Received.selector, 199 | "UNSAFE_RECIPIENT" 200 | ); 201 | } 202 | 203 | /*////////////////////////////////////////////////////////////// 204 | HELPERS 205 | //////////////////////////////////////////////////////////////*/ 206 | 207 | function _isContract(address _addr) private view returns (bool) { 208 | uint256 codeLength; 209 | 210 | // Assembly required for versions < 0.8.0 to check extcodesize. 211 | assembly { 212 | codeLength := extcodesize(_addr) 213 | } 214 | 215 | return codeLength > 0; 216 | } 217 | } 218 | 219 | interface IERC721TokenReceiver { 220 | function onERC721Received(address, address, uint256, bytes calldata) external returns (bytes4); 221 | } 222 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/test/StdChains.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.7.0 <0.9.0; 3 | 4 | import "../src/Test.sol"; 5 | 6 | contract StdChainsMock is Test { 7 | function exposed_getChain(string memory chainAlias) public returns (Chain memory) { 8 | return getChain(chainAlias); 9 | } 10 | 11 | function exposed_getChain(uint256 chainId) public returns (Chain memory) { 12 | return getChain(chainId); 13 | } 14 | 15 | function exposed_setChain(string memory chainAlias, ChainData memory chainData) public { 16 | setChain(chainAlias, chainData); 17 | } 18 | 19 | function exposed_setFallbackToDefaultRpcUrls(bool useDefault) public { 20 | setFallbackToDefaultRpcUrls(useDefault); 21 | } 22 | } 23 | 24 | contract StdChainsTest is Test { 25 | function test_ChainRpcInitialization() public { 26 | // RPCs specified in `foundry.toml` should be updated. 27 | assertEq(getChain(1).rpcUrl, "https://mainnet.infura.io/v3/b1d3925804e74152b316ca7da97060d3"); 28 | assertEq(getChain("optimism_goerli").rpcUrl, "https://goerli.optimism.io/"); 29 | assertEq(getChain("arbitrum_one_goerli").rpcUrl, "https://goerli-rollup.arbitrum.io/rpc/"); 30 | 31 | // Environment variables should be the next fallback 32 | assertEq(getChain("arbitrum_nova").rpcUrl, "https://nova.arbitrum.io/rpc"); 33 | vm.setEnv("ARBITRUM_NOVA_RPC_URL", "myoverride"); 34 | assertEq(getChain("arbitrum_nova").rpcUrl, "myoverride"); 35 | vm.setEnv("ARBITRUM_NOVA_RPC_URL", "https://nova.arbitrum.io/rpc"); 36 | 37 | // Cannot override RPCs defined in `foundry.toml` 38 | vm.setEnv("MAINNET_RPC_URL", "myoverride2"); 39 | assertEq(getChain("mainnet").rpcUrl, "https://mainnet.infura.io/v3/b1d3925804e74152b316ca7da97060d3"); 40 | 41 | // Other RPCs should remain unchanged. 42 | assertEq(getChain(31337).rpcUrl, "http://127.0.0.1:8545"); 43 | assertEq(getChain("sepolia").rpcUrl, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001"); 44 | } 45 | 46 | function testFuzz_Rpc(string memory rpcAlias) internal { 47 | string memory rpcUrl = getChain(rpcAlias).rpcUrl; 48 | vm.createSelectFork(rpcUrl); 49 | } 50 | 51 | // Ensure we can connect to the default RPC URL for each chain. 52 | // function testRpcs() public { 53 | // testRpc("mainnet"); 54 | // testRpc("goerli"); 55 | // testRpc("sepolia"); 56 | // testRpc("optimism"); 57 | // testRpc("optimism_goerli"); 58 | // testRpc("arbitrum_one"); 59 | // testRpc("arbitrum_one_goerli"); 60 | // testRpc("arbitrum_nova"); 61 | // testRpc("polygon"); 62 | // testRpc("polygon_mumbai"); 63 | // testRpc("avalanche"); 64 | // testRpc("avalanche_fuji"); 65 | // testRpc("bnb_smart_chain"); 66 | // testRpc("bnb_smart_chain_testnet"); 67 | // testRpc("gnosis_chain"); 68 | // testRpc("moonbeam"); 69 | // testRpc("moonriver"); 70 | // testRpc("moonbase"); 71 | // testRpc("base_goerli"); 72 | // testRpc("base"); 73 | // } 74 | 75 | function test_ChainNoDefault() public { 76 | // We deploy a mock to properly test the revert. 77 | StdChainsMock stdChainsMock = new StdChainsMock(); 78 | 79 | vm.expectRevert("StdChains getChain(string): Chain with alias \"does_not_exist\" not found."); 80 | stdChainsMock.exposed_getChain("does_not_exist"); 81 | } 82 | 83 | function test_SetChainFirstFails() public { 84 | // We deploy a mock to properly test the revert. 85 | StdChainsMock stdChainsMock = new StdChainsMock(); 86 | 87 | vm.expectRevert("StdChains setChain(string,ChainData): Chain ID 31337 already used by \"anvil\"."); 88 | stdChainsMock.exposed_setChain("anvil2", ChainData("Anvil", 31337, "URL")); 89 | } 90 | 91 | function test_ChainBubbleUp() public { 92 | // We deploy a mock to properly test the revert. 93 | StdChainsMock stdChainsMock = new StdChainsMock(); 94 | 95 | stdChainsMock.exposed_setChain("needs_undefined_env_var", ChainData("", 123456789, "")); 96 | vm.expectRevert( 97 | "Failed to resolve env var `UNDEFINED_RPC_URL_PLACEHOLDER` in `${UNDEFINED_RPC_URL_PLACEHOLDER}`: environment variable not found" 98 | ); 99 | stdChainsMock.exposed_getChain("needs_undefined_env_var"); 100 | } 101 | 102 | function test_CannotSetChain_ChainIdExists() public { 103 | // We deploy a mock to properly test the revert. 104 | StdChainsMock stdChainsMock = new StdChainsMock(); 105 | 106 | stdChainsMock.exposed_setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/")); 107 | 108 | vm.expectRevert('StdChains setChain(string,ChainData): Chain ID 123456789 already used by "custom_chain".'); 109 | 110 | stdChainsMock.exposed_setChain("another_custom_chain", ChainData("", 123456789, "")); 111 | } 112 | 113 | function test_SetChain() public { 114 | setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/")); 115 | Chain memory customChain = getChain("custom_chain"); 116 | assertEq(customChain.name, "Custom Chain"); 117 | assertEq(customChain.chainId, 123456789); 118 | assertEq(customChain.chainAlias, "custom_chain"); 119 | assertEq(customChain.rpcUrl, "https://custom.chain/"); 120 | Chain memory chainById = getChain(123456789); 121 | assertEq(chainById.name, customChain.name); 122 | assertEq(chainById.chainId, customChain.chainId); 123 | assertEq(chainById.chainAlias, customChain.chainAlias); 124 | assertEq(chainById.rpcUrl, customChain.rpcUrl); 125 | customChain.name = "Another Custom Chain"; 126 | customChain.chainId = 987654321; 127 | setChain("another_custom_chain", customChain); 128 | Chain memory anotherCustomChain = getChain("another_custom_chain"); 129 | assertEq(anotherCustomChain.name, "Another Custom Chain"); 130 | assertEq(anotherCustomChain.chainId, 987654321); 131 | assertEq(anotherCustomChain.chainAlias, "another_custom_chain"); 132 | assertEq(anotherCustomChain.rpcUrl, "https://custom.chain/"); 133 | // Verify the first chain data was not overwritten 134 | chainById = getChain(123456789); 135 | assertEq(chainById.name, "Custom Chain"); 136 | assertEq(chainById.chainId, 123456789); 137 | } 138 | 139 | function test_SetNoEmptyAlias() public { 140 | // We deploy a mock to properly test the revert. 141 | StdChainsMock stdChainsMock = new StdChainsMock(); 142 | 143 | vm.expectRevert("StdChains setChain(string,ChainData): Chain alias cannot be the empty string."); 144 | stdChainsMock.exposed_setChain("", ChainData("", 123456789, "")); 145 | } 146 | 147 | function test_SetNoChainId0() public { 148 | // We deploy a mock to properly test the revert. 149 | StdChainsMock stdChainsMock = new StdChainsMock(); 150 | 151 | vm.expectRevert("StdChains setChain(string,ChainData): Chain ID cannot be 0."); 152 | stdChainsMock.exposed_setChain("alias", ChainData("", 0, "")); 153 | } 154 | 155 | function test_GetNoChainId0() public { 156 | // We deploy a mock to properly test the revert. 157 | StdChainsMock stdChainsMock = new StdChainsMock(); 158 | 159 | vm.expectRevert("StdChains getChain(uint256): Chain ID cannot be 0."); 160 | stdChainsMock.exposed_getChain(0); 161 | } 162 | 163 | function test_GetNoEmptyAlias() public { 164 | // We deploy a mock to properly test the revert. 165 | StdChainsMock stdChainsMock = new StdChainsMock(); 166 | 167 | vm.expectRevert("StdChains getChain(string): Chain alias cannot be the empty string."); 168 | stdChainsMock.exposed_getChain(""); 169 | } 170 | 171 | function test_ChainIdNotFound() public { 172 | // We deploy a mock to properly test the revert. 173 | StdChainsMock stdChainsMock = new StdChainsMock(); 174 | 175 | vm.expectRevert("StdChains getChain(string): Chain with alias \"no_such_alias\" not found."); 176 | stdChainsMock.exposed_getChain("no_such_alias"); 177 | } 178 | 179 | function test_ChainAliasNotFound() public { 180 | // We deploy a mock to properly test the revert. 181 | StdChainsMock stdChainsMock = new StdChainsMock(); 182 | 183 | vm.expectRevert("StdChains getChain(uint256): Chain with ID 321 not found."); 184 | 185 | stdChainsMock.exposed_getChain(321); 186 | } 187 | 188 | function test_SetChain_ExistingOne() public { 189 | // We deploy a mock to properly test the revert. 190 | StdChainsMock stdChainsMock = new StdChainsMock(); 191 | 192 | setChain("custom_chain", ChainData("Custom Chain", 123456789, "https://custom.chain/")); 193 | assertEq(getChain(123456789).chainId, 123456789); 194 | 195 | setChain("custom_chain", ChainData("Modified Chain", 999999999, "https://modified.chain/")); 196 | vm.expectRevert("StdChains getChain(uint256): Chain with ID 123456789 not found."); 197 | stdChainsMock.exposed_getChain(123456789); 198 | 199 | Chain memory modifiedChain = getChain(999999999); 200 | assertEq(modifiedChain.name, "Modified Chain"); 201 | assertEq(modifiedChain.chainId, 999999999); 202 | assertEq(modifiedChain.rpcUrl, "https://modified.chain/"); 203 | } 204 | 205 | function test_DontUseDefaultRpcUrl() public { 206 | // We deploy a mock to properly test the revert. 207 | StdChainsMock stdChainsMock = new StdChainsMock(); 208 | 209 | // Should error if default RPCs flag is set to false. 210 | stdChainsMock.exposed_setFallbackToDefaultRpcUrls(false); 211 | vm.expectRevert(); 212 | stdChainsMock.exposed_getChain(31337); 213 | vm.expectRevert(); 214 | stdChainsMock.exposed_getChain("sepolia"); 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/test/StdError.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0 <0.9.0; 3 | 4 | import "../src/StdError.sol"; 5 | import "../src/Test.sol"; 6 | 7 | contract StdErrorsTest is Test { 8 | ErrorsTest test; 9 | 10 | function setUp() public { 11 | test = new ErrorsTest(); 12 | } 13 | 14 | function test_ExpectAssertion() public { 15 | vm.expectRevert(stdError.assertionError); 16 | test.assertionError(); 17 | } 18 | 19 | function test_ExpectArithmetic() public { 20 | vm.expectRevert(stdError.arithmeticError); 21 | test.arithmeticError(10); 22 | } 23 | 24 | function test_ExpectDiv() public { 25 | vm.expectRevert(stdError.divisionError); 26 | test.divError(0); 27 | } 28 | 29 | function test_ExpectMod() public { 30 | vm.expectRevert(stdError.divisionError); 31 | test.modError(0); 32 | } 33 | 34 | function test_ExpectEnum() public { 35 | vm.expectRevert(stdError.enumConversionError); 36 | test.enumConversion(1); 37 | } 38 | 39 | function test_ExpectEncodeStg() public { 40 | vm.expectRevert(stdError.encodeStorageError); 41 | test.encodeStgError(); 42 | } 43 | 44 | function test_ExpectPop() public { 45 | vm.expectRevert(stdError.popError); 46 | test.pop(); 47 | } 48 | 49 | function test_ExpectOOB() public { 50 | vm.expectRevert(stdError.indexOOBError); 51 | test.indexOOBError(1); 52 | } 53 | 54 | function test_ExpectMem() public { 55 | vm.expectRevert(stdError.memOverflowError); 56 | test.mem(); 57 | } 58 | 59 | function test_ExpectIntern() public { 60 | vm.expectRevert(stdError.zeroVarError); 61 | test.intern(); 62 | } 63 | } 64 | 65 | contract ErrorsTest { 66 | enum T { 67 | T1 68 | } 69 | 70 | uint256[] public someArr; 71 | bytes someBytes; 72 | 73 | function assertionError() public pure { 74 | assert(false); 75 | } 76 | 77 | function arithmeticError(uint256 a) public pure { 78 | a -= 100; 79 | } 80 | 81 | function divError(uint256 a) public pure { 82 | 100 / a; 83 | } 84 | 85 | function modError(uint256 a) public pure { 86 | 100 % a; 87 | } 88 | 89 | function enumConversion(uint256 a) public pure { 90 | T(a); 91 | } 92 | 93 | function encodeStgError() public { 94 | /// @solidity memory-safe-assembly 95 | assembly { 96 | sstore(someBytes.slot, 1) 97 | } 98 | keccak256(someBytes); 99 | } 100 | 101 | function pop() public { 102 | someArr.pop(); 103 | } 104 | 105 | function indexOOBError(uint256 a) public pure { 106 | uint256[] memory t = new uint256[](0); 107 | t[a]; 108 | } 109 | 110 | function mem() public pure { 111 | uint256 l = 2 ** 256 / 32; 112 | new uint256[](l); 113 | } 114 | 115 | function intern() public returns (uint256) { 116 | function(uint256) internal returns (uint256) x; 117 | x(2); 118 | return 7; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/test/StdMath.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0 <0.9.0; 3 | 4 | import "../src/StdMath.sol"; 5 | import "../src/Test.sol"; 6 | 7 | contract StdMathMock is Test { 8 | function exposed_percentDelta(uint256 a, uint256 b) public pure returns (uint256) { 9 | return stdMath.percentDelta(a, b); 10 | } 11 | 12 | function exposed_percentDelta(int256 a, int256 b) public pure returns (uint256) { 13 | return stdMath.percentDelta(a, b); 14 | } 15 | } 16 | 17 | contract StdMathTest is Test { 18 | function test_GetAbs() external { 19 | assertEq(stdMath.abs(-50), 50); 20 | assertEq(stdMath.abs(50), 50); 21 | assertEq(stdMath.abs(-1337), 1337); 22 | assertEq(stdMath.abs(0), 0); 23 | 24 | assertEq(stdMath.abs(type(int256).min), (type(uint256).max >> 1) + 1); 25 | assertEq(stdMath.abs(type(int256).max), (type(uint256).max >> 1)); 26 | } 27 | 28 | function testFuzz_GetAbs(int256 a) external { 29 | uint256 manualAbs = getAbs(a); 30 | 31 | uint256 abs = stdMath.abs(a); 32 | 33 | assertEq(abs, manualAbs); 34 | } 35 | 36 | function test_GetDelta_Uint() external { 37 | assertEq(stdMath.delta(uint256(0), uint256(0)), 0); 38 | assertEq(stdMath.delta(uint256(0), uint256(1337)), 1337); 39 | assertEq(stdMath.delta(uint256(0), type(uint64).max), type(uint64).max); 40 | assertEq(stdMath.delta(uint256(0), type(uint128).max), type(uint128).max); 41 | assertEq(stdMath.delta(uint256(0), type(uint256).max), type(uint256).max); 42 | 43 | assertEq(stdMath.delta(0, uint256(0)), 0); 44 | assertEq(stdMath.delta(1337, uint256(0)), 1337); 45 | assertEq(stdMath.delta(type(uint64).max, uint256(0)), type(uint64).max); 46 | assertEq(stdMath.delta(type(uint128).max, uint256(0)), type(uint128).max); 47 | assertEq(stdMath.delta(type(uint256).max, uint256(0)), type(uint256).max); 48 | 49 | assertEq(stdMath.delta(1337, uint256(1337)), 0); 50 | assertEq(stdMath.delta(type(uint256).max, type(uint256).max), 0); 51 | assertEq(stdMath.delta(5000, uint256(1250)), 3750); 52 | } 53 | 54 | function testFuzz_GetDelta_Uint(uint256 a, uint256 b) external { 55 | uint256 manualDelta; 56 | if (a > b) { 57 | manualDelta = a - b; 58 | } else { 59 | manualDelta = b - a; 60 | } 61 | 62 | uint256 delta = stdMath.delta(a, b); 63 | 64 | assertEq(delta, manualDelta); 65 | } 66 | 67 | function test_GetDelta_Int() external { 68 | assertEq(stdMath.delta(int256(0), int256(0)), 0); 69 | assertEq(stdMath.delta(int256(0), int256(1337)), 1337); 70 | assertEq(stdMath.delta(int256(0), type(int64).max), type(uint64).max >> 1); 71 | assertEq(stdMath.delta(int256(0), type(int128).max), type(uint128).max >> 1); 72 | assertEq(stdMath.delta(int256(0), type(int256).max), type(uint256).max >> 1); 73 | 74 | assertEq(stdMath.delta(0, int256(0)), 0); 75 | assertEq(stdMath.delta(1337, int256(0)), 1337); 76 | assertEq(stdMath.delta(type(int64).max, int256(0)), type(uint64).max >> 1); 77 | assertEq(stdMath.delta(type(int128).max, int256(0)), type(uint128).max >> 1); 78 | assertEq(stdMath.delta(type(int256).max, int256(0)), type(uint256).max >> 1); 79 | 80 | assertEq(stdMath.delta(-0, int256(0)), 0); 81 | assertEq(stdMath.delta(-1337, int256(0)), 1337); 82 | assertEq(stdMath.delta(type(int64).min, int256(0)), (type(uint64).max >> 1) + 1); 83 | assertEq(stdMath.delta(type(int128).min, int256(0)), (type(uint128).max >> 1) + 1); 84 | assertEq(stdMath.delta(type(int256).min, int256(0)), (type(uint256).max >> 1) + 1); 85 | 86 | assertEq(stdMath.delta(int256(0), -0), 0); 87 | assertEq(stdMath.delta(int256(0), -1337), 1337); 88 | assertEq(stdMath.delta(int256(0), type(int64).min), (type(uint64).max >> 1) + 1); 89 | assertEq(stdMath.delta(int256(0), type(int128).min), (type(uint128).max >> 1) + 1); 90 | assertEq(stdMath.delta(int256(0), type(int256).min), (type(uint256).max >> 1) + 1); 91 | 92 | assertEq(stdMath.delta(1337, int256(1337)), 0); 93 | assertEq(stdMath.delta(type(int256).max, type(int256).max), 0); 94 | assertEq(stdMath.delta(type(int256).min, type(int256).min), 0); 95 | assertEq(stdMath.delta(type(int256).min, type(int256).max), type(uint256).max); 96 | assertEq(stdMath.delta(5000, int256(1250)), 3750); 97 | } 98 | 99 | function testFuzz_GetDelta_Int(int256 a, int256 b) external { 100 | uint256 absA = getAbs(a); 101 | uint256 absB = getAbs(b); 102 | uint256 absDelta = absA > absB ? absA - absB : absB - absA; 103 | 104 | uint256 manualDelta; 105 | if ((a >= 0 && b >= 0) || (a < 0 && b < 0)) { 106 | manualDelta = absDelta; 107 | } 108 | // (a < 0 && b >= 0) || (a >= 0 && b < 0) 109 | else { 110 | manualDelta = absA + absB; 111 | } 112 | 113 | uint256 delta = stdMath.delta(a, b); 114 | 115 | assertEq(delta, manualDelta); 116 | } 117 | 118 | function test_GetPercentDelta_Uint() external { 119 | StdMathMock stdMathMock = new StdMathMock(); 120 | 121 | assertEq(stdMath.percentDelta(uint256(0), uint256(1337)), 1e18); 122 | assertEq(stdMath.percentDelta(uint256(0), type(uint64).max), 1e18); 123 | assertEq(stdMath.percentDelta(uint256(0), type(uint128).max), 1e18); 124 | assertEq(stdMath.percentDelta(uint256(0), type(uint192).max), 1e18); 125 | 126 | assertEq(stdMath.percentDelta(1337, uint256(1337)), 0); 127 | assertEq(stdMath.percentDelta(type(uint192).max, type(uint192).max), 0); 128 | assertEq(stdMath.percentDelta(0, uint256(2500)), 1e18); 129 | assertEq(stdMath.percentDelta(2500, uint256(2500)), 0); 130 | assertEq(stdMath.percentDelta(5000, uint256(2500)), 1e18); 131 | assertEq(stdMath.percentDelta(7500, uint256(2500)), 2e18); 132 | 133 | vm.expectRevert(stdError.divisionError); 134 | stdMathMock.exposed_percentDelta(uint256(1), 0); 135 | } 136 | 137 | function testFuzz_GetPercentDelta_Uint(uint192 a, uint192 b) external { 138 | vm.assume(b != 0); 139 | uint256 manualDelta; 140 | if (a > b) { 141 | manualDelta = a - b; 142 | } else { 143 | manualDelta = b - a; 144 | } 145 | 146 | uint256 manualPercentDelta = manualDelta * 1e18 / b; 147 | uint256 percentDelta = stdMath.percentDelta(a, b); 148 | 149 | assertEq(percentDelta, manualPercentDelta); 150 | } 151 | 152 | function test_GetPercentDelta_Int() external { 153 | // We deploy a mock version so we can properly test the revert. 154 | StdMathMock stdMathMock = new StdMathMock(); 155 | 156 | assertEq(stdMath.percentDelta(int256(0), int256(1337)), 1e18); 157 | assertEq(stdMath.percentDelta(int256(0), -1337), 1e18); 158 | assertEq(stdMath.percentDelta(int256(0), type(int64).min), 1e18); 159 | assertEq(stdMath.percentDelta(int256(0), type(int128).min), 1e18); 160 | assertEq(stdMath.percentDelta(int256(0), type(int192).min), 1e18); 161 | assertEq(stdMath.percentDelta(int256(0), type(int64).max), 1e18); 162 | assertEq(stdMath.percentDelta(int256(0), type(int128).max), 1e18); 163 | assertEq(stdMath.percentDelta(int256(0), type(int192).max), 1e18); 164 | 165 | assertEq(stdMath.percentDelta(1337, int256(1337)), 0); 166 | assertEq(stdMath.percentDelta(type(int192).max, type(int192).max), 0); 167 | assertEq(stdMath.percentDelta(type(int192).min, type(int192).min), 0); 168 | 169 | assertEq(stdMath.percentDelta(type(int192).min, type(int192).max), 2e18); // rounds the 1 wei diff down 170 | assertEq(stdMath.percentDelta(type(int192).max, type(int192).min), 2e18 - 1); // rounds the 1 wei diff down 171 | assertEq(stdMath.percentDelta(0, int256(2500)), 1e18); 172 | assertEq(stdMath.percentDelta(2500, int256(2500)), 0); 173 | assertEq(stdMath.percentDelta(5000, int256(2500)), 1e18); 174 | assertEq(stdMath.percentDelta(7500, int256(2500)), 2e18); 175 | 176 | vm.expectRevert(stdError.divisionError); 177 | stdMathMock.exposed_percentDelta(int256(1), 0); 178 | } 179 | 180 | function testFuzz_GetPercentDelta_Int(int192 a, int192 b) external { 181 | vm.assume(b != 0); 182 | uint256 absA = getAbs(a); 183 | uint256 absB = getAbs(b); 184 | uint256 absDelta = absA > absB ? absA - absB : absB - absA; 185 | 186 | uint256 manualDelta; 187 | if ((a >= 0 && b >= 0) || (a < 0 && b < 0)) { 188 | manualDelta = absDelta; 189 | } 190 | // (a < 0 && b >= 0) || (a >= 0 && b < 0) 191 | else { 192 | manualDelta = absA + absB; 193 | } 194 | 195 | uint256 manualPercentDelta = manualDelta * 1e18 / absB; 196 | uint256 percentDelta = stdMath.percentDelta(a, b); 197 | 198 | assertEq(percentDelta, manualPercentDelta); 199 | } 200 | 201 | /*////////////////////////////////////////////////////////////////////////// 202 | HELPERS 203 | //////////////////////////////////////////////////////////////////////////*/ 204 | 205 | function getAbs(int256 a) private pure returns (uint256) { 206 | if (a < 0) { 207 | return a == type(int256).min ? uint256(type(int256).max) + 1 : uint256(-a); 208 | } 209 | 210 | return uint256(a); 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/test/Vm.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.0 <0.9.0; 3 | 4 | import {Test} from "../src/Test.sol"; 5 | import {Vm, VmSafe} from "../src/Vm.sol"; 6 | 7 | contract VmTest is Test { 8 | // This test ensures that functions are never accidentally removed from a Vm interface, or 9 | // inadvertently moved between Vm and VmSafe. This test must be updated each time a function is 10 | // added to or removed from Vm or VmSafe. 11 | function test_interfaceId() public { 12 | assertEq(type(VmSafe).interfaceId, bytes4(0x01ec102d), "VmSafe"); 13 | assertEq(type(Vm).interfaceId, bytes4(0xa63eed6b), "Vm"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/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 | -------------------------------------------------------------------------------- /foundry/lib/forge-std/test/fixtures/broadcast.log.json: -------------------------------------------------------------------------------- 1 | { 2 | "transactions": [ 3 | { 4 | "hash": "0xc6006863c267735a11476b7f15b15bc718e117e2da114a2be815dd651e1a509f", 5 | "type": "CALL", 6 | "contractName": "Test", 7 | "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 8 | "function": "multiple_arguments(uint256,address,uint256[]):(uint256)", 9 | "arguments": ["1", "0000000000000000000000000000000000001337", "[3,4]"], 10 | "tx": { 11 | "type": "0x02", 12 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 13 | "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 14 | "gas": "0x73b9", 15 | "value": "0x0", 16 | "data": "0x23e99187000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000013370000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000004", 17 | "nonce": "0x3", 18 | "accessList": [] 19 | } 20 | }, 21 | { 22 | "hash": "0xedf2b38d8d896519a947a1acf720f859bb35c0c5ecb8dd7511995b67b9853298", 23 | "type": "CALL", 24 | "contractName": "Test", 25 | "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 26 | "function": "inc():(uint256)", 27 | "arguments": [], 28 | "tx": { 29 | "type": "0x02", 30 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 31 | "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 32 | "gas": "0xdcb2", 33 | "value": "0x0", 34 | "data": "0x371303c0", 35 | "nonce": "0x4", 36 | "accessList": [] 37 | } 38 | }, 39 | { 40 | "hash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c", 41 | "type": "CALL", 42 | "contractName": "Test", 43 | "contractAddress": "0x7c6b4bbe207d642d98d5c537142d85209e585087", 44 | "function": "t(uint256):(uint256)", 45 | "arguments": ["1"], 46 | "tx": { 47 | "type": "0x02", 48 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 49 | "to": "0x7c6b4bbe207d642d98d5c537142d85209e585087", 50 | "gas": "0x8599", 51 | "value": "0x0", 52 | "data": "0xafe29f710000000000000000000000000000000000000000000000000000000000000001", 53 | "nonce": "0x5", 54 | "accessList": [] 55 | } 56 | } 57 | ], 58 | "receipts": [ 59 | { 60 | "transactionHash": "0x481dc86e40bba90403c76f8e144aa9ff04c1da2164299d0298573835f0991181", 61 | "transactionIndex": "0x0", 62 | "blockHash": "0xef0730448490304e5403be0fa8f8ce64f118e9adcca60c07a2ae1ab921d748af", 63 | "blockNumber": "0x1", 64 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 65 | "to": null, 66 | "cumulativeGasUsed": "0x13f3a", 67 | "gasUsed": "0x13f3a", 68 | "contractAddress": "0x5fbdb2315678afecb367f032d93f642f64180aa3", 69 | "logs": [], 70 | "status": "0x1", 71 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 72 | "effectiveGasPrice": "0xee6b2800" 73 | }, 74 | { 75 | "transactionHash": "0x6a187183545b8a9e7f1790e847139379bf5622baff2cb43acf3f5c79470af782", 76 | "transactionIndex": "0x0", 77 | "blockHash": "0xf3acb96a90071640c2a8c067ae4e16aad87e634ea8d8bbbb5b352fba86ba0148", 78 | "blockNumber": "0x2", 79 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 80 | "to": null, 81 | "cumulativeGasUsed": "0x45d80", 82 | "gasUsed": "0x45d80", 83 | "contractAddress": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 84 | "logs": [], 85 | "status": "0x1", 86 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 87 | "effectiveGasPrice": "0xee6b2800" 88 | }, 89 | { 90 | "transactionHash": "0x064ad173b4867bdef2fb60060bbdaf01735fbf10414541ea857772974e74ea9d", 91 | "transactionIndex": "0x0", 92 | "blockHash": "0x8373d02109d3ee06a0225f23da4c161c656ccc48fe0fcee931d325508ae73e58", 93 | "blockNumber": "0x3", 94 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 95 | "to": "0x4e59b44847b379578588920ca78fbf26c0b4956c", 96 | "cumulativeGasUsed": "0x45feb", 97 | "gasUsed": "0x45feb", 98 | "contractAddress": null, 99 | "logs": [], 100 | "status": "0x1", 101 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 102 | "effectiveGasPrice": "0xee6b2800" 103 | }, 104 | { 105 | "transactionHash": "0xc6006863c267735a11476b7f15b15bc718e117e2da114a2be815dd651e1a509f", 106 | "transactionIndex": "0x0", 107 | "blockHash": "0x16712fae5c0e18f75045f84363fb6b4d9a9fe25e660c4ce286833a533c97f629", 108 | "blockNumber": "0x4", 109 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 110 | "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 111 | "cumulativeGasUsed": "0x5905", 112 | "gasUsed": "0x5905", 113 | "contractAddress": null, 114 | "logs": [], 115 | "status": "0x1", 116 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 117 | "effectiveGasPrice": "0xee6b2800" 118 | }, 119 | { 120 | "transactionHash": "0xedf2b38d8d896519a947a1acf720f859bb35c0c5ecb8dd7511995b67b9853298", 121 | "transactionIndex": "0x0", 122 | "blockHash": "0x156b88c3eb9a1244ba00a1834f3f70de735b39e3e59006dd03af4fe7d5480c11", 123 | "blockNumber": "0x5", 124 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 125 | "to": "0xe7f1725e7734ce288f8367e1bb143e90bb3f0512", 126 | "cumulativeGasUsed": "0xa9c4", 127 | "gasUsed": "0xa9c4", 128 | "contractAddress": null, 129 | "logs": [], 130 | "status": "0x1", 131 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 132 | "effectiveGasPrice": "0xee6b2800" 133 | }, 134 | { 135 | "transactionHash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c", 136 | "transactionIndex": "0x0", 137 | "blockHash": "0xcf61faca67dbb2c28952b0b8a379e53b1505ae0821e84779679390cb8571cadb", 138 | "blockNumber": "0x6", 139 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 140 | "to": "0x7c6b4bbe207d642d98d5c537142d85209e585087", 141 | "cumulativeGasUsed": "0x66c5", 142 | "gasUsed": "0x66c5", 143 | "contractAddress": null, 144 | "logs": [ 145 | { 146 | "address": "0x7c6b4bbe207d642d98d5c537142d85209e585087", 147 | "topics": [ 148 | "0x0b2e13ff20ac7b474198655583edf70dedd2c1dc980e329c4fbb2fc0748b796b" 149 | ], 150 | "data": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000046865726500000000000000000000000000000000000000000000000000000000", 151 | "blockHash": "0xcf61faca67dbb2c28952b0b8a379e53b1505ae0821e84779679390cb8571cadb", 152 | "blockNumber": "0x6", 153 | "transactionHash": "0xa57e8e3981a6c861442e46c9471bd19cb3e21f9a8a6c63a72e7b5c47c6675a7c", 154 | "transactionIndex": "0x1", 155 | "logIndex": "0x0", 156 | "transactionLogIndex": "0x0", 157 | "removed": false 158 | } 159 | ], 160 | "status": "0x1", 161 | "logsBloom": "0x00000000000800000000000000000010000000000000000000000000000180000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100", 162 | "effectiveGasPrice": "0xee6b2800" 163 | }, 164 | { 165 | "transactionHash": "0x11fbb10230c168ca1e36a7e5c69a6dbcd04fd9e64ede39d10a83e36ee8065c16", 166 | "transactionIndex": "0x0", 167 | "blockHash": "0xf1e0ed2eda4e923626ec74621006ed50b3fc27580dc7b4cf68a07ca77420e29c", 168 | "blockNumber": "0x7", 169 | "from": "0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", 170 | "to": "0x0000000000000000000000000000000000001337", 171 | "cumulativeGasUsed": "0x5208", 172 | "gasUsed": "0x5208", 173 | "contractAddress": null, 174 | "logs": [], 175 | "status": "0x1", 176 | "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 177 | "effectiveGasPrice": "0xee6b2800" 178 | } 179 | ], 180 | "libraries": [ 181 | "src/Broadcast.t.sol:F:0x5fbdb2315678afecb367f032d93f642f64180aa3" 182 | ], 183 | "pending": [], 184 | "path": "broadcast/Broadcast.t.sol/31337/run-latest.json", 185 | "returns": {}, 186 | "timestamp": 1655140035 187 | } 188 | -------------------------------------------------------------------------------- /foundry/remappings.txt: -------------------------------------------------------------------------------- 1 | ds-test/=lib/forge-std/lib/ds-test/src/ 2 | forge-std/=lib/forge-std/src/ 3 | @solady/=lib/solady/src/ 4 | forge-gas-metering/=lib/forge-gas-metering/src/ 5 | -------------------------------------------------------------------------------- /foundry/script/DeployAndCall.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.20; 3 | 4 | import {Script} from "forge-std/Script.sol"; 5 | 6 | import {MockERC20} from "src/MockERC20.sol"; 7 | 8 | /// @dev Deploy the mock contract and mint to get reference gas measurements 9 | 10 | contract DeployAndCall is Script { 11 | uint256 constant MINT_ITERATIONS = 2; 12 | 13 | // To run the forge script and pass the target arguments, use the following command: 14 | // forge script script/DeployAndCall.s.sol:DeployAndCall --rpc-url $RPC_URL_SEPOLIA --broadcast -vvvv --sig "run(address, uint256)" 0x0000000000000000000000000000000000000001 0x0000000000000000000000000000000000000000000000000000000000000001 15 | // or 16 | // forge script script/DeployAndCall.s.sol:DeployAndCall --rpc-url $RPC_URL_SEPOLIA --broadcast -vvvv --sig "run(address, uint256)" 0x1111111111111111111111111111111111111111 0x1111111111111111111111111111111111111111111111111111111111111111 17 | function run(address recipient, uint256 amount) public { 18 | vm.startBroadcast(vm.envUint("PRIVATE_KEY")); 19 | MockERC20 mockERC20 = new MockERC20(); 20 | 21 | for (uint256 i = 0; i < MINT_ITERATIONS; i++) { 22 | mockERC20.mint(recipient, amount); 23 | } 24 | 25 | vm.stopBroadcast(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /foundry/src/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.20; 3 | 4 | import {ERC20} from "@solady/tokens/ERC20.sol"; 5 | 6 | /// @dev An ultra-minimalistic ERC20 token implementation. 7 | contract MockERC20 is ERC20 { 8 | constructor() {} 9 | 10 | function mint(address _to, uint256 _amount) external { 11 | _mint(_to, _amount); 12 | } 13 | 14 | /* -------------------------------------------------------------------------- */ 15 | /* METADATA */ 16 | /* -------------------------------------------------------------------------- */ 17 | 18 | function name() public pure override returns (string memory) { 19 | return "MockERC20"; 20 | } 21 | 22 | function symbol() public pure override returns (string memory) { 23 | return "M20"; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /foundry/test/MockERC20.ForgeGasMetering.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.20; 3 | 4 | import {Test} from "forge-std/Test.sol"; 5 | import {MainnetMetering} from "forge-gas-metering/MainnetMetering.sol"; 6 | 7 | import {MockERC20} from "src/MockERC20.sol"; 8 | 9 | /// @dev Compare emo.eth forge-gas-metering with Sepolia testnet txs 10 | /// Note: We can only use a single `meterCallAndLog` per test, hence the 4 tests. 11 | /// Note: There should be a difference of 600 gas between the two tests, 12 | /// due to the difference between zero and non-zero bytes in the call data. 13 | /// This is accurately caught by `meterCallAndLog`, even though there is a 14 | /// significant overhead in gas usage. 15 | 16 | contract MockERC20ForgeGasMetering is MainnetMetering, Test { 17 | MockERC20 mockERC20; 18 | 19 | function setUp() public { 20 | setUpMetering({verbose: false}); 21 | mockERC20 = new MockERC20(); 22 | } 23 | 24 | // 1. https://sepolia.etherscan.io/tx/0x886c7e6d86a3a06d0d6c5cba40579551f0bb83c646f0247da9e326a4291183b2 25 | // gas used: 67,839 26 | // 27 | // Test: 28 | // gas used: 63,879 29 | function test_mintManyZeroes_first_forgeGasMetering() public { 30 | address recipient = 0x0000000000000000000000000000000000000001; 31 | uint256 amount = 0x0000000000000000000000000000000000000000000000000000000000000001; 32 | 33 | meterCallAndLog({ 34 | from: address(0), // equivalent to address(this) 35 | to: address(mockERC20), 36 | callData: abi.encodeWithSelector(mockERC20.mint.selector, recipient, amount), 37 | value: 0, 38 | transaction: true, 39 | expectRevert: false, 40 | message: "mintManyZeroes first tx" 41 | }); 42 | } 43 | 44 | // 1. https://sepolia.etherscan.io/tx/0x6a985f8e7556af5cc90c0c9ef4af90d0b031f090732ea4e9c5e77debe056cd39 45 | // gas used: 68,439 46 | // 47 | // Test: 48 | // gas used: 64,479 49 | function test_mintNoZero_first_forgeGasMetering() public { 50 | address recipient = 0x1111111111111111111111111111111111111111; 51 | uint256 amount = 0x1111111111111111111111111111111111111111111111111111111111111111; 52 | 53 | meterCallAndLog({ 54 | from: address(0), 55 | to: address(mockERC20), 56 | callData: abi.encodeWithSelector(mockERC20.mint.selector, recipient, amount), 57 | value: 0, 58 | transaction: true, 59 | expectRevert: false, 60 | message: "mintNoZero first tx" 61 | }); 62 | } 63 | 64 | // 2. https://sepolia.etherscan.io/tx/0xa30ca53c4856957f95fdbf4885e0e5001892af742335301125d5ef65df867586 65 | // gas used: 33,639 66 | // 67 | // Test: 68 | // gas used: 21,579 69 | function test_mintManyZeroes_second_forgeGasMetering() public { 70 | address recipient = 0x0000000000000000000000000000000000000001; 71 | uint256 amount = 0x0000000000000000000000000000000000000000000000000000000000000001; 72 | 73 | mockERC20.mint(recipient, amount); 74 | 75 | meterCallAndLog({ 76 | from: address(0), // equivalent to address(this) 77 | to: address(mockERC20), 78 | callData: abi.encodeWithSelector(mockERC20.mint.selector, recipient, amount), 79 | value: 0, 80 | transaction: true, 81 | expectRevert: false, 82 | message: "mintManyZeroes second tx" 83 | }); 84 | } 85 | 86 | // 2. https://sepolia.etherscan.io/tx/0x91cc033349873f65cf69e1b967b17ea983eb266a929c044c74ef8de52697f25e 87 | // gas used: 34,239 88 | // 89 | // Test: 90 | // gas used: 22,179 91 | function test_mintNoZero_second_forgeGasMetering() public { 92 | address recipient = 0x1111111111111111111111111111111111111111; 93 | uint256 amount = 0x1111111111111111111111111111111111111111111111111111111111111111; 94 | 95 | mockERC20.mint(recipient, amount); 96 | 97 | meterCallAndLog({ 98 | from: address(0), 99 | to: address(mockERC20), 100 | callData: abi.encodeWithSelector(mockERC20.mint.selector, recipient, amount), 101 | value: 0, 102 | transaction: true, 103 | expectRevert: false, 104 | message: "mintNoZero second tx" 105 | }); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /foundry/test/MockERC20.Foundry.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.20; 3 | 4 | import {Test} from "forge-std/Test.sol"; 5 | 6 | import {MockERC20} from "src/MockERC20.sol"; 7 | 8 | /// @dev Compare Forge gas measurements with Sepolia testnet txs 9 | /// Note: There should be a difference of 600 gas between the two tests, 10 | /// due to the difference between zero and non-zero bytes in the call data. 11 | /// However, Forge fails to measure the difference and returns the exact same 12 | /// gas usage for both tests. 13 | /// Edit: Forge precisely measures gas costs with `--isolate` flag. 14 | /// See https://github.com/foundry-rs/foundry/pull/7186 15 | 16 | contract MockERC20Foundry is Test { 17 | MockERC20 mockERC20; 18 | 19 | uint256 constant MINT_ITERATIONS = 2; 20 | 21 | function setUp() public { 22 | mockERC20 = new MockERC20(); 23 | } 24 | 25 | // 1. https://sepolia.etherscan.io/tx/0x886c7e6d86a3a06d0d6c5cba40579551f0bb83c646f0247da9e326a4291183b2 26 | // gas used: 67,839 27 | // 2. https://sepolia.etherscan.io/tx/0xa30ca53c4856957f95fdbf4885e0e5001892af742335301125d5ef65df867586 28 | // gas used: 33,639 29 | // 30 | // Test (old behavior | --isolate): 31 | // 1. 46,495 | 67,839 32 | // 2. 2,695 | 33,639 33 | function test_mintManyZeroes_native() public { 34 | address recipient = 0x0000000000000000000000000000000000000001; 35 | uint256 amount = 0x0000000000000000000000000000000000000000000000000000000000000001; 36 | 37 | for (uint256 i = 0; i < MINT_ITERATIONS; i++) { 38 | mockERC20.mint(recipient, amount); 39 | } 40 | } 41 | 42 | // 1. https://sepolia.etherscan.io/tx/0x6a985f8e7556af5cc90c0c9ef4af90d0b031f090732ea4e9c5e77debe056cd39 43 | // gas used: 68,439 44 | // 2. https://sepolia.etherscan.io/tx/0x91cc033349873f65cf69e1b967b17ea983eb266a929c044c74ef8de52697f25e 45 | // gas used: 34,239 46 | // 47 | // Test (old behavior | --isolate): 48 | // 1. 46,495 | 68,439 49 | // 2. 2,695 | 34,239 50 | function test_mintNoZero_native() public { 51 | address recipient = 0x1111111111111111111111111111111111111111; 52 | uint256 amount = 0x1111111111111111111111111111111111111111111111111111111111111111; 53 | 54 | for (uint256 i = 0; i < MINT_ITERATIONS; i++) { 55 | mockERC20.mint(recipient, amount); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /hardhat/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | 4 | # Hardhat files 5 | /cache 6 | /artifacts 7 | 8 | # TypeChain files 9 | /typechain 10 | /typechain-types 11 | 12 | # solidity-coverage files 13 | /coverage 14 | /coverage.json 15 | -------------------------------------------------------------------------------- /hardhat/README.md: -------------------------------------------------------------------------------- 1 | # Sample Hardhat Project 2 | 3 | This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, and a script that deploys that contract. 4 | 5 | Try running some of the following tasks: 6 | 7 | ```shell 8 | npx hardhat help 9 | npx hardhat test 10 | REPORT_GAS=true npx hardhat test 11 | npx hardhat node 12 | npx hardhat run scripts/deploy.ts 13 | ``` 14 | -------------------------------------------------------------------------------- /hardhat/contracts/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.20; 3 | 4 | import {ERC20} from "solady/src/tokens/ERC20.sol"; 5 | 6 | /// @dev An ultra-minimalistic ERC20 token implementation. 7 | contract MockERC20 is ERC20 { 8 | constructor() {} 9 | 10 | function mint(address _to, uint256 _amount) external { 11 | _mint(_to, _amount); 12 | } 13 | 14 | /* -------------------------------------------------------------------------- */ 15 | /* METADATA */ 16 | /* -------------------------------------------------------------------------- */ 17 | 18 | function name() public pure override returns (string memory) { 19 | return "MockERC20"; 20 | } 21 | 22 | function symbol() public pure override returns (string memory) { 23 | return "M20"; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /hardhat/hardhat.config.ts: -------------------------------------------------------------------------------- 1 | import { HardhatUserConfig } from 'hardhat/config'; 2 | import '@nomicfoundation/hardhat-toolbox-viem'; 3 | 4 | const config: HardhatUserConfig = { 5 | solidity: { 6 | version: '0.8.20', 7 | settings: { 8 | optimizer: { 9 | enabled: true, 10 | runs: 200, 11 | }, 12 | }, 13 | }, 14 | }; 15 | 16 | export default config; 17 | -------------------------------------------------------------------------------- /hardhat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hardhat", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@nomicfoundation/hardhat-network-helpers": "^1.0.0", 14 | "@nomicfoundation/hardhat-toolbox-viem": "^2.0.0", 15 | "@nomicfoundation/hardhat-viem": "^1.0.0", 16 | "@types/mocha": "^10.0.6", 17 | "@types/node": ">=16.0.0", 18 | "hardhat": "^2.20.1", 19 | "hardhat-gas-reporter": "^1.0.8", 20 | "ts-node": ">=8.0.0", 21 | "typescript": "~5.0.4", 22 | "viem": "^1.15.1" 23 | }, 24 | "dependencies": { 25 | "solady": "^0.0.168" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /hardhat/test/MockERC20.ts: -------------------------------------------------------------------------------- 1 | import { loadFixture } from '@nomicfoundation/hardhat-toolbox-viem/network-helpers'; 2 | import { viem } from 'hardhat'; 3 | 4 | const MINT_ITERATIONS = 2; 5 | 6 | describe('MockERC20', function () { 7 | const deployMockERC20Fixture = async () => { 8 | const mockERC20 = await viem.deployContract('MockERC20', []); 9 | console.log(mockERC20); 10 | const publicClient = await viem.getPublicClient(); 11 | 12 | const mintMultipleAndReturnGasUsed = async ( 13 | recipient: `0x${string}`, 14 | amount: bigint 15 | ): Promise => { 16 | let gasUsed = []; 17 | 18 | for (let i = 0; i < MINT_ITERATIONS; i++) { 19 | const txHash = await mockERC20.write.mint([recipient, amount]); 20 | const receipt = await publicClient.waitForTransactionReceipt({ 21 | hash: txHash, 22 | }); 23 | gasUsed.push(receipt.gasUsed.toString()); 24 | } 25 | 26 | return gasUsed; 27 | }; 28 | 29 | return { mintMultipleAndReturnGasUsed }; 30 | }; 31 | 32 | describe('Mint', function () { 33 | it('Many zero bytes', async function () { 34 | const { mintMultipleAndReturnGasUsed } = await loadFixture( 35 | deployMockERC20Fixture 36 | ); 37 | 38 | const gasUsed = await mintMultipleAndReturnGasUsed( 39 | '0x0000000000000000000000000000000000000001', 40 | BigInt( 41 | '0x0000000000000000000000000000000000000000000000000000000000000001' 42 | ) 43 | ); 44 | 45 | console.log( 46 | 'Gas used with many zero bytes:\n', 47 | gasUsed.map((gas, i) => `Tx ${i + 1}: ${gas}`).join('\n') 48 | ); 49 | }); 50 | 51 | it('No zero byte', async function () { 52 | const { mintMultipleAndReturnGasUsed } = await loadFixture( 53 | deployMockERC20Fixture 54 | ); 55 | 56 | const gasUsed = await mintMultipleAndReturnGasUsed( 57 | '0x1111111111111111111111111111111111111111', 58 | BigInt( 59 | '0x1111111111111111111111111111111111111111111111111111111111111111' 60 | ) 61 | ); 62 | 63 | console.log( 64 | 'Gas used with no zero bytes:\n', 65 | gasUsed.map((gas, i) => `Tx ${i + 1}: ${gas}`).join('\n') 66 | ); 67 | }); 68 | }); 69 | }); 70 | -------------------------------------------------------------------------------- /hardhat/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2020", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tevm/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /tevm/constants.ts: -------------------------------------------------------------------------------- 1 | // See https://sepolia.etherscan.io/address/0x1823FbFF49f731061E8216ad2467112C0469cBFD#code 2 | export const MOCKERC20_BYTECODE = 3 | '0x608060405234801561001057600080fd5b50600436106100cf5760003560e01c806340c10f191161008c57806395d89b411161006657806395d89b41146101ba578063a9059cbb146101d9578063d505accf146101ec578063dd62ed3e146101ff57600080fd5b806340c10f191461015957806370a082311461016e5780637ecebe001461019457600080fd5b806306fdde03146100d4578063095ea7b3146100f257806318160ddd1461011557806323b872dd1461012f578063313ce567146101425780633644e51514610151575b600080fd5b6100dc610228565b6040516100e9919061066a565b60405180910390f35b6101056101003660046106d4565b61024b565b60405190151581526020016100e9565b6805345cdf77eb68f44c545b6040519081526020016100e9565b61010561013d3660046106fe565b61029e565b604051601281526020016100e9565b61012161035c565b61016c6101673660046106d4565b6103d9565b005b61012161017c36600461073a565b6387a211a2600c908152600091909152602090205490565b6101216101a236600461073a565b6338377508600c908152600091909152602090205490565b60408051808201909152600381526204d32360ec1b60208201526100dc565b6101056101e73660046106d4565b6103e7565b61016c6101fa36600461075c565b610462565b61012161020d3660046107cf565b602052637f5e9f20600c908152600091909152603490205490565b60408051808201909152600981526804d6f636b45524332360bc1b602082015290565b600082602052637f5e9f20600c5233600052816034600c205581600052602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560206000a350600192915050565b60008360601b33602052637f5e9f208117600c526034600c20805460018101156102de57808511156102d8576313be252b6000526004601cfd5b84810382555b50506387a211a28117600c526020600c208054808511156103075763f4d678b86000526004601cfd5b84810382555050836000526020600c208381540181555082602052600c5160601c8160601c7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a3505060019392505050565b600080610367610228565b8051906020012090506040517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81528160208201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015260a081209250505090565b6103e382826105eb565b5050565b60006387a211a2600c52336000526020600c208054808411156104125763f4d678b86000526004601cfd5b83810382555050826000526020600c208281540181555081602052600c5160601c337fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a350600192915050565b600061046c610228565b8051906020012090508442111561048b57631a15a3cc6000526004601cfd5b6040518860601b60601c98508760601b60601c975065383775081901600e52886000526020600c2080547f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f83528360208401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604084015246606084015230608084015260a08320602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c983528a60208401528960408401528860608401528060808401528760a084015260c08320604e526042602c206000528660ff1660205285604052846060526020806080600060015afa8b3d51146105975763ddafbaef6000526004601cfd5b0190556303faf4f960a51b88176040526034602c2087905587897f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925602060608501a360405250506000606052505050505050565b6805345cdf77eb68f44c548181018181101561060f5763e5cfe9576000526004601cfd5b806805345cdf77eb68f44c5550506387a211a2600c52816000526020600c208181540181555080602052600c5160601c60007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef602080a35050565b600060208083528351808285015260005b818110156106975785810183015185820160400152820161067b565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b03811681146106cf57600080fd5b919050565b600080604083850312156106e757600080fd5b6106f0836106b8565b946020939093013593505050565b60008060006060848603121561071357600080fd5b61071c846106b8565b925061072a602085016106b8565b9150604084013590509250925092565b60006020828403121561074c57600080fd5b610755826106b8565b9392505050565b600080600080600080600060e0888a03121561077757600080fd5b610780886106b8565b965061078e602089016106b8565b95506040880135945060608801359350608088013560ff811681146107b257600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156107e257600080fd5b6107eb836106b8565b91506107f9602084016106b8565b9050925092905056fea26469706673582212204aefe49a90febe3d6555adfa8ada1e9c46ee52718d61d970224810e1d866d3fb64736f6c63430008140033'; 4 | export const MOCKERC20_ABI = [ 5 | { 6 | inputs: [ 7 | { internalType: 'address', name: '_to', type: 'address' }, 8 | { internalType: 'uint256', name: '_amount', type: 'uint256' }, 9 | ], 10 | name: 'mint', 11 | outputs: [], 12 | stateMutability: 'nonpayable', 13 | type: 'function', 14 | }, 15 | ]; 16 | -------------------------------------------------------------------------------- /tevm/index.ts: -------------------------------------------------------------------------------- 1 | // Run from /tevm with: pnpm ts-node index.ts 2 | import { TevmClient, createMemoryClient } from 'tevm'; 3 | import { MOCKERC20_BYTECODE, MOCKERC20_ABI } from './constants'; 4 | 5 | const MINT_ITERATIONS = 2; 6 | 7 | /* ------------------------------- BENCHMARKS ------------------------------- */ 8 | /** 9 | * Results with many zeroes: { 10 | recipient: '0x0000000000000000000000000000000000000001', 11 | amount: '0x0000000000000000000000000000000000000000000000000000000000000001', 12 | gasUsed: [ '46495', '2695' ] 13 | } 14 | 15 | * Results with no zeroes: { 16 | recipient: '0x1111111111111111111111111111111111111111', 17 | amount: '0x1111111111111111111111111111111111111111111111111111111111111111', 18 | gasUsed: [ '46495', '2695' ] 19 | } 20 | */ 21 | 22 | /* ---------------------------------- TEVM ---------------------------------- */ 23 | // Batch mint provided tokens ids/amounts pairs 24 | const mintTwice = async (recipient: string, amount: string) => { 25 | const caller = `0x${'1'.repeat(40)}` as const; 26 | const tevm = await createMemoryClient({ 27 | fork: { 28 | url: 'https://eth.llamarpc.com', 29 | }, 30 | }); 31 | 32 | const token = '0x171593d3E5Bc8A2E869600F951ed532B9780Cbd2'; 33 | await tevm.setAccount({ 34 | address: token, 35 | deployedBytecode: MOCKERC20_BYTECODE, 36 | }); 37 | 38 | let gasUsed: string[] = []; 39 | for (let i = 0; i < MINT_ITERATIONS; i++) { 40 | const { executionGasUsed, errors } = await tevm.contract({ 41 | caller, 42 | to: token, 43 | abi: MOCKERC20_ABI, 44 | functionName: 'mint', 45 | args: [recipient, amount], 46 | createTransaction: true, 47 | }); 48 | 49 | if (errors) console.log('Errors:', errors); 50 | gasUsed.push(executionGasUsed.toString()); 51 | } 52 | 53 | return { recipient, amount, gasUsed }; 54 | }; 55 | 56 | /* ---------------------------------- MAIN ---------------------------------- */ 57 | const main = async () => { 58 | const withManyZeroes = [ 59 | '0x0000000000000000000000000000000000000001', 60 | '0x0000000000000000000000000000000000000000000000000000000000000001', 61 | ]; 62 | const withNoZero = [ 63 | '0x1111111111111111111111111111111111111111', 64 | '0x1111111111111111111111111111111111111111111111111111111111111111', 65 | ]; 66 | 67 | const resultsWithManyZeroes = await mintTwice( 68 | withManyZeroes[0], 69 | withManyZeroes[1], 70 | ); 71 | const resultsWithNoZero = await mintTwice(withNoZero[0], withNoZero[1]); 72 | 73 | console.log('Results with many zeroes:', resultsWithManyZeroes); 74 | console.log('Results with no zeroes:', resultsWithNoZero); 75 | }; 76 | 77 | main(); 78 | -------------------------------------------------------------------------------- /tevm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tevm-minimal-repro", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "keywords": [], 7 | "author": "", 8 | "license": "ISC", 9 | "dependencies": { 10 | "node-ts": "^6.0.1", 11 | "tevm": "1.0.0-next.39" 12 | }, 13 | "devDependencies": { 14 | "@types/node": "^20.11.17", 15 | "ts-node": "^10.9.2", 16 | "typescript": "^5.3.3" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tevm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "allowJs": true, 5 | "skipLibCheck": true, 6 | "strict": true, 7 | "noEmit": true, 8 | "esModuleInterop": true, 9 | "module": "CommonJS", 10 | "resolveJsonModule": true, 11 | "isolatedModules": true, 12 | "jsx": "preserve", 13 | "incremental": true, 14 | "outDir": "./dist" 15 | }, 16 | "include": ["**/*.ts", "**/*.tsx"], 17 | "exclude": ["node_modules"] 18 | } 19 | --------------------------------------------------------------------------------