├── LICENSE ├── 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 ├── logs ├── 0x185a4dc360CE69bDCceE33b3784B0282f7961aea.csv ├── 0xEFc56627233b02eA95bAE7e19F648d7DcD5Bb132.csv ├── 0xf5a2fE45F4f1308502b1C136b9EF8af136141382.csv ├── prices.csv └── sold.csv ├── package-lock.json ├── package.json ├── script └── DeployMonaco.s.sol ├── src ├── Monaco.sol ├── cars │ ├── Car.sol │ ├── FleckCar.sol │ └── OpenSeaCar.sol └── utils │ └── SignedWadMath.sol └── test └── Monaco.t.sol /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 t11s 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # foundry-template 2 | 3 | Streamlined template for getting started with Foundry and Solmate. 4 | 5 | ## Contributing 6 | 7 | You will need a copy of [Foundry](https://github.com/foundry-rs/foundry) installed before proceeding. See the [installation guide](https://github.com/foundry-rs/foundry#installation) for details. 8 | 9 | ### Setup 10 | 11 | ```sh 12 | git clone https://github.com/transmissions11/foundry-template.git 13 | cd foundry-template 14 | ``` 15 | 16 | ### Run Tests 17 | 18 | ```sh 19 | forge test 20 | ``` 21 | 22 | ### Update Gas Snapshots 23 | 24 | ```sh 25 | forge snapshot 26 | ``` 27 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [fmt] 2 | line_length = 120 3 | 4 | [profile.default] 5 | bytecode_hash = "none" 6 | optimizer_runs = 1000000 7 | solc = "0.8.13" 8 | 9 | [profile.intense] 10 | fuzz_runs = 10000 11 | 12 | -------------------------------------------------------------------------------- /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/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 testDeal() public { 67 | deal(address(this), 1 ether); 68 | assertEq(address(this).balance, 1 ether); 69 | } 70 | 71 | function testDealToken() public { 72 | Bar barToken = new Bar(); 73 | address bar = address(barToken); 74 | deal(bar, address(this), 10000e18); 75 | assertEq(barToken.balanceOf(address(this)), 10000e18); 76 | } 77 | 78 | function testDealTokenAdjustTS() public { 79 | Bar barToken = new Bar(); 80 | address bar = address(barToken); 81 | deal(bar, address(this), 10000e18, true); 82 | assertEq(barToken.balanceOf(address(this)), 10000e18); 83 | assertEq(barToken.totalSupply(), 20000e18); 84 | deal(bar, address(this), 0, true); 85 | assertEq(barToken.balanceOf(address(this)), 0); 86 | assertEq(barToken.totalSupply(), 10000e18); 87 | } 88 | 89 | function testBound() public { 90 | assertEq(bound(5, 0, 4), 0); 91 | assertEq(bound(0, 69, 69), 69); 92 | assertEq(bound(0, 68, 69), 68); 93 | assertEq(bound(10, 150, 190), 160); 94 | assertEq(bound(300, 2800, 3200), 3100); 95 | assertEq(bound(9999, 1337, 6666), 6006); 96 | } 97 | 98 | function testCannotBoundMaxLessThanMin() public { 99 | vm.expectRevert(bytes("Test bound(uint256,uint256,uint256): Max is less than min.")); 100 | bound(5, 100, 10); 101 | } 102 | 103 | function testBound( 104 | uint256 num, 105 | uint256 min, 106 | uint256 max 107 | ) public { 108 | if (min > max) (min, max) = (max, min); 109 | 110 | uint256 bounded = bound(num, min, max); 111 | 112 | assertGe(bounded, min); 113 | assertLe(bounded, max); 114 | } 115 | 116 | function testBoundUint256Max() public { 117 | assertEq(bound(0, type(uint256).max - 1, type(uint256).max), type(uint256).max - 1); 118 | assertEq(bound(1, type(uint256).max - 1, type(uint256).max), type(uint256).max); 119 | } 120 | 121 | function testCannotBoundMaxLessThanMin( 122 | uint256 num, 123 | uint256 min, 124 | uint256 max 125 | ) public { 126 | vm.assume(min > max); 127 | vm.expectRevert(bytes("Test bound(uint256,uint256,uint256): Max is less than min.")); 128 | bound(num, min, max); 129 | } 130 | 131 | function testDeployCode() public { 132 | address deployed = deployCode("StdCheats.t.sol:StdCheatsTest", bytes("")); 133 | assertEq(string(getCode(deployed)), string(getCode(address(this)))); 134 | } 135 | 136 | function testDeployCodeNoArgs() public { 137 | address deployed = deployCode("StdCheats.t.sol:StdCheatsTest"); 138 | assertEq(string(getCode(deployed)), string(getCode(address(this)))); 139 | } 140 | 141 | // We need that payable constructor in order to send ETH on construction 142 | constructor() payable {} 143 | 144 | function testDeployCodeVal() public { 145 | address deployed = deployCode("StdCheats.t.sol:StdCheatsTest", bytes(""), 1 ether); 146 | assertEq(string(getCode(deployed)), string(getCode(address(this)))); 147 | assertEq(deployed.balance, 1 ether); 148 | } 149 | 150 | function testDeployCodeValNoArgs() public { 151 | address deployed = deployCode("StdCheats.t.sol:StdCheatsTest", 1 ether); 152 | assertEq(string(getCode(deployed)), string(getCode(address(this)))); 153 | assertEq(deployed.balance, 1 ether); 154 | } 155 | 156 | // We need this so we can call "this.deployCode" rather than "deployCode" directly 157 | function deployCodeHelper(string memory what) external { 158 | deployCode(what); 159 | } 160 | 161 | function testDeployCodeFail() public { 162 | vm.expectRevert(bytes("Test deployCode(string): Deployment failed.")); 163 | this.deployCodeHelper("StdCheats.t.sol:RevertingContract"); 164 | } 165 | 166 | function getCode(address who) internal view returns (bytes memory o_code) { 167 | /// @solidity memory-safe-assembly 168 | assembly { 169 | // retrieve the size of the code, this needs assembly 170 | let size := extcodesize(who) 171 | // allocate output byte array - this could also be done without assembly 172 | // by using o_code = new bytes(size) 173 | o_code := mload(0x40) 174 | // new "memory end" including padding 175 | mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) 176 | // store length in memory 177 | mstore(o_code, size) 178 | // actually retrieve the code, this needs assembly 179 | extcodecopy(who, add(o_code, 0x20), 0, size) 180 | } 181 | } 182 | } 183 | 184 | contract Bar { 185 | constructor() { 186 | /// `DEAL` STDCHEAT 187 | totalSupply = 10000e18; 188 | balanceOf[address(this)] = totalSupply; 189 | } 190 | 191 | /// `HOAX` STDCHEATS 192 | function bar(address expectedSender) public payable { 193 | require(msg.sender == expectedSender, "!prank"); 194 | } 195 | function origin(address expectedSender) public payable { 196 | require(msg.sender == expectedSender, "!prank"); 197 | require(tx.origin == expectedSender, "!prank"); 198 | } 199 | function origin(address expectedSender, address expectedOrigin) public payable { 200 | require(msg.sender == expectedSender, "!prank"); 201 | require(tx.origin == expectedOrigin, "!prank"); 202 | } 203 | 204 | /// `DEAL` STDCHEAT 205 | mapping (address => uint256) public balanceOf; 206 | uint256 public totalSupply; 207 | } 208 | 209 | contract RevertingContract { 210 | constructor() { 211 | revert(); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /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/andrew3009/0xmonaco/d06d70c7bd6fee0391eb16c3863bf0d9aa2bc120/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/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 | -------------------------------------------------------------------------------- /logs/0x185a4dc360CE69bDCceE33b3784B0282f7961aea.csv: -------------------------------------------------------------------------------- 1 | turns,balance,speed,y 2 | 2,15000,0,0 3 | 3,15000,0,0 4 | 4,14269,3,3 5 | 5,14187,6,9 6 | 6,14187,6,15 7 | 7,14187,1,16 8 | 8,14187,1,17 9 | 9,14187,1,18 10 | 10,10664,4,22 11 | 11,10664,4,26 12 | 12,10664,4,30 13 | 13,10255,7,37 14 | 14,10255,7,44 15 | 15,10255,7,51 16 | 16,9508,10,61 17 | 17,9508,10,71 18 | 18,9508,10,81 19 | 19,8144,13,94 20 | 20,6477,16,110 21 | 21,6477,1,111 22 | 22,6477,1,112 23 | 23,6477,1,113 24 | 24,2762,4,117 25 | 25,2762,4,121 26 | 26,2762,4,125 27 | 27,1281,4,129 28 | 28,1281,4,133 29 | 29,1281,4,137 30 | 30,1281,4,141 31 | 31,1281,4,145 32 | 32,1281,4,149 33 | 33,1281,4,153 34 | 34,1281,4,157 35 | 35,1281,4,161 36 | 36,670,7,168 37 | 37,670,7,175 38 | 38,670,7,182 39 | 39,670,7,189 40 | 40,261,10,199 41 | 41,261,10,209 42 | 42,261,10,219 43 | 43,261,10,229 44 | 44,261,10,239 45 | 45,261,10,249 46 | 46,261,1,250 47 | 47,261,1,251 48 | 48,28,4,255 49 | 49,28,4,259 50 | 50,28,4,263 51 | 51,28,4,267 52 | 52,28,4,271 53 | 53,28,4,275 54 | 54,28,4,279 55 | 55,9,7,286 56 | 56,9,7,293 57 | 57,9,7,300 58 | 58,9,7,307 59 | 59,9,7,314 60 | 60,5,10,324 61 | 61,5,10,334 62 | 62,5,10,344 63 | 63,5,1,345 64 | 64,5,1,346 65 | 65,5,1,347 66 | 66,1,4,351 67 | 67,1,4,355 68 | 68,1,4,359 69 | 69,1,1,360 70 | 70,1,1,361 71 | 71,1,1,362 72 | 72,1,1,363 73 | 73,1,1,364 74 | 74,1,4,368 75 | 75,1,4,372 76 | 76,1,4,376 77 | 77,1,4,380 78 | 78,1,4,384 79 | 79,1,4,388 80 | 80,1,4,392 81 | 81,1,4,396 82 | 82,1,4,400 83 | 83,1,4,404 84 | 84,1,4,408 85 | 85,1,4,412 86 | 86,1,7,419 87 | 87,1,7,426 88 | 88,1,7,433 89 | 89,1,7,440 90 | 90,1,7,447 91 | 91,1,7,454 92 | 92,1,7,461 93 | 93,1,7,468 94 | 93,1,7,475 95 | -------------------------------------------------------------------------------- /logs/0xEFc56627233b02eA95bAE7e19F648d7DcD5Bb132.csv: -------------------------------------------------------------------------------- 1 | turns,balance,speed,y 2 | 2,14956,3,3 3 | 3,14956,3,6 4 | 4,14956,3,9 5 | 5,14956,3,12 6 | 6,14856,6,18 7 | 7,14856,6,24 8 | 8,14856,6,30 9 | 9,14673,9,39 10 | 10,14673,9,48 11 | 11,14673,9,57 12 | 12,14338,12,69 13 | 13,14338,12,81 14 | 14,14338,1,82 15 | 15,13727,4,86 16 | 16,13727,4,90 17 | 17,13727,4,94 18 | 18,12611,7,101 19 | 19,12611,7,108 20 | 20,12611,7,115 21 | 21,12611,7,122 22 | 22,10123,10,132 23 | 23,7083,13,145 24 | 24,7083,13,158 25 | 25,7083,13,171 26 | 26,4043,16,187 27 | 27,4043,16,203 28 | 28,4043,16,219 29 | 29,2376,19,238 30 | 30,2376,19,257 31 | 31,2376,19,276 32 | 32,709,22,298 33 | 33,709,22,320 34 | 34,709,22,342 35 | 35,709,22,364 36 | 36,709,22,386 37 | 37,709,22,408 38 | 38,709,1,409 39 | 39,374,4,413 40 | 40,374,4,417 41 | 41,374,4,421 42 | 42,39,7,428 43 | 43,39,7,435 44 | 44,39,7,442 45 | 45,39,7,449 46 | 46,39,7,456 47 | 47,39,7,463 48 | 48,39,7,470 49 | 49,39,7,477 50 | 50,39,7,484 51 | 51,39,7,491 52 | 52,39,7,498 53 | 53,39,7,505 54 | 54,24,10,515 55 | 55,24,10,525 56 | 56,24,10,535 57 | 57,24,10,545 58 | 58,24,10,555 59 | 59,24,10,565 60 | 60,24,10,575 61 | 61,19,13,588 62 | 62,12,16,604 63 | 63,12,16,620 64 | 64,12,16,636 65 | 65,9,19,655 66 | 66,9,19,674 67 | 67,9,19,693 68 | 68,6,22,715 69 | 69,6,22,737 70 | 70,6,22,759 71 | 71,6,25,784 72 | 72,6,25,809 73 | 73,6,25,834 74 | 74,6,25,859 75 | 75,5,28,887 76 | 76,5,28,915 77 | 77,5,31,946 78 | 78,5,1,947 79 | 79,5,1,948 80 | 80,5,1,949 81 | 81,4,4,953 82 | 82,4,4,957 83 | 83,4,4,961 84 | 84,3,7,968 85 | 85,3,1,969 86 | 86,3,1,970 87 | 87,3,1,971 88 | 88,3,4,975 89 | 89,3,4,979 90 | 90,2,7,986 91 | 91,2,7,993 92 | 92,2,1,994 93 | 93,1,4,998 94 | 93,1,4,1002 95 | -------------------------------------------------------------------------------- /logs/0xf5a2fE45F4f1308502b1C136b9EF8af136141382.csv: -------------------------------------------------------------------------------- 1 | turns,balance,speed,y 2 | 2,15000,0,0 3 | 3,14946,3,3 4 | 4,14946,1,4 5 | 5,14946,1,5 6 | 6,14946,1,6 7 | 7,13343,4,10 8 | 8,13194,7,17 9 | 9,13194,7,24 10 | 10,13194,1,25 11 | 11,12920,4,29 12 | 12,12920,4,33 13 | 13,12920,4,37 14 | 14,7495,7,44 15 | 15,7495,7,51 16 | 16,7495,7,58 17 | 17,6582,10,68 18 | 18,6582,10,78 19 | 19,6582,10,88 20 | 20,6582,10,98 21 | 21,2336,13,111 22 | 22,2336,13,124 23 | 23,2336,13,137 24 | 24,2336,13,150 25 | 25,2336,13,163 26 | 26,2336,13,176 27 | 27,2336,1,177 28 | 28,2336,1,178 29 | 29,2336,1,179 30 | 30,300,4,183 31 | 31,300,4,187 32 | 32,300,4,191 33 | 33,300,4,195 34 | 34,300,4,199 35 | 35,300,4,203 36 | 36,300,4,207 37 | 37,300,4,211 38 | 38,167,4,215 39 | 39,167,4,219 40 | 40,167,4,223 41 | 41,167,4,227 42 | 42,167,4,231 43 | 43,167,4,235 44 | 44,167,4,239 45 | 45,167,4,243 46 | 46,5,7,250 47 | 47,5,7,257 48 | 48,5,1,258 49 | 49,5,1,259 50 | 50,5,1,260 51 | 51,5,1,261 52 | 52,5,1,262 53 | 53,5,1,263 54 | 54,5,1,264 55 | 55,5,1,265 56 | 56,5,1,266 57 | 57,5,1,267 58 | 58,5,1,268 59 | 59,5,1,269 60 | 60,5,1,270 61 | 61,5,1,271 62 | 62,5,1,272 63 | 63,3,1,273 64 | 64,3,1,274 65 | 65,3,1,275 66 | 66,3,1,276 67 | 67,3,1,277 68 | 68,3,1,278 69 | 69,2,1,279 70 | 70,2,1,280 71 | 71,2,1,281 72 | 72,1,4,285 73 | 73,1,4,289 74 | 74,1,4,293 75 | 75,1,4,297 76 | 76,1,4,301 77 | 77,1,4,305 78 | 78,1,4,309 79 | 79,1,7,316 80 | 80,1,10,326 81 | 81,1,10,336 82 | 82,1,10,346 83 | 83,1,13,359 84 | 84,1,13,372 85 | 85,1,13,385 86 | 86,1,13,398 87 | 87,1,13,411 88 | 88,1,13,424 89 | 89,1,16,440 90 | 90,1,16,456 91 | 91,1,1,457 92 | 92,1,4,461 93 | 93,1,4,465 94 | 93,1,4,469 95 | -------------------------------------------------------------------------------- /logs/prices.csv: -------------------------------------------------------------------------------- 1 | turns,accelerateCost,shellCost 2 | 2,14,992 3 | 2,14,992 4 | 2,14,992 5 | 3,18,664 6 | 3,18,664 7 | 3,18,664 8 | 4,22,3299 9 | 4,22,3299 10 | 4,22,3299 11 | 5,27,2210 12 | 5,27,2210 13 | 5,27,2210 14 | 6,33,1481 15 | 6,33,1481 16 | 6,33,1481 17 | 7,40,7351 18 | 7,40,7351 19 | 7,40,7351 20 | 8,49,4925 21 | 8,49,4925 22 | 8,49,4925 23 | 9,60,3299 24 | 9,60,3299 25 | 9,60,3299 26 | 10,74,16375 27 | 10,74,16375 28 | 10,74,16375 29 | 11,90,10971 30 | 11,90,10971 31 | 11,90,10971 32 | 12,110,7351 33 | 12,110,7351 34 | 12,110,7351 35 | 13,135,4925 36 | 13,135,4925 37 | 13,135,4925 38 | 14,164,24441 39 | 14,164,24441 40 | 14,164,24441 41 | 15,201,16375 42 | 15,201,16375 43 | 15,201,16375 44 | 16,246,10971 45 | 16,246,10971 46 | 16,246,10971 47 | 17,300,7351 48 | 17,300,7351 49 | 17,300,7351 50 | 18,367,4925 51 | 18,367,4925 52 | 18,367,4925 53 | 19,449,3299 54 | 19,449,3299 55 | 19,449,3299 56 | 20,548,2210 57 | 20,548,2210 58 | 20,548,2210 59 | 21,670,10971 60 | 21,670,10971 61 | 21,670,10971 62 | 22,818,7351 63 | 22,818,7351 64 | 22,818,7351 65 | 23,1000,4925 66 | 23,1000,4925 67 | 23,1000,4925 68 | 24,1222,3299 69 | 24,1222,3299 70 | 24,1222,3299 71 | 25,818,2210 72 | 25,818,2210 73 | 25,818,2210 74 | 26,1000,1481 75 | 26,1000,1481 76 | 26,1000,1481 77 | 27,670,7351 78 | 27,670,7351 79 | 27,670,7351 80 | 28,449,4925 81 | 28,449,4925 82 | 28,449,4925 83 | 29,548,3299 84 | 29,548,3299 85 | 29,548,3299 86 | 30,670,2210 87 | 30,670,2210 88 | 30,670,2210 89 | 31,449,1481 90 | 31,449,1481 91 | 31,449,1481 92 | 32,548,992 93 | 32,548,992 94 | 32,548,992 95 | 33,367,664 96 | 33,367,664 97 | 33,367,664 98 | 34,246,445 99 | 34,246,445 100 | 34,246,445 101 | 35,164,298 102 | 35,164,298 103 | 35,164,298 104 | 36,201,200 105 | 36,201,200 106 | 36,201,200 107 | 37,135,133 108 | 37,135,133 109 | 37,135,133 110 | 38,90,664 111 | 38,90,664 112 | 38,90,664 113 | 39,110,445 114 | 39,110,445 115 | 39,110,445 116 | 40,135,298 117 | 40,135,298 118 | 40,135,298 119 | 41,90,200 120 | 41,90,200 121 | 41,90,200 122 | 42,110,133 123 | 42,110,133 124 | 42,110,133 125 | 43,74,89 126 | 43,74,89 127 | 43,74,89 128 | 44,49,60 129 | 44,49,60 130 | 44,49,60 131 | 45,33,40 132 | 45,33,40 133 | 45,33,40 134 | 46,40,200 135 | 46,40,200 136 | 46,40,200 137 | 47,27,133 138 | 47,27,133 139 | 47,27,133 140 | 48,33,664 141 | 48,33,664 142 | 48,33,664 143 | 49,22,445 144 | 49,22,445 145 | 49,22,445 146 | 50,14,298 147 | 50,14,298 148 | 50,14,298 149 | 51,10,200 150 | 51,10,200 151 | 51,10,200 152 | 52,6,133 153 | 52,6,133 154 | 52,6,133 155 | 53,4,89 156 | 53,4,89 157 | 53,4,89 158 | 54,5,60 159 | 54,5,60 160 | 54,5,60 161 | 55,6,40 162 | 55,6,40 163 | 55,6,40 164 | 56,4,27 165 | 56,4,27 166 | 56,4,27 167 | 57,3,18 168 | 57,3,18 169 | 57,3,18 170 | 58,2,12 171 | 58,2,12 172 | 58,2,12 173 | 59,1,8 174 | 59,1,8 175 | 59,1,8 176 | 60,1,5 177 | 60,1,5 178 | 60,1,5 179 | 61,2,3 180 | 61,2,3 181 | 61,2,3 182 | 62,2,2 183 | 62,2,2 184 | 62,2,2 185 | 63,1,12 186 | 63,1,12 187 | 63,1,12 188 | 64,1,8 189 | 64,1,8 190 | 64,1,8 191 | 65,1,5 192 | 65,1,5 193 | 65,1,5 194 | 66,1,3 195 | 66,1,3 196 | 66,1,3 197 | 67,1,2 198 | 67,1,2 199 | 67,1,2 200 | 68,1,1 201 | 68,1,1 202 | 68,1,1 203 | 69,0,8 204 | 69,0,8 205 | 69,0,8 206 | 70,0,5 207 | 70,0,5 208 | 70,0,5 209 | 71,0,3 210 | 71,0,3 211 | 71,0,3 212 | 72,0,2 213 | 72,0,2 214 | 72,0,2 215 | 73,0,1 216 | 73,0,1 217 | 73,0,1 218 | 74,0,1 219 | 74,0,1 220 | 74,0,1 221 | 75,0,0 222 | 75,0,0 223 | 75,0,0 224 | 76,0,0 225 | 76,0,0 226 | 76,0,0 227 | 77,0,0 228 | 77,0,0 229 | 77,0,0 230 | 78,0,1 231 | 78,0,1 232 | 78,0,1 233 | 79,0,1 234 | 79,0,1 235 | 79,0,1 236 | 80,0,0 237 | 80,0,0 238 | 80,0,0 239 | 81,0,0 240 | 81,0,0 241 | 81,0,0 242 | 82,0,0 243 | 82,0,0 244 | 82,0,0 245 | 83,0,0 246 | 83,0,0 247 | 83,0,0 248 | 84,0,0 249 | 84,0,0 250 | 84,0,0 251 | 85,0,0 252 | 85,0,0 253 | 85,0,0 254 | 86,0,0 255 | 86,0,0 256 | 86,0,0 257 | 87,0,0 258 | 87,0,0 259 | 87,0,0 260 | 88,0,0 261 | 88,0,0 262 | 88,0,0 263 | 89,0,0 264 | 89,0,0 265 | 89,0,0 266 | 90,0,0 267 | 90,0,0 268 | 90,0,0 269 | 91,0,0 270 | 91,0,0 271 | 91,0,0 272 | 92,0,2 273 | 92,0,2 274 | 92,0,2 275 | 93,0,1 276 | 93,0,1 277 | 93,0,1 278 | 93,0,1 279 | 93,0,1 280 | 93,0,1 281 | -------------------------------------------------------------------------------- /logs/sold.csv: -------------------------------------------------------------------------------- 1 | turns,acceleratesBought,shellsBought 2 | 2,3,0 3 | 2,3,0 4 | 2,3,0 5 | 3,6,0 6 | 3,6,0 7 | 3,6,0 8 | 4,9,1 9 | 4,9,1 10 | 4,9,1 11 | 5,12,1 12 | 5,12,1 13 | 5,12,1 14 | 6,15,1 15 | 6,15,1 16 | 6,15,1 17 | 7,18,2 18 | 7,18,2 19 | 7,18,2 20 | 8,21,2 21 | 8,21,2 22 | 8,21,2 23 | 9,24,2 24 | 9,24,2 25 | 9,24,2 26 | 10,27,3 27 | 10,27,3 28 | 10,27,3 29 | 11,30,3 30 | 11,30,3 31 | 11,30,3 32 | 12,33,3 33 | 12,33,3 34 | 12,33,3 35 | 13,36,3 36 | 13,36,3 37 | 13,36,3 38 | 14,39,4 39 | 14,39,4 40 | 14,39,4 41 | 15,42,4 42 | 15,42,4 43 | 15,42,4 44 | 16,45,4 45 | 16,45,4 46 | 16,45,4 47 | 17,48,4 48 | 17,48,4 49 | 17,48,4 50 | 18,51,4 51 | 18,51,4 52 | 18,51,4 53 | 19,54,4 54 | 19,54,4 55 | 19,54,4 56 | 20,57,4 57 | 20,57,4 58 | 20,57,4 59 | 21,60,5 60 | 21,60,5 61 | 21,60,5 62 | 22,63,5 63 | 22,63,5 64 | 22,63,5 65 | 23,66,5 66 | 23,66,5 67 | 23,66,5 68 | 24,69,5 69 | 24,69,5 70 | 24,69,5 71 | 25,69,5 72 | 25,69,5 73 | 25,69,5 74 | 26,72,5 75 | 26,72,5 76 | 26,72,5 77 | 27,72,6 78 | 27,72,6 79 | 27,72,6 80 | 28,72,6 81 | 28,72,6 82 | 28,72,6 83 | 29,75,6 84 | 29,75,6 85 | 29,75,6 86 | 30,78,6 87 | 30,78,6 88 | 30,78,6 89 | 31,78,6 90 | 31,78,6 91 | 31,78,6 92 | 32,81,6 93 | 32,81,6 94 | 32,81,6 95 | 33,81,6 96 | 33,81,6 97 | 33,81,6 98 | 34,81,6 99 | 34,81,6 100 | 34,81,6 101 | 35,81,6 102 | 35,81,6 103 | 35,81,6 104 | 36,84,6 105 | 36,84,6 106 | 36,84,6 107 | 37,84,6 108 | 37,84,6 109 | 37,84,6 110 | 38,84,7 111 | 38,84,7 112 | 38,84,7 113 | 39,87,7 114 | 39,87,7 115 | 39,87,7 116 | 40,90,7 117 | 40,90,7 118 | 40,90,7 119 | 41,90,7 120 | 41,90,7 121 | 41,90,7 122 | 42,93,7 123 | 42,93,7 124 | 42,93,7 125 | 43,93,7 126 | 43,93,7 127 | 43,93,7 128 | 44,93,7 129 | 44,93,7 130 | 44,93,7 131 | 45,93,7 132 | 45,93,7 133 | 45,93,7 134 | 46,96,8 135 | 46,96,8 136 | 46,96,8 137 | 47,96,8 138 | 47,96,8 139 | 47,96,8 140 | 48,99,9 141 | 48,99,9 142 | 48,99,9 143 | 49,99,9 144 | 49,99,9 145 | 49,99,9 146 | 50,99,9 147 | 50,99,9 148 | 50,99,9 149 | 51,99,9 150 | 51,99,9 151 | 51,99,9 152 | 52,99,9 153 | 52,99,9 154 | 52,99,9 155 | 53,99,9 156 | 53,99,9 157 | 53,99,9 158 | 54,102,9 159 | 54,102,9 160 | 54,102,9 161 | 55,105,9 162 | 55,105,9 163 | 55,105,9 164 | 56,105,9 165 | 56,105,9 166 | 56,105,9 167 | 57,105,9 168 | 57,105,9 169 | 57,105,9 170 | 58,105,9 171 | 58,105,9 172 | 58,105,9 173 | 59,105,9 174 | 59,105,9 175 | 59,105,9 176 | 60,108,9 177 | 60,108,9 178 | 60,108,9 179 | 61,111,9 180 | 61,111,9 181 | 61,111,9 182 | 62,114,9 183 | 62,114,9 184 | 62,114,9 185 | 63,114,10 186 | 63,114,10 187 | 63,114,10 188 | 64,114,10 189 | 64,114,10 190 | 64,114,10 191 | 65,117,10 192 | 65,117,10 193 | 65,117,10 194 | 66,120,10 195 | 66,120,10 196 | 66,120,10 197 | 67,120,10 198 | 67,120,10 199 | 67,120,10 200 | 68,123,10 201 | 68,123,10 202 | 68,123,10 203 | 69,123,11 204 | 69,123,11 205 | 69,123,11 206 | 70,123,11 207 | 70,123,11 208 | 70,123,11 209 | 71,126,11 210 | 71,126,11 211 | 71,126,11 212 | 72,129,11 213 | 72,129,11 214 | 72,129,11 215 | 73,129,11 216 | 73,129,11 217 | 73,129,11 218 | 74,132,11 219 | 74,132,11 220 | 74,132,11 221 | 75,135,11 222 | 75,135,11 223 | 75,135,11 224 | 76,135,11 225 | 76,135,11 226 | 76,135,11 227 | 77,138,11 228 | 77,138,11 229 | 77,138,11 230 | 78,138,12 231 | 78,138,12 232 | 78,138,12 233 | 79,141,12 234 | 79,141,12 235 | 79,141,12 236 | 80,144,12 237 | 80,144,12 238 | 80,144,12 239 | 81,147,12 240 | 81,147,12 241 | 81,147,12 242 | 82,147,12 243 | 82,147,12 244 | 82,147,12 245 | 83,150,12 246 | 83,150,12 247 | 83,150,12 248 | 84,153,12 249 | 84,153,12 250 | 84,153,12 251 | 85,153,13 252 | 85,153,13 253 | 85,153,13 254 | 86,156,13 255 | 86,156,13 256 | 86,156,13 257 | 87,156,13 258 | 87,156,13 259 | 87,156,13 260 | 88,159,13 261 | 88,159,13 262 | 88,159,13 263 | 89,162,13 264 | 89,162,13 265 | 89,162,13 266 | 90,165,13 267 | 90,165,13 268 | 90,165,13 269 | 91,165,14 270 | 91,165,14 271 | 91,165,14 272 | 92,168,15 273 | 92,168,15 274 | 92,168,15 275 | 93,171,15 276 | 93,171,15 277 | 93,171,15 278 | 93,171,15 279 | 93,171,15 280 | 93,171,15 281 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "foundry-template", 3 | "license": "MIT", 4 | "version": "1.0.0", 5 | "description": "Streamlined template for getting started with Foundry and Solmate.", 6 | "files": [ 7 | "src/**/*.sol" 8 | ], 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/transmissions11/foundry-template.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 | -------------------------------------------------------------------------------- /script/DeployMonaco.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.13; 3 | 4 | import "forge-std/Script.sol"; 5 | 6 | import "../src/Monaco.sol"; 7 | 8 | contract DeployMonaco is Script { 9 | function run() public { 10 | vm.startBroadcast(); 11 | 12 | new Monaco(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/cars/Car.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.16; 3 | 4 | import "../Monaco.sol"; 5 | 6 | abstract contract Car { 7 | Monaco internal immutable monaco; 8 | 9 | constructor(Monaco _monaco) { 10 | monaco = _monaco; 11 | } 12 | 13 | // Note: The allCars array comes sorted in descending order of each car's y position. 14 | function takeYourTurn(Monaco.CarData[] calldata allCars, uint256 yourCarIndex) external virtual; 15 | } 16 | -------------------------------------------------------------------------------- /src/cars/FleckCar.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.16; 3 | 4 | import "./Car.sol"; 5 | 6 | interface MonacoInterface { 7 | struct CarData { 8 | uint32 balance; 9 | uint32 speed; 10 | uint32 y; 11 | Car car; 12 | } 13 | } 14 | 15 | contract FleckCars is Car { 16 | constructor(Monaco _monaco) Car(_monaco) {} 17 | 18 | function takeYourTurn(Monaco.CarData[] calldata allCars, uint256 ourCarIndex) external override { 19 | Monaco.CarData memory ourCar = allCars[ourCarIndex]; 20 | 21 | // If we can afford to accelerate 3 times, let's do it. 22 | if (ourCar.balance > monaco.getAccelerateCost(3)) ourCar.balance -= uint24(monaco.buyAcceleration(3)); 23 | 24 | // If we're not in the lead (index 0) + the car ahead of us is going faster + we can afford a shell, smoke em. 25 | if (ourCarIndex != 0 && allCars[ourCarIndex - 1].speed > ourCar.speed && ourCar.balance > monaco.getShellCost(1)) { 26 | monaco.buyShell(1); // This will instantly set the car in front of us' speed to 1. 27 | } 28 | 29 | // handle second place 30 | if (ourCarIndex == 1) {} 31 | 32 | // start 33 | // take lead and inflate shell price 34 | 35 | // middle 36 | 37 | // end game 38 | 39 | // if car is in second place and close to the end 900 > 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/cars/OpenSeaCar.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.16; // (10M optimization runs) 3 | 4 | interface MonacoInterface { 5 | struct CarData { 6 | uint32 balance; // Where 0 means the car has no money. 7 | uint32 speed; // Where 0 means the car isn't moving. 8 | uint32 y; // Where 0 means the car hasn't moved. 9 | Car car; 10 | } 11 | 12 | function buyAcceleration(uint256 amount) external returns (uint256 cost); 13 | 14 | function buyShell(uint256 amount) external returns (uint256 cost); 15 | 16 | function getAccelerateCost(uint256 amount) external view returns (uint256 sum); 17 | 18 | function getShellCost(uint256 amount) external view returns (uint256 sum); 19 | 20 | function turns() external view returns (uint256 turn); 21 | } 22 | 23 | 24 | abstract contract Car { 25 | MonacoInterface internal immutable monaco; 26 | 27 | constructor(MonacoInterface _monaco) { 28 | monaco = _monaco; 29 | } 30 | 31 | // Note: The allCars array comes sorted in descending order of each car's y position. 32 | function takeYourTurn(MonacoInterface.CarData[] calldata allCars, uint256 yourCarIndex) external virtual; 33 | } 34 | 35 | 36 | /// @author 0age 37 | /// @notice Be warned that this contract was hastily and iteratively hobbled together and has known bugs. 38 | contract c000r is Car { 39 | constructor(MonacoInterface _monaco) Car(_monaco) {} 40 | 41 | function takeYourTurn(MonacoInterface.CarData[] calldata allCars, uint256 ourCarIndex) external override { 42 | MonacoInterface.CarData memory ourCar = allCars[ourCarIndex]; 43 | 44 | // Win if possible. 45 | if ( 46 | ourCar.y > 850 && 47 | ourCar.balance >= monaco.getAccelerateCost(1000 - (ourCar.y + ourCar.speed)) 48 | ) { 49 | monaco.buyAcceleration(1000 - (ourCar.y + ourCar.speed)); 50 | return; 51 | } 52 | 53 | // Get the cost of a shell; only throw one per turn. 54 | uint256 shellCost = monaco.getShellCost(1); 55 | if (shellCost < 400 && ourCarIndex != 0 && allCars[0].y > 8 && allCars[1].y == 0 && allCars[2].y == 0) { 56 | // Respond to opening with a large move. 57 | monaco.buyShell(1); 58 | shellCost = 15001; 59 | } else if (shellCost == 0) { 60 | // Buy it if it's free. 61 | monaco.buyShell(1); 62 | shellCost = 15001; 63 | } else if (ourCarIndex == 1 && ourCar.balance >= shellCost && allCars[0].y + allCars[0].speed >= 1000) { 64 | // Don't lose if it can be stopped. 65 | ourCar.balance -= uint24(monaco.buyShell(1)); 66 | shellCost = 15001; 67 | } 68 | 69 | // Handle early-game; hang back for a bit in hopes that other two players duke it out. 70 | if (ourCarIndex != 0 && allCars[0].y < 200) { 71 | // Only move if immobile and not paying gouged prices due to an opponent's big opening move. 72 | if (ourCar.speed < 3 && shellCost < 15000) { 73 | monaco.buyAcceleration(2); 74 | } 75 | 76 | return; 77 | } 78 | 79 | // Handle late-game cases. 80 | if (allCars[0].y > 850) { 81 | // Handle cases where speed is too low and we're in the lead. 82 | if (ourCarIndex == 0 && (allCars[1].speed > ourCar.speed) || allCars[2].speed > ourCar.speed) { 83 | uint256 largerSpeed = allCars[1].speed > allCars[2].speed ? allCars[1].speed : allCars[2].speed; 84 | if (ourCar.balance >= monaco.getAccelerateCost(largerSpeed - ourCar.speed)) { 85 | monaco.buyAcceleration(largerSpeed - ourCar.speed); 86 | } else { 87 | try monaco.buyAcceleration(5) {} catch {} 88 | } 89 | 90 | return; 91 | } 92 | 93 | // Handle cases where we're behind. 94 | if (ourCarIndex != 0) { 95 | uint256 frontCarSpeed = allCars[ourCarIndex - 1].speed; 96 | 97 | // Shell the car ahead if it's moving quickly. 98 | if (ourCar.balance >= shellCost && shellCost < 2000 && ((frontCarSpeed > ourCar.speed && frontCarSpeed > 4) || frontCarSpeed > 8)) { 99 | ourCar.balance -= uint24(monaco.buyShell(1)); 100 | shellCost = 15001; 101 | } 102 | 103 | // Move forward decisively if we have the balance for it. 104 | uint256 bigMove = monaco.getAccelerateCost(7); 105 | if (ourCar.balance >= bigMove && bigMove < 1000) { 106 | ourCar.balance -= uint24(monaco.buyAcceleration(7)); 107 | ourCar.speed += 7; 108 | } 109 | } 110 | } 111 | 112 | // Don't fall behind when in last place and get out of it late in the race. 113 | uint256 costToCatchUp = 0; 114 | if (ourCarIndex == 2) { 115 | if (allCars[1].balance < 200 || (allCars[0].y > 825 && allCars[1].y < 750)) { 116 | // try and get into second place in order to shell next turn. 117 | costToCatchUp = monaco.getAccelerateCost(1 + allCars[1].speed + allCars[1].y - (ourCar.speed + ourCar.y)); 118 | } else if (allCars[1].speed > ourCar.speed) { 119 | // Hold position. 120 | costToCatchUp = monaco.getAccelerateCost(allCars[1].speed - ourCar.speed); 121 | } 122 | } 123 | 124 | // If we're in second place (index 1) + we can afford a shell: 125 | uint256 nextCarSpeed = allCars[0].speed; 126 | if ( 127 | ourCarIndex == 1 && 128 | nextCarSpeed > 3 && 129 | ourCar.balance >= shellCost 130 | ) { 131 | // if the car ahead of us is going fast and it's not really expensive to get em, smoke em. 132 | if (shellCost < 300 && ( 133 | nextCarSpeed > (ourCar.speed + 6) || 134 | nextCarSpeed > 24) 135 | ) { 136 | ourCar.balance -= uint24(monaco.buyShell(1)); 137 | } else if ( 138 | shellCost < 1000 && 139 | (nextCarSpeed > 35 || allCars[0].y - ourCar.y > 50 || allCars[0].y > 950 || ourCar.balance > 1000) 140 | ) { 141 | // The above thresholds for when to shell can be tuned; the ones above 142 | // are conservative to delay shelling until it's a desperate situation. 143 | ourCar.balance -= uint24(monaco.buyShell(1)); 144 | } 145 | } 146 | 147 | if ( 148 | // If we need to get moving, let's do it. 149 | ourCar.balance > (allCars[0].y < 800 ? 2000 : 500) && 150 | ourCar.speed < 6 151 | ) { 152 | try monaco.buyAcceleration(ourCarIndex == 0 ? 2 : 4) returns (uint256 cost) { 153 | ourCar.balance -= uint24(cost); 154 | ourCar.speed += ourCarIndex == 0 ? 2 : 4; 155 | } catch {} 156 | } else if ( 157 | // Keep pace early if in the back. 158 | costToCatchUp != 0 && 159 | ourCar.balance > costToCatchUp && 160 | costToCatchUp < 1000 161 | ) { 162 | uint256 catchUpAccelerationAmount = (allCars[1].speed - ourCar.speed) / (costToCatchUp < 50 ? 1 : 2); 163 | ourCar.balance -= uint24(monaco.buyAcceleration(catchUpAccelerationAmount)); 164 | ourCar.speed += uint32(catchUpAccelerationAmount); 165 | } else { 166 | // Keep moving, faster near the end if balance permits 167 | uint256 accelerationTarget = (ourCar.y > 800) ? 5 : 2; 168 | 169 | uint256 costToAccelerate = monaco.getAccelerateCost(accelerationTarget); 170 | 171 | if ( 172 | ourCar.balance > 200 && 173 | ourCar.balance > costToAccelerate && 174 | costToAccelerate < (ourCar.y > 800 ? 50 : 24) 175 | ) { 176 | ourCar.balance -= uint24(monaco.buyAcceleration(accelerationTarget)); 177 | ourCar.speed += uint32(accelerationTarget); 178 | } 179 | } 180 | 181 | // Go for a final boost when it makes sense 182 | if (ourCarIndex != 0 && allCars[0].y > 700 && ourCar.balance > allCars[0].balance * 2 && ourCar.balance > 220) { 183 | try monaco.buyAcceleration(5) {} catch {} 184 | } 185 | } 186 | 187 | function name() external pure returns (string memory) { 188 | return "c000r"; 189 | } 190 | } -------------------------------------------------------------------------------- /test/Monaco.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.13; 3 | 4 | import "forge-std/Test.sol"; 5 | 6 | import "../src/Monaco.sol"; 7 | import "../src/cars/ExampleCar.sol"; 8 | 9 | contract MonacoTest is Test { 10 | Monaco monaco; 11 | 12 | function setUp() public { 13 | monaco = new Monaco(); 14 | } 15 | 16 | function testGames() public { 17 | ExampleCar w1 = new ExampleCar(monaco); 18 | ExampleCar w2 = new ExampleCar(monaco); 19 | ExampleCar w3 = new ExampleCar(monaco); 20 | 21 | monaco.register(w1); 22 | monaco.register(w2); 23 | monaco.register(w3); 24 | 25 | // You can throw these CSV logs into Excel/Sheets/Numbers or a similar tool to visualize a race! 26 | vm.writeFile(string.concat("logs/", vm.toString(address(w1)), ".csv"), "turns,balance,speed,y\n"); 27 | vm.writeFile(string.concat("logs/", vm.toString(address(w2)), ".csv"), "turns,balance,speed,y\n"); 28 | vm.writeFile(string.concat("logs/", vm.toString(address(w3)), ".csv"), "turns,balance,speed,y\n"); 29 | vm.writeFile("logs/prices.csv", "turns,accelerateCost,shellCost\n"); 30 | vm.writeFile("logs/sold.csv", "turns,acceleratesBought,shellsBought\n"); 31 | 32 | while (monaco.state() != Monaco.State.DONE) { 33 | monaco.play(1); 34 | 35 | emit log(""); 36 | 37 | Monaco.CarData[] memory allCarData = monaco.getAllCarData(); 38 | 39 | for (uint256 i = 0; i < allCarData.length; i++) { 40 | Monaco.CarData memory car = allCarData[i]; 41 | 42 | emit log_address(address(car.car)); 43 | emit log_named_uint("balance", car.balance); 44 | emit log_named_uint("speed", car.speed); 45 | emit log_named_uint("y", car.y); 46 | 47 | vm.writeLine( 48 | string.concat("logs/", vm.toString(address(car.car)), ".csv"), 49 | string.concat( 50 | vm.toString(uint256(monaco.turns())), 51 | ",", 52 | vm.toString(car.balance), 53 | ",", 54 | vm.toString(car.speed), 55 | ",", 56 | vm.toString(car.y) 57 | ) 58 | ); 59 | 60 | vm.writeLine( 61 | "logs/prices.csv", 62 | string.concat( 63 | vm.toString(uint256(monaco.turns())), 64 | ",", 65 | vm.toString(monaco.getAccelerateCost(1)), 66 | ",", 67 | vm.toString(monaco.getShellCost(1)) 68 | ) 69 | ); 70 | 71 | vm.writeLine( 72 | "logs/sold.csv", 73 | string.concat( 74 | vm.toString(uint256(monaco.turns())), 75 | ",", 76 | vm.toString(monaco.getActionsSold(Monaco.ActionType.ACCELERATE)), 77 | ",", 78 | vm.toString(monaco.getActionsSold(Monaco.ActionType.SHELL)) 79 | ) 80 | ); 81 | } 82 | } 83 | 84 | emit log_named_uint("Number Of Turns", monaco.turns()); 85 | } 86 | } 87 | --------------------------------------------------------------------------------