├── .gitattributes ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── foundry.toml ├── lib ├── forge-std │ ├── .github │ │ └── workflows │ │ │ └── tests.yml │ ├── .gitignore │ ├── .gitmodules │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── lib │ │ └── ds-test │ │ │ ├── .gitignore │ │ │ ├── LICENSE │ │ │ ├── Makefile │ │ │ ├── default.nix │ │ │ ├── demo │ │ │ └── demo.sol │ │ │ └── src │ │ │ └── test.sol │ └── src │ │ ├── Script.sol │ │ ├── Test.sol │ │ ├── Vm.sol │ │ ├── console.sol │ │ ├── console2.sol │ │ └── test │ │ ├── Script.t.sol │ │ ├── StdAssertions.t.sol │ │ ├── StdCheats.t.sol │ │ ├── StdError.t.sol │ │ ├── StdMath.t.sol │ │ └── StdStorage.t.sol └── solmate │ ├── .gas-snapshot │ ├── .gitattributes │ ├── .github │ ├── pull_request_template.md │ └── workflows │ │ └── tests.yml │ ├── .gitignore │ ├── .gitmodules │ ├── .prettierignore │ ├── .prettierrc │ ├── .vscode │ └── settings.json │ ├── LICENSE │ ├── README.md │ ├── audits │ └── v6-Fixed-Point-Solutions.pdf │ ├── foundry.toml │ ├── lib │ └── ds-test │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── default.nix │ │ ├── demo │ │ └── demo.sol │ │ └── src │ │ └── test.sol │ ├── package-lock.json │ ├── package.json │ └── src │ ├── auth │ ├── Auth.sol │ ├── Owned.sol │ └── authorities │ │ ├── MultiRolesAuthority.sol │ │ └── RolesAuthority.sol │ ├── mixins │ └── ERC4626.sol │ ├── test │ ├── Auth.t.sol │ ├── Bytes32AddressLib.t.sol │ ├── CREATE3.t.sol │ ├── DSTestPlus.t.sol │ ├── ERC1155.t.sol │ ├── ERC20.t.sol │ ├── ERC4626.t.sol │ ├── ERC721.t.sol │ ├── FixedPointMathLib.t.sol │ ├── MultiRolesAuthority.t.sol │ ├── Owned.t.sol │ ├── ReentrancyGuard.t.sol │ ├── RolesAuthority.t.sol │ ├── SSTORE2.t.sol │ ├── SafeCastLib.t.sol │ ├── SafeTransferLib.t.sol │ ├── WETH.t.sol │ └── utils │ │ ├── DSInvariantTest.sol │ │ ├── DSTestPlus.sol │ │ ├── Hevm.sol │ │ ├── mocks │ │ ├── MockAuthChild.sol │ │ ├── MockAuthority.sol │ │ ├── MockERC1155.sol │ │ ├── MockERC20.sol │ │ ├── MockERC4626.sol │ │ ├── MockERC721.sol │ │ └── MockOwned.sol │ │ └── weird-tokens │ │ ├── MissingReturnToken.sol │ │ ├── ReturnsFalseToken.sol │ │ ├── ReturnsGarbageToken.sol │ │ ├── ReturnsTooLittleToken.sol │ │ ├── ReturnsTooMuchToken.sol │ │ ├── ReturnsTwoToken.sol │ │ └── RevertingToken.sol │ ├── tokens │ ├── ERC1155.sol │ ├── ERC20.sol │ ├── ERC721.sol │ └── WETH.sol │ └── utils │ ├── Bytes32AddressLib.sol │ ├── CREATE3.sol │ ├── FixedPointMathLib.sol │ ├── ReentrancyGuard.sol │ ├── SSTORE2.sol │ ├── SafeCastLib.sol │ └── SafeTransferLib.sol └── src ├── RemcoMathLib.sol └── test ├── FullMath.sol └── RemcoMathLib.t.sol /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | cache/ 2 | out/ 3 | .vscode/ -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # include .env file and export its env vars 2 | # (-include to ignore error if it does not exist) 3 | -include .env 4 | 5 | # deps 6 | install:; forge install 7 | update:; forge update 8 | 9 | # Build & test 10 | build :; forge build 11 | test :; forge test 12 | trace :; forge test -vvv 13 | clean :; forge clean 14 | snapshot :; forge snapshot 15 | fmt :; forge fmt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RemcoMath - WORK IN PROGRESS! 2 | 3 | RemcoMathLib is a **Gas optimized** FullMath implementation inspired by **Remco Bloemen**. 4 | 5 | ```ml 6 | src 7 | ├─ RemcoMathLib — "Gas optimized FullMath Implementation" 8 | ``` 9 | 10 | ## Gas Comparison 11 | 12 | ```ml 13 | ╭───────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ 14 | │ FullMath contract ┆ ┆ ┆ ┆ ┆ │ 15 | ╞═══════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ 16 | │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ 17 | ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ 18 | │ 74748 ┆ 431 ┆ ┆ ┆ ┆ │ 19 | ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ 20 | │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ 21 | ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ 22 | │ mulDiv ┆ 437 ┆ 588 ┆ 588 ┆ 739 ┆ 2 │ 23 | ╰───────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ 24 | ╭───────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ 25 | │ RemcoMathLib contract ┆ ┆ ┆ ┆ ┆ │ 26 | ╞═══════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ 27 | │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ 28 | ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ 29 | │ 67942 ┆ 397 ┆ ┆ ┆ ┆ │ 30 | ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ 31 | │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ 32 | ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ 33 | │ mulDiv ┆ 331 ┆ 504 ┆ 504 ┆ 678 ┆ 2 │ 34 | ╰───────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ 35 | ``` 36 | 37 | ## Installation 38 | 39 | To install with [DappTools](https://github.com/dapphub/dapptools): 40 | 41 | ``` 42 | dapp install 0xClandestine/RemcoMath 43 | ``` 44 | 45 | To install with [Foundry](https://github.com/gakonst/foundry): 46 | 47 | ``` 48 | forge install 0xClandestine/RemcoMath 49 | ``` 50 | 51 | ## Local development 52 | 53 | This project uses [Foundry](https://github.com/gakonst/foundry) as the development framework. 54 | 55 | ### Dependencies 56 | 57 | ``` 58 | make update 59 | ``` 60 | 61 | ### Compilation 62 | 63 | ``` 64 | make build 65 | ``` 66 | 67 | ### Testing 68 | 69 | ``` 70 | make test 71 | ``` 72 | 73 | 74 | ## Acknowledgements 75 | 76 | These contracts were inspired by or directly modified from many sources, primarily: 77 | 78 | - [Remco Bloemen](https://xn--2-umb.com/21/muldiv/index.html) 79 | 80 | 81 | ## Disclaimer 82 | 83 | _These smart contracts are being provided as is. No guarantee, representation or warranty is being made, express or implied, as to the safety or correctness of the user interface or the smart contracts. They have not been audited and as such there can be no assurance they will work as intended, and users may experience delays, failures, errors, omissions, loss of transmitted information or loss of funds. The creators are not liable for any of the foregoing. Users should proceed with caution and use at their own risk._ 84 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [default] 2 | src = 'src' 3 | out = 'out' 4 | libs = ['lib'] 5 | 6 | # See more config options https://github.com/gakonst/foundry/tree/master/config -------------------------------------------------------------------------------- /lib/forge-std/.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | check: 6 | name: Foundry project 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | with: 11 | submodules: recursive 12 | 13 | - name: Install Foundry 14 | uses: onbjerg/foundry-toolchain@v1 15 | with: 16 | version: nightly 17 | 18 | - name: Install dependencies 19 | run: forge install 20 | - name: Run tests 21 | run: forge test -vvv 22 | - name: Build Test with older solc versions 23 | run: | 24 | forge build --contracts src/Test.sol --use solc:0.8.0 25 | forge build --contracts src/Test.sol --use solc:0.7.0 26 | forge build --contracts src/Test.sol --use solc:0.6.0 27 | -------------------------------------------------------------------------------- /lib/forge-std/.gitignore: -------------------------------------------------------------------------------- 1 | cache/ 2 | out/ 3 | .vscode 4 | .idea -------------------------------------------------------------------------------- /lib/forge-std/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/ds-test"] 2 | path = lib/ds-test 3 | url = https://github.com/dapphub/ds-test 4 | -------------------------------------------------------------------------------- /lib/forge-std/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022 Brock Elmore 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE O THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE.R 26 | -------------------------------------------------------------------------------- /lib/forge-std/README.md: -------------------------------------------------------------------------------- 1 | # Forge Standard Library • [![tests](https://github.com/brockelmore/forge-std/actions/workflows/tests.yml/badge.svg)](https://github.com/brockelmore/forge-std/actions/workflows/tests.yml) 2 | 3 | Forge Standard Library is a collection of helpful contracts 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 | -------------------------------------------------------------------------------- /lib/forge-std/lib/ds-test/.gitignore: -------------------------------------------------------------------------------- 1 | /.dapple 2 | /build 3 | /out 4 | -------------------------------------------------------------------------------- /lib/forge-std/lib/ds-test/Makefile: -------------------------------------------------------------------------------- 1 | all:; dapp build 2 | 3 | test: 4 | -dapp --use solc:0.4.23 build 5 | -dapp --use solc:0.4.26 build 6 | -dapp --use solc:0.5.17 build 7 | -dapp --use solc:0.6.12 build 8 | -dapp --use solc:0.7.5 build 9 | 10 | demo: 11 | DAPP_SRC=demo dapp --use solc:0.7.5 build 12 | -hevm dapp-test --verbose 3 13 | 14 | .PHONY: test demo 15 | -------------------------------------------------------------------------------- /lib/forge-std/lib/ds-test/default.nix: -------------------------------------------------------------------------------- 1 | { solidityPackage, dappsys }: solidityPackage { 2 | name = "ds-test"; 3 | src = ./src; 4 | } 5 | -------------------------------------------------------------------------------- /lib/forge-std/lib/ds-test/demo/demo.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import "../src/test.sol"; 5 | 6 | contract DemoTest is DSTest { 7 | function test_this() public pure { 8 | require(true); 9 | } 10 | function test_logs() public { 11 | emit log("-- log(string)"); 12 | emit log("a string"); 13 | 14 | emit log("-- log_named_uint(string, uint)"); 15 | emit log_named_uint("uint", 512); 16 | 17 | emit log("-- log_named_int(string, int)"); 18 | emit log_named_int("int", -512); 19 | 20 | emit log("-- log_named_address(string, address)"); 21 | emit log_named_address("address", address(this)); 22 | 23 | emit log("-- log_named_bytes32(string, bytes32)"); 24 | emit log_named_bytes32("bytes32", "a string"); 25 | 26 | emit log("-- log_named_bytes(string, bytes)"); 27 | emit log_named_bytes("bytes", hex"cafefe"); 28 | 29 | emit log("-- log_named_string(string, string)"); 30 | emit log_named_string("string", "a string"); 31 | 32 | emit log("-- log_named_decimal_uint(string, uint, uint)"); 33 | emit log_named_decimal_uint("decimal uint", 1.0e18, 18); 34 | 35 | emit log("-- log_named_decimal_int(string, int, uint)"); 36 | emit log_named_decimal_int("decimal int", -1.0e18, 18); 37 | } 38 | event log_old_named_uint(bytes32,uint); 39 | function test_old_logs() public { 40 | emit log_old_named_uint("key", 500); 41 | emit log_named_bytes32("bkey", "val"); 42 | } 43 | function test_trace() public view { 44 | this.echo("string 1", "string 2"); 45 | } 46 | function test_multiline() public { 47 | emit log("a multiline\\nstring"); 48 | emit log("a multiline string"); 49 | emit log_bytes("a string"); 50 | emit log_bytes("a multiline\nstring"); 51 | emit log_bytes("a multiline\\nstring"); 52 | emit logs(hex"0000"); 53 | emit log_named_bytes("0x0000", hex"0000"); 54 | emit logs(hex"ff"); 55 | } 56 | function echo(string memory s1, string memory s2) public pure 57 | returns (string memory, string memory) 58 | { 59 | return (s1, s2); 60 | } 61 | 62 | function prove_this(uint x) public { 63 | emit log_named_uint("sym x", x); 64 | assertGt(x + 1, 0); 65 | } 66 | 67 | function test_logn() public { 68 | assembly { 69 | log0(0x01, 0x02) 70 | log1(0x01, 0x02, 0x03) 71 | log2(0x01, 0x02, 0x03, 0x04) 72 | log3(0x01, 0x02, 0x03, 0x04, 0x05) 73 | } 74 | } 75 | 76 | event MyEvent(uint, uint indexed, uint, uint indexed); 77 | function test_events() public { 78 | emit MyEvent(1, 2, 3, 4); 79 | } 80 | 81 | function test_asserts() public { 82 | string memory err = "this test has failed!"; 83 | emit log("## assertTrue(bool)\n"); 84 | assertTrue(false); 85 | emit log("\n"); 86 | assertTrue(false, err); 87 | 88 | emit log("\n## assertEq(address,address)\n"); 89 | assertEq(address(this), msg.sender); 90 | emit log("\n"); 91 | assertEq(address(this), msg.sender, err); 92 | 93 | emit log("\n## assertEq32(bytes32,bytes32)\n"); 94 | assertEq32("bytes 1", "bytes 2"); 95 | emit log("\n"); 96 | assertEq32("bytes 1", "bytes 2", err); 97 | 98 | emit log("\n## assertEq(bytes32,bytes32)\n"); 99 | assertEq32("bytes 1", "bytes 2"); 100 | emit log("\n"); 101 | assertEq32("bytes 1", "bytes 2", err); 102 | 103 | emit log("\n## assertEq(uint,uint)\n"); 104 | assertEq(uint(0), 1); 105 | emit log("\n"); 106 | assertEq(uint(0), 1, err); 107 | 108 | emit log("\n## assertEq(int,int)\n"); 109 | assertEq(-1, -2); 110 | emit log("\n"); 111 | assertEq(-1, -2, err); 112 | 113 | emit log("\n## assertEqDecimal(int,int,uint)\n"); 114 | assertEqDecimal(-1.0e18, -1.1e18, 18); 115 | emit log("\n"); 116 | assertEqDecimal(-1.0e18, -1.1e18, 18, err); 117 | 118 | emit log("\n## assertEqDecimal(uint,uint,uint)\n"); 119 | assertEqDecimal(uint(1.0e18), 1.1e18, 18); 120 | emit log("\n"); 121 | assertEqDecimal(uint(1.0e18), 1.1e18, 18, err); 122 | 123 | emit log("\n## assertGt(uint,uint)\n"); 124 | assertGt(uint(0), 0); 125 | emit log("\n"); 126 | assertGt(uint(0), 0, err); 127 | 128 | emit log("\n## assertGt(int,int)\n"); 129 | assertGt(-1, -1); 130 | emit log("\n"); 131 | assertGt(-1, -1, err); 132 | 133 | emit log("\n## assertGtDecimal(int,int,uint)\n"); 134 | assertGtDecimal(-2.0e18, -1.1e18, 18); 135 | emit log("\n"); 136 | assertGtDecimal(-2.0e18, -1.1e18, 18, err); 137 | 138 | emit log("\n## assertGtDecimal(uint,uint,uint)\n"); 139 | assertGtDecimal(uint(1.0e18), 1.1e18, 18); 140 | emit log("\n"); 141 | assertGtDecimal(uint(1.0e18), 1.1e18, 18, err); 142 | 143 | emit log("\n## assertGe(uint,uint)\n"); 144 | assertGe(uint(0), 1); 145 | emit log("\n"); 146 | assertGe(uint(0), 1, err); 147 | 148 | emit log("\n## assertGe(int,int)\n"); 149 | assertGe(-1, 0); 150 | emit log("\n"); 151 | assertGe(-1, 0, err); 152 | 153 | emit log("\n## assertGeDecimal(int,int,uint)\n"); 154 | assertGeDecimal(-2.0e18, -1.1e18, 18); 155 | emit log("\n"); 156 | assertGeDecimal(-2.0e18, -1.1e18, 18, err); 157 | 158 | emit log("\n## assertGeDecimal(uint,uint,uint)\n"); 159 | assertGeDecimal(uint(1.0e18), 1.1e18, 18); 160 | emit log("\n"); 161 | assertGeDecimal(uint(1.0e18), 1.1e18, 18, err); 162 | 163 | emit log("\n## assertLt(uint,uint)\n"); 164 | assertLt(uint(0), 0); 165 | emit log("\n"); 166 | assertLt(uint(0), 0, err); 167 | 168 | emit log("\n## assertLt(int,int)\n"); 169 | assertLt(-1, -1); 170 | emit log("\n"); 171 | assertLt(-1, -1, err); 172 | 173 | emit log("\n## assertLtDecimal(int,int,uint)\n"); 174 | assertLtDecimal(-1.0e18, -1.1e18, 18); 175 | emit log("\n"); 176 | assertLtDecimal(-1.0e18, -1.1e18, 18, err); 177 | 178 | emit log("\n## assertLtDecimal(uint,uint,uint)\n"); 179 | assertLtDecimal(uint(2.0e18), 1.1e18, 18); 180 | emit log("\n"); 181 | assertLtDecimal(uint(2.0e18), 1.1e18, 18, err); 182 | 183 | emit log("\n## assertLe(uint,uint)\n"); 184 | assertLe(uint(1), 0); 185 | emit log("\n"); 186 | assertLe(uint(1), 0, err); 187 | 188 | emit log("\n## assertLe(int,int)\n"); 189 | assertLe(0, -1); 190 | emit log("\n"); 191 | assertLe(0, -1, err); 192 | 193 | emit log("\n## assertLeDecimal(int,int,uint)\n"); 194 | assertLeDecimal(-1.0e18, -1.1e18, 18); 195 | emit log("\n"); 196 | assertLeDecimal(-1.0e18, -1.1e18, 18, err); 197 | 198 | emit log("\n## assertLeDecimal(uint,uint,uint)\n"); 199 | assertLeDecimal(uint(2.0e18), 1.1e18, 18); 200 | emit log("\n"); 201 | assertLeDecimal(uint(2.0e18), 1.1e18, 18, err); 202 | 203 | emit log("\n## assertEq(string,string)\n"); 204 | string memory s1 = "string 1"; 205 | string memory s2 = "string 2"; 206 | assertEq(s1, s2); 207 | emit log("\n"); 208 | assertEq(s1, s2, err); 209 | 210 | emit log("\n## assertEq0(bytes,bytes)\n"); 211 | assertEq0(hex"abcdef01", hex"abcdef02"); 212 | emit log("\n"); 213 | assertEq0(hex"abcdef01", hex"abcdef02", err); 214 | } 215 | } 216 | 217 | contract DemoTestWithSetUp { 218 | function setUp() public { 219 | } 220 | function test_pass() public pure { 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /lib/forge-std/src/Script.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.6.0 <0.9.0; 3 | 4 | import "./Vm.sol"; 5 | import "./console.sol"; 6 | import "./console2.sol"; 7 | 8 | abstract contract Script { 9 | bool public IS_SCRIPT = true; 10 | address constant private VM_ADDRESS = 11 | address(bytes20(uint160(uint256(keccak256('hevm cheat code'))))); 12 | 13 | Vm public constant vm = Vm(VM_ADDRESS); 14 | 15 | /// @dev Compute the address a contract will be deployed at for a given deployer address and nonce 16 | /// @notice adapated from Solmate implementation (https://github.com/transmissions11/solmate/blob/main/src/utils/LibRLP.sol) 17 | function computeCreateAddress(address deployer, uint256 nonce) internal pure returns (address) { 18 | // The integer zero is treated as an empty byte string, and as a result it only has a length prefix, 0x80, computed via 0x80 + 0. 19 | // A one byte integer uses its own value as its length prefix, there is no additional "0x80 + length" prefix that comes before it. 20 | if (nonce == 0x00) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, bytes1(0x80)))); 21 | if (nonce <= 0x7f) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd6), bytes1(0x94), deployer, uint8(nonce)))); 22 | 23 | // Nonces greater than 1 byte all follow a consistent encoding scheme, where each value is preceded by a prefix of 0x80 + length. 24 | if (nonce <= 2**8 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd7), bytes1(0x94), deployer, bytes1(0x81), uint8(nonce)))); 25 | if (nonce <= 2**16 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd8), bytes1(0x94), deployer, bytes1(0x82), uint16(nonce)))); 26 | if (nonce <= 2**24 - 1) return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xd9), bytes1(0x94), deployer, bytes1(0x83), uint24(nonce)))); 27 | 28 | // More details about RLP encoding can be found here: https://eth.wiki/fundamentals/rlp 29 | // 0xda = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x84 ++ nonce) 30 | // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex) 31 | // 0x84 = 0x80 + 0x04 (0x04 = the bytes length of the nonce, 4 bytes, in hex) 32 | // We assume nobody can have a nonce large enough to require more than 32 bytes. 33 | return addressFromLast20Bytes(keccak256(abi.encodePacked(bytes1(0xda), bytes1(0x94), deployer, bytes1(0x84), uint32(nonce)))); 34 | } 35 | 36 | function addressFromLast20Bytes(bytes32 bytesValue) internal pure returns (address) { 37 | return address(uint160(uint256(bytesValue))); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/forge-std/src/test/Script.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.7.0 <0.9.0; 3 | 4 | import "../Test.sol"; 5 | 6 | contract ScriptTest is Test 7 | { 8 | function testGenerateCorrectAddress() external { 9 | address creation = computeCreateAddress(0x6C9FC64A53c1b71FB3f9Af64d1ae3A4931A5f4E9, 14); 10 | assertEq(creation, 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45); 11 | } 12 | } -------------------------------------------------------------------------------- /lib/forge-std/src/test/StdCheats.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.7.0 <0.9.0; 3 | 4 | import "../Test.sol"; 5 | 6 | contract StdCheatsTest is Test { 7 | Bar test; 8 | 9 | function setUp() public { 10 | test = new Bar(); 11 | } 12 | 13 | function testSkip() public { 14 | vm.warp(100); 15 | skip(25); 16 | assertEq(block.timestamp, 125); 17 | } 18 | 19 | function testRewind() public { 20 | vm.warp(100); 21 | rewind(25); 22 | assertEq(block.timestamp, 75); 23 | } 24 | 25 | function testHoax() public { 26 | hoax(address(1337)); 27 | test.bar{value: 100}(address(1337)); 28 | } 29 | 30 | function testHoaxOrigin() public { 31 | hoax(address(1337), address(1337)); 32 | test.origin{value: 100}(address(1337)); 33 | } 34 | 35 | function testHoaxDifferentAddresses() public { 36 | hoax(address(1337), address(7331)); 37 | test.origin{value: 100}(address(1337), address(7331)); 38 | } 39 | 40 | function testStartHoax() public { 41 | startHoax(address(1337)); 42 | test.bar{value: 100}(address(1337)); 43 | test.bar{value: 100}(address(1337)); 44 | vm.stopPrank(); 45 | test.bar(address(this)); 46 | } 47 | 48 | function testStartHoaxOrigin() public { 49 | startHoax(address(1337), address(1337)); 50 | test.origin{value: 100}(address(1337)); 51 | test.origin{value: 100}(address(1337)); 52 | vm.stopPrank(); 53 | test.bar(address(this)); 54 | } 55 | 56 | function testChangePrank() public { 57 | vm.startPrank(address(1337)); 58 | test.bar(address(1337)); 59 | changePrank(address(0xdead)); 60 | test.bar(address(0xdead)); 61 | changePrank(address(1337)); 62 | test.bar(address(1337)); 63 | vm.stopPrank(); 64 | } 65 | 66 | function testMakeAddrEquivalence() public { 67 | (address addr, ) = makeAddrAndKey("1337"); 68 | assertEq(makeAddr("1337"), addr); 69 | } 70 | 71 | function testMakeAddrSigning() public { 72 | (address addr, uint256 key) = makeAddrAndKey("1337"); 73 | bytes32 hash = keccak256("some_message"); 74 | 75 | (uint8 v, bytes32 r, bytes32 s) = vm.sign(key, hash); 76 | assertEq(ecrecover(hash, v, r, s), addr); 77 | } 78 | 79 | function testDeal() public { 80 | deal(address(this), 1 ether); 81 | assertEq(address(this).balance, 1 ether); 82 | } 83 | 84 | function testDealToken() public { 85 | Bar barToken = new Bar(); 86 | address bar = address(barToken); 87 | deal(bar, address(this), 10000e18); 88 | assertEq(barToken.balanceOf(address(this)), 10000e18); 89 | } 90 | 91 | function testDealTokenAdjustTS() public { 92 | Bar barToken = new Bar(); 93 | address bar = address(barToken); 94 | deal(bar, address(this), 10000e18, true); 95 | assertEq(barToken.balanceOf(address(this)), 10000e18); 96 | assertEq(barToken.totalSupply(), 20000e18); 97 | deal(bar, address(this), 0, true); 98 | assertEq(barToken.balanceOf(address(this)), 0); 99 | assertEq(barToken.totalSupply(), 10000e18); 100 | } 101 | 102 | function testBound() public { 103 | assertEq(bound(5, 0, 4), 0); 104 | assertEq(bound(0, 69, 69), 69); 105 | assertEq(bound(0, 68, 69), 68); 106 | assertEq(bound(10, 150, 190), 160); 107 | assertEq(bound(300, 2800, 3200), 3100); 108 | assertEq(bound(9999, 1337, 6666), 6006); 109 | } 110 | 111 | function testCannotBoundMaxLessThanMin() public { 112 | vm.expectRevert(bytes("Test bound(uint256,uint256,uint256): Max is less than min.")); 113 | bound(5, 100, 10); 114 | } 115 | 116 | function testBound( 117 | uint256 num, 118 | uint256 min, 119 | uint256 max 120 | ) public { 121 | if (min > max) (min, max) = (max, min); 122 | 123 | uint256 bounded = bound(num, min, max); 124 | 125 | assertGe(bounded, min); 126 | assertLe(bounded, max); 127 | } 128 | 129 | function testBoundUint256Max() public { 130 | assertEq(bound(0, type(uint256).max - 1, type(uint256).max), type(uint256).max - 1); 131 | assertEq(bound(1, type(uint256).max - 1, type(uint256).max), type(uint256).max); 132 | } 133 | 134 | function testCannotBoundMaxLessThanMin( 135 | uint256 num, 136 | uint256 min, 137 | uint256 max 138 | ) public { 139 | vm.assume(min > max); 140 | vm.expectRevert(bytes("Test bound(uint256,uint256,uint256): Max is less than min.")); 141 | bound(num, min, max); 142 | } 143 | 144 | function testDeployCode() public { 145 | address deployed = deployCode("StdCheats.t.sol:StdCheatsTest", bytes("")); 146 | assertEq(string(getCode(deployed)), string(getCode(address(this)))); 147 | } 148 | 149 | function testDeployCodeNoArgs() public { 150 | address deployed = deployCode("StdCheats.t.sol:StdCheatsTest"); 151 | assertEq(string(getCode(deployed)), string(getCode(address(this)))); 152 | } 153 | 154 | // We need that payable constructor in order to send ETH on construction 155 | constructor() payable {} 156 | 157 | function testDeployCodeVal() public { 158 | address deployed = deployCode("StdCheats.t.sol:StdCheatsTest", bytes(""), 1 ether); 159 | assertEq(string(getCode(deployed)), string(getCode(address(this)))); 160 | assertEq(deployed.balance, 1 ether); 161 | } 162 | 163 | function testDeployCodeValNoArgs() public { 164 | address deployed = deployCode("StdCheats.t.sol:StdCheatsTest", 1 ether); 165 | assertEq(string(getCode(deployed)), string(getCode(address(this)))); 166 | assertEq(deployed.balance, 1 ether); 167 | } 168 | 169 | // We need this so we can call "this.deployCode" rather than "deployCode" directly 170 | function deployCodeHelper(string memory what) external { 171 | deployCode(what); 172 | } 173 | 174 | function testDeployCodeFail() public { 175 | vm.expectRevert(bytes("Test deployCode(string): Deployment failed.")); 176 | this.deployCodeHelper("StdCheats.t.sol:RevertingContract"); 177 | } 178 | 179 | function getCode(address who) internal view returns (bytes memory o_code) { 180 | /// @solidity memory-safe-assembly 181 | assembly { 182 | // retrieve the size of the code, this needs assembly 183 | let size := extcodesize(who) 184 | // allocate output byte array - this could also be done without assembly 185 | // by using o_code = new bytes(size) 186 | o_code := mload(0x40) 187 | // new "memory end" including padding 188 | mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) 189 | // store length in memory 190 | mstore(o_code, size) 191 | // actually retrieve the code, this needs assembly 192 | extcodecopy(who, add(o_code, 0x20), 0, size) 193 | } 194 | } 195 | } 196 | 197 | contract Bar { 198 | constructor() { 199 | /// `DEAL` STDCHEAT 200 | totalSupply = 10000e18; 201 | balanceOf[address(this)] = totalSupply; 202 | } 203 | 204 | /// `HOAX` STDCHEATS 205 | function bar(address expectedSender) public payable { 206 | require(msg.sender == expectedSender, "!prank"); 207 | } 208 | function origin(address expectedSender) public payable { 209 | require(msg.sender == expectedSender, "!prank"); 210 | require(tx.origin == expectedSender, "!prank"); 211 | } 212 | function origin(address expectedSender, address expectedOrigin) public payable { 213 | require(msg.sender == expectedSender, "!prank"); 214 | require(tx.origin == expectedOrigin, "!prank"); 215 | } 216 | 217 | /// `DEAL` STDCHEAT 218 | mapping (address => uint256) public balanceOf; 219 | uint256 public totalSupply; 220 | } 221 | 222 | contract RevertingContract { 223 | constructor() { 224 | revert(); 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /lib/forge-std/src/test/StdError.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity >=0.8.10 <0.9.0; 3 | 4 | import "../Test.sol"; 5 | 6 | contract StdErrorsTest is Test { 7 | ErrorsTest test; 8 | 9 | function setUp() public { 10 | test = new ErrorsTest(); 11 | } 12 | 13 | function testExpectAssertion() public { 14 | vm.expectRevert(stdError.assertionError); 15 | test.assertionError(); 16 | } 17 | 18 | function testExpectArithmetic() public { 19 | vm.expectRevert(stdError.arithmeticError); 20 | test.arithmeticError(10); 21 | } 22 | 23 | function testExpectDiv() public { 24 | vm.expectRevert(stdError.divisionError); 25 | test.divError(0); 26 | } 27 | 28 | function testExpectMod() public { 29 | vm.expectRevert(stdError.divisionError); 30 | test.modError(0); 31 | } 32 | 33 | function testExpectEnum() public { 34 | vm.expectRevert(stdError.enumConversionError); 35 | test.enumConversion(1); 36 | } 37 | 38 | function testExpectEncodeStg() public { 39 | vm.expectRevert(stdError.encodeStorageError); 40 | test.encodeStgError(); 41 | } 42 | 43 | function testExpectPop() public { 44 | vm.expectRevert(stdError.popError); 45 | test.pop(); 46 | } 47 | 48 | function testExpectOOB() public { 49 | vm.expectRevert(stdError.indexOOBError); 50 | test.indexOOBError(1); 51 | } 52 | 53 | function testExpectMem() public { 54 | vm.expectRevert(stdError.memOverflowError); 55 | test.mem(); 56 | } 57 | 58 | function testExpectIntern() public { 59 | vm.expectRevert(stdError.zeroVarError); 60 | test.intern(); 61 | } 62 | 63 | function testExpectLowLvl() public { 64 | vm.expectRevert(stdError.lowLevelError); 65 | test.someArr(0); 66 | } 67 | } 68 | 69 | contract ErrorsTest { 70 | enum T { 71 | T1 72 | } 73 | 74 | uint256[] public someArr; 75 | bytes someBytes; 76 | 77 | function assertionError() public pure { 78 | assert(false); 79 | } 80 | 81 | function arithmeticError(uint256 a) public pure { 82 | a -= 100; 83 | } 84 | 85 | function divError(uint256 a) public pure { 86 | 100 / a; 87 | } 88 | 89 | function modError(uint256 a) public pure { 90 | 100 % a; 91 | } 92 | 93 | function enumConversion(uint256 a) public pure { 94 | T(a); 95 | } 96 | 97 | function encodeStgError() public { 98 | /// @solidity memory-safe-assembly 99 | assembly { 100 | sstore(someBytes.slot, 1) 101 | } 102 | keccak256(someBytes); 103 | } 104 | 105 | function pop() public { 106 | someArr.pop(); 107 | } 108 | 109 | function indexOOBError(uint256 a) public pure { 110 | uint256[] memory t = new uint256[](0); 111 | t[a]; 112 | } 113 | 114 | function mem() public pure { 115 | uint256 l = 2**256 / 32; 116 | new uint256[](l); 117 | } 118 | 119 | function intern() public returns (uint256) { 120 | function(uint256) internal returns (uint256) x; 121 | x(2); 122 | return 7; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /lib/solmate/.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | .gas-snapshot linguist-language=Julia -------------------------------------------------------------------------------- /lib/solmate/.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Describe the changes made in your pull request here. 4 | 5 | ## Checklist 6 | 7 | Ensure you completed **all of the steps** below before submitting your pull request: 8 | 9 | - [ ] Ran `forge snapshot`? 10 | - [ ] Ran `npm run lint`? 11 | - [ ] Ran `forge test`? 12 | 13 | _Pull requests with an incomplete checklist will be thrown out._ 14 | -------------------------------------------------------------------------------- /lib/solmate/.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Tests 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | tests: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | 11 | - name: Install Foundry 12 | uses: onbjerg/foundry-toolchain@v1 13 | with: 14 | version: nightly 15 | 16 | - name: Install dependencies 17 | run: forge install 18 | 19 | - name: Check contract sizes 20 | run: forge build --sizes 21 | 22 | - name: Check gas snapshots 23 | run: forge snapshot --check 24 | 25 | - name: Run tests 26 | run: forge test 27 | env: 28 | # Only fuzz intensely if we're running this action on a push to main or for a PR going into main: 29 | FOUNDRY_PROFILE: ${{ (github.ref == 'refs/heads/main' || github.base_ref == 'main') && 'intense' }} 30 | -------------------------------------------------------------------------------- /lib/solmate/.gitignore: -------------------------------------------------------------------------------- 1 | /cache 2 | /node_modules 3 | /out -------------------------------------------------------------------------------- /lib/solmate/.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/ds-test"] 2 | path = lib/ds-test 3 | url = https://github.com/dapphub/ds-test 4 | -------------------------------------------------------------------------------- /lib/solmate/.prettierignore: -------------------------------------------------------------------------------- 1 | lib -------------------------------------------------------------------------------- /lib/solmate/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 2, 3 | "printWidth": 100, 4 | 5 | "overrides": [ 6 | { 7 | "files": "*.sol", 8 | "options": { 9 | "tabWidth": 4, 10 | "printWidth": 120 11 | } 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /lib/solmate/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "solidity.packageDefaultDependenciesContractsDirectory": "src", 3 | "solidity.packageDefaultDependenciesDirectory": "lib", 4 | "solidity.compileUsingRemoteVersion": "v0.8.15", 5 | "search.exclude": { "lib": true }, 6 | "files.associations": { 7 | ".gas-snapshot": "julia" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/solmate/README.md: -------------------------------------------------------------------------------- 1 | # solmate 2 | 3 | **Modern**, **opinionated**, and **gas optimized** building blocks for **smart contract development**. 4 | 5 | ## Contracts 6 | 7 | ```ml 8 | auth 9 | ├─ Owned — "Simple single owner authorization" 10 | ├─ Auth — "Flexible and updatable auth pattern" 11 | ├─ authorities 12 | │ ├─ RolesAuthority — "Role based Authority that supports up to 256 roles" 13 | │ ├─ MultiRolesAuthority — "Flexible and target agnostic role based Authority" 14 | mixins 15 | ├─ ERC4626 — "Minimal ERC4626 tokenized Vault implementation" 16 | tokens 17 | ├─ WETH — "Minimalist and modern Wrapped Ether implementation" 18 | ├─ ERC20 — "Modern and gas efficient ERC20 + EIP-2612 implementation" 19 | ├─ ERC721 — "Modern, minimalist, and gas efficient ERC721 implementation" 20 | ├─ ERC1155 — "Minimalist and gas efficient standard ERC1155 implementation" 21 | utils 22 | ├─ SSTORE2 — "Library for cheaper reads and writes to persistent storage" 23 | ├─ CREATE3 — "Deploy to deterministic addresses without an initcode factor" 24 | ├─ SafeCastLib — "Safe unsigned integer casting lib that reverts on overflow" 25 | ├─ ReentrancyGuard — "Gas optimized reentrancy protection for smart contracts" 26 | ├─ FixedPointMathLib — "Arithmetic library with operations for fixed-point numbers" 27 | ├─ Bytes32AddressLib — "Library for converting between addresses and bytes32 values" 28 | ├─ SafeTransferLib — "Safe ERC20/ETH transfer lib that handles missing return values" 29 | ``` 30 | 31 | ## Safety 32 | 33 | This is **experimental software** and is provided on an "as is" and "as available" basis. 34 | 35 | While each [major release has been audited](audits), these contracts are **not designed with user safety** in mind: 36 | 37 | - There are implicit invariants these contracts expect to hold. 38 | - **You can easily shoot yourself in the foot if you're not careful.** 39 | - You should thoroughly read each contract you plan to use top to bottom. 40 | 41 | We **do not give any warranties** and **will not be liable for any loss** incurred through any use of this codebase. 42 | 43 | ## Installation 44 | 45 | To install with [**Foundry**](https://github.com/gakonst/foundry): 46 | 47 | ```sh 48 | forge install transmissions11/solmate 49 | ``` 50 | 51 | To install with [**Hardhat**](https://github.com/nomiclabs/hardhat) or [**Truffle**](https://github.com/trufflesuite/truffle): 52 | 53 | ```sh 54 | npm install solmate 55 | ``` 56 | 57 | ## Acknowledgements 58 | 59 | These contracts were inspired by or directly modified from many sources, primarily: 60 | 61 | - [Gnosis](https://github.com/gnosis/gp-v2-contracts) 62 | - [Uniswap](https://github.com/Uniswap/uniswap-lib) 63 | - [Dappsys](https://github.com/dapphub/dappsys) 64 | - [Dappsys V2](https://github.com/dapp-org/dappsys-v2) 65 | - [0xSequence](https://github.com/0xSequence) 66 | - [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts) 67 | -------------------------------------------------------------------------------- /lib/solmate/audits/v6-Fixed-Point-Solutions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xClandestine/RemcoMath/9bf82925ec98537783f9c8f5a3c41e35092ddaae/lib/solmate/audits/v6-Fixed-Point-Solutions.pdf -------------------------------------------------------------------------------- /lib/solmate/foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | solc = "0.8.15" 3 | bytecode_hash = "none" 4 | optimizer_runs = 1000000 5 | 6 | [profile.intense] 7 | fuzz_runs = 10000 8 | -------------------------------------------------------------------------------- /lib/solmate/lib/ds-test/.gitignore: -------------------------------------------------------------------------------- 1 | /.dapple 2 | /build 3 | /out 4 | -------------------------------------------------------------------------------- /lib/solmate/lib/ds-test/Makefile: -------------------------------------------------------------------------------- 1 | all:; dapp build 2 | 3 | test: 4 | -dapp --use solc:0.4.23 build 5 | -dapp --use solc:0.4.26 build 6 | -dapp --use solc:0.5.17 build 7 | -dapp --use solc:0.6.12 build 8 | -dapp --use solc:0.7.5 build 9 | 10 | demo: 11 | DAPP_SRC=demo dapp --use solc:0.7.5 build 12 | -hevm dapp-test --verbose 3 13 | 14 | .PHONY: test demo 15 | -------------------------------------------------------------------------------- /lib/solmate/lib/ds-test/default.nix: -------------------------------------------------------------------------------- 1 | { solidityPackage, dappsys }: solidityPackage { 2 | name = "ds-test"; 3 | src = ./src; 4 | } 5 | -------------------------------------------------------------------------------- /lib/solmate/lib/ds-test/demo/demo.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: GPL-3.0-or-later 2 | pragma solidity >=0.5.0; 3 | 4 | import "../src/test.sol"; 5 | 6 | contract DemoTest is DSTest { 7 | function test_this() public pure { 8 | require(true); 9 | } 10 | function test_logs() public { 11 | emit log("-- log(string)"); 12 | emit log("a string"); 13 | 14 | emit log("-- log_named_uint(string, uint)"); 15 | emit log_named_uint("uint", 512); 16 | 17 | emit log("-- log_named_int(string, int)"); 18 | emit log_named_int("int", -512); 19 | 20 | emit log("-- log_named_address(string, address)"); 21 | emit log_named_address("address", address(this)); 22 | 23 | emit log("-- log_named_bytes32(string, bytes32)"); 24 | emit log_named_bytes32("bytes32", "a string"); 25 | 26 | emit log("-- log_named_bytes(string, bytes)"); 27 | emit log_named_bytes("bytes", hex"cafefe"); 28 | 29 | emit log("-- log_named_string(string, string)"); 30 | emit log_named_string("string", "a string"); 31 | 32 | emit log("-- log_named_decimal_uint(string, uint, uint)"); 33 | emit log_named_decimal_uint("decimal uint", 1.0e18, 18); 34 | 35 | emit log("-- log_named_decimal_int(string, int, uint)"); 36 | emit log_named_decimal_int("decimal int", -1.0e18, 18); 37 | } 38 | event log_old_named_uint(bytes32,uint); 39 | function test_old_logs() public { 40 | emit log_old_named_uint("key", 500); 41 | emit log_named_bytes32("bkey", "val"); 42 | } 43 | function test_trace() public view { 44 | this.echo("string 1", "string 2"); 45 | } 46 | function test_multiline() public { 47 | emit log("a multiline\\nstring"); 48 | emit log("a multiline string"); 49 | emit log_bytes("a string"); 50 | emit log_bytes("a multiline\nstring"); 51 | emit log_bytes("a multiline\\nstring"); 52 | emit logs(hex"0000"); 53 | emit log_named_bytes("0x0000", hex"0000"); 54 | emit logs(hex"ff"); 55 | } 56 | function echo(string memory s1, string memory s2) public pure 57 | returns (string memory, string memory) 58 | { 59 | return (s1, s2); 60 | } 61 | 62 | function prove_this(uint x) public { 63 | emit log_named_uint("sym x", x); 64 | assertGt(x + 1, 0); 65 | } 66 | 67 | function test_logn() public { 68 | assembly { 69 | log0(0x01, 0x02) 70 | log1(0x01, 0x02, 0x03) 71 | log2(0x01, 0x02, 0x03, 0x04) 72 | log3(0x01, 0x02, 0x03, 0x04, 0x05) 73 | } 74 | } 75 | 76 | event MyEvent(uint, uint indexed, uint, uint indexed); 77 | function test_events() public { 78 | emit MyEvent(1, 2, 3, 4); 79 | } 80 | 81 | function test_asserts() public { 82 | string memory err = "this test has failed!"; 83 | emit log("## assertTrue(bool)\n"); 84 | assertTrue(false); 85 | emit log("\n"); 86 | assertTrue(false, err); 87 | 88 | emit log("\n## assertEq(address,address)\n"); 89 | assertEq(address(this), msg.sender); 90 | emit log("\n"); 91 | assertEq(address(this), msg.sender, err); 92 | 93 | emit log("\n## assertEq32(bytes32,bytes32)\n"); 94 | assertEq32("bytes 1", "bytes 2"); 95 | emit log("\n"); 96 | assertEq32("bytes 1", "bytes 2", err); 97 | 98 | emit log("\n## assertEq(bytes32,bytes32)\n"); 99 | assertEq32("bytes 1", "bytes 2"); 100 | emit log("\n"); 101 | assertEq32("bytes 1", "bytes 2", err); 102 | 103 | emit log("\n## assertEq(uint,uint)\n"); 104 | assertEq(uint(0), 1); 105 | emit log("\n"); 106 | assertEq(uint(0), 1, err); 107 | 108 | emit log("\n## assertEq(int,int)\n"); 109 | assertEq(-1, -2); 110 | emit log("\n"); 111 | assertEq(-1, -2, err); 112 | 113 | emit log("\n## assertEqDecimal(int,int,uint)\n"); 114 | assertEqDecimal(-1.0e18, -1.1e18, 18); 115 | emit log("\n"); 116 | assertEqDecimal(-1.0e18, -1.1e18, 18, err); 117 | 118 | emit log("\n## assertEqDecimal(uint,uint,uint)\n"); 119 | assertEqDecimal(uint(1.0e18), 1.1e18, 18); 120 | emit log("\n"); 121 | assertEqDecimal(uint(1.0e18), 1.1e18, 18, err); 122 | 123 | emit log("\n## assertGt(uint,uint)\n"); 124 | assertGt(uint(0), 0); 125 | emit log("\n"); 126 | assertGt(uint(0), 0, err); 127 | 128 | emit log("\n## assertGt(int,int)\n"); 129 | assertGt(-1, -1); 130 | emit log("\n"); 131 | assertGt(-1, -1, err); 132 | 133 | emit log("\n## assertGtDecimal(int,int,uint)\n"); 134 | assertGtDecimal(-2.0e18, -1.1e18, 18); 135 | emit log("\n"); 136 | assertGtDecimal(-2.0e18, -1.1e18, 18, err); 137 | 138 | emit log("\n## assertGtDecimal(uint,uint,uint)\n"); 139 | assertGtDecimal(uint(1.0e18), 1.1e18, 18); 140 | emit log("\n"); 141 | assertGtDecimal(uint(1.0e18), 1.1e18, 18, err); 142 | 143 | emit log("\n## assertGe(uint,uint)\n"); 144 | assertGe(uint(0), 1); 145 | emit log("\n"); 146 | assertGe(uint(0), 1, err); 147 | 148 | emit log("\n## assertGe(int,int)\n"); 149 | assertGe(-1, 0); 150 | emit log("\n"); 151 | assertGe(-1, 0, err); 152 | 153 | emit log("\n## assertGeDecimal(int,int,uint)\n"); 154 | assertGeDecimal(-2.0e18, -1.1e18, 18); 155 | emit log("\n"); 156 | assertGeDecimal(-2.0e18, -1.1e18, 18, err); 157 | 158 | emit log("\n## assertGeDecimal(uint,uint,uint)\n"); 159 | assertGeDecimal(uint(1.0e18), 1.1e18, 18); 160 | emit log("\n"); 161 | assertGeDecimal(uint(1.0e18), 1.1e18, 18, err); 162 | 163 | emit log("\n## assertLt(uint,uint)\n"); 164 | assertLt(uint(0), 0); 165 | emit log("\n"); 166 | assertLt(uint(0), 0, err); 167 | 168 | emit log("\n## assertLt(int,int)\n"); 169 | assertLt(-1, -1); 170 | emit log("\n"); 171 | assertLt(-1, -1, err); 172 | 173 | emit log("\n## assertLtDecimal(int,int,uint)\n"); 174 | assertLtDecimal(-1.0e18, -1.1e18, 18); 175 | emit log("\n"); 176 | assertLtDecimal(-1.0e18, -1.1e18, 18, err); 177 | 178 | emit log("\n## assertLtDecimal(uint,uint,uint)\n"); 179 | assertLtDecimal(uint(2.0e18), 1.1e18, 18); 180 | emit log("\n"); 181 | assertLtDecimal(uint(2.0e18), 1.1e18, 18, err); 182 | 183 | emit log("\n## assertLe(uint,uint)\n"); 184 | assertLe(uint(1), 0); 185 | emit log("\n"); 186 | assertLe(uint(1), 0, err); 187 | 188 | emit log("\n## assertLe(int,int)\n"); 189 | assertLe(0, -1); 190 | emit log("\n"); 191 | assertLe(0, -1, err); 192 | 193 | emit log("\n## assertLeDecimal(int,int,uint)\n"); 194 | assertLeDecimal(-1.0e18, -1.1e18, 18); 195 | emit log("\n"); 196 | assertLeDecimal(-1.0e18, -1.1e18, 18, err); 197 | 198 | emit log("\n## assertLeDecimal(uint,uint,uint)\n"); 199 | assertLeDecimal(uint(2.0e18), 1.1e18, 18); 200 | emit log("\n"); 201 | assertLeDecimal(uint(2.0e18), 1.1e18, 18, err); 202 | 203 | emit log("\n## assertEq(string,string)\n"); 204 | string memory s1 = "string 1"; 205 | string memory s2 = "string 2"; 206 | assertEq(s1, s2); 207 | emit log("\n"); 208 | assertEq(s1, s2, err); 209 | 210 | emit log("\n## assertEq0(bytes,bytes)\n"); 211 | assertEq0(hex"abcdef01", hex"abcdef02"); 212 | emit log("\n"); 213 | assertEq0(hex"abcdef01", hex"abcdef02", err); 214 | } 215 | } 216 | 217 | contract DemoTestWithSetUp { 218 | function setUp() public { 219 | } 220 | function test_pass() public pure { 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /lib/solmate/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solmate", 3 | "version": "6.5.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@solidity-parser/parser": { 8 | "version": "0.13.2", 9 | "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.13.2.tgz", 10 | "integrity": "sha512-RwHnpRnfrnD2MSPveYoPh8nhofEvX7fgjHk1Oq+NNvCcLx4r1js91CO9o+F/F3fBzOCyvm8kKRTriFICX/odWw==", 11 | "dev": true, 12 | "requires": { 13 | "antlr4ts": "^0.5.0-alpha.4" 14 | } 15 | }, 16 | "ansi-regex": { 17 | "version": "5.0.0", 18 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 19 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 20 | "dev": true 21 | }, 22 | "antlr4ts": { 23 | "version": "0.5.0-alpha.4", 24 | "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", 25 | "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", 26 | "dev": true 27 | }, 28 | "emoji-regex": { 29 | "version": "9.2.2", 30 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 31 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", 32 | "dev": true 33 | }, 34 | "escape-string-regexp": { 35 | "version": "4.0.0", 36 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 37 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 38 | "dev": true 39 | }, 40 | "is-fullwidth-code-point": { 41 | "version": "3.0.0", 42 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 43 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 44 | "dev": true 45 | }, 46 | "lru-cache": { 47 | "version": "6.0.0", 48 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 49 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 50 | "dev": true, 51 | "requires": { 52 | "yallist": "^4.0.0" 53 | } 54 | }, 55 | "prettier": { 56 | "version": "2.3.2", 57 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", 58 | "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", 59 | "dev": true 60 | }, 61 | "prettier-plugin-solidity": { 62 | "version": "1.0.0-beta.16", 63 | "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.16.tgz", 64 | "integrity": "sha512-xVBcnoWpe52dNnCCbqPHC9ZrTWXcNfldf852ZD0DBcHDqVMwjHTAPEdfBVy6FczbFpVa8bmxQil+G5XkEz5WHA==", 65 | "dev": true, 66 | "requires": { 67 | "@solidity-parser/parser": "^0.13.2", 68 | "emoji-regex": "^9.2.2", 69 | "escape-string-regexp": "^4.0.0", 70 | "semver": "^7.3.5", 71 | "solidity-comments-extractor": "^0.0.7", 72 | "string-width": "^4.2.2" 73 | } 74 | }, 75 | "semver": { 76 | "version": "7.3.5", 77 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 78 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 79 | "dev": true, 80 | "requires": { 81 | "lru-cache": "^6.0.0" 82 | } 83 | }, 84 | "solidity-comments-extractor": { 85 | "version": "0.0.7", 86 | "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz", 87 | "integrity": "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==", 88 | "dev": true 89 | }, 90 | "string-width": { 91 | "version": "4.2.2", 92 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 93 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 94 | "dev": true, 95 | "requires": { 96 | "emoji-regex": "^8.0.0", 97 | "is-fullwidth-code-point": "^3.0.0", 98 | "strip-ansi": "^6.0.0" 99 | }, 100 | "dependencies": { 101 | "emoji-regex": { 102 | "version": "8.0.0", 103 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 104 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 105 | "dev": true 106 | } 107 | } 108 | }, 109 | "strip-ansi": { 110 | "version": "6.0.0", 111 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 112 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 113 | "dev": true, 114 | "requires": { 115 | "ansi-regex": "^5.0.0" 116 | } 117 | }, 118 | "yallist": { 119 | "version": "4.0.0", 120 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 121 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 122 | "dev": true 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /lib/solmate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "solmate", 3 | "license": "AGPL-3.0-only", 4 | "version": "6.5.0", 5 | "description": "Modern, opinionated and gas optimized building blocks for smart contract development.", 6 | "files": [ 7 | "src/**/*.sol" 8 | ], 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/transmissions11/solmate.git" 12 | }, 13 | "devDependencies": { 14 | "prettier": "^2.3.1", 15 | "prettier-plugin-solidity": "^1.0.0-beta.13" 16 | }, 17 | "scripts": { 18 | "lint": "prettier --write **.sol" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/solmate/src/auth/Auth.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Provides a flexible and updatable auth pattern which is completely separate from application logic. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol) 6 | /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) 7 | abstract contract Auth { 8 | event OwnerUpdated(address indexed user, address indexed newOwner); 9 | 10 | event AuthorityUpdated(address indexed user, Authority indexed newAuthority); 11 | 12 | address public owner; 13 | 14 | Authority public authority; 15 | 16 | constructor(address _owner, Authority _authority) { 17 | owner = _owner; 18 | authority = _authority; 19 | 20 | emit OwnerUpdated(msg.sender, _owner); 21 | emit AuthorityUpdated(msg.sender, _authority); 22 | } 23 | 24 | modifier requiresAuth() virtual { 25 | require(isAuthorized(msg.sender, msg.sig), "UNAUTHORIZED"); 26 | 27 | _; 28 | } 29 | 30 | function isAuthorized(address user, bytes4 functionSig) internal view virtual returns (bool) { 31 | Authority auth = authority; // Memoizing authority saves us a warm SLOAD, around 100 gas. 32 | 33 | // Checking if the caller is the owner only after calling the authority saves gas in most cases, but be 34 | // aware that this makes protected functions uncallable even to the owner if the authority is out of order. 35 | return (address(auth) != address(0) && auth.canCall(user, address(this), functionSig)) || user == owner; 36 | } 37 | 38 | function setAuthority(Authority newAuthority) public virtual { 39 | // We check if the caller is the owner first because we want to ensure they can 40 | // always swap out the authority even if it's reverting or using up a lot of gas. 41 | require(msg.sender == owner || authority.canCall(msg.sender, address(this), msg.sig)); 42 | 43 | authority = newAuthority; 44 | 45 | emit AuthorityUpdated(msg.sender, newAuthority); 46 | } 47 | 48 | function setOwner(address newOwner) public virtual requiresAuth { 49 | owner = newOwner; 50 | 51 | emit OwnerUpdated(msg.sender, newOwner); 52 | } 53 | } 54 | 55 | /// @notice A generic interface for a contract which provides authorization data to an Auth instance. 56 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol) 57 | /// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol) 58 | interface Authority { 59 | function canCall( 60 | address user, 61 | address target, 62 | bytes4 functionSig 63 | ) external view returns (bool); 64 | } 65 | -------------------------------------------------------------------------------- /lib/solmate/src/auth/Owned.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Simple single owner authorization mixin. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol) 6 | abstract contract Owned { 7 | /*////////////////////////////////////////////////////////////// 8 | EVENTS 9 | //////////////////////////////////////////////////////////////*/ 10 | 11 | event OwnerUpdated(address indexed user, address indexed newOwner); 12 | 13 | /*////////////////////////////////////////////////////////////// 14 | OWNERSHIP STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | address public owner; 18 | 19 | modifier onlyOwner() virtual { 20 | require(msg.sender == owner, "UNAUTHORIZED"); 21 | 22 | _; 23 | } 24 | 25 | /*////////////////////////////////////////////////////////////// 26 | CONSTRUCTOR 27 | //////////////////////////////////////////////////////////////*/ 28 | 29 | constructor(address _owner) { 30 | owner = _owner; 31 | 32 | emit OwnerUpdated(address(0), _owner); 33 | } 34 | 35 | /*////////////////////////////////////////////////////////////// 36 | OWNERSHIP LOGIC 37 | //////////////////////////////////////////////////////////////*/ 38 | 39 | function setOwner(address newOwner) public virtual onlyOwner { 40 | owner = newOwner; 41 | 42 | emit OwnerUpdated(msg.sender, newOwner); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/solmate/src/auth/authorities/MultiRolesAuthority.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {Auth, Authority} from "../Auth.sol"; 5 | 6 | /// @notice Flexible and target agnostic role based Authority that supports up to 256 roles. 7 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/authorities/MultiRolesAuthority.sol) 8 | contract MultiRolesAuthority is Auth, Authority { 9 | /*////////////////////////////////////////////////////////////// 10 | EVENTS 11 | //////////////////////////////////////////////////////////////*/ 12 | 13 | event UserRoleUpdated(address indexed user, uint8 indexed role, bool enabled); 14 | 15 | event PublicCapabilityUpdated(bytes4 indexed functionSig, bool enabled); 16 | 17 | event RoleCapabilityUpdated(uint8 indexed role, bytes4 indexed functionSig, bool enabled); 18 | 19 | event TargetCustomAuthorityUpdated(address indexed target, Authority indexed authority); 20 | 21 | /*////////////////////////////////////////////////////////////// 22 | CONSTRUCTOR 23 | //////////////////////////////////////////////////////////////*/ 24 | 25 | constructor(address _owner, Authority _authority) Auth(_owner, _authority) {} 26 | 27 | /*////////////////////////////////////////////////////////////// 28 | CUSTOM TARGET AUTHORITY STORAGE 29 | //////////////////////////////////////////////////////////////*/ 30 | 31 | mapping(address => Authority) public getTargetCustomAuthority; 32 | 33 | /*////////////////////////////////////////////////////////////// 34 | ROLE/USER STORAGE 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | mapping(address => bytes32) public getUserRoles; 38 | 39 | mapping(bytes4 => bool) public isCapabilityPublic; 40 | 41 | mapping(bytes4 => bytes32) public getRolesWithCapability; 42 | 43 | function doesUserHaveRole(address user, uint8 role) public view virtual returns (bool) { 44 | return (uint256(getUserRoles[user]) >> role) & 1 != 0; 45 | } 46 | 47 | function doesRoleHaveCapability(uint8 role, bytes4 functionSig) public view virtual returns (bool) { 48 | return (uint256(getRolesWithCapability[functionSig]) >> role) & 1 != 0; 49 | } 50 | 51 | /*////////////////////////////////////////////////////////////// 52 | AUTHORIZATION LOGIC 53 | //////////////////////////////////////////////////////////////*/ 54 | 55 | function canCall( 56 | address user, 57 | address target, 58 | bytes4 functionSig 59 | ) public view virtual override returns (bool) { 60 | Authority customAuthority = getTargetCustomAuthority[target]; 61 | 62 | if (address(customAuthority) != address(0)) return customAuthority.canCall(user, target, functionSig); 63 | 64 | return 65 | isCapabilityPublic[functionSig] || bytes32(0) != getUserRoles[user] & getRolesWithCapability[functionSig]; 66 | } 67 | 68 | /*/////////////////////////////////////////////////////////////// 69 | CUSTOM TARGET AUTHORITY CONFIGURATION LOGIC 70 | //////////////////////////////////////////////////////////////*/ 71 | 72 | function setTargetCustomAuthority(address target, Authority customAuthority) public virtual requiresAuth { 73 | getTargetCustomAuthority[target] = customAuthority; 74 | 75 | emit TargetCustomAuthorityUpdated(target, customAuthority); 76 | } 77 | 78 | /*////////////////////////////////////////////////////////////// 79 | PUBLIC CAPABILITY CONFIGURATION LOGIC 80 | //////////////////////////////////////////////////////////////*/ 81 | 82 | function setPublicCapability(bytes4 functionSig, bool enabled) public virtual requiresAuth { 83 | isCapabilityPublic[functionSig] = enabled; 84 | 85 | emit PublicCapabilityUpdated(functionSig, enabled); 86 | } 87 | 88 | /*////////////////////////////////////////////////////////////// 89 | USER ROLE ASSIGNMENT LOGIC 90 | //////////////////////////////////////////////////////////////*/ 91 | 92 | function setUserRole( 93 | address user, 94 | uint8 role, 95 | bool enabled 96 | ) public virtual requiresAuth { 97 | if (enabled) { 98 | getUserRoles[user] |= bytes32(1 << role); 99 | } else { 100 | getUserRoles[user] &= ~bytes32(1 << role); 101 | } 102 | 103 | emit UserRoleUpdated(user, role, enabled); 104 | } 105 | 106 | /*////////////////////////////////////////////////////////////// 107 | ROLE CAPABILITY CONFIGURATION LOGIC 108 | //////////////////////////////////////////////////////////////*/ 109 | 110 | function setRoleCapability( 111 | uint8 role, 112 | bytes4 functionSig, 113 | bool enabled 114 | ) public virtual requiresAuth { 115 | if (enabled) { 116 | getRolesWithCapability[functionSig] |= bytes32(1 << role); 117 | } else { 118 | getRolesWithCapability[functionSig] &= ~bytes32(1 << role); 119 | } 120 | 121 | emit RoleCapabilityUpdated(role, functionSig, enabled); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /lib/solmate/src/auth/authorities/RolesAuthority.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {Auth, Authority} from "../Auth.sol"; 5 | 6 | /// @notice Role based Authority that supports up to 256 roles. 7 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/authorities/RolesAuthority.sol) 8 | /// @author Modified from Dappsys (https://github.com/dapphub/ds-roles/blob/master/src/roles.sol) 9 | contract RolesAuthority is Auth, Authority { 10 | /*////////////////////////////////////////////////////////////// 11 | EVENTS 12 | //////////////////////////////////////////////////////////////*/ 13 | 14 | event UserRoleUpdated(address indexed user, uint8 indexed role, bool enabled); 15 | 16 | event PublicCapabilityUpdated(address indexed target, bytes4 indexed functionSig, bool enabled); 17 | 18 | event RoleCapabilityUpdated(uint8 indexed role, address indexed target, bytes4 indexed functionSig, bool enabled); 19 | 20 | /*////////////////////////////////////////////////////////////// 21 | CONSTRUCTOR 22 | //////////////////////////////////////////////////////////////*/ 23 | 24 | constructor(address _owner, Authority _authority) Auth(_owner, _authority) {} 25 | 26 | /*////////////////////////////////////////////////////////////// 27 | ROLE/USER STORAGE 28 | //////////////////////////////////////////////////////////////*/ 29 | 30 | mapping(address => bytes32) public getUserRoles; 31 | 32 | mapping(address => mapping(bytes4 => bool)) public isCapabilityPublic; 33 | 34 | mapping(address => mapping(bytes4 => bytes32)) public getRolesWithCapability; 35 | 36 | function doesUserHaveRole(address user, uint8 role) public view virtual returns (bool) { 37 | return (uint256(getUserRoles[user]) >> role) & 1 != 0; 38 | } 39 | 40 | function doesRoleHaveCapability( 41 | uint8 role, 42 | address target, 43 | bytes4 functionSig 44 | ) public view virtual returns (bool) { 45 | return (uint256(getRolesWithCapability[target][functionSig]) >> role) & 1 != 0; 46 | } 47 | 48 | /*////////////////////////////////////////////////////////////// 49 | AUTHORIZATION LOGIC 50 | //////////////////////////////////////////////////////////////*/ 51 | 52 | function canCall( 53 | address user, 54 | address target, 55 | bytes4 functionSig 56 | ) public view virtual override returns (bool) { 57 | return 58 | isCapabilityPublic[target][functionSig] || 59 | bytes32(0) != getUserRoles[user] & getRolesWithCapability[target][functionSig]; 60 | } 61 | 62 | /*////////////////////////////////////////////////////////////// 63 | ROLE CAPABILITY CONFIGURATION LOGIC 64 | //////////////////////////////////////////////////////////////*/ 65 | 66 | function setPublicCapability( 67 | address target, 68 | bytes4 functionSig, 69 | bool enabled 70 | ) public virtual requiresAuth { 71 | isCapabilityPublic[target][functionSig] = enabled; 72 | 73 | emit PublicCapabilityUpdated(target, functionSig, enabled); 74 | } 75 | 76 | function setRoleCapability( 77 | uint8 role, 78 | address target, 79 | bytes4 functionSig, 80 | bool enabled 81 | ) public virtual requiresAuth { 82 | if (enabled) { 83 | getRolesWithCapability[target][functionSig] |= bytes32(1 << role); 84 | } else { 85 | getRolesWithCapability[target][functionSig] &= ~bytes32(1 << role); 86 | } 87 | 88 | emit RoleCapabilityUpdated(role, target, functionSig, enabled); 89 | } 90 | 91 | /*////////////////////////////////////////////////////////////// 92 | USER ROLE ASSIGNMENT LOGIC 93 | //////////////////////////////////////////////////////////////*/ 94 | 95 | function setUserRole( 96 | address user, 97 | uint8 role, 98 | bool enabled 99 | ) public virtual requiresAuth { 100 | if (enabled) { 101 | getUserRoles[user] |= bytes32(1 << role); 102 | } else { 103 | getUserRoles[user] &= ~bytes32(1 << role); 104 | } 105 | 106 | emit UserRoleUpdated(user, role, enabled); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /lib/solmate/src/mixins/ERC4626.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC20} from "../tokens/ERC20.sol"; 5 | import {SafeTransferLib} from "../utils/SafeTransferLib.sol"; 6 | import {FixedPointMathLib} from "../utils/FixedPointMathLib.sol"; 7 | 8 | /// @notice Minimal ERC4626 tokenized Vault implementation. 9 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/mixins/ERC4626.sol) 10 | abstract contract ERC4626 is ERC20 { 11 | using SafeTransferLib for ERC20; 12 | using FixedPointMathLib for uint256; 13 | 14 | /*////////////////////////////////////////////////////////////// 15 | EVENTS 16 | //////////////////////////////////////////////////////////////*/ 17 | 18 | event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares); 19 | 20 | event Withdraw( 21 | address indexed caller, 22 | address indexed receiver, 23 | address indexed owner, 24 | uint256 assets, 25 | uint256 shares 26 | ); 27 | 28 | /*////////////////////////////////////////////////////////////// 29 | IMMUTABLES 30 | //////////////////////////////////////////////////////////////*/ 31 | 32 | ERC20 public immutable asset; 33 | 34 | constructor( 35 | ERC20 _asset, 36 | string memory _name, 37 | string memory _symbol 38 | ) ERC20(_name, _symbol, _asset.decimals()) { 39 | asset = _asset; 40 | } 41 | 42 | /*////////////////////////////////////////////////////////////// 43 | DEPOSIT/WITHDRAWAL LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares) { 47 | // Check for rounding error since we round down in previewDeposit. 48 | require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES"); 49 | 50 | // Need to transfer before minting or ERC777s could reenter. 51 | asset.safeTransferFrom(msg.sender, address(this), assets); 52 | 53 | _mint(receiver, shares); 54 | 55 | emit Deposit(msg.sender, receiver, assets, shares); 56 | 57 | afterDeposit(assets, shares); 58 | } 59 | 60 | function mint(uint256 shares, address receiver) public virtual returns (uint256 assets) { 61 | assets = previewMint(shares); // No need to check for rounding error, previewMint rounds up. 62 | 63 | // Need to transfer before minting or ERC777s could reenter. 64 | asset.safeTransferFrom(msg.sender, address(this), assets); 65 | 66 | _mint(receiver, shares); 67 | 68 | emit Deposit(msg.sender, receiver, assets, shares); 69 | 70 | afterDeposit(assets, shares); 71 | } 72 | 73 | function withdraw( 74 | uint256 assets, 75 | address receiver, 76 | address owner 77 | ) public virtual returns (uint256 shares) { 78 | shares = previewWithdraw(assets); // No need to check for rounding error, previewWithdraw rounds up. 79 | 80 | if (msg.sender != owner) { 81 | uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals. 82 | 83 | if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares; 84 | } 85 | 86 | beforeWithdraw(assets, shares); 87 | 88 | _burn(owner, shares); 89 | 90 | emit Withdraw(msg.sender, receiver, owner, assets, shares); 91 | 92 | asset.safeTransfer(receiver, assets); 93 | } 94 | 95 | function redeem( 96 | uint256 shares, 97 | address receiver, 98 | address owner 99 | ) public virtual returns (uint256 assets) { 100 | if (msg.sender != owner) { 101 | uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals. 102 | 103 | if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares; 104 | } 105 | 106 | // Check for rounding error since we round down in previewRedeem. 107 | require((assets = previewRedeem(shares)) != 0, "ZERO_ASSETS"); 108 | 109 | beforeWithdraw(assets, shares); 110 | 111 | _burn(owner, shares); 112 | 113 | emit Withdraw(msg.sender, receiver, owner, assets, shares); 114 | 115 | asset.safeTransfer(receiver, assets); 116 | } 117 | 118 | /*////////////////////////////////////////////////////////////// 119 | ACCOUNTING LOGIC 120 | //////////////////////////////////////////////////////////////*/ 121 | 122 | function totalAssets() public view virtual returns (uint256); 123 | 124 | function convertToShares(uint256 assets) public view virtual returns (uint256) { 125 | uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. 126 | 127 | return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets()); 128 | } 129 | 130 | function convertToAssets(uint256 shares) public view virtual returns (uint256) { 131 | uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. 132 | 133 | return supply == 0 ? shares : shares.mulDivDown(totalAssets(), supply); 134 | } 135 | 136 | function previewDeposit(uint256 assets) public view virtual returns (uint256) { 137 | return convertToShares(assets); 138 | } 139 | 140 | function previewMint(uint256 shares) public view virtual returns (uint256) { 141 | uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. 142 | 143 | return supply == 0 ? shares : shares.mulDivUp(totalAssets(), supply); 144 | } 145 | 146 | function previewWithdraw(uint256 assets) public view virtual returns (uint256) { 147 | uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. 148 | 149 | return supply == 0 ? assets : assets.mulDivUp(supply, totalAssets()); 150 | } 151 | 152 | function previewRedeem(uint256 shares) public view virtual returns (uint256) { 153 | return convertToAssets(shares); 154 | } 155 | 156 | /*////////////////////////////////////////////////////////////// 157 | DEPOSIT/WITHDRAWAL LIMIT LOGIC 158 | //////////////////////////////////////////////////////////////*/ 159 | 160 | function maxDeposit(address) public view virtual returns (uint256) { 161 | return type(uint256).max; 162 | } 163 | 164 | function maxMint(address) public view virtual returns (uint256) { 165 | return type(uint256).max; 166 | } 167 | 168 | function maxWithdraw(address owner) public view virtual returns (uint256) { 169 | return convertToAssets(balanceOf[owner]); 170 | } 171 | 172 | function maxRedeem(address owner) public view virtual returns (uint256) { 173 | return balanceOf[owner]; 174 | } 175 | 176 | /*////////////////////////////////////////////////////////////// 177 | INTERNAL HOOKS LOGIC 178 | //////////////////////////////////////////////////////////////*/ 179 | 180 | function beforeWithdraw(uint256 assets, uint256 shares) internal virtual {} 181 | 182 | function afterDeposit(uint256 assets, uint256 shares) internal virtual {} 183 | } 184 | -------------------------------------------------------------------------------- /lib/solmate/src/test/Auth.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | import {MockAuthChild} from "./utils/mocks/MockAuthChild.sol"; 6 | import {MockAuthority} from "./utils/mocks/MockAuthority.sol"; 7 | 8 | import {Authority} from "../auth/Auth.sol"; 9 | 10 | contract OutOfOrderAuthority is Authority { 11 | function canCall( 12 | address, 13 | address, 14 | bytes4 15 | ) public pure override returns (bool) { 16 | revert("OUT_OF_ORDER"); 17 | } 18 | } 19 | 20 | contract AuthTest is DSTestPlus { 21 | MockAuthChild mockAuthChild; 22 | 23 | function setUp() public { 24 | mockAuthChild = new MockAuthChild(); 25 | } 26 | 27 | function testSetOwnerAsOwner() public { 28 | mockAuthChild.setOwner(address(0xBEEF)); 29 | assertEq(mockAuthChild.owner(), address(0xBEEF)); 30 | } 31 | 32 | function testSetAuthorityAsOwner() public { 33 | mockAuthChild.setAuthority(Authority(address(0xBEEF))); 34 | assertEq(address(mockAuthChild.authority()), address(0xBEEF)); 35 | } 36 | 37 | function testCallFunctionAsOwner() public { 38 | mockAuthChild.updateFlag(); 39 | } 40 | 41 | function testSetOwnerWithPermissiveAuthority() public { 42 | mockAuthChild.setAuthority(new MockAuthority(true)); 43 | mockAuthChild.setOwner(address(0)); 44 | mockAuthChild.setOwner(address(this)); 45 | } 46 | 47 | function testSetAuthorityWithPermissiveAuthority() public { 48 | mockAuthChild.setAuthority(new MockAuthority(true)); 49 | mockAuthChild.setOwner(address(0)); 50 | mockAuthChild.setAuthority(Authority(address(0xBEEF))); 51 | } 52 | 53 | function testCallFunctionWithPermissiveAuthority() public { 54 | mockAuthChild.setAuthority(new MockAuthority(true)); 55 | mockAuthChild.setOwner(address(0)); 56 | mockAuthChild.updateFlag(); 57 | } 58 | 59 | function testSetAuthorityAsOwnerWithOutOfOrderAuthority() public { 60 | mockAuthChild.setAuthority(new OutOfOrderAuthority()); 61 | mockAuthChild.setAuthority(new MockAuthority(true)); 62 | } 63 | 64 | function testFailSetOwnerAsNonOwner() public { 65 | mockAuthChild.setOwner(address(0)); 66 | mockAuthChild.setOwner(address(0xBEEF)); 67 | } 68 | 69 | function testFailSetAuthorityAsNonOwner() public { 70 | mockAuthChild.setOwner(address(0)); 71 | mockAuthChild.setAuthority(Authority(address(0xBEEF))); 72 | } 73 | 74 | function testFailCallFunctionAsNonOwner() public { 75 | mockAuthChild.setOwner(address(0)); 76 | mockAuthChild.updateFlag(); 77 | } 78 | 79 | function testFailSetOwnerWithRestrictiveAuthority() public { 80 | mockAuthChild.setAuthority(new MockAuthority(false)); 81 | mockAuthChild.setOwner(address(0)); 82 | mockAuthChild.setOwner(address(this)); 83 | } 84 | 85 | function testFailSetAuthorityWithRestrictiveAuthority() public { 86 | mockAuthChild.setAuthority(new MockAuthority(false)); 87 | mockAuthChild.setOwner(address(0)); 88 | mockAuthChild.setAuthority(Authority(address(0xBEEF))); 89 | } 90 | 91 | function testFailCallFunctionWithRestrictiveAuthority() public { 92 | mockAuthChild.setAuthority(new MockAuthority(false)); 93 | mockAuthChild.setOwner(address(0)); 94 | mockAuthChild.updateFlag(); 95 | } 96 | 97 | function testFailSetOwnerAsOwnerWithOutOfOrderAuthority() public { 98 | mockAuthChild.setAuthority(new OutOfOrderAuthority()); 99 | mockAuthChild.setOwner(address(0)); 100 | } 101 | 102 | function testFailCallFunctionAsOwnerWithOutOfOrderAuthority() public { 103 | mockAuthChild.setAuthority(new OutOfOrderAuthority()); 104 | mockAuthChild.updateFlag(); 105 | } 106 | 107 | function testSetOwnerAsOwner(address newOwner) public { 108 | mockAuthChild.setOwner(newOwner); 109 | assertEq(mockAuthChild.owner(), newOwner); 110 | } 111 | 112 | function testSetAuthorityAsOwner(Authority newAuthority) public { 113 | mockAuthChild.setAuthority(newAuthority); 114 | assertEq(address(mockAuthChild.authority()), address(newAuthority)); 115 | } 116 | 117 | function testSetOwnerWithPermissiveAuthority(address deadOwner, address newOwner) public { 118 | if (deadOwner == address(this)) deadOwner = address(0); 119 | 120 | mockAuthChild.setAuthority(new MockAuthority(true)); 121 | mockAuthChild.setOwner(deadOwner); 122 | mockAuthChild.setOwner(newOwner); 123 | } 124 | 125 | function testSetAuthorityWithPermissiveAuthority(address deadOwner, Authority newAuthority) public { 126 | if (deadOwner == address(this)) deadOwner = address(0); 127 | 128 | mockAuthChild.setAuthority(new MockAuthority(true)); 129 | mockAuthChild.setOwner(deadOwner); 130 | mockAuthChild.setAuthority(newAuthority); 131 | } 132 | 133 | function testCallFunctionWithPermissiveAuthority(address deadOwner) public { 134 | if (deadOwner == address(this)) deadOwner = address(0); 135 | 136 | mockAuthChild.setAuthority(new MockAuthority(true)); 137 | mockAuthChild.setOwner(deadOwner); 138 | mockAuthChild.updateFlag(); 139 | } 140 | 141 | function testFailSetOwnerAsNonOwner(address deadOwner, address newOwner) public { 142 | if (deadOwner == address(this)) deadOwner = address(0); 143 | 144 | mockAuthChild.setOwner(deadOwner); 145 | mockAuthChild.setOwner(newOwner); 146 | } 147 | 148 | function testFailSetAuthorityAsNonOwner(address deadOwner, Authority newAuthority) public { 149 | if (deadOwner == address(this)) deadOwner = address(0); 150 | 151 | mockAuthChild.setOwner(deadOwner); 152 | mockAuthChild.setAuthority(newAuthority); 153 | } 154 | 155 | function testFailCallFunctionAsNonOwner(address deadOwner) public { 156 | if (deadOwner == address(this)) deadOwner = address(0); 157 | 158 | mockAuthChild.setOwner(deadOwner); 159 | mockAuthChild.updateFlag(); 160 | } 161 | 162 | function testFailSetOwnerWithRestrictiveAuthority(address deadOwner, address newOwner) public { 163 | if (deadOwner == address(this)) deadOwner = address(0); 164 | 165 | mockAuthChild.setAuthority(new MockAuthority(false)); 166 | mockAuthChild.setOwner(deadOwner); 167 | mockAuthChild.setOwner(newOwner); 168 | } 169 | 170 | function testFailSetAuthorityWithRestrictiveAuthority(address deadOwner, Authority newAuthority) public { 171 | if (deadOwner == address(this)) deadOwner = address(0); 172 | 173 | mockAuthChild.setAuthority(new MockAuthority(false)); 174 | mockAuthChild.setOwner(deadOwner); 175 | mockAuthChild.setAuthority(newAuthority); 176 | } 177 | 178 | function testFailCallFunctionWithRestrictiveAuthority(address deadOwner) public { 179 | if (deadOwner == address(this)) deadOwner = address(0); 180 | 181 | mockAuthChild.setAuthority(new MockAuthority(false)); 182 | mockAuthChild.setOwner(deadOwner); 183 | mockAuthChild.updateFlag(); 184 | } 185 | 186 | function testFailSetOwnerAsOwnerWithOutOfOrderAuthority(address deadOwner) public { 187 | if (deadOwner == address(this)) deadOwner = address(0); 188 | 189 | mockAuthChild.setAuthority(new OutOfOrderAuthority()); 190 | mockAuthChild.setOwner(deadOwner); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /lib/solmate/src/test/Bytes32AddressLib.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | 6 | import {Bytes32AddressLib} from "../utils/Bytes32AddressLib.sol"; 7 | 8 | contract Bytes32AddressLibTest is DSTestPlus { 9 | function testFillLast12Bytes() public { 10 | assertEq( 11 | Bytes32AddressLib.fillLast12Bytes(0xfEEDFaCEcaFeBEEFfEEDFACecaFEBeeFfeEdfAce), 12 | 0xfeedfacecafebeeffeedfacecafebeeffeedface000000000000000000000000 13 | ); 14 | } 15 | 16 | function testFromLast20Bytes() public { 17 | assertEq( 18 | Bytes32AddressLib.fromLast20Bytes(0xfeedfacecafebeeffeedfacecafebeeffeedfacecafebeeffeedfacecafebeef), 19 | 0xCAfeBeefFeedfAceCAFeBEEffEEDfaCecafEBeeF 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/solmate/src/test/CREATE3.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {WETH} from "../tokens/WETH.sol"; 5 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 6 | import {MockERC20} from "./utils/mocks/MockERC20.sol"; 7 | import {MockAuthChild} from "./utils/mocks/MockAuthChild.sol"; 8 | 9 | import {CREATE3} from "../utils/CREATE3.sol"; 10 | 11 | contract CREATE3Test is DSTestPlus { 12 | function testDeployERC20() public { 13 | bytes32 salt = keccak256(bytes("A salt!")); 14 | 15 | MockERC20 deployed = MockERC20( 16 | CREATE3.deploy( 17 | salt, 18 | abi.encodePacked(type(MockERC20).creationCode, abi.encode("Mock Token", "MOCK", 18)), 19 | 0 20 | ) 21 | ); 22 | 23 | assertEq(address(deployed), CREATE3.getDeployed(salt)); 24 | 25 | assertEq(deployed.name(), "Mock Token"); 26 | assertEq(deployed.symbol(), "MOCK"); 27 | assertEq(deployed.decimals(), 18); 28 | } 29 | 30 | function testFailDoubleDeploySameBytecode() public { 31 | bytes32 salt = keccak256(bytes("Salty...")); 32 | 33 | CREATE3.deploy(salt, type(MockAuthChild).creationCode, 0); 34 | CREATE3.deploy(salt, type(MockAuthChild).creationCode, 0); 35 | } 36 | 37 | function testFailDoubleDeployDifferentBytecode() public { 38 | bytes32 salt = keccak256(bytes("and sweet!")); 39 | 40 | CREATE3.deploy(salt, type(WETH).creationCode, 0); 41 | CREATE3.deploy(salt, type(MockAuthChild).creationCode, 0); 42 | } 43 | 44 | function testDeployERC20( 45 | bytes32 salt, 46 | string calldata name, 47 | string calldata symbol, 48 | uint8 decimals 49 | ) public { 50 | MockERC20 deployed = MockERC20( 51 | CREATE3.deploy(salt, abi.encodePacked(type(MockERC20).creationCode, abi.encode(name, symbol, decimals)), 0) 52 | ); 53 | 54 | assertEq(address(deployed), CREATE3.getDeployed(salt)); 55 | 56 | assertEq(deployed.name(), name); 57 | assertEq(deployed.symbol(), symbol); 58 | assertEq(deployed.decimals(), decimals); 59 | } 60 | 61 | function testFailDoubleDeploySameBytecode(bytes32 salt, bytes calldata bytecode) public { 62 | CREATE3.deploy(salt, bytecode, 0); 63 | CREATE3.deploy(salt, bytecode, 0); 64 | } 65 | 66 | function testFailDoubleDeployDifferentBytecode( 67 | bytes32 salt, 68 | bytes calldata bytecode1, 69 | bytes calldata bytecode2 70 | ) public { 71 | CREATE3.deploy(salt, bytecode1, 0); 72 | CREATE3.deploy(salt, bytecode2, 0); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/solmate/src/test/DSTestPlus.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | 6 | contract DSTestPlusTest is DSTestPlus { 7 | function testBound() public { 8 | assertEq(bound(0, 69, 69), 69); 9 | assertEq(bound(0, 68, 69), 68); 10 | assertEq(bound(5, 0, 4), 0); 11 | assertEq(bound(9999, 1337, 6666), 6006); 12 | assertEq(bound(0, type(uint256).max - 6, type(uint256).max), type(uint256).max - 6); 13 | assertEq(bound(6, type(uint256).max - 6, type(uint256).max), type(uint256).max); 14 | } 15 | 16 | function testFailBoundMinBiggerThanMax() public { 17 | bound(5, 100, 10); 18 | } 19 | 20 | function testRelApproxEqBothZeroesPasses() public { 21 | assertRelApproxEq(0, 0, 1e18); 22 | assertRelApproxEq(0, 0, 0); 23 | } 24 | 25 | function testBound( 26 | uint256 num, 27 | uint256 min, 28 | uint256 max 29 | ) public { 30 | if (min > max) (min, max) = (max, min); 31 | 32 | uint256 bounded = bound(num, min, max); 33 | 34 | assertGe(bounded, min); 35 | assertLe(bounded, max); 36 | } 37 | 38 | function testFailBoundMinBiggerThanMax( 39 | uint256 num, 40 | uint256 min, 41 | uint256 max 42 | ) public { 43 | if (max == min) { 44 | unchecked { 45 | min++; // Overflow is handled below. 46 | } 47 | } 48 | 49 | if (max > min) (min, max) = (max, min); 50 | 51 | bound(num, min, max); 52 | } 53 | 54 | function testBrutalizeMemory() public brutalizeMemory("FEEDFACECAFEBEEFFEEDFACECAFEBEEF") { 55 | bytes32 scratchSpace1; 56 | bytes32 scratchSpace2; 57 | bytes32 freeMem1; 58 | bytes32 freeMem2; 59 | 60 | assembly { 61 | scratchSpace1 := mload(0) 62 | scratchSpace2 := mload(32) 63 | freeMem1 := mload(mload(0x40)) 64 | freeMem2 := mload(add(mload(0x40), 32)) 65 | } 66 | 67 | assertGt(uint256(freeMem1), 0); 68 | assertGt(uint256(freeMem2), 0); 69 | assertGt(uint256(scratchSpace1), 0); 70 | assertGt(uint256(scratchSpace2), 0); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /lib/solmate/src/test/Owned.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | import {MockOwned} from "./utils/mocks/MockOwned.sol"; 6 | 7 | contract OwnedTest is DSTestPlus { 8 | MockOwned mockOwned; 9 | 10 | function setUp() public { 11 | mockOwned = new MockOwned(); 12 | } 13 | 14 | function testSetOwner() public { 15 | testSetOwner(address(0xBEEF)); 16 | } 17 | 18 | function testCallFunctionAsNonOwner() public { 19 | testCallFunctionAsNonOwner(address(0)); 20 | } 21 | 22 | function testCallFunctionAsOwner() public { 23 | mockOwned.updateFlag(); 24 | } 25 | 26 | function testSetOwner(address newOwner) public { 27 | mockOwned.setOwner(newOwner); 28 | 29 | assertEq(mockOwned.owner(), newOwner); 30 | } 31 | 32 | function testCallFunctionAsNonOwner(address owner) public { 33 | hevm.assume(owner != address(this)); 34 | 35 | mockOwned.setOwner(owner); 36 | 37 | hevm.expectRevert("UNAUTHORIZED"); 38 | mockOwned.updateFlag(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lib/solmate/src/test/ReentrancyGuard.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | 6 | import {ReentrancyGuard} from "../utils/ReentrancyGuard.sol"; 7 | 8 | contract RiskyContract is ReentrancyGuard { 9 | uint256 public enterTimes; 10 | 11 | function unprotectedCall() public { 12 | enterTimes++; 13 | 14 | if (enterTimes > 1) return; 15 | 16 | this.protectedCall(); 17 | } 18 | 19 | function protectedCall() public nonReentrant { 20 | enterTimes++; 21 | 22 | if (enterTimes > 1) return; 23 | 24 | this.protectedCall(); 25 | } 26 | 27 | function overprotectedCall() public nonReentrant {} 28 | } 29 | 30 | contract ReentrancyGuardTest is DSTestPlus { 31 | RiskyContract riskyContract; 32 | 33 | function setUp() public { 34 | riskyContract = new RiskyContract(); 35 | } 36 | 37 | function invariantReentrancyStatusAlways1() public { 38 | assertEq(uint256(hevm.load(address(riskyContract), 0)), 1); 39 | } 40 | 41 | function testFailUnprotectedCall() public { 42 | riskyContract.unprotectedCall(); 43 | 44 | assertEq(riskyContract.enterTimes(), 1); 45 | } 46 | 47 | function testProtectedCall() public { 48 | try riskyContract.protectedCall() { 49 | fail("Reentrancy Guard Failed To Stop Attacker"); 50 | } catch {} 51 | } 52 | 53 | function testNoReentrancy() public { 54 | riskyContract.overprotectedCall(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /lib/solmate/src/test/RolesAuthority.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | import {MockAuthority} from "./utils/mocks/MockAuthority.sol"; 6 | 7 | import {Authority} from "../auth/Auth.sol"; 8 | 9 | import {RolesAuthority} from "../auth/authorities/RolesAuthority.sol"; 10 | 11 | contract RolesAuthorityTest is DSTestPlus { 12 | RolesAuthority rolesAuthority; 13 | 14 | function setUp() public { 15 | rolesAuthority = new RolesAuthority(address(this), Authority(address(0))); 16 | } 17 | 18 | function testSetRoles() public { 19 | assertFalse(rolesAuthority.doesUserHaveRole(address(0xBEEF), 0)); 20 | 21 | rolesAuthority.setUserRole(address(0xBEEF), 0, true); 22 | assertTrue(rolesAuthority.doesUserHaveRole(address(0xBEEF), 0)); 23 | 24 | rolesAuthority.setUserRole(address(0xBEEF), 0, false); 25 | assertFalse(rolesAuthority.doesUserHaveRole(address(0xBEEF), 0)); 26 | } 27 | 28 | function testSetRoleCapabilities() public { 29 | assertFalse(rolesAuthority.doesRoleHaveCapability(0, address(0xCAFE), 0xBEEFCAFE)); 30 | 31 | rolesAuthority.setRoleCapability(0, address(0xCAFE), 0xBEEFCAFE, true); 32 | assertTrue(rolesAuthority.doesRoleHaveCapability(0, address(0xCAFE), 0xBEEFCAFE)); 33 | 34 | rolesAuthority.setRoleCapability(0, address(0xCAFE), 0xBEEFCAFE, false); 35 | assertFalse(rolesAuthority.doesRoleHaveCapability(0, address(0xCAFE), 0xBEEFCAFE)); 36 | } 37 | 38 | function testSetPublicCapabilities() public { 39 | assertFalse(rolesAuthority.isCapabilityPublic(address(0xCAFE), 0xBEEFCAFE)); 40 | 41 | rolesAuthority.setPublicCapability(address(0xCAFE), 0xBEEFCAFE, true); 42 | assertTrue(rolesAuthority.isCapabilityPublic(address(0xCAFE), 0xBEEFCAFE)); 43 | 44 | rolesAuthority.setPublicCapability(address(0xCAFE), 0xBEEFCAFE, false); 45 | assertFalse(rolesAuthority.isCapabilityPublic(address(0xCAFE), 0xBEEFCAFE)); 46 | } 47 | 48 | function testCanCallWithAuthorizedRole() public { 49 | assertFalse(rolesAuthority.canCall(address(0xBEEF), address(0xCAFE), 0xBEEFCAFE)); 50 | 51 | rolesAuthority.setUserRole(address(0xBEEF), 0, true); 52 | assertFalse(rolesAuthority.canCall(address(0xBEEF), address(0xCAFE), 0xBEEFCAFE)); 53 | 54 | rolesAuthority.setRoleCapability(0, address(0xCAFE), 0xBEEFCAFE, true); 55 | assertTrue(rolesAuthority.canCall(address(0xBEEF), address(0xCAFE), 0xBEEFCAFE)); 56 | 57 | rolesAuthority.setRoleCapability(0, address(0xCAFE), 0xBEEFCAFE, false); 58 | assertFalse(rolesAuthority.canCall(address(0xBEEF), address(0xCAFE), 0xBEEFCAFE)); 59 | 60 | rolesAuthority.setRoleCapability(0, address(0xCAFE), 0xBEEFCAFE, true); 61 | assertTrue(rolesAuthority.canCall(address(0xBEEF), address(0xCAFE), 0xBEEFCAFE)); 62 | 63 | rolesAuthority.setUserRole(address(0xBEEF), 0, false); 64 | assertFalse(rolesAuthority.canCall(address(0xBEEF), address(0xCAFE), 0xBEEFCAFE)); 65 | } 66 | 67 | function testCanCallPublicCapability() public { 68 | assertFalse(rolesAuthority.canCall(address(0xBEEF), address(0xCAFE), 0xBEEFCAFE)); 69 | 70 | rolesAuthority.setPublicCapability(address(0xCAFE), 0xBEEFCAFE, true); 71 | assertTrue(rolesAuthority.canCall(address(0xBEEF), address(0xCAFE), 0xBEEFCAFE)); 72 | 73 | rolesAuthority.setPublicCapability(address(0xCAFE), 0xBEEFCAFE, false); 74 | assertFalse(rolesAuthority.canCall(address(0xBEEF), address(0xCAFE), 0xBEEFCAFE)); 75 | } 76 | 77 | function testSetRoles(address user, uint8 role) public { 78 | assertFalse(rolesAuthority.doesUserHaveRole(user, role)); 79 | 80 | rolesAuthority.setUserRole(user, role, true); 81 | assertTrue(rolesAuthority.doesUserHaveRole(user, role)); 82 | 83 | rolesAuthority.setUserRole(user, role, false); 84 | assertFalse(rolesAuthority.doesUserHaveRole(user, role)); 85 | } 86 | 87 | function testSetRoleCapabilities( 88 | uint8 role, 89 | address target, 90 | bytes4 functionSig 91 | ) public { 92 | assertFalse(rolesAuthority.doesRoleHaveCapability(role, target, functionSig)); 93 | 94 | rolesAuthority.setRoleCapability(role, target, functionSig, true); 95 | assertTrue(rolesAuthority.doesRoleHaveCapability(role, target, functionSig)); 96 | 97 | rolesAuthority.setRoleCapability(role, target, functionSig, false); 98 | assertFalse(rolesAuthority.doesRoleHaveCapability(role, target, functionSig)); 99 | } 100 | 101 | function testSetPublicCapabilities(address target, bytes4 functionSig) public { 102 | assertFalse(rolesAuthority.isCapabilityPublic(target, functionSig)); 103 | 104 | rolesAuthority.setPublicCapability(target, functionSig, true); 105 | assertTrue(rolesAuthority.isCapabilityPublic(target, functionSig)); 106 | 107 | rolesAuthority.setPublicCapability(target, functionSig, false); 108 | assertFalse(rolesAuthority.isCapabilityPublic(target, functionSig)); 109 | } 110 | 111 | function testCanCallWithAuthorizedRole( 112 | address user, 113 | uint8 role, 114 | address target, 115 | bytes4 functionSig 116 | ) public { 117 | assertFalse(rolesAuthority.canCall(user, target, functionSig)); 118 | 119 | rolesAuthority.setUserRole(user, role, true); 120 | assertFalse(rolesAuthority.canCall(user, target, functionSig)); 121 | 122 | rolesAuthority.setRoleCapability(role, target, functionSig, true); 123 | assertTrue(rolesAuthority.canCall(user, target, functionSig)); 124 | 125 | rolesAuthority.setRoleCapability(role, target, functionSig, false); 126 | assertFalse(rolesAuthority.canCall(user, target, functionSig)); 127 | 128 | rolesAuthority.setRoleCapability(role, target, functionSig, true); 129 | assertTrue(rolesAuthority.canCall(user, target, functionSig)); 130 | 131 | rolesAuthority.setUserRole(user, role, false); 132 | assertFalse(rolesAuthority.canCall(user, target, functionSig)); 133 | } 134 | 135 | function testCanCallPublicCapability( 136 | address user, 137 | address target, 138 | bytes4 functionSig 139 | ) public { 140 | assertFalse(rolesAuthority.canCall(user, target, functionSig)); 141 | 142 | rolesAuthority.setPublicCapability(target, functionSig, true); 143 | assertTrue(rolesAuthority.canCall(user, target, functionSig)); 144 | 145 | rolesAuthority.setPublicCapability(target, functionSig, false); 146 | assertFalse(rolesAuthority.canCall(user, target, functionSig)); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /lib/solmate/src/test/SSTORE2.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | 6 | import {SSTORE2} from "../utils/SSTORE2.sol"; 7 | 8 | contract SSTORE2Test is DSTestPlus { 9 | function testWriteRead() public { 10 | bytes memory testBytes = abi.encode("this is a test"); 11 | 12 | address pointer = SSTORE2.write(testBytes); 13 | 14 | assertBytesEq(SSTORE2.read(pointer), testBytes); 15 | } 16 | 17 | function testWriteReadFullStartBound() public { 18 | assertBytesEq(SSTORE2.read(SSTORE2.write(hex"11223344"), 0), hex"11223344"); 19 | } 20 | 21 | function testWriteReadCustomStartBound() public { 22 | assertBytesEq(SSTORE2.read(SSTORE2.write(hex"11223344"), 1), hex"223344"); 23 | } 24 | 25 | function testWriteReadFullBoundedRead() public { 26 | bytes memory testBytes = abi.encode("this is a test"); 27 | 28 | assertBytesEq(SSTORE2.read(SSTORE2.write(testBytes), 0, testBytes.length), testBytes); 29 | } 30 | 31 | function testWriteReadCustomBounds() public { 32 | assertBytesEq(SSTORE2.read(SSTORE2.write(hex"11223344"), 1, 3), hex"2233"); 33 | } 34 | 35 | function testWriteReadEmptyBound() public { 36 | SSTORE2.read(SSTORE2.write(hex"11223344"), 3, 3); 37 | } 38 | 39 | function testFailReadInvalidPointer() public view { 40 | SSTORE2.read(DEAD_ADDRESS); 41 | } 42 | 43 | function testFailReadInvalidPointerCustomStartBound() public view { 44 | SSTORE2.read(DEAD_ADDRESS, 1); 45 | } 46 | 47 | function testFailReadInvalidPointerCustomBounds() public view { 48 | SSTORE2.read(DEAD_ADDRESS, 2, 4); 49 | } 50 | 51 | function testFailWriteReadOutOfStartBound() public { 52 | SSTORE2.read(SSTORE2.write(hex"11223344"), 41000); 53 | } 54 | 55 | function testFailWriteReadEmptyOutOfBounds() public { 56 | SSTORE2.read(SSTORE2.write(hex"11223344"), 42000, 42000); 57 | } 58 | 59 | function testFailWriteReadOutOfBounds() public { 60 | SSTORE2.read(SSTORE2.write(hex"11223344"), 41000, 42000); 61 | } 62 | 63 | function testWriteRead(bytes calldata testBytes, bytes calldata brutalizeWith) 64 | public 65 | brutalizeMemory(brutalizeWith) 66 | { 67 | assertBytesEq(SSTORE2.read(SSTORE2.write(testBytes)), testBytes); 68 | } 69 | 70 | function testWriteReadCustomStartBound( 71 | bytes calldata testBytes, 72 | uint256 startIndex, 73 | bytes calldata brutalizeWith 74 | ) public brutalizeMemory(brutalizeWith) { 75 | if (testBytes.length == 0) return; 76 | 77 | startIndex = bound(startIndex, 0, testBytes.length); 78 | 79 | assertBytesEq(SSTORE2.read(SSTORE2.write(testBytes), startIndex), bytes(testBytes[startIndex:])); 80 | } 81 | 82 | function testWriteReadCustomBounds( 83 | bytes calldata testBytes, 84 | uint256 startIndex, 85 | uint256 endIndex, 86 | bytes calldata brutalizeWith 87 | ) public brutalizeMemory(brutalizeWith) { 88 | if (testBytes.length == 0) return; 89 | 90 | endIndex = bound(endIndex, 0, testBytes.length); 91 | startIndex = bound(startIndex, 0, testBytes.length); 92 | 93 | if (startIndex > endIndex) return; 94 | 95 | assertBytesEq( 96 | SSTORE2.read(SSTORE2.write(testBytes), startIndex, endIndex), 97 | bytes(testBytes[startIndex:endIndex]) 98 | ); 99 | } 100 | 101 | function testFailReadInvalidPointer(address pointer, bytes calldata brutalizeWith) 102 | public 103 | view 104 | brutalizeMemory(brutalizeWith) 105 | { 106 | if (pointer.code.length > 0) revert(); 107 | 108 | SSTORE2.read(pointer); 109 | } 110 | 111 | function testFailReadInvalidPointerCustomStartBound( 112 | address pointer, 113 | uint256 startIndex, 114 | bytes calldata brutalizeWith 115 | ) public view brutalizeMemory(brutalizeWith) { 116 | if (pointer.code.length > 0) revert(); 117 | 118 | SSTORE2.read(pointer, startIndex); 119 | } 120 | 121 | function testFailReadInvalidPointerCustomBounds( 122 | address pointer, 123 | uint256 startIndex, 124 | uint256 endIndex, 125 | bytes calldata brutalizeWith 126 | ) public view brutalizeMemory(brutalizeWith) { 127 | if (pointer.code.length > 0) revert(); 128 | 129 | SSTORE2.read(pointer, startIndex, endIndex); 130 | } 131 | 132 | function testFailWriteReadCustomStartBoundOutOfRange( 133 | bytes calldata testBytes, 134 | uint256 startIndex, 135 | bytes calldata brutalizeWith 136 | ) public brutalizeMemory(brutalizeWith) { 137 | startIndex = bound(startIndex, testBytes.length + 1, type(uint256).max); 138 | 139 | SSTORE2.read(SSTORE2.write(testBytes), startIndex); 140 | } 141 | 142 | function testFailWriteReadCustomBoundsOutOfRange( 143 | bytes calldata testBytes, 144 | uint256 startIndex, 145 | uint256 endIndex, 146 | bytes calldata brutalizeWith 147 | ) public brutalizeMemory(brutalizeWith) { 148 | endIndex = bound(endIndex, testBytes.length + 1, type(uint256).max); 149 | 150 | SSTORE2.read(SSTORE2.write(testBytes), startIndex, endIndex); 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /lib/solmate/src/test/SafeCastLib.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | 6 | import {SafeCastLib} from "../utils/SafeCastLib.sol"; 7 | 8 | contract SafeCastLibTest is DSTestPlus { 9 | function testSafeCastTo248() public { 10 | assertEq(SafeCastLib.safeCastTo248(2.5e45), 2.5e45); 11 | assertEq(SafeCastLib.safeCastTo248(2.5e27), 2.5e27); 12 | } 13 | 14 | function testSafeCastTo224() public { 15 | assertEq(SafeCastLib.safeCastTo224(2.5e36), 2.5e36); 16 | assertEq(SafeCastLib.safeCastTo224(2.5e27), 2.5e27); 17 | } 18 | 19 | function testSafeCastTo192() public { 20 | assertEq(SafeCastLib.safeCastTo192(2.5e36), 2.5e36); 21 | assertEq(SafeCastLib.safeCastTo192(2.5e27), 2.5e27); 22 | } 23 | 24 | function testSafeCastTo160() public { 25 | assertEq(SafeCastLib.safeCastTo160(2.5e36), 2.5e36); 26 | assertEq(SafeCastLib.safeCastTo160(2.5e27), 2.5e27); 27 | } 28 | 29 | function testSafeCastTo128() public { 30 | assertEq(SafeCastLib.safeCastTo128(2.5e27), 2.5e27); 31 | assertEq(SafeCastLib.safeCastTo128(2.5e18), 2.5e18); 32 | } 33 | 34 | function testSafeCastTo96() public { 35 | assertEq(SafeCastLib.safeCastTo96(2.5e18), 2.5e18); 36 | assertEq(SafeCastLib.safeCastTo96(2.5e17), 2.5e17); 37 | } 38 | 39 | function testSafeCastTo64() public { 40 | assertEq(SafeCastLib.safeCastTo64(2.5e18), 2.5e18); 41 | assertEq(SafeCastLib.safeCastTo64(2.5e17), 2.5e17); 42 | } 43 | 44 | function testSafeCastTo32() public { 45 | assertEq(SafeCastLib.safeCastTo32(2.5e8), 2.5e8); 46 | assertEq(SafeCastLib.safeCastTo32(2.5e7), 2.5e7); 47 | } 48 | 49 | function testSafeCastTo24() public { 50 | assertEq(SafeCastLib.safeCastTo24(2.5e4), 2.5e4); 51 | assertEq(SafeCastLib.safeCastTo24(2.5e3), 2.5e3); 52 | } 53 | 54 | function testSafeCastTo8() public { 55 | assertEq(SafeCastLib.safeCastTo8(100), 100); 56 | assertEq(SafeCastLib.safeCastTo8(250), 250); 57 | } 58 | 59 | function testFailSafeCastTo248() public pure { 60 | SafeCastLib.safeCastTo248(type(uint248).max + 1); 61 | } 62 | 63 | function testFailSafeCastTo224() public pure { 64 | SafeCastLib.safeCastTo224(type(uint224).max + 1); 65 | } 66 | 67 | function testFailSafeCastTo192() public pure { 68 | SafeCastLib.safeCastTo192(type(uint192).max + 1); 69 | } 70 | 71 | function testFailSafeCastTo160() public pure { 72 | SafeCastLib.safeCastTo160(type(uint160).max + 1); 73 | } 74 | 75 | function testFailSafeCastTo128() public pure { 76 | SafeCastLib.safeCastTo128(type(uint128).max + 1); 77 | } 78 | 79 | function testFailSafeCastTo96() public pure { 80 | SafeCastLib.safeCastTo96(type(uint96).max + 1); 81 | } 82 | 83 | function testFailSafeCastTo64() public pure { 84 | SafeCastLib.safeCastTo64(type(uint64).max + 1); 85 | } 86 | 87 | function testFailSafeCastTo32() public pure { 88 | SafeCastLib.safeCastTo32(type(uint32).max + 1); 89 | } 90 | 91 | function testFailSafeCastTo8() public pure { 92 | SafeCastLib.safeCastTo8(type(uint8).max + 1); 93 | } 94 | 95 | function testSafeCastTo248(uint256 x) public { 96 | x = bound(x, 0, type(uint248).max); 97 | 98 | assertEq(SafeCastLib.safeCastTo248(x), x); 99 | } 100 | 101 | function testSafeCastTo224(uint256 x) public { 102 | x = bound(x, 0, type(uint224).max); 103 | 104 | assertEq(SafeCastLib.safeCastTo224(x), x); 105 | } 106 | 107 | function testSafeCastTo192(uint256 x) public { 108 | x = bound(x, 0, type(uint192).max); 109 | 110 | assertEq(SafeCastLib.safeCastTo192(x), x); 111 | } 112 | 113 | function testSafeCastTo160(uint256 x) public { 114 | x = bound(x, 0, type(uint160).max); 115 | 116 | assertEq(SafeCastLib.safeCastTo160(x), x); 117 | } 118 | 119 | function testSafeCastTo128(uint256 x) public { 120 | x = bound(x, 0, type(uint128).max); 121 | 122 | assertEq(SafeCastLib.safeCastTo128(x), x); 123 | } 124 | 125 | function testSafeCastTo96(uint256 x) public { 126 | x = bound(x, 0, type(uint96).max); 127 | 128 | assertEq(SafeCastLib.safeCastTo96(x), x); 129 | } 130 | 131 | function testSafeCastTo64(uint256 x) public { 132 | x = bound(x, 0, type(uint64).max); 133 | 134 | assertEq(SafeCastLib.safeCastTo64(x), x); 135 | } 136 | 137 | function testSafeCastTo32(uint256 x) public { 138 | x = bound(x, 0, type(uint32).max); 139 | 140 | assertEq(SafeCastLib.safeCastTo32(x), x); 141 | } 142 | 143 | function testSafeCastTo8(uint256 x) public { 144 | x = bound(x, 0, type(uint8).max); 145 | 146 | assertEq(SafeCastLib.safeCastTo8(x), x); 147 | } 148 | 149 | function testFailSafeCastTo248(uint256 x) public { 150 | x = bound(x, type(uint248).max + 1, type(uint256).max); 151 | 152 | SafeCastLib.safeCastTo248(x); 153 | } 154 | 155 | function testFailSafeCastTo224(uint256 x) public { 156 | x = bound(x, type(uint224).max + 1, type(uint256).max); 157 | 158 | SafeCastLib.safeCastTo224(x); 159 | } 160 | 161 | function testFailSafeCastTo192(uint256 x) public { 162 | x = bound(x, type(uint192).max + 1, type(uint256).max); 163 | 164 | SafeCastLib.safeCastTo192(x); 165 | } 166 | 167 | function testFailSafeCastTo160(uint256 x) public { 168 | x = bound(x, type(uint160).max + 1, type(uint256).max); 169 | 170 | SafeCastLib.safeCastTo160(x); 171 | } 172 | 173 | function testFailSafeCastTo128(uint256 x) public { 174 | x = bound(x, type(uint128).max + 1, type(uint256).max); 175 | 176 | SafeCastLib.safeCastTo128(x); 177 | } 178 | 179 | function testFailSafeCastTo96(uint256 x) public { 180 | x = bound(x, type(uint96).max + 1, type(uint256).max); 181 | 182 | SafeCastLib.safeCastTo96(x); 183 | } 184 | 185 | function testFailSafeCastTo64(uint256 x) public { 186 | x = bound(x, type(uint64).max + 1, type(uint256).max); 187 | 188 | SafeCastLib.safeCastTo64(x); 189 | } 190 | 191 | function testFailSafeCastTo32(uint256 x) public { 192 | x = bound(x, type(uint32).max + 1, type(uint256).max); 193 | 194 | SafeCastLib.safeCastTo32(x); 195 | } 196 | 197 | function testFailSafeCastTo24(uint256 x) public { 198 | x = bound(x, type(uint24).max + 1, type(uint256).max); 199 | 200 | SafeCastLib.safeCastTo24(x); 201 | } 202 | 203 | function testFailSafeCastTo8(uint256 x) public { 204 | x = bound(x, type(uint8).max + 1, type(uint256).max); 205 | 206 | SafeCastLib.safeCastTo8(x); 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /lib/solmate/src/test/WETH.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity 0.8.15; 3 | 4 | import {DSTestPlus} from "./utils/DSTestPlus.sol"; 5 | import {DSInvariantTest} from "./utils/DSInvariantTest.sol"; 6 | 7 | import {SafeTransferLib} from "../utils/SafeTransferLib.sol"; 8 | 9 | import {WETH} from "../tokens/WETH.sol"; 10 | 11 | contract WETHTest is DSTestPlus { 12 | WETH weth; 13 | 14 | function setUp() public { 15 | weth = new WETH(); 16 | } 17 | 18 | function testFallbackDeposit() public { 19 | assertEq(weth.balanceOf(address(this)), 0); 20 | assertEq(weth.totalSupply(), 0); 21 | 22 | SafeTransferLib.safeTransferETH(address(weth), 1 ether); 23 | 24 | assertEq(weth.balanceOf(address(this)), 1 ether); 25 | assertEq(weth.totalSupply(), 1 ether); 26 | } 27 | 28 | function testDeposit() public { 29 | assertEq(weth.balanceOf(address(this)), 0); 30 | assertEq(weth.totalSupply(), 0); 31 | 32 | weth.deposit{value: 1 ether}(); 33 | 34 | assertEq(weth.balanceOf(address(this)), 1 ether); 35 | assertEq(weth.totalSupply(), 1 ether); 36 | } 37 | 38 | function testWithdraw() public { 39 | uint256 startingBalance = address(this).balance; 40 | 41 | weth.deposit{value: 1 ether}(); 42 | 43 | weth.withdraw(1 ether); 44 | 45 | uint256 balanceAfterWithdraw = address(this).balance; 46 | 47 | assertEq(balanceAfterWithdraw, startingBalance); 48 | assertEq(weth.balanceOf(address(this)), 0); 49 | assertEq(weth.totalSupply(), 0); 50 | } 51 | 52 | function testPartialWithdraw() public { 53 | weth.deposit{value: 1 ether}(); 54 | 55 | uint256 balanceBeforeWithdraw = address(this).balance; 56 | 57 | weth.withdraw(0.5 ether); 58 | 59 | uint256 balanceAfterWithdraw = address(this).balance; 60 | 61 | assertEq(balanceAfterWithdraw, balanceBeforeWithdraw + 0.5 ether); 62 | assertEq(weth.balanceOf(address(this)), 0.5 ether); 63 | assertEq(weth.totalSupply(), 0.5 ether); 64 | } 65 | 66 | function testFallbackDeposit(uint256 amount) public { 67 | amount = bound(amount, 0, address(this).balance); 68 | 69 | assertEq(weth.balanceOf(address(this)), 0); 70 | assertEq(weth.totalSupply(), 0); 71 | 72 | SafeTransferLib.safeTransferETH(address(weth), amount); 73 | 74 | assertEq(weth.balanceOf(address(this)), amount); 75 | assertEq(weth.totalSupply(), amount); 76 | } 77 | 78 | function testDeposit(uint256 amount) public { 79 | amount = bound(amount, 0, address(this).balance); 80 | 81 | assertEq(weth.balanceOf(address(this)), 0); 82 | assertEq(weth.totalSupply(), 0); 83 | 84 | weth.deposit{value: amount}(); 85 | 86 | assertEq(weth.balanceOf(address(this)), amount); 87 | assertEq(weth.totalSupply(), amount); 88 | } 89 | 90 | function testWithdraw(uint256 depositAmount, uint256 withdrawAmount) public { 91 | depositAmount = bound(depositAmount, 0, address(this).balance); 92 | withdrawAmount = bound(withdrawAmount, 0, depositAmount); 93 | 94 | weth.deposit{value: depositAmount}(); 95 | 96 | uint256 balanceBeforeWithdraw = address(this).balance; 97 | 98 | weth.withdraw(withdrawAmount); 99 | 100 | uint256 balanceAfterWithdraw = address(this).balance; 101 | 102 | assertEq(balanceAfterWithdraw, balanceBeforeWithdraw + withdrawAmount); 103 | assertEq(weth.balanceOf(address(this)), depositAmount - withdrawAmount); 104 | assertEq(weth.totalSupply(), depositAmount - withdrawAmount); 105 | } 106 | 107 | receive() external payable {} 108 | } 109 | 110 | contract WETHInvariants is DSTestPlus, DSInvariantTest { 111 | WETHTester wethTester; 112 | WETH weth; 113 | 114 | function setUp() public { 115 | weth = new WETH(); 116 | wethTester = new WETHTester{value: address(this).balance}(weth); 117 | 118 | addTargetContract(address(wethTester)); 119 | } 120 | 121 | function invariantTotalSupplyEqualsBalance() public { 122 | assertEq(address(weth).balance, weth.totalSupply()); 123 | } 124 | } 125 | 126 | contract WETHTester { 127 | WETH weth; 128 | 129 | constructor(WETH _weth) payable { 130 | weth = _weth; 131 | } 132 | 133 | function deposit(uint256 amount) public { 134 | weth.deposit{value: amount}(); 135 | } 136 | 137 | function fallbackDeposit(uint256 amount) public { 138 | SafeTransferLib.safeTransferETH(address(weth), amount); 139 | } 140 | 141 | function withdraw(uint256 amount) public { 142 | weth.withdraw(amount); 143 | } 144 | 145 | receive() external payable {} 146 | } 147 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/DSInvariantTest.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract DSInvariantTest { 5 | address[] private targets; 6 | 7 | function targetContracts() public view virtual returns (address[] memory) { 8 | require(targets.length > 0, "NO_TARGET_CONTRACTS"); 9 | 10 | return targets; 11 | } 12 | 13 | function addTargetContract(address newTargetContract) internal virtual { 14 | targets.push(newTargetContract); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/DSTestPlus.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {DSTest} from "ds-test/test.sol"; 5 | 6 | import {Hevm} from "./Hevm.sol"; 7 | 8 | /// @notice Extended testing framework for DappTools projects. 9 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/test/utils/DSTestPlus.sol) 10 | contract DSTestPlus is DSTest { 11 | Hevm internal constant hevm = Hevm(HEVM_ADDRESS); 12 | 13 | address internal constant DEAD_ADDRESS = 0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF; 14 | 15 | string private checkpointLabel; 16 | uint256 private checkpointGasLeft = 1; // Start the slot warm. 17 | 18 | modifier brutalizeMemory(bytes memory brutalizeWith) { 19 | /// @solidity memory-safe-assembly 20 | assembly { 21 | // Fill the 64 bytes of scratch space with the data. 22 | pop( 23 | staticcall( 24 | gas(), // Pass along all the gas in the call. 25 | 0x04, // Call the identity precompile address. 26 | brutalizeWith, // Offset is the bytes' pointer. 27 | 64, // Copy enough to only fill the scratch space. 28 | 0, // Store the return value in the scratch space. 29 | 64 // Scratch space is only 64 bytes in size, we don't want to write further. 30 | ) 31 | ) 32 | 33 | let size := add(mload(brutalizeWith), 32) // Add 32 to include the 32 byte length slot. 34 | 35 | // Fill the free memory pointer's destination with the data. 36 | pop( 37 | staticcall( 38 | gas(), // Pass along all the gas in the call. 39 | 0x04, // Call the identity precompile address. 40 | brutalizeWith, // Offset is the bytes' pointer. 41 | size, // We want to pass the length of the bytes. 42 | mload(0x40), // Store the return value at the free memory pointer. 43 | size // Since the precompile just returns its input, we reuse size. 44 | ) 45 | ) 46 | } 47 | 48 | _; 49 | } 50 | 51 | function startMeasuringGas(string memory label) internal virtual { 52 | checkpointLabel = label; 53 | 54 | checkpointGasLeft = gasleft(); 55 | } 56 | 57 | function stopMeasuringGas() internal virtual { 58 | uint256 checkpointGasLeft2 = gasleft(); 59 | 60 | // Subtract 100 to account for the warm SLOAD in startMeasuringGas. 61 | uint256 gasDelta = checkpointGasLeft - checkpointGasLeft2 - 100; 62 | 63 | emit log_named_uint(string(abi.encodePacked(checkpointLabel, " Gas")), gasDelta); 64 | } 65 | 66 | function fail(string memory err) internal virtual { 67 | emit log_named_string("Error", err); 68 | fail(); 69 | } 70 | 71 | function assertFalse(bool data) internal virtual { 72 | assertTrue(!data); 73 | } 74 | 75 | function assertUint128Eq(uint128 a, uint128 b) internal virtual { 76 | assertEq(uint256(a), uint256(b)); 77 | } 78 | 79 | function assertUint64Eq(uint64 a, uint64 b) internal virtual { 80 | assertEq(uint256(a), uint256(b)); 81 | } 82 | 83 | function assertUint96Eq(uint96 a, uint96 b) internal virtual { 84 | assertEq(uint256(a), uint256(b)); 85 | } 86 | 87 | function assertUint32Eq(uint32 a, uint32 b) internal virtual { 88 | assertEq(uint256(a), uint256(b)); 89 | } 90 | 91 | function assertBoolEq(bool a, bool b) internal virtual { 92 | b ? assertTrue(a) : assertFalse(a); 93 | } 94 | 95 | function assertApproxEq( 96 | uint256 a, 97 | uint256 b, 98 | uint256 maxDelta 99 | ) internal virtual { 100 | uint256 delta = a > b ? a - b : b - a; 101 | 102 | if (delta > maxDelta) { 103 | emit log("Error: a ~= b not satisfied [uint]"); 104 | emit log_named_uint(" Expected", b); 105 | emit log_named_uint(" Actual", a); 106 | emit log_named_uint(" Max Delta", maxDelta); 107 | emit log_named_uint(" Delta", delta); 108 | fail(); 109 | } 110 | } 111 | 112 | function assertRelApproxEq( 113 | uint256 a, 114 | uint256 b, 115 | uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100% 116 | ) internal virtual { 117 | if (b == 0) return assertEq(a, b); // If the expected is 0, actual must be too. 118 | 119 | uint256 percentDelta = ((a > b ? a - b : b - a) * 1e18) / b; 120 | 121 | if (percentDelta > maxPercentDelta) { 122 | emit log("Error: a ~= b not satisfied [uint]"); 123 | emit log_named_uint(" Expected", b); 124 | emit log_named_uint(" Actual", a); 125 | emit log_named_decimal_uint(" Max % Delta", maxPercentDelta, 18); 126 | emit log_named_decimal_uint(" % Delta", percentDelta, 18); 127 | fail(); 128 | } 129 | } 130 | 131 | function assertBytesEq(bytes memory a, bytes memory b) internal virtual { 132 | if (keccak256(a) != keccak256(b)) { 133 | emit log("Error: a == b not satisfied [bytes]"); 134 | emit log_named_bytes(" Expected", b); 135 | emit log_named_bytes(" Actual", a); 136 | fail(); 137 | } 138 | } 139 | 140 | function assertUintArrayEq(uint256[] memory a, uint256[] memory b) internal virtual { 141 | require(a.length == b.length, "LENGTH_MISMATCH"); 142 | 143 | for (uint256 i = 0; i < a.length; i++) { 144 | assertEq(a[i], b[i]); 145 | } 146 | } 147 | 148 | function bound( 149 | uint256 x, 150 | uint256 min, 151 | uint256 max 152 | ) internal virtual returns (uint256 result) { 153 | require(max >= min, "MAX_LESS_THAN_MIN"); 154 | 155 | uint256 size = max - min; 156 | 157 | if (size == 0) result = min; 158 | else if (size == type(uint256).max) result = x; 159 | else { 160 | ++size; // Make max inclusive. 161 | uint256 mod = x % size; 162 | result = min + mod; 163 | } 164 | 165 | emit log_named_uint("Bound Result", result); 166 | } 167 | 168 | function min3( 169 | uint256 a, 170 | uint256 b, 171 | uint256 c 172 | ) internal pure returns (uint256) { 173 | return a > b ? (b > c ? c : b) : (a > c ? c : a); 174 | } 175 | 176 | function min2(uint256 a, uint256 b) internal pure returns (uint256) { 177 | return a > b ? b : a; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/Hevm.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | interface Hevm { 5 | /// @notice Sets the block timestamp. 6 | function warp(uint256) external; 7 | 8 | /// @notice Sets the block height. 9 | function roll(uint256) external; 10 | 11 | /// @notice Sets the block base fee. 12 | function fee(uint256) external; 13 | 14 | /// @notice Loads a storage slot from an address. 15 | function load(address, bytes32) external returns (bytes32); 16 | 17 | /// @notice Stores a value to an address' storage slot. 18 | function store( 19 | address, 20 | bytes32, 21 | bytes32 22 | ) external; 23 | 24 | /// @notice Signs a digest with a private key, returns v r s. 25 | function sign(uint256, bytes32) 26 | external 27 | returns ( 28 | uint8, 29 | bytes32, 30 | bytes32 31 | ); 32 | 33 | /// @notice Gets address for a given private key. 34 | function addr(uint256) external returns (address); 35 | 36 | /// @notice Performs a foreign function call via a terminal call. 37 | function ffi(string[] calldata) external returns (bytes memory); 38 | 39 | /// @notice Sets the next call's msg.sender to be the input address. 40 | function prank(address) external; 41 | 42 | /// @notice Sets all subsequent calls' msg.sender to be the input address until stopPrank is called. 43 | function startPrank(address) external; 44 | 45 | /// @notice Sets the next call's msg.sender to be the input address and the tx.origin to be the second input. 46 | function prank(address, address) external; 47 | 48 | /// @notice Sets all subsequent calls' msg.sender to be the input address and 49 | /// sets tx.origin to be the second address inputted until stopPrank is called. 50 | function startPrank(address, address) external; 51 | 52 | /// @notice Resets msg.sender to its original value before a prank. 53 | function stopPrank() external; 54 | 55 | /// @notice Sets an address' balance. 56 | function deal(address, uint256) external; 57 | 58 | /// @notice Sets an address' code. 59 | function etch(address, bytes calldata) external; 60 | 61 | /// @notice Expects an error from the next call. 62 | function expectRevert(bytes calldata) external; 63 | 64 | /// @notice Expects a revert from the next call. 65 | function expectRevert(bytes4) external; 66 | 67 | /// @notice Record all storage reads and writes. 68 | function record() external; 69 | 70 | /// @notice Gets all accessed reads and write slots from a recording session, for a given address. 71 | function accesses(address) external returns (bytes32[] memory reads, bytes32[] memory writes); 72 | 73 | /// @notice Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData). 74 | /// @notice Call this function, then emit an event, then call a function. Internally after the call, we check 75 | /// if logs were emitted in the expected order with the expected topics and data as specified by the booleans. 76 | function expectEmit( 77 | bool, 78 | bool, 79 | bool, 80 | bool 81 | ) external; 82 | 83 | /// @notice Mocks the behavior of a contract call, setting the input and output for a function. 84 | /// @notice Calldata can either be strict or a partial match, e.g. if only passed 85 | /// a selector to the expected calldata, then the entire function will be mocked. 86 | function mockCall( 87 | address, 88 | bytes calldata, 89 | bytes calldata 90 | ) external; 91 | 92 | /// @notice Clears all mocked calls. 93 | function clearMockedCalls() external; 94 | 95 | /// @notice Expect a call to an address with the specified calldata. 96 | /// @notice Calldata can either be strict or a partial match. 97 | function expectCall(address, bytes calldata) external; 98 | 99 | /// @notice Fetches the contract bytecode from its artifact file. 100 | function getCode(string calldata) external returns (bytes memory); 101 | 102 | /// @notice Label an address in test traces. 103 | function label(address addr, string calldata label) external; 104 | 105 | /// @notice When fuzzing, generate new inputs if the input conditional is not met. 106 | function assume(bool) external; 107 | } 108 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockAuthChild.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {Auth, Authority} from "../../../auth/Auth.sol"; 5 | 6 | contract MockAuthChild is Auth(msg.sender, Authority(address(0))) { 7 | bool public flag; 8 | 9 | function updateFlag() public virtual requiresAuth { 10 | flag = true; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockAuthority.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {Authority} from "../../../auth/Auth.sol"; 5 | 6 | contract MockAuthority is Authority { 7 | bool immutable allowCalls; 8 | 9 | constructor(bool _allowCalls) { 10 | allowCalls = _allowCalls; 11 | } 12 | 13 | function canCall( 14 | address, 15 | address, 16 | bytes4 17 | ) public view override returns (bool) { 18 | return allowCalls; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockERC1155.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC1155} from "../../../tokens/ERC1155.sol"; 5 | 6 | contract MockERC1155 is ERC1155 { 7 | function uri(uint256) public pure virtual override returns (string memory) {} 8 | 9 | function mint( 10 | address to, 11 | uint256 id, 12 | uint256 amount, 13 | bytes memory data 14 | ) public virtual { 15 | _mint(to, id, amount, data); 16 | } 17 | 18 | function batchMint( 19 | address to, 20 | uint256[] memory ids, 21 | uint256[] memory amounts, 22 | bytes memory data 23 | ) public virtual { 24 | _batchMint(to, ids, amounts, data); 25 | } 26 | 27 | function burn( 28 | address from, 29 | uint256 id, 30 | uint256 amount 31 | ) public virtual { 32 | _burn(from, id, amount); 33 | } 34 | 35 | function batchBurn( 36 | address from, 37 | uint256[] memory ids, 38 | uint256[] memory amounts 39 | ) public virtual { 40 | _batchBurn(from, ids, amounts); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC20} from "../../../tokens/ERC20.sol"; 5 | 6 | contract MockERC20 is ERC20 { 7 | constructor( 8 | string memory _name, 9 | string memory _symbol, 10 | uint8 _decimals 11 | ) ERC20(_name, _symbol, _decimals) {} 12 | 13 | function mint(address to, uint256 value) public virtual { 14 | _mint(to, value); 15 | } 16 | 17 | function burn(address from, uint256 value) public virtual { 18 | _burn(from, value); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockERC4626.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC20} from "../../../tokens/ERC20.sol"; 5 | import {ERC4626} from "../../../mixins/ERC4626.sol"; 6 | 7 | contract MockERC4626 is ERC4626 { 8 | uint256 public beforeWithdrawHookCalledCounter = 0; 9 | uint256 public afterDepositHookCalledCounter = 0; 10 | 11 | constructor( 12 | ERC20 _underlying, 13 | string memory _name, 14 | string memory _symbol 15 | ) ERC4626(_underlying, _name, _symbol) {} 16 | 17 | function totalAssets() public view override returns (uint256) { 18 | return asset.balanceOf(address(this)); 19 | } 20 | 21 | function beforeWithdraw(uint256, uint256) internal override { 22 | beforeWithdrawHookCalledCounter++; 23 | } 24 | 25 | function afterDeposit(uint256, uint256) internal override { 26 | afterDepositHookCalledCounter++; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC721} from "../../../tokens/ERC721.sol"; 5 | 6 | contract MockERC721 is ERC721 { 7 | constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {} 8 | 9 | function tokenURI(uint256) public pure virtual override returns (string memory) {} 10 | 11 | function mint(address to, uint256 tokenId) public virtual { 12 | _mint(to, tokenId); 13 | } 14 | 15 | function burn(uint256 tokenId) public virtual { 16 | _burn(tokenId); 17 | } 18 | 19 | function safeMint(address to, uint256 tokenId) public virtual { 20 | _safeMint(to, tokenId); 21 | } 22 | 23 | function safeMint( 24 | address to, 25 | uint256 tokenId, 26 | bytes memory data 27 | ) public virtual { 28 | _safeMint(to, tokenId, data); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/mocks/MockOwned.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {Owned} from "../../../auth/Owned.sol"; 5 | 6 | contract MockOwned is Owned(msg.sender) { 7 | bool public flag; 8 | 9 | function updateFlag() public virtual onlyOwner { 10 | flag = true; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/MissingReturnToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract MissingReturnToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "MissingReturnToken"; 18 | 19 | string public constant symbol = "MRT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | CONSTRUCTOR 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | constructor() { 38 | totalSupply = type(uint256).max; 39 | balanceOf[msg.sender] = type(uint256).max; 40 | } 41 | 42 | /*/////////////////////////////////////////////////////////////// 43 | ERC20 LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function approve(address spender, uint256 amount) public virtual { 47 | allowance[msg.sender][spender] = amount; 48 | 49 | emit Approval(msg.sender, spender, amount); 50 | } 51 | 52 | function transfer(address to, uint256 amount) public virtual { 53 | balanceOf[msg.sender] -= amount; 54 | 55 | // Cannot overflow because the sum of all user 56 | // balances can't exceed the max uint256 value. 57 | unchecked { 58 | balanceOf[to] += amount; 59 | } 60 | 61 | emit Transfer(msg.sender, to, amount); 62 | } 63 | 64 | function transferFrom( 65 | address from, 66 | address to, 67 | uint256 amount 68 | ) public virtual { 69 | uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. 70 | 71 | if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; 72 | 73 | balanceOf[from] -= amount; 74 | 75 | // Cannot overflow because the sum of all user 76 | // balances can't exceed the max uint256 value. 77 | unchecked { 78 | balanceOf[to] += amount; 79 | } 80 | 81 | emit Transfer(from, to, amount); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/ReturnsFalseToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract ReturnsFalseToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "ReturnsFalseToken"; 18 | 19 | string public constant symbol = "RFT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | CONSTRUCTOR 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | constructor() { 38 | totalSupply = type(uint256).max; 39 | balanceOf[msg.sender] = type(uint256).max; 40 | } 41 | 42 | /*/////////////////////////////////////////////////////////////// 43 | ERC20 LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function approve(address, uint256) public virtual returns (bool) { 47 | return false; 48 | } 49 | 50 | function transfer(address, uint256) public virtual returns (bool) { 51 | return false; 52 | } 53 | 54 | function transferFrom( 55 | address, 56 | address, 57 | uint256 58 | ) public virtual returns (bool) { 59 | return false; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/ReturnsGarbageToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract ReturnsGarbageToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "ReturnsGarbageToken"; 18 | 19 | string public constant symbol = "RGT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | MOCK STORAGE 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | bytes garbage; 38 | 39 | /*/////////////////////////////////////////////////////////////// 40 | CONSTRUCTOR 41 | //////////////////////////////////////////////////////////////*/ 42 | 43 | constructor() { 44 | totalSupply = type(uint256).max; 45 | balanceOf[msg.sender] = type(uint256).max; 46 | } 47 | 48 | /*/////////////////////////////////////////////////////////////// 49 | ERC20 LOGIC 50 | //////////////////////////////////////////////////////////////*/ 51 | 52 | function approve(address spender, uint256 amount) public virtual { 53 | allowance[msg.sender][spender] = amount; 54 | 55 | emit Approval(msg.sender, spender, amount); 56 | 57 | bytes memory _garbage = garbage; 58 | 59 | assembly { 60 | return(add(_garbage, 32), mload(_garbage)) 61 | } 62 | } 63 | 64 | function transfer(address to, uint256 amount) public virtual { 65 | balanceOf[msg.sender] -= amount; 66 | 67 | // Cannot overflow because the sum of all user 68 | // balances can't exceed the max uint256 value. 69 | unchecked { 70 | balanceOf[to] += amount; 71 | } 72 | 73 | emit Transfer(msg.sender, to, amount); 74 | 75 | bytes memory _garbage = garbage; 76 | 77 | assembly { 78 | return(add(_garbage, 32), mload(_garbage)) 79 | } 80 | } 81 | 82 | function transferFrom( 83 | address from, 84 | address to, 85 | uint256 amount 86 | ) public virtual { 87 | uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. 88 | 89 | if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; 90 | 91 | balanceOf[from] -= amount; 92 | 93 | // Cannot overflow because the sum of all user 94 | // balances can't exceed the max uint256 value. 95 | unchecked { 96 | balanceOf[to] += amount; 97 | } 98 | 99 | emit Transfer(from, to, amount); 100 | 101 | bytes memory _garbage = garbage; 102 | 103 | assembly { 104 | return(add(_garbage, 32), mload(_garbage)) 105 | } 106 | } 107 | 108 | /*/////////////////////////////////////////////////////////////// 109 | MOCK LOGIC 110 | //////////////////////////////////////////////////////////////*/ 111 | 112 | function setGarbage(bytes memory _garbage) public virtual { 113 | garbage = _garbage; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/ReturnsTooLittleToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract ReturnsTooLittleToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "ReturnsTooLittleToken"; 18 | 19 | string public constant symbol = "RTLT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | CONSTRUCTOR 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | constructor() { 38 | totalSupply = type(uint256).max; 39 | balanceOf[msg.sender] = type(uint256).max; 40 | } 41 | 42 | /*/////////////////////////////////////////////////////////////// 43 | ERC20 LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function approve(address, uint256) public virtual { 47 | assembly { 48 | mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) 49 | return(0, 8) 50 | } 51 | } 52 | 53 | function transfer(address, uint256) public virtual { 54 | assembly { 55 | mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) 56 | return(0, 8) 57 | } 58 | } 59 | 60 | function transferFrom( 61 | address, 62 | address, 63 | uint256 64 | ) public virtual { 65 | assembly { 66 | mstore(0, 0x0100000000000000000000000000000000000000000000000000000000000000) 67 | return(0, 8) 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/ReturnsTooMuchToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract ReturnsTooMuchToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "ReturnsTooMuchToken"; 18 | 19 | string public constant symbol = "RTMT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | CONSTRUCTOR 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | constructor() { 38 | totalSupply = type(uint256).max; 39 | balanceOf[msg.sender] = type(uint256).max; 40 | } 41 | 42 | /*/////////////////////////////////////////////////////////////// 43 | ERC20 LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function approve(address spender, uint256 amount) public virtual { 47 | allowance[msg.sender][spender] = amount; 48 | 49 | emit Approval(msg.sender, spender, amount); 50 | 51 | assembly { 52 | mstore(0, 1) 53 | return(0, 4096) 54 | } 55 | } 56 | 57 | function transfer(address to, uint256 amount) public virtual { 58 | balanceOf[msg.sender] -= amount; 59 | 60 | // Cannot overflow because the sum of all user 61 | // balances can't exceed the max uint256 value. 62 | unchecked { 63 | balanceOf[to] += amount; 64 | } 65 | 66 | emit Transfer(msg.sender, to, amount); 67 | 68 | assembly { 69 | mstore(0, 1) 70 | return(0, 4096) 71 | } 72 | } 73 | 74 | function transferFrom( 75 | address from, 76 | address to, 77 | uint256 amount 78 | ) public virtual { 79 | uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. 80 | 81 | if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; 82 | 83 | balanceOf[from] -= amount; 84 | 85 | // Cannot overflow because the sum of all user 86 | // balances can't exceed the max uint256 value. 87 | unchecked { 88 | balanceOf[to] += amount; 89 | } 90 | 91 | emit Transfer(from, to, amount); 92 | 93 | assembly { 94 | mstore(0, 1) 95 | return(0, 4096) 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/ReturnsTwoToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract ReturnsTwoToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "ReturnsFalseToken"; 18 | 19 | string public constant symbol = "RTT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | CONSTRUCTOR 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | constructor() { 38 | totalSupply = type(uint256).max; 39 | balanceOf[msg.sender] = type(uint256).max; 40 | } 41 | 42 | /*/////////////////////////////////////////////////////////////// 43 | ERC20 LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function approve(address, uint256) public virtual returns (uint256) { 47 | return 2; 48 | } 49 | 50 | function transfer(address, uint256) public virtual returns (uint256) { 51 | return 2; 52 | } 53 | 54 | function transferFrom( 55 | address, 56 | address, 57 | uint256 58 | ) public virtual returns (uint256) { 59 | return 2; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/solmate/src/test/utils/weird-tokens/RevertingToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | contract RevertingToken { 5 | /*/////////////////////////////////////////////////////////////// 6 | EVENTS 7 | //////////////////////////////////////////////////////////////*/ 8 | 9 | event Transfer(address indexed from, address indexed to, uint256 amount); 10 | 11 | event Approval(address indexed owner, address indexed spender, uint256 amount); 12 | 13 | /*/////////////////////////////////////////////////////////////// 14 | METADATA STORAGE 15 | //////////////////////////////////////////////////////////////*/ 16 | 17 | string public constant name = "RevertingToken"; 18 | 19 | string public constant symbol = "RT"; 20 | 21 | uint8 public constant decimals = 18; 22 | 23 | /*/////////////////////////////////////////////////////////////// 24 | ERC20 STORAGE 25 | //////////////////////////////////////////////////////////////*/ 26 | 27 | uint256 public totalSupply; 28 | 29 | mapping(address => uint256) public balanceOf; 30 | 31 | mapping(address => mapping(address => uint256)) public allowance; 32 | 33 | /*/////////////////////////////////////////////////////////////// 34 | CONSTRUCTOR 35 | //////////////////////////////////////////////////////////////*/ 36 | 37 | constructor() { 38 | totalSupply = type(uint256).max; 39 | balanceOf[msg.sender] = type(uint256).max; 40 | } 41 | 42 | /*/////////////////////////////////////////////////////////////// 43 | ERC20 LOGIC 44 | //////////////////////////////////////////////////////////////*/ 45 | 46 | function approve(address, uint256) public virtual { 47 | revert(); 48 | } 49 | 50 | function transfer(address, uint256) public virtual { 51 | revert(); 52 | } 53 | 54 | function transferFrom( 55 | address, 56 | address, 57 | uint256 58 | ) public virtual { 59 | revert(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/solmate/src/tokens/ERC1155.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Minimalist and gas efficient standard ERC1155 implementation. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) 6 | abstract contract ERC1155 { 7 | /*////////////////////////////////////////////////////////////// 8 | EVENTS 9 | //////////////////////////////////////////////////////////////*/ 10 | 11 | event TransferSingle( 12 | address indexed operator, 13 | address indexed from, 14 | address indexed to, 15 | uint256 id, 16 | uint256 amount 17 | ); 18 | 19 | event TransferBatch( 20 | address indexed operator, 21 | address indexed from, 22 | address indexed to, 23 | uint256[] ids, 24 | uint256[] amounts 25 | ); 26 | 27 | event ApprovalForAll(address indexed owner, address indexed operator, bool approved); 28 | 29 | event URI(string value, uint256 indexed id); 30 | 31 | /*////////////////////////////////////////////////////////////// 32 | ERC1155 STORAGE 33 | //////////////////////////////////////////////////////////////*/ 34 | 35 | mapping(address => mapping(uint256 => uint256)) public balanceOf; 36 | 37 | mapping(address => mapping(address => bool)) public isApprovedForAll; 38 | 39 | /*////////////////////////////////////////////////////////////// 40 | METADATA LOGIC 41 | //////////////////////////////////////////////////////////////*/ 42 | 43 | function uri(uint256 id) public view virtual returns (string memory); 44 | 45 | /*////////////////////////////////////////////////////////////// 46 | ERC1155 LOGIC 47 | //////////////////////////////////////////////////////////////*/ 48 | 49 | function setApprovalForAll(address operator, bool approved) public virtual { 50 | isApprovedForAll[msg.sender][operator] = approved; 51 | 52 | emit ApprovalForAll(msg.sender, operator, approved); 53 | } 54 | 55 | function safeTransferFrom( 56 | address from, 57 | address to, 58 | uint256 id, 59 | uint256 amount, 60 | bytes calldata data 61 | ) public virtual { 62 | require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); 63 | 64 | balanceOf[from][id] -= amount; 65 | balanceOf[to][id] += amount; 66 | 67 | emit TransferSingle(msg.sender, from, to, id, amount); 68 | 69 | require( 70 | to.code.length == 0 71 | ? to != address(0) 72 | : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == 73 | ERC1155TokenReceiver.onERC1155Received.selector, 74 | "UNSAFE_RECIPIENT" 75 | ); 76 | } 77 | 78 | function safeBatchTransferFrom( 79 | address from, 80 | address to, 81 | uint256[] calldata ids, 82 | uint256[] calldata amounts, 83 | bytes calldata data 84 | ) public virtual { 85 | require(ids.length == amounts.length, "LENGTH_MISMATCH"); 86 | 87 | require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); 88 | 89 | // Storing these outside the loop saves ~15 gas per iteration. 90 | uint256 id; 91 | uint256 amount; 92 | 93 | for (uint256 i = 0; i < ids.length; ) { 94 | id = ids[i]; 95 | amount = amounts[i]; 96 | 97 | balanceOf[from][id] -= amount; 98 | balanceOf[to][id] += amount; 99 | 100 | // An array can't have a total length 101 | // larger than the max uint256 value. 102 | unchecked { 103 | ++i; 104 | } 105 | } 106 | 107 | emit TransferBatch(msg.sender, from, to, ids, amounts); 108 | 109 | require( 110 | to.code.length == 0 111 | ? to != address(0) 112 | : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == 113 | ERC1155TokenReceiver.onERC1155BatchReceived.selector, 114 | "UNSAFE_RECIPIENT" 115 | ); 116 | } 117 | 118 | function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) 119 | public 120 | view 121 | virtual 122 | returns (uint256[] memory balances) 123 | { 124 | require(owners.length == ids.length, "LENGTH_MISMATCH"); 125 | 126 | balances = new uint256[](owners.length); 127 | 128 | // Unchecked because the only math done is incrementing 129 | // the array index counter which cannot possibly overflow. 130 | unchecked { 131 | for (uint256 i = 0; i < owners.length; ++i) { 132 | balances[i] = balanceOf[owners[i]][ids[i]]; 133 | } 134 | } 135 | } 136 | 137 | /*////////////////////////////////////////////////////////////// 138 | ERC165 LOGIC 139 | //////////////////////////////////////////////////////////////*/ 140 | 141 | function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { 142 | return 143 | interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 144 | interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 145 | interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI 146 | } 147 | 148 | /*////////////////////////////////////////////////////////////// 149 | INTERNAL MINT/BURN LOGIC 150 | //////////////////////////////////////////////////////////////*/ 151 | 152 | function _mint( 153 | address to, 154 | uint256 id, 155 | uint256 amount, 156 | bytes memory data 157 | ) internal virtual { 158 | balanceOf[to][id] += amount; 159 | 160 | emit TransferSingle(msg.sender, address(0), to, id, amount); 161 | 162 | require( 163 | to.code.length == 0 164 | ? to != address(0) 165 | : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) == 166 | ERC1155TokenReceiver.onERC1155Received.selector, 167 | "UNSAFE_RECIPIENT" 168 | ); 169 | } 170 | 171 | function _batchMint( 172 | address to, 173 | uint256[] memory ids, 174 | uint256[] memory amounts, 175 | bytes memory data 176 | ) internal virtual { 177 | uint256 idsLength = ids.length; // Saves MLOADs. 178 | 179 | require(idsLength == amounts.length, "LENGTH_MISMATCH"); 180 | 181 | for (uint256 i = 0; i < idsLength; ) { 182 | balanceOf[to][ids[i]] += amounts[i]; 183 | 184 | // An array can't have a total length 185 | // larger than the max uint256 value. 186 | unchecked { 187 | ++i; 188 | } 189 | } 190 | 191 | emit TransferBatch(msg.sender, address(0), to, ids, amounts); 192 | 193 | require( 194 | to.code.length == 0 195 | ? to != address(0) 196 | : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == 197 | ERC1155TokenReceiver.onERC1155BatchReceived.selector, 198 | "UNSAFE_RECIPIENT" 199 | ); 200 | } 201 | 202 | function _batchBurn( 203 | address from, 204 | uint256[] memory ids, 205 | uint256[] memory amounts 206 | ) internal virtual { 207 | uint256 idsLength = ids.length; // Saves MLOADs. 208 | 209 | require(idsLength == amounts.length, "LENGTH_MISMATCH"); 210 | 211 | for (uint256 i = 0; i < idsLength; ) { 212 | balanceOf[from][ids[i]] -= amounts[i]; 213 | 214 | // An array can't have a total length 215 | // larger than the max uint256 value. 216 | unchecked { 217 | ++i; 218 | } 219 | } 220 | 221 | emit TransferBatch(msg.sender, from, address(0), ids, amounts); 222 | } 223 | 224 | function _burn( 225 | address from, 226 | uint256 id, 227 | uint256 amount 228 | ) internal virtual { 229 | balanceOf[from][id] -= amount; 230 | 231 | emit TransferSingle(msg.sender, from, address(0), id, amount); 232 | } 233 | } 234 | 235 | /// @notice A generic interface for a contract which properly accepts ERC1155 tokens. 236 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) 237 | abstract contract ERC1155TokenReceiver { 238 | function onERC1155Received( 239 | address, 240 | address, 241 | uint256, 242 | uint256, 243 | bytes calldata 244 | ) external virtual returns (bytes4) { 245 | return ERC1155TokenReceiver.onERC1155Received.selector; 246 | } 247 | 248 | function onERC1155BatchReceived( 249 | address, 250 | address, 251 | uint256[] calldata, 252 | uint256[] calldata, 253 | bytes calldata 254 | ) external virtual returns (bytes4) { 255 | return ERC1155TokenReceiver.onERC1155BatchReceived.selector; 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /lib/solmate/src/tokens/ERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) 6 | /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) 7 | /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. 8 | abstract contract ERC20 { 9 | /*////////////////////////////////////////////////////////////// 10 | EVENTS 11 | //////////////////////////////////////////////////////////////*/ 12 | 13 | event Transfer(address indexed from, address indexed to, uint256 amount); 14 | 15 | event Approval(address indexed owner, address indexed spender, uint256 amount); 16 | 17 | /*////////////////////////////////////////////////////////////// 18 | METADATA STORAGE 19 | //////////////////////////////////////////////////////////////*/ 20 | 21 | string public name; 22 | 23 | string public symbol; 24 | 25 | uint8 public immutable decimals; 26 | 27 | /*////////////////////////////////////////////////////////////// 28 | ERC20 STORAGE 29 | //////////////////////////////////////////////////////////////*/ 30 | 31 | uint256 public totalSupply; 32 | 33 | mapping(address => uint256) public balanceOf; 34 | 35 | mapping(address => mapping(address => uint256)) public allowance; 36 | 37 | /*////////////////////////////////////////////////////////////// 38 | EIP-2612 STORAGE 39 | //////////////////////////////////////////////////////////////*/ 40 | 41 | uint256 internal immutable INITIAL_CHAIN_ID; 42 | 43 | bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; 44 | 45 | mapping(address => uint256) public nonces; 46 | 47 | /*////////////////////////////////////////////////////////////// 48 | CONSTRUCTOR 49 | //////////////////////////////////////////////////////////////*/ 50 | 51 | constructor( 52 | string memory _name, 53 | string memory _symbol, 54 | uint8 _decimals 55 | ) { 56 | name = _name; 57 | symbol = _symbol; 58 | decimals = _decimals; 59 | 60 | INITIAL_CHAIN_ID = block.chainid; 61 | INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); 62 | } 63 | 64 | /*////////////////////////////////////////////////////////////// 65 | ERC20 LOGIC 66 | //////////////////////////////////////////////////////////////*/ 67 | 68 | function approve(address spender, uint256 amount) public virtual returns (bool) { 69 | allowance[msg.sender][spender] = amount; 70 | 71 | emit Approval(msg.sender, spender, amount); 72 | 73 | return true; 74 | } 75 | 76 | function transfer(address to, uint256 amount) public virtual returns (bool) { 77 | balanceOf[msg.sender] -= amount; 78 | 79 | // Cannot overflow because the sum of all user 80 | // balances can't exceed the max uint256 value. 81 | unchecked { 82 | balanceOf[to] += amount; 83 | } 84 | 85 | emit Transfer(msg.sender, to, amount); 86 | 87 | return true; 88 | } 89 | 90 | function transferFrom( 91 | address from, 92 | address to, 93 | uint256 amount 94 | ) public virtual returns (bool) { 95 | uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. 96 | 97 | if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; 98 | 99 | balanceOf[from] -= amount; 100 | 101 | // Cannot overflow because the sum of all user 102 | // balances can't exceed the max uint256 value. 103 | unchecked { 104 | balanceOf[to] += amount; 105 | } 106 | 107 | emit Transfer(from, to, amount); 108 | 109 | return true; 110 | } 111 | 112 | /*////////////////////////////////////////////////////////////// 113 | EIP-2612 LOGIC 114 | //////////////////////////////////////////////////////////////*/ 115 | 116 | function permit( 117 | address owner, 118 | address spender, 119 | uint256 value, 120 | uint256 deadline, 121 | uint8 v, 122 | bytes32 r, 123 | bytes32 s 124 | ) public virtual { 125 | require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); 126 | 127 | // Unchecked because the only math done is incrementing 128 | // the owner's nonce which cannot realistically overflow. 129 | unchecked { 130 | address recoveredAddress = ecrecover( 131 | keccak256( 132 | abi.encodePacked( 133 | "\x19\x01", 134 | DOMAIN_SEPARATOR(), 135 | keccak256( 136 | abi.encode( 137 | keccak256( 138 | "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" 139 | ), 140 | owner, 141 | spender, 142 | value, 143 | nonces[owner]++, 144 | deadline 145 | ) 146 | ) 147 | ) 148 | ), 149 | v, 150 | r, 151 | s 152 | ); 153 | 154 | require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); 155 | 156 | allowance[recoveredAddress][spender] = value; 157 | } 158 | 159 | emit Approval(owner, spender, value); 160 | } 161 | 162 | function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { 163 | return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); 164 | } 165 | 166 | function computeDomainSeparator() internal view virtual returns (bytes32) { 167 | return 168 | keccak256( 169 | abi.encode( 170 | keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), 171 | keccak256(bytes(name)), 172 | keccak256("1"), 173 | block.chainid, 174 | address(this) 175 | ) 176 | ); 177 | } 178 | 179 | /*////////////////////////////////////////////////////////////// 180 | INTERNAL MINT/BURN LOGIC 181 | //////////////////////////////////////////////////////////////*/ 182 | 183 | function _mint(address to, uint256 amount) internal virtual { 184 | totalSupply += amount; 185 | 186 | // Cannot overflow because the sum of all user 187 | // balances can't exceed the max uint256 value. 188 | unchecked { 189 | balanceOf[to] += amount; 190 | } 191 | 192 | emit Transfer(address(0), to, amount); 193 | } 194 | 195 | function _burn(address from, uint256 amount) internal virtual { 196 | balanceOf[from] -= amount; 197 | 198 | // Cannot underflow because a user's balance 199 | // will never be larger than the total supply. 200 | unchecked { 201 | totalSupply -= amount; 202 | } 203 | 204 | emit Transfer(from, address(0), amount); 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /lib/solmate/src/tokens/ERC721.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Modern, minimalist, and gas efficient ERC-721 implementation. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) 6 | abstract contract ERC721 { 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 | CONSTRUCTOR 55 | //////////////////////////////////////////////////////////////*/ 56 | 57 | constructor(string memory _name, string memory _symbol) { 58 | name = _name; 59 | symbol = _symbol; 60 | } 61 | 62 | /*////////////////////////////////////////////////////////////// 63 | ERC721 LOGIC 64 | //////////////////////////////////////////////////////////////*/ 65 | 66 | function approve(address spender, uint256 id) public virtual { 67 | address owner = _ownerOf[id]; 68 | 69 | require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); 70 | 71 | getApproved[id] = spender; 72 | 73 | emit Approval(owner, spender, id); 74 | } 75 | 76 | function setApprovalForAll(address operator, bool approved) public virtual { 77 | isApprovedForAll[msg.sender][operator] = approved; 78 | 79 | emit ApprovalForAll(msg.sender, operator, approved); 80 | } 81 | 82 | function transferFrom( 83 | address from, 84 | address to, 85 | uint256 id 86 | ) public virtual { 87 | require(from == _ownerOf[id], "WRONG_FROM"); 88 | 89 | require(to != address(0), "INVALID_RECIPIENT"); 90 | 91 | require( 92 | msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], 93 | "NOT_AUTHORIZED" 94 | ); 95 | 96 | // Underflow of the sender's balance is impossible because we check for 97 | // ownership above and the recipient's balance can't realistically overflow. 98 | unchecked { 99 | _balanceOf[from]--; 100 | 101 | _balanceOf[to]++; 102 | } 103 | 104 | _ownerOf[id] = to; 105 | 106 | delete getApproved[id]; 107 | 108 | emit Transfer(from, to, id); 109 | } 110 | 111 | function safeTransferFrom( 112 | address from, 113 | address to, 114 | uint256 id 115 | ) public virtual { 116 | transferFrom(from, to, id); 117 | 118 | require( 119 | to.code.length == 0 || 120 | ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == 121 | ERC721TokenReceiver.onERC721Received.selector, 122 | "UNSAFE_RECIPIENT" 123 | ); 124 | } 125 | 126 | function safeTransferFrom( 127 | address from, 128 | address to, 129 | uint256 id, 130 | bytes calldata data 131 | ) public virtual { 132 | transferFrom(from, to, id); 133 | 134 | require( 135 | to.code.length == 0 || 136 | ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == 137 | ERC721TokenReceiver.onERC721Received.selector, 138 | "UNSAFE_RECIPIENT" 139 | ); 140 | } 141 | 142 | /*////////////////////////////////////////////////////////////// 143 | ERC165 LOGIC 144 | //////////////////////////////////////////////////////////////*/ 145 | 146 | function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { 147 | return 148 | interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 149 | interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 150 | interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata 151 | } 152 | 153 | /*////////////////////////////////////////////////////////////// 154 | INTERNAL MINT/BURN LOGIC 155 | //////////////////////////////////////////////////////////////*/ 156 | 157 | function _mint(address to, uint256 id) internal virtual { 158 | require(to != address(0), "INVALID_RECIPIENT"); 159 | 160 | require(_ownerOf[id] == address(0), "ALREADY_MINTED"); 161 | 162 | // Counter overflow is incredibly unrealistic. 163 | unchecked { 164 | _balanceOf[to]++; 165 | } 166 | 167 | _ownerOf[id] = to; 168 | 169 | emit Transfer(address(0), to, id); 170 | } 171 | 172 | function _burn(uint256 id) internal virtual { 173 | address owner = _ownerOf[id]; 174 | 175 | require(owner != address(0), "NOT_MINTED"); 176 | 177 | // Ownership check above ensures no underflow. 178 | unchecked { 179 | _balanceOf[owner]--; 180 | } 181 | 182 | delete _ownerOf[id]; 183 | 184 | delete getApproved[id]; 185 | 186 | emit Transfer(owner, address(0), id); 187 | } 188 | 189 | /*////////////////////////////////////////////////////////////// 190 | INTERNAL SAFE MINT LOGIC 191 | //////////////////////////////////////////////////////////////*/ 192 | 193 | function _safeMint(address to, uint256 id) internal virtual { 194 | _mint(to, id); 195 | 196 | require( 197 | to.code.length == 0 || 198 | ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == 199 | ERC721TokenReceiver.onERC721Received.selector, 200 | "UNSAFE_RECIPIENT" 201 | ); 202 | } 203 | 204 | function _safeMint( 205 | address to, 206 | uint256 id, 207 | bytes memory data 208 | ) internal virtual { 209 | _mint(to, id); 210 | 211 | require( 212 | to.code.length == 0 || 213 | ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == 214 | ERC721TokenReceiver.onERC721Received.selector, 215 | "UNSAFE_RECIPIENT" 216 | ); 217 | } 218 | } 219 | 220 | /// @notice A generic interface for a contract which properly accepts ERC721 tokens. 221 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) 222 | abstract contract ERC721TokenReceiver { 223 | function onERC721Received( 224 | address, 225 | address, 226 | uint256, 227 | bytes calldata 228 | ) external virtual returns (bytes4) { 229 | return ERC721TokenReceiver.onERC721Received.selector; 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /lib/solmate/src/tokens/WETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC20} from "./ERC20.sol"; 5 | 6 | import {SafeTransferLib} from "../utils/SafeTransferLib.sol"; 7 | 8 | /// @notice Minimalist and modern Wrapped Ether implementation. 9 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/WETH.sol) 10 | /// @author Inspired by WETH9 (https://github.com/dapphub/ds-weth/blob/master/src/weth9.sol) 11 | contract WETH is ERC20("Wrapped Ether", "WETH", 18) { 12 | using SafeTransferLib for address; 13 | 14 | event Deposit(address indexed from, uint256 amount); 15 | 16 | event Withdrawal(address indexed to, uint256 amount); 17 | 18 | function deposit() public payable virtual { 19 | _mint(msg.sender, msg.value); 20 | 21 | emit Deposit(msg.sender, msg.value); 22 | } 23 | 24 | function withdraw(uint256 amount) public virtual { 25 | _burn(msg.sender, amount); 26 | 27 | emit Withdrawal(msg.sender, amount); 28 | 29 | msg.sender.safeTransferETH(amount); 30 | } 31 | 32 | receive() external payable virtual { 33 | deposit(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/Bytes32AddressLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Library for converting between addresses and bytes32 values. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Bytes32AddressLib.sol) 6 | library Bytes32AddressLib { 7 | function fromLast20Bytes(bytes32 bytesValue) internal pure returns (address) { 8 | return address(uint160(uint256(bytesValue))); 9 | } 10 | 11 | function fillLast12Bytes(address addressValue) internal pure returns (bytes32) { 12 | return bytes32(bytes20(addressValue)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/CREATE3.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {Bytes32AddressLib} from "./Bytes32AddressLib.sol"; 5 | 6 | /// @notice Deploy to deterministic addresses without an initcode factor. 7 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/CREATE3.sol) 8 | /// @author Modified from 0xSequence (https://github.com/0xSequence/create3/blob/master/contracts/Create3.sol) 9 | library CREATE3 { 10 | using Bytes32AddressLib for bytes32; 11 | 12 | //--------------------------------------------------------------------------------// 13 | // Opcode | Opcode + Arguments | Description | Stack View // 14 | //--------------------------------------------------------------------------------// 15 | // 0x36 | 0x36 | CALLDATASIZE | size // 16 | // 0x3d | 0x3d | RETURNDATASIZE | 0 size // 17 | // 0x3d | 0x3d | RETURNDATASIZE | 0 0 size // 18 | // 0x37 | 0x37 | CALLDATACOPY | // 19 | // 0x36 | 0x36 | CALLDATASIZE | size // 20 | // 0x3d | 0x3d | RETURNDATASIZE | 0 size // 21 | // 0x34 | 0x34 | CALLVALUE | value 0 size // 22 | // 0xf0 | 0xf0 | CREATE | newContract // 23 | //--------------------------------------------------------------------------------// 24 | // Opcode | Opcode + Arguments | Description | Stack View // 25 | //--------------------------------------------------------------------------------// 26 | // 0x67 | 0x67XXXXXXXXXXXXXXXX | PUSH8 bytecode | bytecode // 27 | // 0x3d | 0x3d | RETURNDATASIZE | 0 bytecode // 28 | // 0x52 | 0x52 | MSTORE | // 29 | // 0x60 | 0x6008 | PUSH1 08 | 8 // 30 | // 0x60 | 0x6018 | PUSH1 18 | 24 8 // 31 | // 0xf3 | 0xf3 | RETURN | // 32 | //--------------------------------------------------------------------------------// 33 | bytes internal constant PROXY_BYTECODE = hex"67_36_3d_3d_37_36_3d_34_f0_3d_52_60_08_60_18_f3"; 34 | 35 | bytes32 internal constant PROXY_BYTECODE_HASH = keccak256(PROXY_BYTECODE); 36 | 37 | function deploy( 38 | bytes32 salt, 39 | bytes memory creationCode, 40 | uint256 value 41 | ) internal returns (address deployed) { 42 | bytes memory proxyChildBytecode = PROXY_BYTECODE; 43 | 44 | address proxy; 45 | assembly { 46 | // Deploy a new contract with our pre-made bytecode via CREATE2. 47 | // We start 32 bytes into the code to avoid copying the byte length. 48 | proxy := create2(0, add(proxyChildBytecode, 32), mload(proxyChildBytecode), salt) 49 | } 50 | require(proxy != address(0), "DEPLOYMENT_FAILED"); 51 | 52 | deployed = getDeployed(salt); 53 | (bool success, ) = proxy.call{value: value}(creationCode); 54 | require(success && deployed.code.length != 0, "INITIALIZATION_FAILED"); 55 | } 56 | 57 | function getDeployed(bytes32 salt) internal view returns (address) { 58 | address proxy = keccak256( 59 | abi.encodePacked( 60 | // Prefix: 61 | bytes1(0xFF), 62 | // Creator: 63 | address(this), 64 | // Salt: 65 | salt, 66 | // Bytecode hash: 67 | PROXY_BYTECODE_HASH 68 | ) 69 | ).fromLast20Bytes(); 70 | 71 | return 72 | keccak256( 73 | abi.encodePacked( 74 | // 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01) 75 | // 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex) 76 | hex"d6_94", 77 | proxy, 78 | hex"01" // Nonce of the proxy contract (1) 79 | ) 80 | ).fromLast20Bytes(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/FixedPointMathLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Arithmetic library with operations for fixed-point numbers. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) 6 | /// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) 7 | library FixedPointMathLib { 8 | /*////////////////////////////////////////////////////////////// 9 | SIMPLIFIED FIXED POINT OPERATIONS 10 | //////////////////////////////////////////////////////////////*/ 11 | 12 | uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. 13 | 14 | function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { 15 | return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. 16 | } 17 | 18 | function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { 19 | return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. 20 | } 21 | 22 | function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { 23 | return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. 24 | } 25 | 26 | function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { 27 | return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. 28 | } 29 | 30 | /*////////////////////////////////////////////////////////////// 31 | LOW LEVEL FIXED POINT OPERATIONS 32 | //////////////////////////////////////////////////////////////*/ 33 | 34 | function mulDivDown( 35 | uint256 x, 36 | uint256 y, 37 | uint256 denominator 38 | ) internal pure returns (uint256 z) { 39 | assembly { 40 | // Store x * y in z for now. 41 | z := mul(x, y) 42 | 43 | // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) 44 | if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { 45 | revert(0, 0) 46 | } 47 | 48 | // Divide z by the denominator. 49 | z := div(z, denominator) 50 | } 51 | } 52 | 53 | function mulDivUp( 54 | uint256 x, 55 | uint256 y, 56 | uint256 denominator 57 | ) internal pure returns (uint256 z) { 58 | assembly { 59 | // Store x * y in z for now. 60 | z := mul(x, y) 61 | 62 | // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) 63 | if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { 64 | revert(0, 0) 65 | } 66 | 67 | // First, divide z - 1 by the denominator and add 1. 68 | // We allow z - 1 to underflow if z is 0, because we multiply the 69 | // end result by 0 if z is zero, ensuring we return 0 if z is zero. 70 | z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1)) 71 | } 72 | } 73 | 74 | function rpow( 75 | uint256 x, 76 | uint256 n, 77 | uint256 scalar 78 | ) internal pure returns (uint256 z) { 79 | assembly { 80 | switch x 81 | case 0 { 82 | switch n 83 | case 0 { 84 | // 0 ** 0 = 1 85 | z := scalar 86 | } 87 | default { 88 | // 0 ** n = 0 89 | z := 0 90 | } 91 | } 92 | default { 93 | switch mod(n, 2) 94 | case 0 { 95 | // If n is even, store scalar in z for now. 96 | z := scalar 97 | } 98 | default { 99 | // If n is odd, store x in z for now. 100 | z := x 101 | } 102 | 103 | // Shifting right by 1 is like dividing by 2. 104 | let half := shr(1, scalar) 105 | 106 | for { 107 | // Shift n right by 1 before looping to halve it. 108 | n := shr(1, n) 109 | } n { 110 | // Shift n right by 1 each iteration to halve it. 111 | n := shr(1, n) 112 | } { 113 | // Revert immediately if x ** 2 would overflow. 114 | // Equivalent to iszero(eq(div(xx, x), x)) here. 115 | if shr(128, x) { 116 | revert(0, 0) 117 | } 118 | 119 | // Store x squared. 120 | let xx := mul(x, x) 121 | 122 | // Round to the nearest number. 123 | let xxRound := add(xx, half) 124 | 125 | // Revert if xx + half overflowed. 126 | if lt(xxRound, xx) { 127 | revert(0, 0) 128 | } 129 | 130 | // Set x to scaled xxRound. 131 | x := div(xxRound, scalar) 132 | 133 | // If n is even: 134 | if mod(n, 2) { 135 | // Compute z * x. 136 | let zx := mul(z, x) 137 | 138 | // If z * x overflowed: 139 | if iszero(eq(div(zx, x), z)) { 140 | // Revert if x is non-zero. 141 | if iszero(iszero(x)) { 142 | revert(0, 0) 143 | } 144 | } 145 | 146 | // Round to the nearest number. 147 | let zxRound := add(zx, half) 148 | 149 | // Revert if zx + half overflowed. 150 | if lt(zxRound, zx) { 151 | revert(0, 0) 152 | } 153 | 154 | // Return properly scaled zxRound. 155 | z := div(zxRound, scalar) 156 | } 157 | } 158 | } 159 | } 160 | } 161 | 162 | /*////////////////////////////////////////////////////////////// 163 | GENERAL NUMBER UTILITIES 164 | //////////////////////////////////////////////////////////////*/ 165 | 166 | function sqrt(uint256 x) internal pure returns (uint256 z) { 167 | assembly { 168 | // Start off with z at 1. 169 | z := 1 170 | 171 | // Used below to help find a nearby power of 2. 172 | let y := x 173 | 174 | // Find the lowest power of 2 that is at least sqrt(x). 175 | if iszero(lt(y, 0x100000000000000000000000000000000)) { 176 | y := shr(128, y) // Like dividing by 2 ** 128. 177 | z := shl(64, z) // Like multiplying by 2 ** 64. 178 | } 179 | if iszero(lt(y, 0x10000000000000000)) { 180 | y := shr(64, y) // Like dividing by 2 ** 64. 181 | z := shl(32, z) // Like multiplying by 2 ** 32. 182 | } 183 | if iszero(lt(y, 0x100000000)) { 184 | y := shr(32, y) // Like dividing by 2 ** 32. 185 | z := shl(16, z) // Like multiplying by 2 ** 16. 186 | } 187 | if iszero(lt(y, 0x10000)) { 188 | y := shr(16, y) // Like dividing by 2 ** 16. 189 | z := shl(8, z) // Like multiplying by 2 ** 8. 190 | } 191 | if iszero(lt(y, 0x100)) { 192 | y := shr(8, y) // Like dividing by 2 ** 8. 193 | z := shl(4, z) // Like multiplying by 2 ** 4. 194 | } 195 | if iszero(lt(y, 0x10)) { 196 | y := shr(4, y) // Like dividing by 2 ** 4. 197 | z := shl(2, z) // Like multiplying by 2 ** 2. 198 | } 199 | if iszero(lt(y, 0x8)) { 200 | // Equivalent to 2 ** z. 201 | z := shl(1, z) 202 | } 203 | 204 | // Shifting right by 1 is like dividing by 2. 205 | z := shr(1, add(z, div(x, z))) 206 | z := shr(1, add(z, div(x, z))) 207 | z := shr(1, add(z, div(x, z))) 208 | z := shr(1, add(z, div(x, z))) 209 | z := shr(1, add(z, div(x, z))) 210 | z := shr(1, add(z, div(x, z))) 211 | z := shr(1, add(z, div(x, z))) 212 | 213 | // Compute a rounded down version of z. 214 | let zRoundDown := div(x, z) 215 | 216 | // If zRoundDown is smaller, use it. 217 | if lt(zRoundDown, z) { 218 | z := zRoundDown 219 | } 220 | } 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/ReentrancyGuard.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Gas optimized reentrancy protection for smart contracts. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol) 6 | /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol) 7 | abstract contract ReentrancyGuard { 8 | uint256 private locked = 1; 9 | 10 | modifier nonReentrant() virtual { 11 | require(locked == 1, "REENTRANCY"); 12 | 13 | locked = 2; 14 | 15 | _; 16 | 17 | locked = 1; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/SSTORE2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Read and write to persistent storage at a fraction of the cost. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SSTORE2.sol) 6 | /// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol) 7 | library SSTORE2 { 8 | uint256 internal constant DATA_OFFSET = 1; // We skip the first byte as it's a STOP opcode to ensure the contract can't be called. 9 | 10 | /*////////////////////////////////////////////////////////////// 11 | WRITE LOGIC 12 | //////////////////////////////////////////////////////////////*/ 13 | 14 | function write(bytes memory data) internal returns (address pointer) { 15 | // Prefix the bytecode with a STOP opcode to ensure it cannot be called. 16 | bytes memory runtimeCode = abi.encodePacked(hex"00", data); 17 | 18 | bytes memory creationCode = abi.encodePacked( 19 | //---------------------------------------------------------------------------------------------------------------// 20 | // Opcode | Opcode + Arguments | Description | Stack View // 21 | //---------------------------------------------------------------------------------------------------------------// 22 | // 0x60 | 0x600B | PUSH1 11 | codeOffset // 23 | // 0x59 | 0x59 | MSIZE | 0 codeOffset // 24 | // 0x81 | 0x81 | DUP2 | codeOffset 0 codeOffset // 25 | // 0x38 | 0x38 | CODESIZE | codeSize codeOffset 0 codeOffset // 26 | // 0x03 | 0x03 | SUB | (codeSize - codeOffset) 0 codeOffset // 27 | // 0x80 | 0x80 | DUP | (codeSize - codeOffset) (codeSize - codeOffset) 0 codeOffset // 28 | // 0x92 | 0x92 | SWAP3 | codeOffset (codeSize - codeOffset) 0 (codeSize - codeOffset) // 29 | // 0x59 | 0x59 | MSIZE | 0 codeOffset (codeSize - codeOffset) 0 (codeSize - codeOffset) // 30 | // 0x39 | 0x39 | CODECOPY | 0 (codeSize - codeOffset) // 31 | // 0xf3 | 0xf3 | RETURN | // 32 | //---------------------------------------------------------------------------------------------------------------// 33 | hex"60_0B_59_81_38_03_80_92_59_39_F3", // Returns all code in the contract except for the first 11 (0B in hex) bytes. 34 | runtimeCode // The bytecode we want the contract to have after deployment. Capped at 1 byte less than the code size limit. 35 | ); 36 | 37 | assembly { 38 | // Deploy a new contract with the generated creation code. 39 | // We start 32 bytes into the code to avoid copying the byte length. 40 | pointer := create(0, add(creationCode, 32), mload(creationCode)) 41 | } 42 | 43 | require(pointer != address(0), "DEPLOYMENT_FAILED"); 44 | } 45 | 46 | /*////////////////////////////////////////////////////////////// 47 | READ LOGIC 48 | //////////////////////////////////////////////////////////////*/ 49 | 50 | function read(address pointer) internal view returns (bytes memory) { 51 | return readBytecode(pointer, DATA_OFFSET, pointer.code.length - DATA_OFFSET); 52 | } 53 | 54 | function read(address pointer, uint256 start) internal view returns (bytes memory) { 55 | start += DATA_OFFSET; 56 | 57 | return readBytecode(pointer, start, pointer.code.length - start); 58 | } 59 | 60 | function read( 61 | address pointer, 62 | uint256 start, 63 | uint256 end 64 | ) internal view returns (bytes memory) { 65 | start += DATA_OFFSET; 66 | end += DATA_OFFSET; 67 | 68 | require(pointer.code.length >= end, "OUT_OF_BOUNDS"); 69 | 70 | return readBytecode(pointer, start, end - start); 71 | } 72 | 73 | /*////////////////////////////////////////////////////////////// 74 | INTERNAL HELPER LOGIC 75 | //////////////////////////////////////////////////////////////*/ 76 | 77 | function readBytecode( 78 | address pointer, 79 | uint256 start, 80 | uint256 size 81 | ) private view returns (bytes memory data) { 82 | assembly { 83 | // Get a pointer to some free memory. 84 | data := mload(0x40) 85 | 86 | // Update the free memory pointer to prevent overriding our data. 87 | // We use and(x, not(31)) as a cheaper equivalent to sub(x, mod(x, 32)). 88 | // Adding 31 to size and running the result through the logic above ensures 89 | // the memory pointer remains word-aligned, following the Solidity convention. 90 | mstore(0x40, add(data, and(add(add(size, 32), 31), not(31)))) 91 | 92 | // Store the size of the data in the first 32 byte chunk of free memory. 93 | mstore(data, size) 94 | 95 | // Copy the code into memory right after the 32 bytes we used to store the size. 96 | extcodecopy(pointer, add(data, 32), start, size) 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/SafeCastLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | /// @notice Safe unsigned integer casting library that reverts on overflow. 5 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeCastLib.sol) 6 | /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol) 7 | library SafeCastLib { 8 | function safeCastTo248(uint256 x) internal pure returns (uint248 y) { 9 | require(x < 1 << 248); 10 | 11 | y = uint248(x); 12 | } 13 | 14 | function safeCastTo224(uint256 x) internal pure returns (uint224 y) { 15 | require(x < 1 << 224); 16 | 17 | y = uint224(x); 18 | } 19 | 20 | function safeCastTo192(uint256 x) internal pure returns (uint192 y) { 21 | require(x < 1 << 192); 22 | 23 | y = uint192(x); 24 | } 25 | 26 | function safeCastTo160(uint256 x) internal pure returns (uint160 y) { 27 | require(x < 1 << 160); 28 | 29 | y = uint160(x); 30 | } 31 | 32 | function safeCastTo128(uint256 x) internal pure returns (uint128 y) { 33 | require(x < 1 << 128); 34 | 35 | y = uint128(x); 36 | } 37 | 38 | function safeCastTo96(uint256 x) internal pure returns (uint96 y) { 39 | require(x < 1 << 96); 40 | 41 | y = uint96(x); 42 | } 43 | 44 | function safeCastTo64(uint256 x) internal pure returns (uint64 y) { 45 | require(x < 1 << 64); 46 | 47 | y = uint64(x); 48 | } 49 | 50 | function safeCastTo32(uint256 x) internal pure returns (uint32 y) { 51 | require(x < 1 << 32); 52 | 53 | y = uint32(x); 54 | } 55 | 56 | function safeCastTo24(uint256 x) internal pure returns (uint24 y) { 57 | require(x < 1 << 24); 58 | 59 | y = uint24(x); 60 | } 61 | 62 | function safeCastTo8(uint256 x) internal pure returns (uint8 y) { 63 | require(x < 1 << 8); 64 | 65 | y = uint8(x); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/solmate/src/utils/SafeTransferLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: AGPL-3.0-only 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC20} from "../tokens/ERC20.sol"; 5 | 6 | /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. 7 | /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) 8 | /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. 9 | /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. 10 | library SafeTransferLib { 11 | /*////////////////////////////////////////////////////////////// 12 | ETH OPERATIONS 13 | //////////////////////////////////////////////////////////////*/ 14 | 15 | function safeTransferETH(address to, uint256 amount) internal { 16 | bool success; 17 | 18 | assembly { 19 | // Transfer the ETH and store if it succeeded or not. 20 | success := call(gas(), to, amount, 0, 0, 0, 0) 21 | } 22 | 23 | require(success, "ETH_TRANSFER_FAILED"); 24 | } 25 | 26 | /*////////////////////////////////////////////////////////////// 27 | ERC20 OPERATIONS 28 | //////////////////////////////////////////////////////////////*/ 29 | 30 | function safeTransferFrom( 31 | ERC20 token, 32 | address from, 33 | address to, 34 | uint256 amount 35 | ) internal { 36 | bool success; 37 | 38 | assembly { 39 | // Get a pointer to some free memory. 40 | let freeMemoryPointer := mload(0x40) 41 | 42 | // Write the abi-encoded calldata into memory, beginning with the function selector. 43 | mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) 44 | mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument. 45 | mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument. 46 | mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. 47 | 48 | success := and( 49 | // Set success to whether the call reverted, if not we check it either 50 | // returned exactly 1 (can't just be non-zero data), or had no return data. 51 | or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), 52 | // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. 53 | // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. 54 | // Counterintuitively, this call must be positioned second to the or() call in the 55 | // surrounding and() call or else returndatasize() will be zero during the computation. 56 | call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) 57 | ) 58 | } 59 | 60 | require(success, "TRANSFER_FROM_FAILED"); 61 | } 62 | 63 | function safeTransfer( 64 | ERC20 token, 65 | address to, 66 | uint256 amount 67 | ) internal { 68 | bool success; 69 | 70 | assembly { 71 | // Get a pointer to some free memory. 72 | let freeMemoryPointer := mload(0x40) 73 | 74 | // Write the abi-encoded calldata into memory, beginning with the function selector. 75 | mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) 76 | mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. 77 | mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. 78 | 79 | success := and( 80 | // Set success to whether the call reverted, if not we check it either 81 | // returned exactly 1 (can't just be non-zero data), or had no return data. 82 | or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), 83 | // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. 84 | // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. 85 | // Counterintuitively, this call must be positioned second to the or() call in the 86 | // surrounding and() call or else returndatasize() will be zero during the computation. 87 | call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) 88 | ) 89 | } 90 | 91 | require(success, "TRANSFER_FAILED"); 92 | } 93 | 94 | function safeApprove( 95 | ERC20 token, 96 | address to, 97 | uint256 amount 98 | ) internal { 99 | bool success; 100 | 101 | assembly { 102 | // Get a pointer to some free memory. 103 | let freeMemoryPointer := mload(0x40) 104 | 105 | // Write the abi-encoded calldata into memory, beginning with the function selector. 106 | mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) 107 | mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. 108 | mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. 109 | 110 | success := and( 111 | // Set success to whether the call reverted, if not we check it either 112 | // returned exactly 1 (can't just be non-zero data), or had no return data. 113 | or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), 114 | // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. 115 | // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. 116 | // Counterintuitively, this call must be positioned second to the or() call in the 117 | // surrounding and() call or else returndatasize() will be zero during the computation. 118 | call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) 119 | ) 120 | } 121 | 122 | require(success, "APPROVE_FAILED"); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/RemcoMathLib.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.8.10; 3 | 4 | library RemcoMathLib { 5 | /// @notice Calculates (x × y ÷ denominator) rounded down with full precision. 6 | /// Reverts if result does not fit within a uint256 value or denominator is zero. 7 | /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv 8 | function mulDiv( 9 | uint256 x, 10 | uint256 y, 11 | uint256 denominator 12 | ) internal pure returns (uint256 z) { 13 | assembly { 14 | let mm := mulmod(x, y, not(0)) 15 | let z0 := mul(x, y) 16 | let z1 := sub(sub(mm, z0), lt(mm, z0)) 17 | 18 | // Short-circuit to save gas for non-overflow cases, 256 by 256 division. 19 | if iszero(z1) { 20 | let freeMemoryPointer := mload(0x40) 21 | mstore(freeMemoryPointer, div(z0, denominator)) 22 | return(freeMemoryPointer, 32) 23 | } 24 | 25 | // Make sure the result is less than 2**256 and ensure denominator is not zero. 26 | if iszero(gt(denominator, z1)) { 27 | revert(0, 0) 28 | } 29 | 30 | let twos := and(sub(0, denominator), denominator) 31 | denominator := div(denominator, twos) 32 | 33 | let remainder := mulmod(x, y, denominator) 34 | z1 := sub(z1, gt(remainder, z0)) 35 | z0 := add(div(sub(z0, remainder), twos), mul(z1, add(div(sub(0, twos), twos), 1))) 36 | 37 | // Invert denominator mod 2**256. Now that denominator is an odd number, 38 | // it has an inverse modulo 2**256 such that denominator * inv = 1 mod 39 | // 2**256. Now we compute the inverse by starting with a seed that is 40 | // correct for four bits (denominator * inv = 1 mod 2**4). 41 | let inv := xor(mul(3, denominator), 2) 42 | 43 | // Now we use Newton-Raphson iteration to improve the precision. Thanks to 44 | // Hensel's lifting lemma, this also works in modular arithmetic, doubling 45 | // the correct bits in each step. 46 | inv := mul(inv, sub(2, mul(denominator, inv))) // inv mod 2^8 47 | inv := mul(inv, sub(2, mul(denominator, inv))) // inv mod 2^16 48 | inv := mul(inv, sub(2, mul(denominator, inv))) // inv mod 2^32 49 | inv := mul(inv, sub(2, mul(denominator, inv))) // inv mod 2^64 50 | inv := mul(inv, sub(2, mul(denominator, inv))) // inv mod 2^128 51 | inv := mul(inv, sub(2, mul(denominator, inv))) // inv mod 2^256 52 | 53 | // Because the division is now exact we can divide by multiplying with the 54 | // modular inverse of denominator. This will give us the correct result modulo 55 | // 2**256. Since the precoditions guarantee that the outcome is less than 2**256, 56 | // this is the final result. We don't need to compute the high bits of the result 57 | // and prod1 is no longer required. 58 | z := mul(z0, inv) 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /src/test/FullMath.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.10; 3 | 4 | /// @title Contains 512-bit math functions 5 | /// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision 6 | /// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits 7 | library FullMath { 8 | /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 9 | /// @param a The multiplicand 10 | /// @param b The multiplier 11 | /// @param denominator The divisor 12 | /// @return result The 256-bit result 13 | /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv 14 | function mulDiv( 15 | uint256 a, 16 | uint256 b, 17 | uint256 denominator 18 | ) internal pure returns (uint256 result) { 19 | unchecked { 20 | // 512-bit multiply [prod1 prod0] = a * b 21 | // Compute the product mod 2**256 and mod 2**256 - 1 22 | // then use the Chinese Remainder Theorem to reconstruct 23 | // the 512 bit result. The result is stored in two 256 24 | // variables such that product = prod1 * 2**256 + prod0 25 | uint256 prod0; // Least significant 256 bits of the product 26 | uint256 prod1; // Most significant 256 bits of the product 27 | assembly { 28 | let mm := mulmod(a, b, not(0)) 29 | prod0 := mul(a, b) 30 | prod1 := sub(sub(mm, prod0), lt(mm, prod0)) 31 | } 32 | 33 | // Handle non-overflow cases, 256 by 256 division 34 | if (prod1 == 0) { 35 | require(denominator > 0); 36 | assembly { 37 | result := div(prod0, denominator) 38 | } 39 | return result; 40 | } 41 | 42 | // Make sure the result is less than 2**256. 43 | // Also prevents denominator == 0 44 | require(denominator > prod1); 45 | 46 | /////////////////////////////////////////////// 47 | // 512 by 256 division. 48 | /////////////////////////////////////////////// 49 | 50 | // Make division exact by subtracting the remainder from [prod1 prod0] 51 | // Compute remainder using mulmod 52 | uint256 remainder; 53 | assembly { 54 | remainder := mulmod(a, b, denominator) 55 | } 56 | // Subtract 256 bit number from 512 bit number 57 | assembly { 58 | prod1 := sub(prod1, gt(remainder, prod0)) 59 | prod0 := sub(prod0, remainder) 60 | } 61 | 62 | // Factor powers of two out of denominator 63 | // Compute largest power of two divisor of denominator. 64 | // Always >= 1. 65 | uint256 twos = (0 - denominator) & denominator; 66 | // Divide denominator by power of two 67 | assembly { 68 | denominator := div(denominator, twos) 69 | } 70 | 71 | // Divide [prod1 prod0] by the factors of two 72 | assembly { 73 | prod0 := div(prod0, twos) 74 | } 75 | // Shift in bits from prod1 into prod0. For this we need 76 | // to flip `twos` such that it is 2**256 / twos. 77 | // If twos is zero, then it becomes one 78 | assembly { 79 | twos := add(div(sub(0, twos), twos), 1) 80 | } 81 | prod0 |= prod1 * twos; 82 | 83 | // Invert denominator mod 2**256 84 | // Now that denominator is an odd number, it has an inverse 85 | // modulo 2**256 such that denominator * inv = 1 mod 2**256. 86 | // Compute the inverse by starting with a seed that is correct 87 | // correct for four bits. That is, denominator * inv = 1 mod 2**4 88 | uint256 inv = (3 * denominator) ^ 2; 89 | // Now use Newton-Raphson iteration to improve the precision. 90 | // Thanks to Hensel's lifting lemma, this also works in modular 91 | // arithmetic, doubling the correct bits in each step. 92 | inv *= 2 - denominator * inv; // inverse mod 2**8 93 | inv *= 2 - denominator * inv; // inverse mod 2**16 94 | inv *= 2 - denominator * inv; // inverse mod 2**32 95 | inv *= 2 - denominator * inv; // inverse mod 2**64 96 | inv *= 2 - denominator * inv; // inverse mod 2**128 97 | inv *= 2 - denominator * inv; // inverse mod 2**256 98 | 99 | // Because the division is now exact we can divide by multiplying 100 | // with the modular inverse of denominator. This will give us the 101 | // correct result modulo 2**256. Since the precoditions guarantee 102 | // that the outcome is less than 2**256, this is the final result. 103 | // We don't need to compute the high bits of the result and prod1 104 | // is no longer required. 105 | result = prod0 * inv; 106 | return result; 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /src/test/RemcoMathLib.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity 0.8.10; 3 | 4 | import {Test} from "forge-std/Test.sol"; 5 | import {FullMath} from "./FullMath.sol"; // reference 6 | import {RemcoMathLib} from "../RemcoMathLib.sol"; 7 | 8 | 9 | /** 10 | NOTE: to test gas you must change FullMath.mulDiv() & RemcoMathLib.mulDiv() 11 | function visibility to public temporarily. 12 | ╭───────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ 13 | │ FullMath contract ┆ ┆ ┆ ┆ ┆ │ 14 | ╞═══════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ 15 | │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ 16 | ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ 17 | │ 74748 ┆ 431 ┆ ┆ ┆ ┆ │ 18 | ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ 19 | │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ 20 | ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ 21 | │ mulDiv ┆ 437 ┆ 588 ┆ 588 ┆ 739 ┆ 2 │ 22 | ╰───────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ 23 | ╭───────────────────────┬─────────────────┬─────┬────────┬─────┬─────────╮ 24 | │ RemcoMathLib contract ┆ ┆ ┆ ┆ ┆ │ 25 | ╞═══════════════════════╪═════════════════╪═════╪════════╪═════╪═════════╡ 26 | │ Deployment Cost ┆ Deployment Size ┆ ┆ ┆ ┆ │ 27 | ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ 28 | │ 67942 ┆ 397 ┆ ┆ ┆ ┆ │ 29 | ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ 30 | │ Function Name ┆ min ┆ avg ┆ median ┆ max ┆ # calls │ 31 | ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤ 32 | │ mulDiv ┆ 331 ┆ 504 ┆ 504 ┆ 678 ┆ 2 │ 33 | ╰───────────────────────┴─────────────────┴─────┴────────┴─────┴─────────╯ 34 | */ 35 | contract RemcoMathLibTest is Test { 36 | 37 | // function testGasFullMath() public { 38 | // FullMath.mulDiv(type(uint256).max, 1, 1); 39 | // } 40 | 41 | // function testGasRemcoMathLib() public { 42 | // RemcoMathLib.mulDiv(type(uint256).max, 1, 1); 43 | // } 44 | 45 | // function testGasFullMathOverflow() public { 46 | // FullMath.mulDiv(type(uint256).max, 2, 2); 47 | // } 48 | 49 | // function testGasRemcoMathLibOverflow() public { 50 | // RemcoMathLib.mulDiv(type(uint256).max, 2, 2); 51 | // } 52 | 53 | // Kind of a pain in the ass to fuzz tbh 54 | function testFuzz(uint128 a, uint128 b, uint128 c) public { 55 | 56 | vm.assume(c > 0); // avoid division by zero error 57 | 58 | uint256 fullMath = FullMath.mulDiv(a, b, c); 59 | uint256 remcoMath = RemcoMathLib.mulDiv(a, b, c); 60 | 61 | assertEq(fullMath, remcoMath); 62 | } 63 | } 64 | --------------------------------------------------------------------------------