├── .gas-snapshot ├── .github └── workflows │ ├── CI.yml │ └── shadow-beacon.yml ├── .gitignore ├── .gitmodules ├── .prettierrc ├── .solhint.json ├── LICENSE ├── README.md ├── foundry.toml ├── package.json ├── remappings.txt ├── scripts ├── codegen.go └── deploy.csv ├── src ├── IndexMarker.sol ├── IndexMarkerV2.sol ├── RomanNumerals.sol ├── Ronin.sol ├── ShadowBeacon.sol ├── ShadowBeaconDummy.sol ├── ShadowDistribution.sol ├── ShadowNFT.sol ├── TombIndex.sol ├── TombMetadata.sol ├── recovery │ ├── RecoveryVoteAggregator.sol │ └── TombRecoveryGovernor.sol ├── scripts │ ├── AdminMintIndexMarkers.sol │ ├── DeployIndexMarkerV2.s.sol │ ├── DeployRecoveryGovernor.s.sol │ ├── MigrationMintIndexMarkerV2.s.sol │ ├── SaveRanking.sol │ ├── SyncShadowBeacon.sol │ └── generateSaveRanking.js ├── test │ ├── IndexMarkerV2.t.sol │ ├── Ronin.t.sol │ ├── ShadowBeacon.t.sol │ ├── ShadowDistribution.t.sol │ ├── TombIndex.t.sol │ ├── TombMarker.t.sol │ ├── recovery │ │ └── TombRecoveryGovernor.t.sol │ └── utils │ │ ├── Console.sol │ │ ├── MockOwnable721.sol │ │ └── Utilities.sol └── utils │ └── IERC173.sol └── yarn.lock /.gas-snapshot: -------------------------------------------------------------------------------- 1 | CatTest:testFailPremint() (gas: 49982) 2 | IndexMarkerV2Test:testAdminMint() (gas: 145412) 3 | IndexMarkerV2Test:testCanMint() (gas: 30804) 4 | IndexMarkerV2Test:testDeleteDefaultRoyalty() (gas: 22062) 5 | IndexMarkerV2Test:testManageMarketFilterDAOSubscription() (gas: 120865) 6 | IndexMarkerV2Test:testMigrationMint() (gas: 315973) 7 | IndexMarkerV2Test:testMint() (gas: 118971) 8 | IndexMarkerV2Test:testResetTokenRoyalty() (gas: 32893) 9 | IndexMarkerV2Test:testRevertAdminMintNotOwner() (gas: 21602) 10 | IndexMarkerV2Test:testRevertDeleteDefaultRoyaltyNotOwner() (gas: 15507) 11 | IndexMarkerV2Test:testRevertManageMarketFilterDAOSubscriptionNotOwner() (gas: 21743) 12 | IndexMarkerV2Test:testRevertMigrationMintNotOwner() (gas: 188448) 13 | IndexMarkerV2Test:testRevertMintWithoutWaiting() (gas: 45824) 14 | IndexMarkerV2Test:testRevertResetTokenRoyaltyNotOwner() (gas: 39923) 15 | IndexMarkerV2Test:testRevertSetBaseURINotOwner() (gas: 15849) 16 | IndexMarkerV2Test:testRevertSetDefaultRoyaltyNotOwner() (gas: 15758) 17 | IndexMarkerV2Test:testRevertSetTokenClaimSignerNotOwner() (gas: 15648) 18 | IndexMarkerV2Test:testRevertSetTokenRoyaltyNotOwner() (gas: 15859) 19 | IndexMarkerV2Test:testRevertUpdateMarketFilterSettingsNotOwner() (gas: 22592) 20 | IndexMarkerV2Test:testRoyaltyInfo() (gas: 21826) 21 | IndexMarkerV2Test:testSetBaseURI() (gas: 25192) 22 | IndexMarkerV2Test:testSetDefaultRoyalty() (gas: 25173) 23 | IndexMarkerV2Test:testSetTokenClaimSigner() (gas: 21972) 24 | IndexMarkerV2Test:testSetTokenRoyalty() (gas: 40228) 25 | IndexMarkerV2Test:testSetTombContracts() (gas: 66519) 26 | IndexMarkerV2Test:testSetTombTokens() (gas: 72547) 27 | IndexMarkerV2Test:testTokenURI() (gas: 260476) 28 | IndexMarkerV2Test:testUpdateMarketFilterSettings() (gas: 45214) 29 | IndexMarkerV2Test:testUpgrade() (gas: 4675225) 30 | RoninTest:testAMint() (gas: 68275) 31 | RoninTest:testFailASecondMint() (gas: 9741) 32 | RoninTest:testFailTokenURI() (gas: 5395) 33 | RoninTest:testRoyaltyInfo() (gas: 10237) 34 | RoninTest:testTokenURI() (gas: 170666) 35 | ShadowBeaconTest:testFailSafeTransferFrom() (gas: 8620) 36 | ShadowBeaconTest:testFailSetApprovalForAll() (gas: 8504) 37 | ShadowBeaconTest:testFailTransferFrom() (gas: 10714) 38 | ShadowBeaconTest:testSignerTransferFrom() (gas: 43737) 39 | ShadowBeaconTest:testSignerTransferFromMint() (gas: 60568) 40 | ShadowDistributionTest:testClaim() (gas: 89438) 41 | ShadowDistributionTest:testFailClaimTwice() (gas: 96085) 42 | ShadowDistributionTest:testFailDifferentWallet() (gas: 45156) 43 | ShadowDistributionTest:testOtherWallet() (gas: 91458) 44 | TombContractTest:testBatchSave() (gas: 84682) 45 | TombContractTest:testExternalOwnerOf() (gas: 22352) 46 | TombContractTest:testFailDoesntExist() (gas: 14386) 47 | TombContractTest:testFailIsFrozen() (gas: 38185) 48 | TombContractTest:testFailUseOwnerFunction() (gas: 15221) 49 | TombContractTest:testOwnerOf() (gas: 10004) 50 | TombContractTest:testSetURI() (gas: 22599) 51 | TombContractTest:testSingleSave() (gas: 62044) 52 | TombContractTest:testTerrainTokenURI() (gas: 72458) 53 | TombRecoveryGovernorTest:test_Flow() (gas: 2333808) 54 | TombRecoveryGovernorTest:test_FlowAggregate() (gas: 2359277) -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | 8 | jobs: 9 | run-ci: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | with: 14 | submodules: recursive 15 | 16 | - name: Cache build state 17 | id: cache-build-state 18 | uses: actions/cache@v3 19 | with: 20 | path: ./out 21 | key: ${{ runner.os }} 22 | 23 | - name: Cache node modules 24 | id: cache-node-modules 25 | uses: actions/cache@v3 26 | with: 27 | path: ./node_modules 28 | key: ${{ runner.os }} 29 | 30 | - name: Cache build cache 31 | id: cache-build-cache 32 | uses: actions/cache@v3 33 | with: 34 | path: ./cache 35 | key: ${{ runner.os }} 36 | 37 | - uses: actions/setup-node@v2 38 | - name: Install dev dependencies 39 | run: yarn install 40 | 41 | - name: Install Foundry 42 | uses: onbjerg/foundry-toolchain@v1 43 | with: 44 | version: nightly 45 | 46 | - name: Run tests 47 | run: forge test 48 | -------------------------------------------------------------------------------- /.github/workflows/shadow-beacon.yml: -------------------------------------------------------------------------------- 1 | name: Sync shadow beacon 2 | 3 | on: 4 | schedule: 5 | - cron: "*/30 * * * *" 6 | push: 7 | branches: 8 | - main 9 | 10 | jobs: 11 | shadow-beacon: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | with: 16 | submodules: recursive 17 | 18 | - name: Cache build state 19 | id: cache-build-state 20 | uses: actions/cache@v3 21 | with: 22 | path: ./out 23 | key: ${{ runner.os }} 24 | 25 | - name: Cache node modules 26 | id: cache-node-modules 27 | uses: actions/cache@v3 28 | with: 29 | path: ./node_modules 30 | key: ${{ runner.os }} 31 | 32 | - name: Cache build cache 33 | id: cache-build-cache 34 | uses: actions/cache@v3 35 | with: 36 | path: ./cache 37 | key: ${{ runner.os }} 38 | 39 | - uses: actions/setup-node@v2 40 | - name: Install dev dependencies 41 | run: yarn install 42 | 43 | - name: Install Foundry 44 | uses: onbjerg/foundry-toolchain@v1 45 | with: 46 | version: nightly 47 | 48 | - name: Sync beacon 49 | run: forge script SyncShadowBeacon --chain-id 1 --broadcast 50 | env: 51 | GOERLI_RPC_URL: ${{ secrets.GOERLI_RPC_URL }} 52 | MAINNET_RPC_URL: ${{ secrets.MAINNET_RPC_URL }} 53 | MUMBAI_RPC_URL: ${{ secrets.MUMBAI_RPC_URL }} 54 | POLYGON_RPC_URL: ${{ secrets.POLYGON_RPC_URL }} 55 | SHADOW_BEACON_RELAY_PRIVATE_KEY: ${{ secrets.SHADOW_BEACON_RELAY_PRIVATE_KEY }} 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | cache/ 2 | out/ 3 | broadcast/ 4 | node_modules/ 5 | .DS_Store 6 | .env 7 | .env.* 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/ds-test"] 2 | path = lib/ds-test 3 | url = https://github.com/dapphub/ds-test 4 | [submodule "lib/solmate"] 5 | path = lib/solmate 6 | url = https://github.com/Rari-Capital/solmate 7 | [submodule "lib/openzeppelin-contracts"] 8 | path = lib/openzeppelin-contracts 9 | url = https://github.com/OpenZeppelin/openzeppelin-contracts 10 | [submodule "lib/base64"] 11 | path = lib/base64 12 | url = https://github.com/Brechtpd/base64 13 | [submodule "lib/forge-std"] 14 | path = lib/forge-std 15 | url = https://github.com/brockelmore/forge-std 16 | [submodule "lib/openzeppelin-contracts-upgradeable"] 17 | path = lib/openzeppelin-contracts-upgradeable 18 | url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable 19 | [submodule "lib/zora-drops-contracts"] 20 | path = lib/zora-drops-contracts 21 | url = https://github.com/ourzora/zora-drops-contracts 22 | [submodule "lib/recovery-protocol"] 23 | path = lib/recovery-protocol 24 | url = https://github.com/ourzora/recovery-protocol 25 | [submodule "lib/solady"] 26 | path = lib/solady 27 | url = https://github.com/Vectorized/solady -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 124 3 | } 4 | -------------------------------------------------------------------------------- /.solhint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solhint:recommended", 3 | "rules": { 4 | "quotes": ["warn", "double"], 5 | "compiler-version": ["error", ">=0.8.0"], 6 | "avoid-low-level-calls": "off", 7 | "contract-name-camelcase": "off", 8 | "func-visibility": ["warn", { "ignoreConstructors": true }], 9 | "max-line-length": ["warn", 124], 10 | "indent": ["error", 4], 11 | "cyclomatic-complexity": ["warn", 10] 12 | }, 13 | "plugins": ["prettier"] 14 | } 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2023 Luke Miles 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tombs 2 | 3 | Solidity repository for the Tomb Series 4 | -------------------------------------------------------------------------------- /foundry.toml: -------------------------------------------------------------------------------- 1 | [profile.default] 2 | src = 'src' 3 | out = 'out' 4 | libs = ['lib'] 5 | fs_permissions = [{ access = "read", path = "./"}] 6 | optimizer = true 7 | optimizer_runs = 1000 8 | 9 | 10 | # See more config options https://github.com/gakonst/foundry/tree/master/config 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tombs", 3 | "version": "1.0.0", 4 | "homepage": "https://github.com/FrankieIsLost/forge-template#readme", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/FrankieIsLost/forge-template.git" 8 | }, 9 | "scripts": { 10 | "prettier": "prettier --write 'src/**/*.sol'", 11 | "prettier:list": "prettier --list-different 'src/**/*.sol'", 12 | "prettier:check": "prettier --check 'src/**/*.sol'", 13 | "solhint": "solhint --config ./.solhint.json 'src/**/*.sol' --fix", 14 | "solhint:check": "solhint --config ./.solhint.json 'src/**/*.sol'", 15 | "lint": "yarn run prettier && npm run solhint", 16 | "lint:check": "yarn run prettier:check && npm run solhint:check" 17 | }, 18 | "devDependencies": { 19 | "prettier": "^2.5.1", 20 | "prettier-plugin-solidity": "^1.0.0-beta.19", 21 | "solhint": "^3.3.6", 22 | "solhint-plugin-prettier": "^0.0.5" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /remappings.txt: -------------------------------------------------------------------------------- 1 | ds-test/=lib/ds-test/src/ 2 | openzeppelin/=lib/openzeppelin-contracts/contracts 3 | openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts 4 | weird-erc20/=lib/solmate/lib/weird-erc20/src/ 5 | solmate/=lib/solmate/src/ 6 | base64/=lib/base64/ 7 | forge-std/=lib/forge-std/src 8 | zora-drops-contracts/=lib/zora-drops-contracts/ 9 | recovery-protocol/=lib/recovery-protocol/src/ 10 | solady/=lib/solady/src -------------------------------------------------------------------------------- /scripts/codegen.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/csv" 5 | "fmt" 6 | "log" 7 | "os" 8 | "strings" 9 | ) 10 | 11 | func main() { 12 | // open file 13 | f, err := os.Open("./deploy.csv") 14 | if err != nil { 15 | log.Fatal(err) 16 | } 17 | 18 | // remember to close the file at the end of the program 19 | defer f.Close() 20 | 21 | houseMap := make(map[string]string) 22 | houseMap["GENESIS"] = "0" 23 | houseMap["LUX"] = "1" 24 | houseMap["X2"] = "2" 25 | houseMap["SHADOW"] = "3" 26 | houseMap["COMETS"] = "4" 27 | houseMap["DEVASTATORS"] = "5" 28 | houseMap["TERRA"] = "6" 29 | houseMap["RONIN"] = "7" 30 | 31 | // read csv values using csv.Reader 32 | csvReader := csv.NewReader(f) 33 | data, err := csvReader.ReadAll() 34 | if err != nil { 35 | log.Fatal(err) 36 | } 37 | 38 | data = data[1:] 39 | 40 | for i := range data { 41 | name := data[i][1] 42 | house := houseMap[data[i][2]] 43 | numberInHouse := data[i][3] 44 | weight := strings.ReplaceAll(data[i][4], ".", "") 45 | if weight == "" { 46 | weight = "0" 47 | } 48 | fmt.Println(fmt.Sprintf(`_saveTomb(%v, "%s", Tomb({ 49 | _initialized: true, 50 | weight: %s, 51 | numberInHouse: %s, 52 | house: %s, 53 | deployment: deployment({ 54 | hostContract: 0x0000000000000000000000000000000000000000, 55 | tokenID: 0, 56 | chainID: 0, 57 | deployed: false 58 | }) 59 | }));`, 60 | i+1, name, weight, numberInHouse, house, 61 | )) 62 | fmt.Println("") 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /scripts/deploy.csv: -------------------------------------------------------------------------------- 1 | Numeral,Name,H [House],HN [Number In House],W [Weight] 2 | I,AEON,GENESIS,1,18.762.694 3 | II,TAROT,GENESIS,2,21.598.168 4 | III,CADMIUM,GENESIS,3,24.129.641 5 | IV,NIAGARA,GENESIS,4,22.108.549 6 | V,ARK,GENESIS,5,23.257.493 7 | VI,ORION,GENESIS,6,23.205.361 8 | VII,MIDNIGHT,GENESIS,7,19.431.160 9 | VIII,ORIGIN,LUX,1, 10 | IX,TURING,RONIN,1, 11 | X,HOME,TERRA,1, 12 | XI,EPOCH,COMETS,1, 13 | XII,TEMPO,COMETS,2, 14 | XIII,THE NEW JEWS,X2,1, 15 | XIV,ORIGIN UNKNOWN,DEVASTATORS,1, 16 | XV,HEAT,DEVASTATORS,2, 17 | XVI,FFF,DEVASTATORS,3, 18 | XVII,NEW FORM ZONE,X2,2, 19 | XVIII,ANAMNESIS,RONIN,2, 20 | XIX,SYNTAX,TERRA,2, 21 | XX,NUXUI-N,RONIN,3,18.447.712 22 | XXI,EQUINOX,RONIN,4, 23 | XXII,EUROPE AFTER THE RAIN,TERRA,3, 24 | XXIII,SEA OF SQUARES,X2,3, 25 | XXIV,STORM,DEVASTATORS,4, 26 | XXV,FANTAZIA,DEVASTATORS,5, 27 | XXVI,DREAMSCAPE,DEVASTATORS,6, 28 | XXVII,HYPERSPECTRAL DAWN,X2,4, 29 | XXVIII,SKYLINE,DEVASTATORS,7, 30 | XXIX,KHAOS,DEVASTATORS,8, 31 | XXX,ON REMAND,DEVASTATORS,9, 32 | XXXI,OUTER,COMETS,3, 33 | XXXII,ORDER,COMETS,4, 34 | XXXIII,ALPHA,SHADOW,1, 35 | XXXIV,VAPOUR,SHADOW,2, 36 | XXXV,HYPER,SHADOW,3, 37 | XXXVI,EXODUS,SHADOW,4, 38 | XXXVII,DAWN,SHADOW,5, 39 | XXXVIII,TOTAL ECLIPSE,SHADOW,6, 40 | XXXIX,VANISHING POINT,SHADOW,7, 41 | XL,FAINT,SHADOW,8, 42 | XLI,IRIDIUM,GENESIS,8, 43 | XLII,KILO,GENESIS,9, 44 | XLIII,CENSER,GENESIS,10, 45 | XLIV,QUARTO,GENESIS,11, 46 | XLV,KINGFISHER,GENESIS,12, 47 | XLVI,UNITE OR PERISH,GENESIS,13, 48 | XLVII,NANGA PARBAT,GENESIS,14, 49 | XLVIII,DUAL EVENT,SHADOW,9, 50 | XLIX,OPACITY,SHADOW,10, 51 | L,NEXUS,TERRA,4, 52 | LI,POINT,COMETS,5, 53 | LII,HALON,COMETS,6, 54 | LIII,VOID,SHADOW,11, 55 | LIV,EXCEEDING LIGHT,SHADOW,12, 56 | LV,BLACK HOLES IN THE NOW,SHADOW,13, 57 | LVI,UNKNOWN,SHADOW,14, 58 | LVII,TRANSPARENCY,SHADOW,15, 59 | LVIII,UNANIMOUS NIGHT,SHADOW,16, 60 | LIX,GHOST,SHADOW,17, 61 | LX,ENTIRE WORLDS,SHADOW,18, 62 | LXI,ANTIGEN,RONIN,5, 63 | LXII,FREED FROM DESIRE,TERRA,5, 64 | LXIII,PARADISE CONQUISTADORS,X2,5, 65 | LXIV,HARD LEADERS II,DEVASTATORS,10, 66 | LXV,WHITE 001,DEVASTATORS,11, 67 | LXVI,JUNGLIST,DEVASTATORS,12, 68 | LXVII,VOID ARROWS,X2,6, 69 | LXVIII,EARTH,RONIN,6, 70 | LXIX,THE KNOT TIES ITSELF,TERRA,6, 71 | LXX,DEATH IMITATES LANGUAGE,RONIN,7, 72 | LXXI,NECTAR AND LIGHT,X2,7, 73 | LXXII,RECUR,COMETS,7, 74 | LXXIII,PAX,LUX,2, 75 | LXXIV,FLOW COMA,DEVASTATORS,13, 76 | LXXV,TOTAL XSTACY,DEVASTATORS,14, 77 | LXXVI,TRAGEDY [FOR YOU],DEVASTATORS,15, 78 | LXXVII,VERDANT PERJURY,X2,8, 79 | LXXVIII,ACEN,DEVASTATORS,16, 80 | LXXIX,PROTOCOL,RONIN,8, 81 | LXXX,NONREAL PACKET MAZE,X2,9, 82 | LXXXI,ABSOLUTE POWER,GENESIS,15, 83 | LXXXII,TANTŌ,GENESIS,16, 84 | LXXXIII,JAG MANDIR,GENESIS,17, 85 | LXXXIV,NATION,GENESIS,18, 86 | LXXXV,SESSION,GENESIS,19, 87 | LXXXVI,HERE,GENESIS,20, 88 | LXXXVII,TACTA,GENESIS,21, 89 | LXXXVIII,WING OF A BLUE ROLLER,TERRA,7, 90 | LXXXIX,SHADDAI,LUX,3, 91 | XC,DEFENSOR MUNDI,TERRA,8, 92 | XCI,TIME PASSES,GENESIS,22, 93 | XCII,DYNAMICS,GENESIS,23, 94 | XCIII,CONFUSION,GENESIS,24, 95 | XCIV,IDEEËN,GENESIS,25, 96 | XCV,ZEITUNG,GENESIS,26, 97 | XCVI,MONUMENT,GENESIS,27, 98 | XCVII,ENERGY REMAINS,GENESIS,28, 99 | XCVIII,HACKED AMAZON,X2,10, 100 | XCIX,SUPRA,COMETS,8, 101 | C,ÆTHER,LUX,4, 102 | CI,RADAR,COMETS,9, 103 | CII,ARRAY,COMETS,10, 104 | CIII,QUADRATIC EMPIRE,X2,11, 105 | CIV,ENERGY FLASH,DEVASTATORS,17, 106 | CV,INTO DREAMS,DEVASTATORS,18, 107 | CVI,SLOW,DEVASTATORS,19, 108 | CVII,VENOM HORIZON,X2,12, 109 | CVIII,2099,DEVASTATORS,20, 110 | CIX,LEMUR,RONIN,9, 111 | CX,SUBTROPICAL SHRINES,X2,13, 112 | CXI,TERRAIN,RONIN,10,22.862.184 113 | CXII,AEGIS,TERRA,9, 114 | CXIII,VIBE SARCOPHAGI,X2,14, 115 | CXIV,HALCYON,DEVASTATORS,21, 116 | CXV,JOYRIDER 2,DEVASTATORS,22, 117 | CXVI,WORLD [PRICE OF LOVE],DEVASTATORS,23, 118 | CXVII,OZYMANDIAS,X2,15, 119 | CXVIII,FOREVER,RONIN,11, 120 | CXIX,FRONTIER,TERRA,10, 121 | CXX,STRAYLIGHT,RONIN,12, 122 | CXXI,HYDRA,COMETS,11, 123 | CXXII,SWIFT,COMETS,12, 124 | CXXIII,ANON,SHADOW,19, 125 | CXXIV,INDEX,SHADOW,20, 126 | CXXV,HARD TARGET,SHADOW,21, 127 | CXXVI,BLACKBIRD,SHADOW,22, 128 | CXXVII,OBSERVE,SHADOW,23, 129 | CXXVIII,AFTER EARTH,SHADOW,24, 130 | CXXIX,UMBRA,SHADOW,25, 131 | CXXX,POEM,SHADOW,26, 132 | CXXXI,MONT BLANC,GENESIS,29, 133 | CXXXII,TOURBILLON,GENESIS,30, 134 | CXXXIII,CALIBAN,GENESIS,31, 135 | CXXXIV,CYGNUS,GENESIS,32, 136 | CXXXV,VOYAGES,GENESIS,33, 137 | CXXXVI,LOAM,GENESIS,34, 138 | CXXXVII,HNX_T01,GENESIS,35, 139 | CXXXVIII,ENDSTATE,SHADOW,27, 140 | CXXXIX,TERMINAL,SHADOW,28, 141 | CXL,FORGERY,TERRA,11, 142 | CXLI,NOMAD,COMETS,13, 143 | CXLII,XENON,COMETS,14, 144 | CXLIII,REVEAL,SHADOW,29, 145 | CXLIV,LONE AND LEVEL,SHADOW,30, 146 | CXLV,PHANTOM,SHADOW,31, 147 | CXLVI,TRUE,SHADOW,32, 148 | CXLVII,STEALTH,SHADOW,33, 149 | CXLVIII,VANTA,SHADOW,34, 150 | CXLIX,KAIROS,SHADOW,35, 151 | CL,SHADOW,SHADOW,36, 152 | CLI,TRANCE,RONIN,13, 153 | CLII,REPLICA,TERRA,12, 154 | CLIII,THE FOG OF JUNK PSALMS,X2,16, 155 | CLIV,VALLEY OF THE SHADOWS,DEVASTATORS,24, 156 | CLV,THE END,DEVASTATORS,25, 157 | CLVI,PHOSPHOR,DEVASTATORS,26, 158 | CLVII,ABOUT PLATO'S CAVE,X2,17, 159 | CLVIII,IX. SECTOR,RONIN,14, 160 | CLIX,FICTION,TERRA,13, 161 | CLX,SOLUTION,RONIN,15, 162 | CLXI,TOPOS,COMETS,15, 163 | CLXII,LIGHT,COMETS,16, 164 | CLXIII,THE BEZEL EPOQUE,X2,18, 165 | CLXIV,I STILL DREAM,DEVASTATORS,27, 166 | CLXV,TIME PROBLEM,DEVASTATORS,28, 167 | CLXVI,ARCOURS,DEVASTATORS,29, 168 | CLXVII,SELBSTVERSELBSTLICHUNG,X2,19, 169 | CLXVIII,ISENHEIM,TERRA,14, 170 | CLXIX,T1A–T [RONIN],RONIN,16, 171 | CLXX,ETERNA,LUX,5, 172 | CLXXI,EMPYREAN,GENESIS,36, 173 | CLXXII,TACIT BLUE,GENESIS,37, 174 | CLXXIII,ARDENNES,GENESIS,38, 175 | CLXXIV,VOYAGES 2,GENESIS,39, 176 | CLXXV,INPUT,GENESIS,40, 177 | CLXXVI,ULTRA,GENESIS,41, 178 | CLXXVII,GENESIS,GENESIS,42, -------------------------------------------------------------------------------- /src/IndexMarker.sol: -------------------------------------------------------------------------------- 1 | // .^7??????????????????????????????????????????????????????????????????7!: .~7????????????????????????????????: 2 | // :#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Y ^#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5 3 | // ^@@@@@@#BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB&@@@@@B ~@@@@@@#BBBBBBBBBBBBBBBBBBBBBBBBBBBBB#7 4 | // Y@@@@@# ~@@@@@@ P@@@@@G 5 | // .&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&G~ ~@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Y :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&P~ 6 | // J&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#.!B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B~ .Y&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B 7 | // ...........................B@@@@@5 .7#@@@@@@@#?^.................... ..........................:#@@@@@J 8 | // ^5YYYJJJJJJJJJJJJJJJJJJJJJJJJJJY&@@@@@? .J&@@@@@@&5JJJJJJJJJJJJJJJJJJJYYYYYYYYYYJJJJJJJJJJJJJJJJJJJJJJJJJJY@@@@@@! 9 | // 5@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@? :5&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@7 10 | // !GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPY~ ^JPGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPJ^ 11 | 12 | // _____________________________________________________ Tomb Series _____________________________________________________ 13 | 14 | // :!JYYYYJ!. .JYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY?~. 7YYYYYYYYY?~. ^JYYYYYYYYY^ 15 | // ~&@@@@@@@@@@#7. ?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@P &@@@@@@@@@@@@B! :@@@@@@@@@@@5 16 | // ^@@@@@@BB@@@@@@@B! ?@@@@@&PGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG&@@@@@# JGGGGGGG#@@@@@@@G^ !PGGGGGGGGG! 17 | // 5@@@@@5 .7#@@@@@@@P^ ?@@@@@P .@@@@@@. .J&@@@@@@&5: 18 | // Y@@@@@Y .J&@@@@@@&5: ?@@@@@G @@@@@@. :Y&@@@@@@&J. 19 | // Y@@@@@5 :5&@@@@@@&J. ?@@@@@G @@@@@@. ^P@@@@@@@#7. 20 | // Y@@@@@5 ^P@@@@@@@#7. J@@@@@G @@@@@@. ~G@@@@@@@B! 21 | // Y@@@@@5 ~B@@@@@@@BG@@@@@@! PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP#@@@@@# JGPPPPPPPP5: .7#@@@@@@@GPPPPPPG~ 22 | // 5@@@@@5 .7#@@@@@@@@@@&! .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@G &@@@@@@@@@@& .J&@@@@@@@@@@@@5 23 | // ^5YYY5~ .!JYYYYY7: Y5YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYJ~. ?5YYYYYYY5J. :7JYYYYYYYY5^ 24 | 25 | // __________________________________________________ Tomb Index Marker ___________________________________________________ 26 | 27 | // ________________________________________________ Deployed by TERRAIN 2022 _______________________________________________ 28 | 29 | // ____________________________________________ All tombs drawn by David Rudnick ___________________________________________ 30 | 31 | // ____________________________________________ Contract architect: Luke Miles _____________________________________________ 32 | 33 | // SPDX-License-Identifier: MIT 34 | 35 | import "solmate/tokens/ERC721.sol"; 36 | import "openzeppelin/utils/cryptography/ECDSA.sol"; 37 | import "openzeppelin/utils/Strings.sol"; 38 | import "openzeppelin/access/Ownable.sol"; 39 | 40 | pragma solidity >=0.8.0; 41 | 42 | contract IndexMarker is Ownable, ERC721 { 43 | string public baseURI; 44 | address public signer; 45 | 46 | bool public isMintingAllowed = false; 47 | uint256 public mintExpiry = 1672531199; // Sat Dec 31 2022 23:59:59 GMT+0000 48 | uint256 public royaltyPct = 10; 49 | uint16 public maxIndex = 3000; 50 | 51 | ERC721 indexContract; 52 | 53 | mapping(bytes32 => uint256) public premintTimes; 54 | 55 | address public royaltyDestination; 56 | address internal _tombArtist = 0x4a61d76ea05A758c1db9C9b5a5ad22f445A38C46; 57 | 58 | constructor( 59 | address _signer, 60 | string memory _baseURI, 61 | address _indexContract, 62 | address _royaltyDestination 63 | ) ERC721("Tomb Index Marker", "MKR") { 64 | royaltyDestination = _royaltyDestination; 65 | signer = _signer; 66 | baseURI = _baseURI; 67 | indexContract = ERC721(_indexContract); 68 | 69 | // initialize RONIN 70 | _mint(msg.sender, 0); 71 | } 72 | 73 | function canMint() public view returns (bool) { 74 | // solhint-disable-next-line not-rely-on-time 75 | return isMintingAllowed && mintExpiry > block.timestamp; 76 | } 77 | 78 | function calculateMintHash( 79 | uint256 tokenID, 80 | bytes memory signature, 81 | address sender 82 | ) internal pure returns (bytes32) { 83 | return keccak256(abi.encodePacked(tokenID, signature, sender)); 84 | } 85 | 86 | function premint(bytes32 _hash) public { 87 | // This function reserve the tokenID for the user calling the key. 88 | // Prevents against someone checking the mempool for calls to mint. 89 | 90 | // Don't allow overriding the hash, otherwise someone could frontrun 91 | // by resetting someone's hash value to the current timestamp. 92 | require(premintTimes[_hash] == 0, "Can't override hash value"); 93 | 94 | // solhint-disable-next-line not-rely-on-time 95 | premintTimes[_hash] = block.timestamp; 96 | } 97 | 98 | function mint(uint256 tokenID, bytes memory signature) public { 99 | require(canMint(), "Public minting is not active"); 100 | require(tokenID <= maxIndex, "Index is too high"); 101 | bytes32 mintHash = calculateMintHash(tokenID, signature, msg.sender); 102 | uint256 premintTime = premintTimes[mintHash]; 103 | require(premintTime != 0, "Token is not preminted"); 104 | 105 | require( 106 | // solhint-disable-next-line not-rely-on-time 107 | block.timestamp - premintTime > 60, 108 | "Claim is too new" 109 | ); 110 | 111 | (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(keccak256(abi.encodePacked(tokenID)), signature); 112 | require(error == ECDSA.RecoverError.NoError && recovered == signer, "Invalid signature"); 113 | 114 | _mint(msg.sender, tokenID); 115 | } 116 | 117 | function creatorClaim(uint256[] calldata tokenIDs, address destination) public onlyOwner { 118 | require(!canMint(), "Can't admin claim when mint active"); 119 | for (uint256 i = 0; i < tokenIDs.length; i++) { 120 | require(tokenIDs[i] <= maxIndex, "Index is too high"); 121 | _mint(destination, tokenIDs[i]); 122 | } 123 | } 124 | 125 | function updateSigner(address _signer) public onlyOwner { 126 | signer = _signer; 127 | } 128 | 129 | function updateRoyaltyPct(uint256 _newRoyaltyPct) public onlyOwner { 130 | royaltyPct = _newRoyaltyPct; 131 | } 132 | 133 | function updateRoyaltyDestination(address _newRoyaltyDestination) public onlyOwner { 134 | royaltyDestination = _newRoyaltyDestination; 135 | } 136 | 137 | function setBaseURI(string memory _baseURI) public onlyOwner { 138 | baseURI = _baseURI; 139 | } 140 | 141 | function setMintInformation(bool _isMintingAllowed, uint256 _mintExpiry) public onlyOwner { 142 | isMintingAllowed = _isMintingAllowed; 143 | mintExpiry = _mintExpiry; 144 | } 145 | 146 | function tokenURI(uint256 tokenID) public view override returns (string memory) { 147 | // for the RONIN metadata 148 | if (tokenID == 0) { 149 | return indexContract.tokenURI(21); 150 | } 151 | 152 | return string(abi.encodePacked(baseURI, Strings.toString(tokenID))); 153 | } 154 | 155 | function royaltyInfo(uint256 _tokenID, uint256 _salePrice) 156 | external 157 | view 158 | returns (address receiver, uint256 royaltyAmount) 159 | { 160 | if (royaltyPct < 1) { 161 | return (address(0), 0); 162 | } 163 | 164 | receiver = royaltyDestination; 165 | 166 | if (_tokenID == 0) { 167 | receiver = _tombArtist; 168 | } 169 | 170 | royaltyAmount = _salePrice / royaltyPct; 171 | } 172 | 173 | function supportsInterface(bytes4 interfaceId) public pure override(ERC721) returns (bool) { 174 | return 175 | interfaceId == 0x7f5828d0 || // ERC165 Interface ID for ERC173 176 | interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 177 | interfaceId == 0x5b5e139f || // ERC165 Interface ID for ERC165 178 | interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC721Metadata 179 | interfaceId == 0x2a55205a; // ERC165 Interface ID for https://eips.ethereum.org/EIPS/eip-2981 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/IndexMarkerV2.sol: -------------------------------------------------------------------------------- 1 | // .^7??????????????????????????????????????????????????????????????????7!: .~7????????????????????????????????: 2 | // :#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Y ^#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5 3 | // ^@@@@@@#BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB&@@@@@B ~@@@@@@#BBBBBBBBBBBBBBBBBBBBBBBBBBBBB#7 4 | // Y@@@@@# ~@@@@@@ P@@@@@G 5 | // .&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&G~ ~@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Y :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&P~ 6 | // J&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#.!B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B~ .Y&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B 7 | // ...........................B@@@@@5 .7#@@@@@@@#?^.................... ..........................:#@@@@@J 8 | // ^5YYYJJJJJJJJJJJJJJJJJJJJJJJJJJY&@@@@@? .J&@@@@@@&5JJJJJJJJJJJJJJJJJJJYYYYYYYYYYJJJJJJJJJJJJJJJJJJJJJJJJJJY@@@@@@! 9 | // 5@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@? :5&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@7 10 | // !GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPY~ ^JPGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPJ^ 11 | 12 | // _____________________________________________________ Tomb Series _____________________________________________________ 13 | 14 | // :!JYYYYJ!. .JYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY?~. 7YYYYYYYYY?~. ^JYYYYYYYYY^ 15 | // ~&@@@@@@@@@@#7. ?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@P &@@@@@@@@@@@@B! :@@@@@@@@@@@5 16 | // ^@@@@@@BB@@@@@@@B! ?@@@@@&PGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG&@@@@@# JGGGGGGG#@@@@@@@G^ !PGGGGGGGGG! 17 | // 5@@@@@5 .7#@@@@@@@P^ ?@@@@@P .@@@@@@. .J&@@@@@@&5: 18 | // Y@@@@@Y .J&@@@@@@&5: ?@@@@@G @@@@@@. :Y&@@@@@@&J. 19 | // Y@@@@@5 :5&@@@@@@&J. ?@@@@@G @@@@@@. ^P@@@@@@@#7. 20 | // Y@@@@@5 ^P@@@@@@@#7. J@@@@@G @@@@@@. ~G@@@@@@@B! 21 | // Y@@@@@5 ~B@@@@@@@BG@@@@@@! PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP#@@@@@# JGPPPPPPPP5: .7#@@@@@@@GPPPPPPG~ 22 | // 5@@@@@5 .7#@@@@@@@@@@&! .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@G &@@@@@@@@@@& .J&@@@@@@@@@@@@5 23 | // ^5YYY5~ .!JYYYYY7: Y5YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYJ~. ?5YYYYYYY5J. :7JYYYYYYYY5^ 24 | 25 | // __________________________________________________ Tomb Index Marker ___________________________________________________ 26 | 27 | // _______________________________________________ Deployed by TERRAIN 2022 _______________________________________________ 28 | 29 | // ___________________________________________ All tombs drawn by David Rudnick ___________________________________________ 30 | 31 | // ___________________________________ Contract architects: James Geary and Luke Miles ____________________________________ 32 | 33 | // SPDX-License-Identifier: MIT 34 | pragma solidity 0.8.17; 35 | 36 | import "openzeppelin-upgradeable/access/OwnableUpgradeable.sol"; 37 | import "openzeppelin-upgradeable/proxy/utils/Initializable.sol"; 38 | import "openzeppelin-upgradeable/proxy/utils/UUPSUpgradeable.sol"; 39 | import "openzeppelin-upgradeable/token/common/ERC2981Upgradeable.sol"; 40 | import "openzeppelin-upgradeable/token/ERC721/IERC721Upgradeable.sol"; 41 | import "openzeppelin-upgradeable/token/ERC721/ERC721Upgradeable.sol"; 42 | import "openzeppelin-upgradeable/token/ERC721/extensions/ERC721VotesUpgradeable.sol"; 43 | import "openzeppelin-upgradeable/utils/cryptography/EIP712Upgradeable.sol"; 44 | import "openzeppelin-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; 45 | import "openzeppelin-upgradeable/utils/StringsUpgradeable.sol"; 46 | import "zora-drops-contracts/src/interfaces/IOperatorFilterRegistry.sol"; 47 | import "./utils/IERC173.sol"; 48 | 49 | contract IndexMarkerV2 is 50 | Initializable, 51 | ERC721Upgradeable, 52 | OwnableUpgradeable, 53 | EIP712Upgradeable, 54 | ERC721VotesUpgradeable, 55 | ERC2981Upgradeable, 56 | UUPSUpgradeable 57 | { 58 | uint96 internal constant DEFAULT_ROYALTY_BPS = 1_000; // 10% 59 | uint16 internal constant MAX_SUPPLY = 3_000; 60 | 61 | address payable public constant TOMB_ARTIST = payable(0x4a61d76ea05A758c1db9C9b5a5ad22f445A38C46); 62 | IOperatorFilterRegistry public immutable operatorFilterRegistry = 63 | IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E); 64 | address public marketFilterDAOAddress; 65 | 66 | ERC721Upgradeable public indexContract; 67 | IERC721Upgradeable public indexMarkerV1; 68 | address public tokenClaimSigner; 69 | uint256 public mintExpiry; 70 | bool public isMintAllowed; 71 | mapping(bytes32 => uint256) public premintTimes; 72 | mapping(address => bool) public isTombContract; 73 | mapping(address => mapping(uint256 => bool)) public isSingletonTombToken; 74 | 75 | string public baseURI; 76 | 77 | constructor() { 78 | _disableInitializers(); 79 | } 80 | 81 | function initialize( 82 | address _marketFilterDAOAddress, 83 | address _tokenClaimSigner, 84 | address _indexMarkerV1, 85 | address payable _defaultRoyalty, 86 | address _indexContract 87 | ) public initializer { 88 | __Ownable_init(); 89 | __ERC721_init("Tomb Index Marker", "MKR"); 90 | __EIP712_init("Tomb Index Marker", "1"); 91 | __ERC721Votes_init(); 92 | __UUPSUpgradeable_init(); 93 | __ERC2981_init(); 94 | 95 | // initialize RONIN 96 | _mint(_msgSender(), 0); 97 | 98 | indexMarkerV1 = IERC721Upgradeable(_indexMarkerV1); 99 | mintExpiry = 1672531199; // Sat Dec 31 2022 23:59:59 GMT+0000 100 | isMintAllowed = false; 101 | marketFilterDAOAddress = _marketFilterDAOAddress; 102 | tokenClaimSigner = _tokenClaimSigner; 103 | baseURI = "ipfs://QmYZEr3xvwdd5v5wbFR4LEDrqaBRLG3gXg5uC6SK37GfaQ/"; 104 | indexContract = ERC721Upgradeable(_indexContract); 105 | _setTokenRoyalty(0, TOMB_ARTIST, DEFAULT_ROYALTY_BPS); 106 | _setDefaultRoyalty(_defaultRoyalty, DEFAULT_ROYALTY_BPS); 107 | } 108 | 109 | /// TOKEN AND MINTING /// 110 | 111 | function tokenURI(uint256 tokenID) public view override returns (string memory) { 112 | _requireMinted(tokenID); 113 | 114 | if (tokenID == 0) { 115 | return indexContract.tokenURI(21); 116 | } 117 | 118 | return string(abi.encodePacked(baseURI, StringsUpgradeable.toString(tokenID))); 119 | } 120 | 121 | function setBaseURI(string calldata newBaseURI) external onlyOwner { 122 | baseURI = newBaseURI; 123 | } 124 | 125 | function _beforeTokenTransfer( 126 | address from, 127 | address to, 128 | uint256 tokenId, 129 | uint256 batchSize 130 | ) internal override(ERC721Upgradeable) { 131 | if (from != _msgSender() && address(operatorFilterRegistry).code.length > 0) { 132 | require( 133 | operatorFilterRegistry.isOperatorAllowed(address(this), _msgSender()), 134 | "IndexMarker: operator not allowed" 135 | ); 136 | } 137 | 138 | super._beforeTokenTransfer(from, to, tokenId, batchSize); 139 | } 140 | 141 | function _afterTokenTransfer( 142 | address from, 143 | address to, 144 | uint256 tokenId, 145 | uint256 batchSize 146 | ) internal override(ERC721Upgradeable, ERC721VotesUpgradeable) { 147 | super._afterTokenTransfer(from, to, tokenId, batchSize); 148 | } 149 | 150 | function migrationMint(uint256[] calldata tokenIds) public onlyOwner { 151 | for (uint256 i = 0; i < tokenIds.length; i++) { 152 | address recipient = indexMarkerV1.ownerOf(tokenIds[i]); 153 | require(recipient != address(0), "IndexMarker: token does not exist"); 154 | _mint(recipient, tokenIds[i]); 155 | } 156 | } 157 | 158 | function adminMint(uint256[] calldata tokenIds, address[] calldata recipients) public onlyOwner { 159 | require(!canMint(), "Can't admin claim when mint active"); 160 | require(tokenIds.length == recipients.length, "IndexMarker: invalid input"); 161 | for (uint256 i = 0; i < tokenIds.length; i++) { 162 | require(tokenIds[i] <= MAX_SUPPLY, "IndexMarker: Index is too high"); 163 | _mint(recipients[i], tokenIds[i]); 164 | } 165 | } 166 | 167 | function canMint() public view returns (bool) { 168 | return isMintAllowed && mintExpiry > block.timestamp; 169 | } 170 | 171 | function calculateMintHash( 172 | uint256 tokenId, 173 | bytes memory signature, 174 | address sender 175 | ) internal pure returns (bytes32) { 176 | return keccak256(abi.encodePacked(tokenId, signature, sender)); 177 | } 178 | 179 | function premint(bytes32 _hash) public { 180 | require(premintTimes[_hash] == 0, "IndexMarker: Can't override hash value"); 181 | premintTimes[_hash] = block.timestamp; 182 | } 183 | 184 | function mint(uint256 tokenId, bytes memory signature) public { 185 | require(canMint(), "IndexMarker: Public minting is not active"); 186 | require(tokenId <= MAX_SUPPLY, "IndexMarker: Index is too high"); 187 | bytes32 mintHash = calculateMintHash(tokenId, signature, _msgSender()); 188 | uint256 premintTime = premintTimes[mintHash]; 189 | require(premintTime != 0, "IndexMarker: Token is not preminted"); 190 | 191 | require(block.timestamp - premintTime > 60, "IndexMarker: Claim is too new"); 192 | 193 | (address recovered, ECDSAUpgradeable.RecoverError error) = ECDSAUpgradeable.tryRecover( 194 | keccak256(abi.encodePacked(tokenId)), 195 | signature 196 | ); 197 | require( 198 | error == ECDSAUpgradeable.RecoverError.NoError && recovered == tokenClaimSigner, 199 | "IndexMarker: Invalid signature" 200 | ); 201 | 202 | _mint(_msgSender(), tokenId); 203 | } 204 | 205 | function setTokenClaimSigner(address _tokenClaimSigner) public onlyOwner { 206 | tokenClaimSigner = _tokenClaimSigner; 207 | } 208 | 209 | function setMintAllowedAndExpiry(bool _isMintAllowed, uint256 _expiry) public onlyOwner { 210 | isMintAllowed = _isMintAllowed; 211 | mintExpiry = _expiry; 212 | } 213 | 214 | /// ROYALTIES /// 215 | 216 | function setDefaultRoyalty(address receiver, uint96 feeNumerator) public onlyOwner { 217 | _setDefaultRoyalty(receiver, feeNumerator); 218 | } 219 | 220 | function deleteDefaultRoyalty() public onlyOwner { 221 | _deleteDefaultRoyalty(); 222 | } 223 | 224 | function setTokenRoyalty( 225 | uint256 tokenId, 226 | address receiver, 227 | uint96 feeNumerator 228 | ) public onlyOwner { 229 | _setTokenRoyalty(tokenId, receiver, feeNumerator); 230 | } 231 | 232 | function resetTokenRoyalty(uint256 tokenId) public onlyOwner { 233 | _resetTokenRoyalty(tokenId); 234 | } 235 | 236 | /// OPERATOR FILTERING /// 237 | 238 | function updateMarketFilterSettings(bytes calldata args) external onlyOwner returns (bytes memory) { 239 | (bool success, bytes memory ret) = address(operatorFilterRegistry).call(args); 240 | require(success, "IndexMarker: failed to update market settings"); 241 | return ret; 242 | } 243 | 244 | function manageMarketFilterDAOSubscription(bool enable) external onlyOwner { 245 | address self = address(this); 246 | require(marketFilterDAOAddress != address(0), "IndexMarker: DAO not set"); 247 | if (!operatorFilterRegistry.isRegistered(self) && enable) { 248 | operatorFilterRegistry.registerAndSubscribe(self, marketFilterDAOAddress); 249 | } else if (enable) { 250 | operatorFilterRegistry.subscribe(self, marketFilterDAOAddress); 251 | } else { 252 | operatorFilterRegistry.unsubscribe(self, false); 253 | operatorFilterRegistry.unregister(self); 254 | } 255 | } 256 | 257 | /// TOMB REGISTRY /// 258 | 259 | function setTombContracts(address[] memory _contracts, bool[] memory _isTombContract) public onlyOwner { 260 | require(_contracts.length == _isTombContract.length, "IndexMarker: invalid input"); 261 | for (uint256 i = 0; i < _contracts.length; i++) { 262 | isTombContract[_contracts[i]] = _isTombContract[i]; 263 | } 264 | } 265 | 266 | function setTombTokens( 267 | address[] memory _contracts, 268 | uint256[] memory _tokenIds, 269 | bool[] memory _isTombToken 270 | ) public onlyOwner { 271 | require( 272 | _contracts.length == _tokenIds.length && _tokenIds.length == _isTombToken.length, 273 | "IndexMarker: invalid input" 274 | ); 275 | for (uint256 i = 0; i < _contracts.length; i++) { 276 | isSingletonTombToken[_contracts[i]][_tokenIds[i]] = _isTombToken[i]; 277 | } 278 | } 279 | 280 | function isTomb(address _tokenContract, uint256 _tokenId) public view returns (bool) { 281 | return isTombContract[_tokenContract] || isSingletonTombToken[_tokenContract][_tokenId]; 282 | } 283 | 284 | /// UUPS /// 285 | 286 | function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} 287 | 288 | /// ERC165 /// 289 | 290 | function supportsInterface(bytes4 interfaceId) 291 | public 292 | view 293 | override(ERC721Upgradeable, ERC2981Upgradeable) 294 | returns (bool) 295 | { 296 | return interfaceId == type(IERC173).interfaceId || super.supportsInterface(interfaceId); 297 | } 298 | } 299 | -------------------------------------------------------------------------------- /src/RomanNumerals.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | 4 | error NumberTooBig(); 5 | 6 | // Only includes information to encode a subset of roman numerals 7 | library RomanNumeral { 8 | function ofNum(uint256 n) internal pure returns (string memory) { 9 | uint8[9] memory key = [100, 90, 50, 40, 10, 9, 5, 4, 1]; 10 | string[9] memory numerals = ["C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"]; 11 | if (n >= 400) revert NumberTooBig(); 12 | bytes memory res = ""; 13 | for (uint256 i = 0; i < key.length; i++) { 14 | while (n >= key[i]) { 15 | n -= key[i]; 16 | res = abi.encodePacked(res, numerals[i]); 17 | } 18 | } 19 | return string(res); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Ronin.sol: -------------------------------------------------------------------------------- 1 | // .^7??????????????????????????????????????????????????????????????????7!: .~7????????????????????????????????: 2 | // :#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Y ^#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5 3 | // ^@@@@@@#BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB&@@@@@B ~@@@@@@#BBBBBBBBBBBBBBBBBBBBBBBBBBBBB#7 4 | // Y@@@@@# ~@@@@@@ P@@@@@G 5 | // .&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&G~ ~@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Y :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&P~ 6 | // J&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#.!B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B~ .Y&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B 7 | // ...........................B@@@@@5 .7#@@@@@@@#?^.................... ..........................:#@@@@@J 8 | // ^5YYYJJJJJJJJJJJJJJJJJJJJJJJJJJY&@@@@@? .J&@@@@@@&5JJJJJJJJJJJJJJJJJJJYYYYYYYYYYJJJJJJJJJJJJJJJJJJJJJJJJJJY@@@@@@! 9 | // 5@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@? :5&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@7 10 | // !GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPY~ ^JPGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPJ^ 11 | 12 | // __________________________________________________ Tomb Series ___________________________________________________ 13 | 14 | // _____________________________________________________ RONIN _______________________________________________________ 15 | 16 | // _______________________________________________ TOMB CLX: SOLUTION ________________________________________________ 17 | 18 | // ________________________________________ A collaboration with Ezra Miller ________________________________________ 19 | 20 | // ______________________________________________ Drawn by David Rudnick _____________________________________________ 21 | 22 | // _________________________________________ Contract architect: Luke Miles __________________________________________ 23 | 24 | // SPDX-License-Identifier: MIT 25 | pragma solidity ^0.8.10; 26 | 27 | import "solmate/tokens/ERC721.sol"; 28 | import "solmate/utils/SafeTransferLib.sol"; 29 | import "openzeppelin/access/Ownable.sol"; 30 | 31 | contract Ronin is ERC721, Ownable { 32 | error InvalidTomb(); 33 | error AlreadyMinted(); 34 | error Unauthorized(); 35 | 36 | ERC721 IndexContract; 37 | uint8 internal constant _tombID = 160; 38 | bool public tombMinted = false; 39 | address internal _tombArtist = 0x4a61d76ea05A758c1db9C9b5a5ad22f445A38C46; 40 | 41 | constructor(address indexContract) ERC721("Tomb Series: RONIN", "TOMB") { 42 | IndexContract = ERC721(indexContract); 43 | } 44 | 45 | function tokenURI(uint256 id) public view override returns (string memory) { 46 | if (id != _tombID) revert InvalidTomb(); 47 | return IndexContract.tokenURI(id); 48 | } 49 | 50 | function mint() public { 51 | if (tombMinted) revert AlreadyMinted(); 52 | address owner = owner(); 53 | if (tx.origin != owner) revert Unauthorized(); 54 | 55 | _mint(owner, _tombID); 56 | tombMinted = true; 57 | } 58 | 59 | function royaltyInfo(uint256 _tokenId, uint256 _salePrice) 60 | external 61 | view 62 | returns (address receiver, uint256 royaltyAmount) 63 | { 64 | if (_tokenId != _tombID) revert InvalidTomb(); 65 | receiver = _tombArtist; 66 | royaltyAmount = _salePrice / 10; 67 | } 68 | 69 | function supportsInterface(bytes4 interfaceId) public pure override(ERC721) returns (bool) { 70 | return 71 | interfaceId == 0x7f5828d0 || // ERC165 Interface ID for ERC173 72 | interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 73 | interfaceId == 0x5b5e139f || // ERC165 Interface ID for ERC165 74 | interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC721Metadata 75 | interfaceId == 0x2a55205a; // ERC165 Interface ID for ERC2981 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/ShadowBeacon.sol: -------------------------------------------------------------------------------- 1 | // .^7??????????????????????????????????????????????????????????????????7!: .~7????????????????????????????????: 2 | // :#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Y ^#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5 3 | // ^@@@@@@#BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB&@@@@@B ~@@@@@@#BBBBBBBBBBBBBBBBBBBBBBBBBBBBB#7 4 | // Y@@@@@# ~@@@@@@ P@@@@@G 5 | // .&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&G~ ~@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Y :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&P~ 6 | // J&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#.!B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B~ .Y&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B 7 | // ...........................B@@@@@5 .7#@@@@@@@#?^.................... ..........................:#@@@@@J 8 | // ^5YYYJJJJJJJJJJJJJJJJJJJJJJJJJJY&@@@@@? .J&@@@@@@&5JJJJJJJJJJJJJJJJJJJYYYYYYYYYYJJJJJJJJJJJJJJJJJJJJJJJJJJY@@@@@@! 9 | // 5@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@? :5&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@7 10 | // !GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPY~ ^JPGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPJ^ 11 | 12 | // _______________________________________________________ Tomb Series ___________________________________________________ 13 | 14 | // Shadow Beacon 15 | // Contract by Luke Miles (@worm_emoji) 16 | // SPDX-License-Identifier: MIT 17 | 18 | import "solmate/tokens/ERC721.sol"; 19 | import "openzeppelin/utils/Strings.sol"; 20 | import "openzeppelin/access/Ownable.sol"; 21 | 22 | pragma solidity >=0.8.10; 23 | 24 | contract ShadowBeacon is ERC721, Ownable { 25 | string public baseURI; 26 | address public allowedSigner; 27 | 28 | error TokenIsNonTransferrable(); 29 | error OnlyAuthorizedSigner(); 30 | 31 | constructor(address _allowedSigner, string memory _baseURI) ERC721("SHADOW Beacon", "SHDB") { 32 | allowedSigner = _allowedSigner; 33 | baseURI = _baseURI; 34 | } 35 | 36 | // Admin functions // 37 | 38 | function setBaseURI(string memory _baseURI) public onlyOwner { 39 | baseURI = _baseURI; 40 | } 41 | 42 | function setAllowedSigner(address _allowedSigner) public onlyOwner { 43 | allowedSigner = _allowedSigner; 44 | } 45 | 46 | // Signer functions // 47 | 48 | function transferFrom( 49 | address from, 50 | address to, 51 | uint256 id 52 | ) public override { 53 | if (msg.sender != allowedSigner) revert OnlyAuthorizedSigner(); 54 | require(from == ownerOf[id], "WRONG_FROM"); 55 | 56 | // Underflow of the sender's balance is impossible because we check for 57 | // ownership above and the recipient's balance can't realistically overflow. 58 | unchecked { 59 | if (from != address(0)) { 60 | balanceOf[from]--; 61 | } 62 | balanceOf[to]++; 63 | } 64 | 65 | ownerOf[id] = to; 66 | emit Transfer(from, to, id); 67 | } 68 | 69 | // View functions // 70 | 71 | function tokenURI(uint256 tokenID) public view override returns (string memory) { 72 | return string(abi.encodePacked(baseURI, Strings.toString(tokenID))); 73 | } 74 | 75 | // Disabled functions // 76 | 77 | function approve(address, uint256) public pure override { 78 | revert TokenIsNonTransferrable(); 79 | } 80 | 81 | function setApprovalForAll(address, bool) public pure override { 82 | revert TokenIsNonTransferrable(); 83 | } 84 | 85 | function safeTransferFrom( 86 | address, 87 | address, 88 | uint256 89 | ) public pure override { 90 | revert TokenIsNonTransferrable(); 91 | } 92 | 93 | function safeTransferFrom( 94 | address, 95 | address, 96 | uint256, 97 | bytes memory 98 | ) public pure override { 99 | revert TokenIsNonTransferrable(); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/ShadowBeaconDummy.sol: -------------------------------------------------------------------------------- 1 | // File: contracts/Shadow.sol 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "solmate/tokens/ERC721.sol"; 6 | import "openzeppelin/access/Ownable.sol"; 7 | 8 | // used for testing shadow beacon on goerli 9 | contract ShadowBeaconDummy is ERC721, Ownable { 10 | constructor() public ERC721("House SHADOW TEST", "SHD") { 11 | for (uint256 i = 1; i <= 36; i++) { 12 | _mint(msg.sender, i); 13 | } 14 | } 15 | 16 | function tokenURI(uint256 tokenID) public pure override returns (string memory) { 17 | return ""; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/ShadowDistribution.sol: -------------------------------------------------------------------------------- 1 | // .^7??????????????????????????????????????????????????????????????????7!: .~7????????????????????????????????: 2 | // :#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Y ^#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5 3 | // ^@@@@@@#BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB&@@@@@B ~@@@@@@#BBBBBBBBBBBBBBBBBBBBBBBBBBBBB#7 4 | // Y@@@@@# ~@@@@@@ P@@@@@G 5 | // .&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&G~ ~@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Y :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&P~ 6 | // J&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#.!B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B~ .Y&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B 7 | // ...........................B@@@@@5 .7#@@@@@@@#?^.................... ..........................:#@@@@@J 8 | // ^5YYYJJJJJJJJJJJJJJJJJJJJJJJJJJY&@@@@@? .J&@@@@@@&5JJJJJJJJJJJJJJJJJJJYYYYYYYYYYJJJJJJJJJJJJJJJJJJJJJJJJJJY@@@@@@! 9 | // 5@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@? :5&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@7 10 | // !GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPY~ ^JPGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPJ^ 11 | 12 | // _______________________________________________________ Tomb Series ___________________________________________________ 13 | 14 | // Shadow Distribution 15 | // Contract by Luke Miles (@worm_emoji) 16 | 17 | // SPDX-License-Identifier: MIT 18 | pragma solidity ^0.8.10; 19 | 20 | import "openzeppelin/utils/cryptography/ECDSA.sol"; 21 | import "openzeppelin/access/Ownable.sol"; 22 | 23 | interface SIERC721 { 24 | function safeTransferFrom( 25 | address from, 26 | address to, 27 | uint256 tokenId 28 | ) external; 29 | } 30 | 31 | contract ShadowDistribution is Ownable { 32 | SIERC721 internal _shadowContract; 33 | address internal _councilWallet; 34 | mapping(uint256 => address) public ownerMapping; 35 | 36 | event Claimed(uint256 tokenId, address winner, address destination); 37 | event WinnerStored(uint256 tokenId, address winner); 38 | 39 | constructor(address shadowContract, address councilWallet) { 40 | _shadowContract = SIERC721(shadowContract); 41 | _councilWallet = councilWallet; 42 | } 43 | 44 | function setCouncilWallet(address councilWallet) public onlyOwner { 45 | _councilWallet = councilWallet; 46 | } 47 | 48 | function saveMapping(uint256[] calldata tokenIds, address[] calldata owners) public onlyOwner { 49 | if (tokenIds.length != owners.length) revert("Invalid input"); 50 | for (uint256 i = 0; i < tokenIds.length; i++) { 51 | emit WinnerStored(tokenIds[i], owners[i]); 52 | ownerMapping[tokenIds[i]] = owners[i]; 53 | } 54 | } 55 | 56 | function makeHash(uint256 tokenID, address destination) internal pure returns (bytes32) { 57 | return 58 | ECDSA.toEthSignedMessageHash( 59 | abi.encodePacked( 60 | "This message confirms that this wallet owner has been allocated ownership of Tomb #", 61 | Strings.toString(tokenID), 62 | " in the SHADOW House. Signing this message will initiate a transfer to the following wallet address, which I confirm is Polygon-compatible: ", 63 | Strings.toHexString(destination) 64 | ) 65 | ); 66 | } 67 | 68 | function claimNFT( 69 | uint256 tokenID, 70 | address winner, 71 | address destination, 72 | bytes memory sig 73 | ) public { 74 | address approvedAddress = ownerMapping[tokenID]; 75 | require(approvedAddress == winner, "Invalid winner"); 76 | 77 | (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(makeHash(tokenID, destination), sig); 78 | require( 79 | error == ECDSA.RecoverError.NoError && recovered == approvedAddress && recovered == winner, 80 | "Invalid signature" 81 | ); 82 | 83 | ownerMapping[tokenID] = address(0); 84 | emit Claimed(tokenID, winner, destination); 85 | _shadowContract.safeTransferFrom(_councilWallet, destination, tokenID); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/ShadowNFT.sol: -------------------------------------------------------------------------------- 1 | // File: contracts/Shadow.sol 2 | 3 | pragma solidity ^0.8.0; 4 | 5 | import "solmate/tokens/ERC721.sol"; 6 | import "openzeppelin/access/Ownable.sol"; 7 | 8 | contract Shadow is ERC721, Ownable { 9 | address tombCouncil; 10 | 11 | constructor(address _tombCouncil) public ERC721("House SHADOW", "SHD") { 12 | tombCouncil = _tombCouncil; 13 | } 14 | 15 | function init() public { 16 | require(msg.sender == tombCouncil, "Only tombCouncil can init"); 17 | for (uint256 i = 1; i <= 36; i++) { 18 | _mint(tombCouncil, i); 19 | } 20 | } 21 | 22 | function tokenURI(uint256 tokenID) public pure override returns (string memory) { 23 | return ""; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/TombMetadata.sol: -------------------------------------------------------------------------------- 1 | // .^7??????????????????????????????????????????????????????????????????7!: .~7????????????????????????????????: 2 | // :#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Y ^#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5 3 | // ^@@@@@@#BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB&@@@@@B ~@@@@@@#BBBBBBBBBBBBBBBBBBBBBBBBBBBBB#7 4 | // Y@@@@@# ~@@@@@@ P@@@@@G 5 | // .&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&G~ ~@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@Y :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&P~ 6 | // J&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#.!B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B~ .Y&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B 7 | // ...........................B@@@@@5 .7#@@@@@@@#?^.................... ..........................:#@@@@@J 8 | // ^5YYYJJJJJJJJJJJJJJJJJJJJJJJJJJY&@@@@@? .J&@@@@@@&5JJJJJJJJJJJJJJJJJJJYYYYYYYYYYJJJJJJJJJJJJJJJJJJJJJJJJJJY@@@@@@! 9 | // 5@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@? :5&@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@7 10 | // !GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPY~ ^JPGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGPJ^ 11 | 12 | // _____________________________________________________ Tomb Series _____________________________________________________ 13 | 14 | // :!JYYYYJ!. .JYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY?~. 7YYYYYYYYY?~. ^JYYYYYYYYY^ 15 | // ~&@@@@@@@@@@#7. ?@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@P &@@@@@@@@@@@@B! :@@@@@@@@@@@5 16 | // ^@@@@@@BB@@@@@@@B! ?@@@@@&PGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG&@@@@@# JGGGGGGG#@@@@@@@G^ !PGGGGGGGGG! 17 | // 5@@@@@5 .7#@@@@@@@P^ ?@@@@@P .@@@@@@. .J&@@@@@@&5: 18 | // Y@@@@@Y .J&@@@@@@&5: ?@@@@@G @@@@@@. :Y&@@@@@@&J. 19 | // Y@@@@@5 :5&@@@@@@&J. ?@@@@@G @@@@@@. ^P@@@@@@@#7. 20 | // Y@@@@@5 ^P@@@@@@@#7. J@@@@@G @@@@@@. ~G@@@@@@@B! 21 | // Y@@@@@5 ~B@@@@@@@BG@@@@@@! PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP#@@@@@# JGPPPPPPPP5: .7#@@@@@@@GPPPPPPG~ 22 | // 5@@@@@5 .7#@@@@@@@@@@&! .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@G &@@@@@@@@@@& .J&@@@@@@@@@@@@5 23 | // ^5YYY5~ .!JYYYYY7: Y5YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYJ~. ?5YYYYYYY5J. :7JYYYYYYYY5^ 24 | 25 | // ____________________________________________________ Tomb Metadata _____________________________________________________ 26 | 27 | // ________________________________________________ Deployed by TERRAIN 2022 _______________________________________________ 28 | 29 | // ____________________________________________ All tombs drawn by David Rudnick ___________________________________________ 30 | 31 | // ____________________________________________ Contract architect: Luke Miles _____________________________________________ 32 | 33 | // SPDX-License-Identifier: MIT 34 | pragma solidity >=0.8.0; 35 | 36 | interface IIndexMarker { 37 | function isTomb(address _tokenContract, uint256 _tokenId) external view returns (bool); 38 | } 39 | 40 | interface IOwnable { 41 | function ownerOf(uint256 _tokenID) external view returns (address); 42 | } 43 | 44 | import "openzeppelin/access/Ownable.sol"; 45 | import "solady/utils/Multicallable.sol"; 46 | 47 | contract TombMetadata is Ownable, Multicallable { 48 | address public IndexMarker; 49 | 50 | event EngravingSet(address indexed _tokenContract, uint256 indexed _tokenId, address author, string _engraving); 51 | event BootlinkSet(address indexed _tokenContract, uint256 indexed _tokenId, address author, string _bootLink); 52 | 53 | mapping(address => mapping(uint256 => string)) private engravings; 54 | mapping(address => mapping(uint256 => string)) private bootLinks; 55 | 56 | constructor(address _indexMarker) { 57 | IndexMarker = _indexMarker; 58 | } 59 | 60 | modifier onlyTomb(address _tokenContract, uint256 _tokenId) { 61 | require(IIndexMarker(IndexMarker).isTomb(_tokenContract, _tokenId), "TombMetadata: Not a tomb"); 62 | _; 63 | } 64 | 65 | modifier onlyTombOwnerOrAdmin(address _tokenContract, uint256 _tokenId) { 66 | if (msg.sender == owner()) { 67 | _; 68 | return; 69 | } 70 | 71 | require(IOwnable(_tokenContract).ownerOf(_tokenId) == msg.sender, "TombMetadata: Not tomb owner"); 72 | _; 73 | } 74 | 75 | function getEngraving(address _tokenContract, uint256 _tokenId) 76 | public 77 | view 78 | onlyTomb(_tokenContract, _tokenId) 79 | returns (string memory) 80 | { 81 | return engravings[_tokenContract][_tokenId]; 82 | } 83 | 84 | function getBootLink(address _tokenContract, uint256 _tokenId) 85 | public 86 | view 87 | onlyTomb(_tokenContract, _tokenId) 88 | returns (string memory) 89 | { 90 | return bootLinks[_tokenContract][_tokenId]; 91 | } 92 | 93 | function setBootlink(address _tokenContract, uint256 _tokenId, string memory _bootLink) 94 | public 95 | onlyTomb(_tokenContract, _tokenId) 96 | onlyTombOwnerOrAdmin(_tokenContract, _tokenId) 97 | { 98 | emit BootlinkSet(_tokenContract, _tokenId, msg.sender, _bootLink); 99 | bootLinks[_tokenContract][_tokenId] = _bootLink; 100 | } 101 | 102 | function setEngraving(address _tokenContract, uint256 _tokenId, string memory _engraving) 103 | public 104 | onlyTomb(_tokenContract, _tokenId) 105 | onlyTombOwnerOrAdmin(_tokenContract, _tokenId) 106 | { 107 | emit EngravingSet(_tokenContract, _tokenId, msg.sender, _engraving); 108 | engravings[_tokenContract][_tokenId] = _engraving; 109 | } 110 | 111 | function updateIndexMarker(address _indexMarker) public onlyOwner { 112 | IndexMarker = _indexMarker; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/recovery/RecoveryVoteAggregator.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.17; 3 | 4 | import {TombRecoveryGovernor} from "./TombRecoveryGovernor.sol"; 5 | 6 | contract RecoveryVoteAggregator { 7 | function votes(address[] memory _governors, uint256[] memory _proposalIds, uint8[] memory _supports) public { 8 | for (uint256 i = 0; i < _governors.length; i++) { 9 | TombRecoveryGovernor(payable(_governors[i])).castVoteOnBehalfOf(_proposalIds[i], msg.sender, _supports[i]); 10 | } 11 | } 12 | 13 | function votesWithReason( 14 | address[] memory _governors, 15 | uint256[] memory _proposalIds, 16 | uint8[] memory _supports, 17 | string[] memory _reasons 18 | ) public { 19 | for (uint256 i = 0; i < _governors.length; i++) { 20 | TombRecoveryGovernor(payable(_governors[i])).castVoteOnBehalfOfWithReason( 21 | _proposalIds[i], msg.sender, _supports[i], _reasons[i] 22 | ); 23 | } 24 | } 25 | 26 | function votesWithReasonAndParams( 27 | address[] memory _governors, 28 | uint256[] memory _proposalIds, 29 | uint8[] memory _supports, 30 | string[] memory _reasons, 31 | bytes[] memory _params 32 | ) public { 33 | for (uint256 i = 0; i < _governors.length; i++) { 34 | TombRecoveryGovernor(payable(_governors[i])).castVoteOnBehalfOfWithReasonAndParams( 35 | _proposalIds[i], msg.sender, _supports[i], _reasons[i], _params[i] 36 | ); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/recovery/TombRecoveryGovernor.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.17; 3 | 4 | import {IERC721Upgradeable} from "openzeppelin-upgradeable/token/ERC721/IERC721Upgradeable.sol"; 5 | import {RecoveryGovernor} from "recovery-protocol/governance/RecoveryGovernor.sol"; 6 | import {IndexMarkerV2} from "../IndexMarkerV2.sol"; 7 | 8 | contract TombRecoveryGovernor is RecoveryGovernor { 9 | address immutable indexMarkerAddress; 10 | address immutable voteAggregator; 11 | 12 | mapping(address => mapping(uint256 => mapping(uint256 => bool))) public tombVotedOnProposal; 13 | 14 | constructor(address indexMarkerAddress_, address voteAggregator_) { 15 | indexMarkerAddress = indexMarkerAddress_; 16 | voteAggregator = voteAggregator_; 17 | } 18 | 19 | modifier onlyVoteAggregator() { 20 | require(msg.sender == voteAggregator, "Governor: Only vote aggregator can call"); 21 | _; 22 | } 23 | 24 | function castVoteOnBehalfOf(uint256 proposalId, address account, uint8 support) 25 | public 26 | onlyVoteAggregator 27 | returns (uint256) 28 | { 29 | return _castVote(proposalId, account, support, ""); 30 | } 31 | 32 | function castVoteOnBehalfOfWithReason(uint256 proposalId, address account, uint8 support, string memory reason) 33 | public 34 | onlyVoteAggregator 35 | returns (uint256) 36 | { 37 | return _castVote(proposalId, account, support, reason); 38 | } 39 | 40 | function castVoteOnBehalfOfWithReasonAndParams( 41 | uint256 proposalId, 42 | address account, 43 | uint8 support, 44 | string memory reason, 45 | bytes memory params 46 | ) public onlyVoteAggregator returns (uint256) { 47 | return _castVote(proposalId, account, support, reason, params); 48 | } 49 | 50 | function _castVote(uint256 proposalId, address account, uint8 support, string memory reason, bytes memory params) 51 | internal 52 | override 53 | returns (uint256) 54 | { 55 | require(state(proposalId) == ProposalState.Active, "Governor: vote not currently active"); 56 | uint256 weight = _getVotes(account, proposalSnapshot(proposalId), params); 57 | if (params.length > 0) { 58 | (address[] memory tombTokenContracts, uint256[] memory tombTokenIds) = 59 | abi.decode(params, (address[], uint256[])); 60 | if (tombTokenContracts.length != tombTokenIds.length) { 61 | revert("TombRecoveryGovernor: token contract and token id arrays must be the same length"); 62 | } 63 | for (uint256 i = 0; i < tombTokenIds.length; i++) { 64 | if (tombTokenContracts[i] == recoveryParentTokenContract && tombTokenIds[i] == recoveryParentTokenId) { 65 | continue; 66 | } 67 | if (!IndexMarkerV2(indexMarkerAddress).isTomb(tombTokenContracts[i], tombTokenIds[i])) { 68 | revert("TombRecoveryGovernor: token provided is not a tomb"); 69 | } 70 | if (IERC721Upgradeable(tombTokenContracts[i]).ownerOf(tombTokenIds[i]) != account) { 71 | revert("TombRecoveryGovernor: token provided is not owned by voter"); 72 | } 73 | if (tombVotedOnProposal[tombTokenContracts[i]][tombTokenIds[i]][proposalId]) { 74 | revert("TombRecoveryGovernor: tomb already voted on proposal"); 75 | } 76 | tombVotedOnProposal[tombTokenContracts[i]][tombTokenIds[i]][proposalId] = true; 77 | weight += 1; 78 | } 79 | } 80 | 81 | if (account == recoveryParentTokenOwner()) { 82 | require( 83 | !recoveryParentTokenOwnerVotedOnProposal[proposalId], 84 | "Governor: recovery parent token owner already voted on proposal" 85 | ); 86 | recoveryParentTokenOwnerVotedOnProposal[proposalId] = true; 87 | weight += recoveryParentTokenOwnerVotingWeight; 88 | } 89 | _countVote(proposalId, account, support, weight, params); 90 | 91 | if (params.length == 0) { 92 | emit VoteCast(account, proposalId, support, weight, reason); 93 | } else { 94 | emit VoteCastWithParams(account, proposalId, support, weight, reason, params); 95 | } 96 | 97 | return weight; 98 | } 99 | 100 | function quorumDenominator() public view override returns (uint256) { 101 | return 1000; 102 | } 103 | 104 | // extra storage 105 | uint256[50] private __gap; 106 | } 107 | -------------------------------------------------------------------------------- /src/scripts/AdminMintIndexMarkers.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | 4 | import "forge-std/Script.sol"; 5 | import "../IndexMarkerV2.sol"; 6 | 7 | contract AdminMintIndexMarkers is Script { 8 | address public constant V2_INDEX_MARKER = 0xa5c93e5d9eb8fb1B40228bb93fD40990913dB523; 9 | address public constant COUNCIL_DAO = 0x1CC0271fe94c490B26d0f6369B1c947ecAd9b946; 10 | 11 | function run() public { 12 | IndexMarkerV2 marker = IndexMarkerV2(V2_INDEX_MARKER); 13 | uint256 tokenIdsFileLength = 242; 14 | uint256 BATCH_SIZE = 50; 15 | // prepare batches of tokenIds 16 | string memory line; 17 | uint256[][] memory tokenIdBatches = new uint256[][](tokenIdsFileLength / BATCH_SIZE + 1); 18 | for (uint256 i = 0; i < tokenIdBatches.length; i++) { 19 | if (i == tokenIdBatches.length - 1) { 20 | tokenIdBatches[i] = new uint256[](tokenIdsFileLength % BATCH_SIZE); 21 | } else { 22 | tokenIdBatches[i] = new uint256[](BATCH_SIZE); 23 | } 24 | } 25 | for (uint256 i = 0; i < tokenIdsFileLength; i++) { 26 | line = vm.readLine("./tokens.txt"); 27 | tokenIdBatches[i / BATCH_SIZE][i % BATCH_SIZE] = parseInt(line); 28 | } 29 | 30 | uint256 deployerPrivateKey = vm.envUint("SHADOW_BEACON_RELAY_PRIVATE_KEY"); 31 | vm.startBroadcast(deployerPrivateKey); 32 | 33 | for (uint256 i = 0; i < tokenIdBatches.length; i++) { 34 | address[] memory destinationAddress = new address[](tokenIdBatches[i].length); 35 | for (uint256 j = 0; j < tokenIdBatches[i].length; j++) { 36 | destinationAddress[j] = COUNCIL_DAO; 37 | } 38 | 39 | if (tokenIdBatches[i].length == 0) { 40 | continue; 41 | } 42 | 43 | marker.adminMint(tokenIdBatches[i], destinationAddress); 44 | } 45 | 46 | vm.stopBroadcast(); 47 | } 48 | 49 | function parseInt(string memory s) internal pure returns (uint256 result) { 50 | bytes memory b = bytes(s); 51 | uint256 i; 52 | result = 0; 53 | for (i = 0; i < b.length; i++) { 54 | if ((uint8(uint8(b[i])) >= 48) && (uint8(uint8(b[i])) <= 57)) { 55 | result = result * 10 + uint8(b[i]) - 48; 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/scripts/DeployIndexMarkerV2.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.17; 3 | 4 | import "forge-std/Script.sol"; 5 | import "openzeppelin/proxy/ERC1967/ERC1967Proxy.sol"; 6 | import "../IndexMarkerV2.sol"; 7 | 8 | contract DeployIndexMarkerV2 is Script { 9 | address public constant MARKET_FILTER_DAO_ADDRESS_GOERLI = 0x9b866b819376cb5c19c510edAAAbA9BA44e8b87c; 10 | address public constant INDEX_MARKER_V1_GOERLI = 0xC95Fb6E56B52A20693Ec98fb3b91F549C5eBECa8; 11 | address public constant TOMB_INDEX_GOERLI = 0xeC0a7349dC663a4C2363E72ee9de5aE24FA01163; 12 | 13 | address public constant SIGNER_MAINNET = 0x7176E0d59a8bF299d57c6f4809ce88FB11D1cc31; 14 | address payable public constant ROYALTY_RECIPIENT_MAINNET = payable(0x9699b55a6e3093D76F1147E936a2d59EC3a3B0B3); 15 | address public constant MARKET_FILTER_DAO_ADDRESS_MAINNET = 0x3AE2804De4A54283601Db24a897856D9772eA0D8; 16 | address public constant INDEX_MARKER_V1_MAINNET = 0x741d6BF0997A313720b5884F749685f7e9a994D6; 17 | address public constant TOMB_INDEX_MAINNET = 0x185E8a578bF6896e3988e7c38a6A23889CA2aF9f; 18 | 19 | function run() public { 20 | if (block.chainid == 1) { 21 | run( 22 | SIGNER_MAINNET, 23 | ROYALTY_RECIPIENT_MAINNET, 24 | INDEX_MARKER_V1_MAINNET, 25 | MARKET_FILTER_DAO_ADDRESS_MAINNET, 26 | TOMB_INDEX_MAINNET 27 | ); 28 | } else if (block.chainid == 5) { 29 | address payable owner = payable(vm.envAddress("DEPLOYER_ADDRESS")); 30 | run(owner, owner, INDEX_MARKER_V1_GOERLI, MARKET_FILTER_DAO_ADDRESS_GOERLI, TOMB_INDEX_GOERLI); 31 | } else { 32 | revert("Unsupported chain"); 33 | } 34 | } 35 | 36 | function run( 37 | address signer, 38 | address payable royaltyRecipient, 39 | address indexMarkerV1, 40 | address marketFilterDAO, 41 | address tombIndex 42 | ) public { 43 | uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); 44 | 45 | vm.startBroadcast(deployerPrivateKey); 46 | 47 | IndexMarkerV2 implementation = new IndexMarkerV2(); 48 | 49 | ERC1967Proxy proxy = new ERC1967Proxy( 50 | address(implementation), 51 | abi.encodeWithSignature( 52 | "initialize(address,address,address,address,address)", 53 | marketFilterDAO, 54 | signer, 55 | indexMarkerV1, 56 | royaltyRecipient, 57 | tombIndex 58 | ) 59 | ); 60 | 61 | // IndexMarkerV2(address(proxy)).manageMarketFilterDAOSubscription(true); 62 | 63 | vm.stopBroadcast(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/scripts/DeployRecoveryGovernor.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.17; 3 | 4 | import "forge-std/Script.sol"; 5 | import "../recovery/TombRecoveryGovernor.sol"; 6 | 7 | contract DeployRecoveryGovernor is Script { 8 | address public constant INDEX_MARKER_MAINNET = 0xa5c93e5d9eb8fb1B40228bb93fD40990913dB523; 9 | address constant INDEX_MARKER_GOERLI = 0x17DB883ed31582A82c69FeEe0B28ac662c877f00; 10 | address constant VOTE_AGGREGATOR_MAINNET = 0x6623884dA17E2A0BFf68773A5376292d5142AEe4; 11 | address constant VOTE_AGGREGATOR_GOERLI = 0xDCA75297e26353889f4BB7A66D6BfEB6DB8dFad0; 12 | 13 | function run() public { 14 | if (block.chainid == 1) { 15 | run(INDEX_MARKER_MAINNET, VOTE_AGGREGATOR_MAINNET); 16 | } else if (block.chainid == 5) { 17 | run(INDEX_MARKER_GOERLI, VOTE_AGGREGATOR_GOERLI); 18 | } else { 19 | revert("Unsupported chain"); 20 | } 21 | } 22 | 23 | function run(address indexMarker, address voteAggregator) public { 24 | uint256 key = vm.envUint("PRIVATE_KEY"); 25 | vm.startBroadcast(key); 26 | require(voteAggregator != address(0), "Vote aggregator is required"); 27 | 28 | new TombRecoveryGovernor(indexMarker, voteAggregator); 29 | 30 | vm.stopBroadcast(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/scripts/MigrationMintIndexMarkerV2.s.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity 0.8.17; 3 | 4 | import "forge-std/Script.sol"; 5 | import "../IndexMarkerV2.sol"; 6 | import "../IndexMarker.sol"; 7 | 8 | contract MigrationMintIndexMarkerV2 is Script { 9 | uint256 public constant BATCH_SIZE = 50; 10 | address public constant INDEX_MARKER_V1_GOERLI = 0xC95Fb6E56B52A20693Ec98fb3b91F549C5eBECa8; 11 | address public constant INDEX_MARKER_V2_GOERLI = 0x17DB883ed31582A82c69FeEe0B28ac662c877f00; 12 | string public constant TOKEN_IDS_FILE_PATH_GOERLI = "./goerli-token-ids.txt"; 13 | uint256 public constant TOKEN_IDS_FILE_LENGTH_GOERLI = 638; 14 | 15 | address public constant INDEX_MARKER_V1_MAINNET = 0x741d6BF0997A313720b5884F749685f7e9a994D6; 16 | address public constant INDEX_MARKER_V2_MAINNET = 0xa5c93e5d9eb8fb1B40228bb93fD40990913dB523; 17 | string public constant TOKEN_IDS_FILE_PATH_MAINNET = "./mainnet-token-ids.txt"; 18 | uint256 public constant TOKEN_IDS_FILE_LENGTH_MAINNET = 0; 19 | 20 | function run() public { 21 | if (block.chainid == 1) { 22 | run( 23 | INDEX_MARKER_V1_MAINNET, 24 | INDEX_MARKER_V2_MAINNET, 25 | TOKEN_IDS_FILE_PATH_MAINNET, 26 | TOKEN_IDS_FILE_LENGTH_MAINNET 27 | ); 28 | } else if (block.chainid == 5) { 29 | run(INDEX_MARKER_V1_GOERLI, INDEX_MARKER_V2_GOERLI, TOKEN_IDS_FILE_PATH_GOERLI, TOKEN_IDS_FILE_LENGTH_GOERLI); 30 | } else { 31 | revert("Unsupported chain"); 32 | } 33 | } 34 | 35 | function run( 36 | address indexMarkerV1, 37 | address indexMarkerV2, 38 | string memory tokenIdsFilePath, 39 | uint256 tokenIdsFileLength 40 | ) public { 41 | require(indexMarkerV2 != address(0), "indexMarkerV2 not set"); 42 | 43 | // prepare batches of tokenIds 44 | string memory line; 45 | uint256[][] memory tokenIdBatches = new uint256[][](tokenIdsFileLength / BATCH_SIZE + 1); 46 | for (uint256 i = 0; i < tokenIdBatches.length; i++) { 47 | if (i == tokenIdBatches.length - 1) { 48 | tokenIdBatches[i] = new uint256[](tokenIdsFileLength % BATCH_SIZE); 49 | } else { 50 | tokenIdBatches[i] = new uint256[](BATCH_SIZE); 51 | } 52 | } 53 | for (uint256 i = 0; i < tokenIdsFileLength; i++) { 54 | line = vm.readLine(tokenIdsFilePath); 55 | tokenIdBatches[i / BATCH_SIZE][i % BATCH_SIZE] = parseInt(line); 56 | } 57 | 58 | // send mint transactions 59 | uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); 60 | vm.startBroadcast(deployerPrivateKey); 61 | for (uint256 i = 0; i < tokenIdBatches.length; i++) { 62 | IndexMarkerV2(indexMarkerV2).migrationMint(tokenIdBatches[i]); 63 | } 64 | vm.stopBroadcast(); 65 | 66 | // confirm mints 67 | for (uint256 i = 0; i < tokenIdsFileLength; i++) { 68 | uint256 tokenId = tokenIdBatches[i / BATCH_SIZE][i % BATCH_SIZE]; 69 | require( 70 | IndexMarkerV2(indexMarkerV2).ownerOf(tokenId) == IndexMarker(indexMarkerV1).ownerOf(tokenId), 71 | "Migration failed" 72 | ); 73 | } 74 | } 75 | 76 | function parseInt(string memory s) internal pure returns (uint256 result) { 77 | bytes memory b = bytes(s); 78 | uint256 i; 79 | result = 0; 80 | for (i = 0; i < b.length; i++) { 81 | if ((uint8(uint8(b[i])) >= 48) && (uint8(uint8(b[i])) <= 57)) { 82 | result = result * 10 + uint8(b[i]) - 48; 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/scripts/SaveRanking.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.8.10; 3 | 4 | import "forge-std/Script.sol"; 5 | import "../ShadowDistribution.sol"; 6 | 7 | contract SaveRanking is Script { 8 | function run() external { 9 | uint256[] memory ids = new uint256[](36); 10 | address[] memory addrs = new address[](36); 11 | 12 | for (uint256 i = 0; i < 36; i++) { 13 | ids[i] = i + 1; 14 | } 15 | 16 | addrs[0] = 0x1483a878832Ac0BD00F635E3615af9937fde258d; 17 | addrs[1] = 0x9303EA8dDAf762a3a1F9A8C82c4F16FB70733aC3; 18 | addrs[2] = 0x4b10DA491b54ffe167Ec5AAf7046804fADA027d2; 19 | addrs[3] = 0x518201899E316bf98c957C73e1326b77672Fe52b; 20 | addrs[4] = 0x76a7bD1B8527662BcDbE2981049D052eD3b6DDC5; 21 | addrs[5] = 0x625D6405DCac9C82F4b681A131d9182115448F75; 22 | addrs[6] = 0x63dC34b6A35C1DCA3de2460c15138d2Aa92C523a; 23 | addrs[7] = 0x113d754Ff2e6Ca9Fd6aB51932493E4F9DabdF596; 24 | addrs[8] = 0x67F3E43c779449be61580FC75a42D143e840f04c; 25 | addrs[9] = 0x834C69EF569F26815B5dCc87e24267346346CE08; 26 | addrs[10] = 0x4a61d76ea05A758c1db9C9b5a5ad22f445A38C46; 27 | addrs[11] = 0xa0eb90B7AAC3f508aBC5e21D87dCa1c3f2129C77; 28 | addrs[12] = 0x912b37E4AD159882f60De59B27882c5daf3d7E5B; 29 | addrs[13] = 0xC4cd14A15a94Be727af253335abAFD6b6F411aCd; 30 | addrs[14] = 0x20b48BdF395232ACAe5D6E3b345c0f107FFA8AbD; 31 | addrs[15] = 0x8d138c01765483cB79d787ce5933F609CbFDabcF; 32 | addrs[16] = 0x6E56a3D5188EEde5984B4EE004795AC0aaB1cD4c; 33 | addrs[17] = 0xF930b0A0500D8F53b2E7EFa4F7bCB5cc0c71067E; 34 | addrs[18] = 0x6Af920b0D2Db08c2d1C7AC7EF841615cAeFFD025; 35 | addrs[19] = 0xC9C022FCFebE730710aE93CA9247c5Ec9d9236d0; 36 | addrs[20] = 0xCBBea7Ec33D60Db283AB79bdAC9ffbfa46A83134; 37 | addrs[21] = 0xaCAA5d549e2f18314C5424D2a94711034faa6F64; 38 | addrs[22] = 0xfB843f8c4992EfDb6b42349C35f025ca55742D33; 39 | addrs[23] = 0xF73FE15cFB88ea3C7f301F16adE3c02564ACa407; 40 | addrs[24] = 0xdA2ba9f10C336e76CD31b8A9005F05C7D560066a; 41 | addrs[25] = 0x3d9456Ad6463a77bD77123Cb4836e463030bfAb4; 42 | addrs[26] = 0x062E0B7846094C24848F9fa3dcD892515e9cA13F; 43 | addrs[27] = 0x666669651612b8b1Ce852012F3c00bD3038AF143; 44 | addrs[28] = 0xcADe1E68A994C5b1459cCD19150128Ffef09Ea3c; 45 | addrs[29] = 0x592d90c916D3082fF9640e99Fe2C8503948d1EBc; 46 | addrs[30] = 0xdBD6D78de900074Aac480b6AA56973CBE3cdd821; 47 | addrs[31] = 0xB00A93fF31217E49c3674e05b525f239a85bb78f; 48 | addrs[32] = 0x0885F0e1a641F08416536e3921C30c5D9dC9c0f4; 49 | addrs[33] = 0x7E5507281F62C0f8d666beAEA212751cD88994b8; 50 | addrs[34] = 0xDD94b65218366e60ddB45cf119D636426Fdec3Cf; 51 | addrs[35] = 0x6Be0b92D94F3bb772E2d76cc72C62B14895F32f3; 52 | 53 | vm.startBroadcast(0x9aaC8cCDf50dD34d06DF661602076a07750941F6); 54 | ShadowDistribution shadowDistribution = new ShadowDistribution( 55 | 0xE877CDACBB7827d4232Cde5f8de58371F144a0A4, 56 | 0xcC1775Ea6D7F62b4DCA8FAF075F864d3e15Dd0F0 57 | ); 58 | shadowDistribution.saveMapping(ids, addrs); 59 | vm.stopBroadcast(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/scripts/SyncShadowBeacon.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | 4 | import "forge-std/Script.sol"; 5 | import "../ShadowBeacon.sol"; 6 | import "../ShadowNFT.sol"; 7 | 8 | contract SyncShadowBeacon is Script { 9 | address public constant SHADOW_BEACON_GOERLI = 0x975cED3A79e4FCc48B6E309A286DC49A4Bc44042; 10 | address public constant CANONICAL_SHADOW_MUMBAI = 0xA6C299948F095C2dCD7d0e6a3b7B2C7AaD0e28b4; 11 | string public goerliRPCUrl = vm.envString("GOERLI_RPC_URL"); 12 | string public mumbaiRPCUrl = vm.envString("MUMBAI_RPC_URL"); 13 | 14 | address public constant SHADOW_BEACON_MAINNET = 0x819c573D8d8BE12095606Cb846E81913F2cDd140; 15 | address public constant CANONICAL_SHADOW_POLYGON = 0xE877CDACBB7827d4232Cde5f8de58371F144a0A4; 16 | string public mainnetRPCUrl = vm.envString("MAINNET_RPC_URL"); 17 | string public polygonRPCUrl = vm.envString("POLYGON_RPC_URL"); 18 | 19 | function run() public { 20 | if (block.chainid == 1) { 21 | run(SHADOW_BEACON_MAINNET, CANONICAL_SHADOW_POLYGON, mainnetRPCUrl, polygonRPCUrl); 22 | } else { 23 | run(SHADOW_BEACON_GOERLI, CANONICAL_SHADOW_MUMBAI, goerliRPCUrl, mumbaiRPCUrl); 24 | } 25 | } 26 | 27 | function run( 28 | address beaconAddress, 29 | address canonicalShadowAddress, 30 | string memory beaconRpcUrl, 31 | string memory canonicalShadowRpcUrl 32 | ) public { 33 | uint256 shadowRPC = vm.createFork(canonicalShadowRpcUrl); 34 | uint256 beaconRPC = vm.createFork(beaconRpcUrl); 35 | 36 | address[] memory canonicalOwners = new address[](36); 37 | 38 | vm.selectFork(shadowRPC); 39 | Shadow shadowNFT = Shadow(canonicalShadowAddress); 40 | 41 | for (uint256 i = 0; i < 36; i++) { 42 | canonicalOwners[i] = shadowNFT.ownerOf(i + 1); 43 | } 44 | 45 | vm.selectFork(beaconRPC); 46 | ShadowBeacon beacon = ShadowBeacon(beaconAddress); 47 | 48 | uint256 deployerPrivateKey = vm.envUint("SHADOW_BEACON_RELAY_PRIVATE_KEY"); 49 | vm.startBroadcast(deployerPrivateKey); 50 | for (uint256 i = 0; i < 36; i++) { 51 | address owner = beacon.ownerOf(i + 1); 52 | if (owner != canonicalOwners[i]) { 53 | console.log("owner of %d is %s", i + 1, owner); 54 | console.log("canonical owner of %d is %s", i + 1, canonicalOwners[i]); 55 | beacon.transferFrom(owner, canonicalOwners[i], i + 1); 56 | } 57 | } 58 | vm.stopBroadcast(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/scripts/generateSaveRanking.js: -------------------------------------------------------------------------------- 1 | const ethers = require("ethers"); 2 | 3 | const map = { 4 | 1: "0x1483a878832ac0bd00f635e3615af9937fde258d", 5 | 2: "0x9303ea8ddaf762a3a1f9a8c82c4f16fb70733ac3", 6 | 3: "0x4b10da491b54ffe167ec5aaf7046804fada027d2", 7 | 4: "0x518201899e316bf98c957c73e1326b77672fe52b", 8 | 5: "0x76a7bd1b8527662bcdbe2981049d052ed3b6ddc5", 9 | 6: "0x625d6405dcac9c82f4b681a131d9182115448f75", 10 | 7: "0x63dc34b6a35c1dca3de2460c15138d2aa92c523a", 11 | 8: "0x113d754ff2e6ca9fd6ab51932493e4f9dabdf596", 12 | 9: "0x67f3e43c779449be61580fc75a42d143e840f04c", 13 | 10: "0x834c69ef569f26815b5dcc87e24267346346ce08", 14 | 11: "0x4a61d76ea05a758c1db9c9b5a5ad22f445a38c46", 15 | 12: "0xa0eb90b7aac3f508abc5e21d87dca1c3f2129c77", 16 | 13: "0x912b37e4ad159882f60de59b27882c5daf3d7e5b", 17 | 14: "0xc4cd14a15a94be727af253335abafd6b6f411acd", 18 | 15: "0x20b48bdf395232acae5d6e3b345c0f107ffa8abd", 19 | 16: "0x8d138c01765483cb79d787ce5933f609cbfdabcf", 20 | 17: "0x6e56a3d5188eede5984b4ee004795ac0aab1cd4c", 21 | 18: "0xf930b0a0500d8f53b2e7efa4f7bcb5cc0c71067e", 22 | 19: "0x6af920b0d2db08c2d1c7ac7ef841615caeffd025", 23 | 20: "0xc9c022fcfebe730710ae93ca9247c5ec9d9236d0", 24 | 21: "0xcbbea7ec33d60db283ab79bdac9ffbfa46a83134", 25 | 22: "0xacaa5d549e2f18314c5424d2a94711034faa6f64", 26 | 23: "0xfb843f8c4992efdb6b42349c35f025ca55742d33", 27 | 24: "0xf73fe15cfb88ea3c7f301f16ade3c02564aca407", 28 | 25: "0xda2ba9f10c336e76cd31b8a9005f05c7d560066a", 29 | 26: "0x3d9456ad6463a77bd77123cb4836e463030bfab4", 30 | 27: "0x062e0b7846094c24848f9fa3dcd892515e9ca13f", 31 | 28: "0x666669651612b8b1ce852012f3c00bd3038af143", 32 | 29: "0xcade1e68a994c5b1459ccd19150128ffef09ea3c", 33 | 30: "0x592d90c916d3082ff9640e99fe2c8503948d1ebc", 34 | 31: "0xdbd6d78de900074aac480b6aa56973cbe3cdd821", 35 | 32: "0xb00a93ff31217e49c3674e05b525f239a85bb78f", 36 | 33: "0x0885f0e1a641f08416536e3921c30c5d9dc9c0f4", 37 | 34: "0x7e5507281f62c0f8d666beaea212751cd88994b8", 38 | 35: "0xdd94b65218366e60ddb45cf119d636426fdec3cf", 39 | 36: "0x6be0b92d94f3bb772e2d76cc72c62b14895f32f3", 40 | }; 41 | 42 | Object.keys(map).forEach((key) => { 43 | const a = ethers.utils.getAddress(map[key]); 44 | console.log(`addrs[${key - 1}] = ${a};`); 45 | }); 46 | -------------------------------------------------------------------------------- /src/test/IndexMarkerV2.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | pragma solidity >=0.8.0; 3 | 4 | import {ERC1967Proxy} from "openzeppelin/proxy/ERC1967/ERC1967Proxy.sol"; 5 | import {Strings} from "openzeppelin/utils/Strings.sol"; 6 | import {OperatorFilterRegistry} from "zora-drops-contracts/test/filter/OperatorFilterRegistry.sol"; 7 | import {OperatorFilterRegistryErrorsAndEvents} from 8 | "zora-drops-contracts/test/filter/OperatorFilterRegistryErrorsAndEvents.sol"; 9 | import {OwnedSubscriptionManager} from "zora-drops-contracts/src/filter/OwnedSubscriptionManager.sol"; 10 | import {DSTest} from "ds-test/test.sol"; 11 | import {console} from "./utils/Console.sol"; 12 | import {Vm} from "forge-std/Vm.sol"; 13 | import {IndexMarkerV2} from "../IndexMarkerV2.sol"; 14 | import {IndexMarker} from "../IndexMarker.sol"; 15 | import {TombIndex} from "../TombIndex.sol"; 16 | import {TombMetadata} from "../TombMetadata.sol"; 17 | import {ERC721} from "solady/tokens/ERC721.sol"; 18 | 19 | contract Tomb721 is ERC721 { 20 | function name() public view virtual override returns (string memory) { 21 | return "TOMB"; 22 | } 23 | 24 | function symbol() public view virtual override returns (string memory) { 25 | return "TOMBT"; 26 | } 27 | 28 | function mint(address _to, uint256 _tokenId) public { 29 | _mint(_to, _tokenId); 30 | } 31 | 32 | function tokenURI(uint256 id) public view virtual override returns (string memory) { 33 | return ""; 34 | } 35 | } 36 | 37 | contract IndexMarkerV2Test is DSTest { 38 | address payable public constant TOMB_ARTIST = payable(0x4a61d76ea05A758c1db9C9b5a5ad22f445A38C46); 39 | Vm internal immutable vm = Vm(HEVM_ADDRESS); 40 | uint256 internal constant SIGNER_PK = 1; 41 | address internal signer; 42 | address payable internal royaltyRecipient = payable(address(0x1234)); 43 | address public ownedSubscriptionManager; 44 | address internal markerV2; 45 | address internal markerV1; 46 | address internal tombIndex; 47 | Tomb721 internal tombNFT; 48 | TombMetadata internal metadata; 49 | address internal constant OPERATOR_FILTER_REGISTRY = address(0x000000000000AAeB6D7670E522A718067333cd4E); 50 | address internal constant ADMIN = address(0x789); 51 | 52 | event Upgraded(address indexed implementation); 53 | event EngravingSet(address indexed _tokenContract, uint256 indexed _tokenId, address author, string _engraving); 54 | event BootlinkSet(address indexed _tokenContract, uint256 indexed _tokenId, address author, string _bootLink); 55 | 56 | function setUp() public { 57 | signer = vm.addr(SIGNER_PK); 58 | vm.etch(address(0x000000000000AAeB6D7670E522A718067333cd4E), address(new OperatorFilterRegistry()).code); 59 | ownedSubscriptionManager = address(new OwnedSubscriptionManager(address(0x123456))); 60 | tombIndex = address(new TombIndex("https://imageuri.com/", TOMB_ARTIST)); 61 | markerV1 = address(new IndexMarker(signer, "https://baseuri.com/", tombIndex, royaltyRecipient)); 62 | IndexMarker(markerV1).setMintInformation(true, 1672531199); 63 | IndexMarker(markerV1).transferOwnership(ADMIN); 64 | markerV2 = address( 65 | new ERC1967Proxy( 66 | address(new IndexMarkerV2()), 67 | abi.encodeWithSignature( 68 | "initialize(address,address,address,address,address)", 69 | ownedSubscriptionManager, 70 | signer, 71 | markerV1, 72 | royaltyRecipient, 73 | tombIndex 74 | ) 75 | ) 76 | ); 77 | IndexMarkerV2(markerV2).setMintAllowedAndExpiry(true, 1672531199); 78 | IndexMarkerV2(markerV2).transferOwnership(ADMIN); 79 | tombNFT = new Tomb721(); 80 | vm.prank(ADMIN); 81 | metadata = new TombMetadata(address(markerV2)); 82 | } 83 | 84 | function mintV1(uint256 tokenID, address dest) public { 85 | (uint8 v, bytes32 r, bytes32 s) = vm.sign(SIGNER_PK, keccak256(abi.encodePacked(uint256(tokenID)))); 86 | bytes memory sig = abi.encodePacked(r, s, v); 87 | bytes32 hash = keccak256(abi.encodePacked(uint256(tokenID), sig, dest)); 88 | vm.prank(dest); 89 | IndexMarker(markerV1).premint(hash); 90 | vm.prank(dest); 91 | vm.warp(block.timestamp + 100); 92 | IndexMarker(markerV1).mint(tokenID, sig); 93 | } 94 | 95 | function mint(uint256 tokenID, address dest) public { 96 | (uint8 v, bytes32 r, bytes32 s) = vm.sign(SIGNER_PK, keccak256(abi.encodePacked(uint256(tokenID)))); 97 | bytes memory sig = abi.encodePacked(r, s, v); 98 | bytes32 hash = keccak256(abi.encodePacked(uint256(tokenID), sig, dest)); 99 | vm.prank(dest); 100 | IndexMarkerV2(markerV2).premint(hash); 101 | vm.prank(dest); 102 | vm.warp(block.timestamp + 100); 103 | IndexMarkerV2(markerV2).mint(tokenID, sig); 104 | } 105 | 106 | function testTokenURI() public { 107 | assertEq(IndexMarkerV2(markerV2).tokenURI(0), TombIndex(tombIndex).tokenURI(21)); 108 | 109 | mint(1, msg.sender); 110 | assertEq( 111 | IndexMarkerV2(markerV2).tokenURI(1), 112 | string(abi.encodePacked("ipfs://QmYZEr3xvwdd5v5wbFR4LEDrqaBRLG3gXg5uC6SK37GfaQ/", Strings.toString(1))) 113 | ); 114 | } 115 | 116 | function testSetBaseURI() public { 117 | vm.prank(ADMIN); 118 | IndexMarkerV2(markerV2).setBaseURI("https://newbaseuri.com/"); 119 | assertEq(IndexMarkerV2(markerV2).baseURI(), "https://newbaseuri.com/"); 120 | } 121 | 122 | function testRevertSetBaseURINotOwner() public { 123 | vm.expectRevert("Ownable: caller is not the owner"); 124 | IndexMarkerV2(markerV2).setBaseURI("https://newbaseuri.com/"); 125 | } 126 | 127 | function testMigrationMint() public { 128 | uint256[] memory tokenIds = new uint256[](2); 129 | tokenIds[0] = 1; 130 | tokenIds[1] = 2; 131 | address[] memory owners = new address[](2); 132 | owners[0] = address(0x1); 133 | owners[1] = address(0x2); 134 | mintV1(tokenIds[0], owners[0]); 135 | mintV1(tokenIds[1], owners[1]); 136 | assertEq(IndexMarker(markerV1).ownerOf(tokenIds[0]), owners[0]); 137 | assertEq(IndexMarker(markerV1).ownerOf(tokenIds[1]), owners[1]); 138 | vm.prank(ADMIN); 139 | IndexMarkerV2(markerV2).migrationMint(tokenIds); 140 | assertEq(IndexMarkerV2(markerV2).ownerOf(tokenIds[0]), owners[0]); 141 | assertEq(IndexMarkerV2(markerV2).ownerOf(tokenIds[1]), owners[1]); 142 | } 143 | 144 | function testRevertMigrationMintNotOwner() public { 145 | uint256[] memory tokenIds = new uint256[](2); 146 | tokenIds[0] = 1; 147 | tokenIds[1] = 2; 148 | address[] memory owners = new address[](2); 149 | owners[0] = address(0x1); 150 | owners[1] = address(0x2); 151 | mintV1(tokenIds[0], owners[0]); 152 | mintV1(tokenIds[1], owners[1]); 153 | assertEq(IndexMarker(markerV1).ownerOf(tokenIds[0]), owners[0]); 154 | assertEq(IndexMarker(markerV1).ownerOf(tokenIds[1]), owners[1]); 155 | vm.expectRevert("Ownable: caller is not the owner"); 156 | IndexMarkerV2(markerV2).migrationMint(tokenIds); 157 | } 158 | 159 | function testAdminMint() public { 160 | uint256[] memory tokenIds = new uint256[](2); 161 | tokenIds[0] = 1; 162 | tokenIds[1] = 2; 163 | address[] memory owners = new address[](2); 164 | owners[0] = address(0x1); 165 | owners[1] = address(0x2); 166 | 167 | vm.startPrank(ADMIN); 168 | IndexMarkerV2(markerV2).setMintAllowedAndExpiry(false, 1672531199); 169 | IndexMarkerV2(markerV2).adminMint(tokenIds, owners); 170 | vm.stopPrank(); 171 | 172 | assertEq(IndexMarkerV2(markerV2).ownerOf(tokenIds[0]), owners[0]); 173 | assertEq(IndexMarkerV2(markerV2).ownerOf(tokenIds[1]), owners[1]); 174 | } 175 | 176 | function testRevertAdminMintNotOwner() public { 177 | uint256[] memory tokenIds = new uint256[](2); 178 | tokenIds[0] = 1; 179 | tokenIds[1] = 2; 180 | address[] memory owners = new address[](2); 181 | owners[0] = address(0x1); 182 | owners[1] = address(0x2); 183 | vm.prank(ADMIN); 184 | IndexMarkerV2(markerV2).setMintAllowedAndExpiry(false, 1672531199); 185 | 186 | vm.expectRevert("Ownable: caller is not the owner"); 187 | IndexMarkerV2(markerV2).adminMint(tokenIds, owners); 188 | } 189 | 190 | function testMint() public { 191 | address minter = address(0x1); 192 | mint(100, minter); 193 | assertEq(IndexMarkerV2(markerV2).ownerOf(100), minter); 194 | } 195 | 196 | function testRevertMintWithoutWaiting() public { 197 | address minter = address(0x1); 198 | vm.warp(1655678279); 199 | (uint8 v, bytes32 r, bytes32 s) = vm.sign(SIGNER_PK, keccak256(abi.encodePacked(uint256(100)))); 200 | bytes memory sig = abi.encodePacked(r, s, v); 201 | bytes32 hash = keccak256(abi.encodePacked(uint256(100), sig, minter)); 202 | vm.prank(minter); 203 | IndexMarkerV2(markerV2).premint(hash); 204 | vm.prank(minter); 205 | vm.warp(1655678280); 206 | vm.expectRevert("IndexMarker: Claim is too new"); 207 | IndexMarkerV2(markerV2).mint(100, sig); 208 | } 209 | 210 | function testCanMint() public { 211 | assertTrue(IndexMarkerV2(markerV2).isMintAllowed()); 212 | assertEq(IndexMarkerV2(markerV2).mintExpiry(), uint256(1672531199)); 213 | assertTrue(IndexMarkerV2(markerV2).canMint()); 214 | 215 | vm.startPrank(ADMIN); 216 | IndexMarkerV2(markerV2).setMintAllowedAndExpiry(false, 1672531199); 217 | assertEq(IndexMarkerV2(markerV2).mintExpiry(), uint256(1672531199)); 218 | assertTrue(!IndexMarkerV2(markerV2).canMint()); 219 | IndexMarkerV2(markerV2).setMintAllowedAndExpiry(true, 1672531199); 220 | vm.stopPrank(); 221 | 222 | vm.warp(1672531200); 223 | assertTrue(!IndexMarkerV2(markerV2).canMint()); 224 | } 225 | 226 | function testSetTokenClaimSigner() public { 227 | vm.prank(ADMIN); 228 | IndexMarkerV2(markerV2).setTokenClaimSigner(address(0x1)); 229 | assertEq(IndexMarkerV2(markerV2).tokenClaimSigner(), address(0x1)); 230 | } 231 | 232 | function testRevertSetTokenClaimSignerNotOwner() public { 233 | vm.expectRevert("Ownable: caller is not the owner"); 234 | IndexMarkerV2(markerV2).setTokenClaimSigner(address(0x1)); 235 | } 236 | 237 | function testRoyaltyInfo() public { 238 | (address dest, uint256 royalty) = IndexMarkerV2(markerV2).royaltyInfo(0, 150); 239 | assertEq(dest, address(TOMB_ARTIST)); 240 | assertEq(royalty, 15); 241 | 242 | (dest, royalty) = IndexMarkerV2(markerV2).royaltyInfo(1, 150); 243 | assertEq(dest, address(royaltyRecipient)); 244 | assertEq(royalty, 15); 245 | } 246 | 247 | function testSetDefaultRoyalty() public { 248 | vm.prank(ADMIN); 249 | IndexMarkerV2(markerV2).setDefaultRoyalty(address(0x1), 2_000); 250 | 251 | (address dest, uint256 royalty) = IndexMarkerV2(markerV2).royaltyInfo(1, 200); 252 | assertEq(dest, address(0x1)); 253 | assertEq(royalty, 40); 254 | } 255 | 256 | function testRevertSetDefaultRoyaltyNotOwner() public { 257 | vm.expectRevert("Ownable: caller is not the owner"); 258 | IndexMarkerV2(markerV2).setDefaultRoyalty(address(0x1), 2_000); 259 | } 260 | 261 | function testDeleteDefaultRoyalty() public { 262 | vm.startPrank(ADMIN); 263 | IndexMarkerV2(markerV2).setDefaultRoyalty(address(0x1), 2_000); 264 | IndexMarkerV2(markerV2).deleteDefaultRoyalty(); 265 | vm.stopPrank(); 266 | 267 | (address dest, uint256 royalty) = IndexMarkerV2(markerV2).royaltyInfo(1, 200); 268 | assertEq(dest, address(0)); 269 | assertEq(royalty, 0); 270 | } 271 | 272 | function testRevertDeleteDefaultRoyaltyNotOwner() public { 273 | vm.expectRevert("Ownable: caller is not the owner"); 274 | IndexMarkerV2(markerV2).deleteDefaultRoyalty(); 275 | } 276 | 277 | function testSetTokenRoyalty() public { 278 | vm.prank(ADMIN); 279 | IndexMarkerV2(markerV2).setTokenRoyalty(1, address(0x2), 2_000); 280 | 281 | (address dest, uint256 royalty) = IndexMarkerV2(markerV2).royaltyInfo(1, 200); 282 | assertEq(dest, address(0x2)); 283 | assertEq(royalty, 40); 284 | } 285 | 286 | function testRevertSetTokenRoyaltyNotOwner() public { 287 | vm.expectRevert("Ownable: caller is not the owner"); 288 | IndexMarkerV2(markerV2).setTokenRoyalty(1, address(0x2), 2_000); 289 | } 290 | 291 | function testResetTokenRoyalty() public { 292 | vm.startPrank(ADMIN); 293 | IndexMarkerV2(markerV2).setTokenRoyalty(1, address(0x2), 2_000); 294 | IndexMarkerV2(markerV2).resetTokenRoyalty(1); 295 | vm.stopPrank(); 296 | 297 | (address dest, uint256 royalty) = IndexMarkerV2(markerV2).royaltyInfo(1, 150); 298 | assertEq(dest, address(royaltyRecipient)); 299 | assertEq(royalty, 15); 300 | } 301 | 302 | function testRevertResetTokenRoyaltyNotOwner() public { 303 | vm.prank(ADMIN); 304 | IndexMarkerV2(markerV2).setTokenRoyalty(1, address(0x2), 2_000); 305 | 306 | vm.expectRevert("Ownable: caller is not the owner"); 307 | IndexMarkerV2(markerV2).resetTokenRoyalty(1); 308 | } 309 | 310 | function testUpdateMarketFilterSettings() public { 311 | vm.prank(ADMIN); 312 | bytes memory baseCall = abi.encodeWithSelector(OperatorFilterRegistry.register.selector, address(markerV2)); 313 | IndexMarkerV2(markerV2).updateMarketFilterSettings(baseCall); 314 | assertTrue(OperatorFilterRegistry(OPERATOR_FILTER_REGISTRY).isRegistered(address(markerV2))); 315 | } 316 | 317 | function testRevertUpdateMarketFilterSettingsNotOwner() public { 318 | bytes memory baseCall = abi.encodeWithSelector(OperatorFilterRegistry.register.selector, address(markerV2)); 319 | vm.expectRevert("Ownable: caller is not the owner"); 320 | IndexMarkerV2(markerV2).updateMarketFilterSettings(baseCall); 321 | assertTrue(!OperatorFilterRegistry(OPERATOR_FILTER_REGISTRY).isRegistered(address(markerV2))); 322 | } 323 | 324 | function testManageMarketFilterDAOSubscription() public { 325 | vm.prank(ADMIN); 326 | IndexMarkerV2(markerV2).manageMarketFilterDAOSubscription(true); 327 | assertEq( 328 | OperatorFilterRegistry(OPERATOR_FILTER_REGISTRY).subscriptionOf(address(markerV2)), 329 | address(ownedSubscriptionManager) 330 | ); 331 | } 332 | 333 | function testRevertManageMarketFilterDAOSubscriptionNotOwner() public { 334 | vm.expectRevert("Ownable: caller is not the owner"); 335 | IndexMarkerV2(markerV2).manageMarketFilterDAOSubscription(true); 336 | vm.expectRevert(); 337 | OperatorFilterRegistry(OPERATOR_FILTER_REGISTRY).subscriptionOf(address(markerV2)); 338 | } 339 | 340 | function testSetTombContracts() public { 341 | address[] memory tombContracts = new address[](2); 342 | tombContracts[0] = address(0x1); 343 | tombContracts[1] = address(0x2); 344 | bool[] memory isTombContract = new bool[](2); 345 | isTombContract[0] = true; 346 | isTombContract[1] = true; 347 | vm.prank(ADMIN); 348 | IndexMarkerV2(markerV2).setTombContracts(tombContracts, isTombContract); 349 | assertTrue(IndexMarkerV2(markerV2).isTomb(address(0x1), 0)); 350 | assertTrue(IndexMarkerV2(markerV2).isTomb(address(0x2), 0)); 351 | } 352 | 353 | function testSetTombTokens() public { 354 | address[] memory tombContracts = new address[](2); 355 | tombContracts[0] = address(0x1); 356 | tombContracts[1] = address(0x2); 357 | uint256[] memory tombTokenIDs = new uint256[](2); 358 | tombTokenIDs[0] = 1; 359 | tombTokenIDs[1] = 2; 360 | bool[] memory isTombToken = new bool[](2); 361 | isTombToken[0] = true; 362 | isTombToken[1] = true; 363 | vm.prank(ADMIN); 364 | IndexMarkerV2(markerV2).setTombTokens(tombContracts, tombTokenIDs, isTombToken); 365 | assertTrue(IndexMarkerV2(markerV2).isTomb(address(0x1), 1)); 366 | assertTrue(IndexMarkerV2(markerV2).isTomb(address(0x2), 2)); 367 | } 368 | 369 | function testUpgrade() public { 370 | address newImpl = address(new IndexMarkerV2()); 371 | vm.prank(ADMIN); 372 | vm.expectEmit(true, false, false, false); 373 | emit Upgraded(newImpl); 374 | IndexMarkerV2(markerV2).upgradeTo(newImpl); 375 | } 376 | 377 | function testMetadata() public { 378 | address tombOwner = address(123); 379 | address[] memory tombContracts = new address[](1); 380 | tombContracts[0] = address(tombNFT); 381 | bool[] memory isTombContract = new bool[](1); 382 | isTombContract[0] = true; 383 | tombNFT.mint(tombOwner, 1); 384 | tombNFT.mint(tombOwner, 3); 385 | 386 | vm.prank(ADMIN); 387 | IndexMarkerV2(markerV2).setTombContracts(tombContracts, isTombContract); 388 | 389 | vm.prank(tombOwner, tombOwner); 390 | vm.expectEmit(true, false, false, false); 391 | emit BootlinkSet(address(tombNFT), 1, tombOwner, "google.com"); 392 | metadata.setBootlink(address(tombNFT), 1, "google.com"); 393 | 394 | vm.prank(tombOwner, tombOwner); 395 | vm.expectEmit(true, false, false, false); 396 | emit EngravingSet(address(tombNFT), 1, tombOwner, "Here we go!"); 397 | metadata.setEngraving(address(tombNFT), 1, "Here we go!"); 398 | 399 | vm.prank(ADMIN); 400 | vm.expectEmit(true, false, false, false); 401 | emit BootlinkSet(address(tombNFT), 3, address(ADMIN), "admin.com"); 402 | metadata.setBootlink(address(tombNFT), 3, "admin.com"); 403 | 404 | vm.prank(ADMIN); 405 | vm.expectEmit(true, false, false, false); 406 | emit EngravingSet(address(tombNFT), 3, address(ADMIN), "admin!"); 407 | metadata.setEngraving(address(tombNFT), 3, "admin!"); 408 | 409 | assertEq(metadata.getBootLink(address(tombNFT), 1), "google.com"); 410 | assertEq(metadata.getEngraving(address(tombNFT), 1), "Here we go!"); 411 | assertEq(metadata.getBootLink(address(tombNFT), 3), "admin.com"); 412 | assertEq(metadata.getEngraving(address(tombNFT), 3), "admin!"); 413 | 414 | vm.prank(address(100)); 415 | vm.expectRevert("TombMetadata: Not tomb owner"); 416 | metadata.setEngraving(address(tombNFT), 3, "Not my tomb"); 417 | 418 | vm.expectRevert("TombMetadata: Not a tomb"); 419 | metadata.setEngraving(address(100), 3, "Not my tomb"); 420 | } 421 | } 422 | -------------------------------------------------------------------------------- /src/test/Ronin.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | pragma solidity ^0.8.10; 3 | 4 | import "ds-test/test.sol"; 5 | import "../TombIndex.sol"; 6 | import "../Ronin.sol"; 7 | 8 | interface CheatCodes { 9 | function prank(address) external; 10 | 11 | function prank(address, address) external; 12 | 13 | function ffi(string[] calldata) external returns (bytes memory); 14 | } 15 | 16 | contract RoninTest is DSTest { 17 | CheatCodes cheats = CheatCodes(HEVM_ADDRESS); 18 | address ArtistAddress = 0x4a61d76ea05A758c1db9C9b5a5ad22f445A38C46; 19 | address OtherAddress = 0xfB843f8c4992EfDb6b42349C35f025ca55742D33; 20 | TombIndex internal TombContract; 21 | Ronin internal RoninContract; 22 | 23 | function setUp() public { 24 | TombContract = new TombIndex("https://tombseri.es/img/", ArtistAddress); 25 | RoninContract = new Ronin(address(TombContract)); 26 | } 27 | 28 | function testTokenURI() public { 29 | bytes memory uri = TombContract.jsonForTomb(160); 30 | emit log(string(uri)); 31 | assertEq(TombContract.tokenURI(160), RoninContract.tokenURI(160)); 32 | } 33 | 34 | function testFailTokenURI() public view { 35 | RoninContract.tokenURI(1); 36 | } 37 | 38 | function testAMint() public { 39 | cheats.prank(RoninContract.owner(), RoninContract.owner()); 40 | RoninContract.mint(); 41 | assertEq(RoninContract.ownerOf(160), RoninContract.owner()); 42 | } 43 | 44 | function testFailASecondMint() public { 45 | RoninContract.mint(); 46 | RoninContract.mint(); 47 | } 48 | 49 | function testRoyaltyInfo() public { 50 | (address artist, uint256 amount) = RoninContract.royaltyInfo(160, 4234000000); 51 | assertEq(artist, ArtistAddress); 52 | assertEq(amount, 423400000); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/ShadowBeacon.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | pragma solidity >=0.8.0; 3 | 4 | import {ShadowBeacon} from "../ShadowBeacon.sol"; 5 | import {DSTest} from "ds-test/test.sol"; 6 | import {Utilities} from "./utils/Utilities.sol"; 7 | import {Vm} from "forge-std/Vm.sol"; 8 | 9 | contract ShadowBeaconTest is DSTest { 10 | ShadowBeacon internal beacon; 11 | Vm internal immutable vm = Vm(HEVM_ADDRESS); 12 | address signer = address(1234); 13 | 14 | function setUp() public { 15 | beacon = new ShadowBeacon(signer, ""); 16 | vm.prank(signer, signer); 17 | beacon.transferFrom(address(0), address(1), 1); 18 | } 19 | 20 | function testFailSetApprovalForAll() public { 21 | vm.prank(address(1), address(1)); 22 | beacon.setApprovalForAll(address(2421), true); 23 | } 24 | 25 | function testFailTransferFrom() public { 26 | vm.prank(address(1), address(1)); 27 | beacon.transferFrom(address(1), address(2), 1); 28 | } 29 | 30 | function testFailSafeTransferFrom() public { 31 | vm.prank(address(1), address(1)); 32 | beacon.safeTransferFrom(address(1), address(2), 1); 33 | } 34 | 35 | function testSignerTransferFrom() public { 36 | vm.prank(signer, signer); 37 | beacon.transferFrom(address(1), address(2), 1); 38 | assertEq(beacon.ownerOf(1), address(2)); 39 | } 40 | 41 | function testSignerTransferFromMint() public { 42 | vm.prank(signer, signer); 43 | beacon.transferFrom(address(0), address(62), 60); 44 | assertEq(beacon.ownerOf(60), address(62)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/ShadowDistribution.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | pragma solidity ^0.8.10; 3 | 4 | import "ds-test/test.sol"; 5 | import "../ShadowNFT.sol"; 6 | import {Vm} from "forge-std/Vm.sol"; 7 | import {Utilities} from "./utils/Utilities.sol"; 8 | 9 | import {console} from "./utils/Console.sol"; 10 | 11 | import "../ShadowDistribution.sol"; 12 | import "base64/base64.sol"; 13 | 14 | contract ShadowDistributionTest is DSTest { 15 | Shadow internal ShadowContract; 16 | Vm internal immutable vm = Vm(HEVM_ADDRESS); 17 | 18 | ShadowDistribution internal ShadowDistributionContract; 19 | address internal TombCouncil = 0xcC1775Ea6D7F62b4DCA8FAF075F864d3e15Dd0F0; 20 | address internal Worm = 0xfB843f8c4992EfDb6b42349C35f025ca55742D33; 21 | Utilities internal utils = new Utilities(); 22 | address internal relayer; 23 | address internal unauthorizedUser; 24 | address internal otherWallet = 0xb18989f87630b57B45d8820558ed6583d62Cb9e7; 25 | 26 | function setUp() public { 27 | relayer = utils.createUsers(1)[0]; 28 | unauthorizedUser = utils.createUsers(1)[0]; 29 | 30 | ShadowContract = new Shadow(TombCouncil); 31 | ShadowDistributionContract = new ShadowDistribution(address(ShadowContract), TombCouncil); 32 | 33 | vm.prank(TombCouncil, TombCouncil); 34 | ShadowContract.init(); 35 | ShadowContract.setApprovalForAll(address(ShadowDistributionContract), true); 36 | 37 | vm.prank(ShadowDistributionContract.owner(), ShadowDistributionContract.owner()); 38 | uint256[] memory ids = new uint256[](1); 39 | address[] memory addrs = new address[](1); 40 | 41 | ids[0] = 4; 42 | addrs[0] = Worm; 43 | 44 | ShadowDistributionContract.saveMapping(ids, addrs); 45 | 46 | vm.prank(TombCouncil, TombCouncil); 47 | ShadowContract.setApprovalForAll(address(ShadowDistributionContract), true); 48 | } 49 | 50 | function testClaim() public { 51 | vm.prank(relayer, relayer); 52 | 53 | assertEq(ShadowContract.ownerOf(4), TombCouncil, "owner should be council"); 54 | ShadowDistributionContract.claimNFT( 55 | 4, 56 | Worm, 57 | Worm, 58 | hex"21bdc3e08df19e2f747c2268e853faf9871263f5fa06719efa3831b014a7c38958da6a6bb929e74919e58a69f3167323db748c3b5abb94efb79f838da73c3cdc1c" 59 | ); 60 | assertEq(ShadowContract.ownerOf(4), Worm); 61 | } 62 | 63 | function testFailClaimTwice() public { 64 | vm.prank(relayer, relayer); 65 | 66 | assertEq(ShadowContract.ownerOf(4), TombCouncil, "owner should be council"); 67 | ShadowDistributionContract.claimNFT( 68 | 4, 69 | Worm, 70 | Worm, 71 | hex"21bdc3e08df19e2f747c2268e853faf9871263f5fa06719efa3831b014a7c38958da6a6bb929e74919e58a69f3167323db748c3b5abb94efb79f838da73c3cdc1c" 72 | ); 73 | assertEq(ShadowContract.ownerOf(4), Worm); 74 | ShadowDistributionContract.claimNFT( 75 | 4, 76 | Worm, 77 | Worm, 78 | hex"21bdc3e08df19e2f747c2268e853faf9871263f5fa06719efa3831b014a7c38958da6a6bb929e74919e58a69f3167323db748c3b5abb94efb79f838da73c3cdc1c" 79 | ); 80 | } 81 | 82 | function testFailDifferentWallet() public { 83 | vm.prank(relayer, relayer); 84 | 85 | assertEq(ShadowContract.ownerOf(4), TombCouncil, "owner should be council"); 86 | ShadowDistributionContract.claimNFT( 87 | 4, 88 | Worm, 89 | unauthorizedUser, 90 | hex"21bdc3e08df19e2f747c2268e853faf9871263f5fa06719efa3831b014a7c38958da6a6bb929e74919e58a69f3167323db748c3b5abb94efb79f838da73c3cdc1c" 91 | ); 92 | assertEq(ShadowContract.ownerOf(4), Worm); 93 | } 94 | 95 | function testOtherWallet() public { 96 | vm.prank(relayer, relayer); 97 | 98 | assertEq(ShadowContract.ownerOf(4), TombCouncil, "owner should be council"); 99 | ShadowDistributionContract.claimNFT( 100 | 4, 101 | Worm, 102 | otherWallet, 103 | hex"6ca05722ee848ce7815fd08897ac35de44523f95b17f4235522a1e88981378250f109342db0bd113e520ca40449dcc0079de43d9b7bef590d74189a1a713988c1c" 104 | ); 105 | assertEq(ShadowContract.ownerOf(4), otherWallet); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/test/TombIndex.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | pragma solidity ^0.8.10; 3 | 4 | import "ds-test/test.sol"; 5 | import "solmate/tokens/ERC721.sol"; 6 | import "../TombIndex.sol"; 7 | import "base64/base64.sol"; 8 | 9 | interface CheatCodes { 10 | function prank(address) external; 11 | 12 | function ffi(string[] calldata) external returns (bytes memory); 13 | } 14 | 15 | contract ExampleRonin is ERC721 { 16 | constructor() ERC721("Ronin", "RNIN") {} 17 | 18 | function tokenURI(uint256 id) public view override returns (string memory) { 19 | return ""; 20 | } 21 | 22 | address OtherAddress = 0xfB843f8c4992EfDb6b42349C35f025ca55742D33; 23 | 24 | function mint2() public { 25 | _mint(OtherAddress, 0); 26 | } 27 | } 28 | 29 | contract TombContractTest is DSTest { 30 | CheatCodes cheats = CheatCodes(HEVM_ADDRESS); 31 | ExampleRonin internal ExtNFTContract = ExampleRonin(0x517e643F53EB3622Fd2c3A12C6BFde5E7Bc8D5ca); 32 | address ArtistAddress = 0x4a61d76ea05A758c1db9C9b5a5ad22f445A38C46; 33 | address OtherAddress = 0xfB843f8c4992EfDb6b42349C35f025ca55742D33; 34 | TombIndex internal TombContract; 35 | 36 | enum House { 37 | GENESIS, 38 | LUX, 39 | X2, 40 | SHADOW, 41 | COMETS, 42 | DEVASTATORS, 43 | TERRA, 44 | RONIN 45 | } 46 | 47 | struct Tomb { 48 | bool _active; 49 | string name; 50 | uint256 weight; 51 | House house; 52 | address deployedContract; 53 | uint256 deployedTokenID; 54 | } 55 | 56 | function setUp() public { 57 | ExtNFTContract = new ExampleRonin(); 58 | ExtNFTContract.mint2(); 59 | TombContract = new TombIndex("https://tombseri.es/img/", ArtistAddress); 60 | 61 | uint256[] memory ids = new uint256[](1); 62 | ids[0] = 21; 63 | 64 | string[] memory names = new string[](1); 65 | names[0] = "EQUINOX"; 66 | 67 | TombIndex.Tomb[] memory tombs = new TombIndex.Tomb[](1); 68 | tombs[0] = TombIndex.Tomb({ 69 | _initialized: true, 70 | weight: 18356125, 71 | numberInHouse: 10, 72 | house: 7, 73 | deployment: TombIndex.deployment({ 74 | hostContract: address(ExtNFTContract), 75 | tokenID: 0, 76 | chainID: 1, 77 | deployed: true 78 | }) 79 | }); 80 | 81 | TombContract.saveTombs(ids, names, tombs); 82 | TombContract.transferOwnership(ArtistAddress); 83 | } 84 | 85 | function testOwnerOf() public { 86 | assertEq(TombContract.ownerOf(111), ArtistAddress); 87 | } 88 | 89 | function testExternalOwnerOf() public { 90 | assertEq(TombContract.ownerOfTomb(21), OtherAddress); 91 | } 92 | 93 | function testSetURI() public { 94 | cheats.prank(ArtistAddress); 95 | TombContract.setImageURI("test"); 96 | } 97 | 98 | function testFailUseOwnerFunction() public { 99 | cheats.prank(OtherAddress); 100 | TombContract.setImageURI("test"); 101 | } 102 | 103 | function testFailDoesntExist() public { 104 | emit log(TombContract.tokenURI(178)); 105 | } 106 | 107 | function testTerrainTokenURI() public { 108 | bytes memory uri = TombContract.jsonForTomb(111); 109 | emit log(string(uri)); 110 | } 111 | 112 | function testSingleSave() public { 113 | cheats.prank(ArtistAddress); 114 | uint256[] memory ids = new uint256[](1); 115 | ids[0] = 177; 116 | 117 | string[] memory names = new string[](1); 118 | names[0] = "SAVETEST"; 119 | 120 | TombIndex.Tomb[] memory tombs = new TombIndex.Tomb[](1); 121 | 122 | tombs[0] = TombIndex.Tomb({ 123 | _initialized: true, 124 | weight: 18356125, 125 | numberInHouse: 10, 126 | house: 0, 127 | deployment: TombIndex.deployment({ 128 | hostContract: address(ExtNFTContract), 129 | tokenID: 0, 130 | chainID: 1, 131 | deployed: true 132 | }) 133 | }); 134 | 135 | TombContract.saveTombs(ids, names, tombs); 136 | } 137 | 138 | function testBatchSave() public { 139 | cheats.prank(ArtistAddress); 140 | uint256[] memory ids = new uint256[](2); 141 | ids[0] = 1; 142 | ids[1] = 177; 143 | 144 | string[] memory names = new string[](2); 145 | names[0] = "SAVETEST"; 146 | names[1] = "EQUINOX"; 147 | 148 | TombIndex.Tomb[] memory tombs = new TombIndex.Tomb[](2); 149 | 150 | tombs[0] = TombIndex.Tomb({ 151 | _initialized: true, 152 | weight: 18356125, 153 | numberInHouse: 10, 154 | house: 0, 155 | deployment: TombIndex.deployment({ 156 | hostContract: address(ExtNFTContract), 157 | tokenID: 0, 158 | chainID: 1, 159 | deployed: true 160 | }) 161 | }); 162 | 163 | tombs[1] = TombIndex.Tomb({ 164 | _initialized: true, 165 | weight: 18356125, 166 | numberInHouse: 10, 167 | house: 0, 168 | deployment: TombIndex.deployment({ 169 | hostContract: address(ExtNFTContract), 170 | tokenID: 0, 171 | chainID: 1, 172 | deployed: true 173 | }) 174 | }); 175 | 176 | TombContract.saveTombs(ids, names, tombs); 177 | } 178 | 179 | function testFailIsFrozen() public { 180 | cheats.prank(ArtistAddress); 181 | TombContract.freezeContract(); 182 | TombContract.setImageURI("test"); 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /src/test/TombMarker.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | pragma solidity >=0.8.0; 3 | 4 | import {DSTest} from "ds-test/test.sol"; 5 | import {Utilities} from "./utils/Utilities.sol"; 6 | import {console} from "./utils/Console.sol"; 7 | import {Vm} from "forge-std/Vm.sol"; 8 | import {IndexMarker} from "../IndexMarker.sol"; 9 | import {TombIndex} from "../TombIndex.sol"; 10 | 11 | contract CatTest is DSTest { 12 | Vm internal immutable vm = Vm(HEVM_ADDRESS); 13 | IndexMarker internal marker; 14 | TombIndex internal index; 15 | Utilities internal utils; 16 | address payable[] internal users; 17 | bytes internal sig; 18 | 19 | function setUp() public { 20 | index = new TombIndex("https://tombseri.es/img/", 0x4a61d76ea05A758c1db9C9b5a5ad22f445A38C46); 21 | marker = new IndexMarker( 22 | 0x818d7CA5aa6E964784267aAaEAEab323d5894A86, 23 | "https://tombseri.es", 24 | address(index), 25 | msg.sender 26 | ); 27 | marker.setMintInformation(true, 1672531199); 28 | utils = new Utilities(); 29 | users = utils.createUsers(5); 30 | sig = hex"be6f3b9f9b009848f4245269a8b532a47bac1cd3a38880907c897b41176cce2bf63ac6f53ab8efb0bf2fafe9cc8b94dee65a6ba3a94699426d1dfd4d57590dcf"; 31 | } 32 | 33 | // function testPremint() public { 34 | // vm.warp(1655678279); 35 | // bytes32 hash = keccak256(abi.encodePacked(uint256(100), sig, msg.sender)); 36 | // vm.prank(0x00a329c0648769A73afAc7F9381E08FB43dBEA72); 37 | // marker.premint(hash); 38 | // vm.prank(0x00a329c0648769A73afAc7F9381E08FB43dBEA72); 39 | // vm.warp(1655678340); 40 | // marker.mint(100, sig); 41 | // } 42 | 43 | function testFailPremint() public { 44 | // try to premint without waiting too long 45 | vm.warp(1655678279); 46 | bytes32 hash = keccak256(abi.encodePacked(uint256(100), sig, msg.sender)); 47 | vm.prank(0x00a329c0648769A73afAc7F9381E08FB43dBEA72); 48 | marker.premint(hash); 49 | vm.prank(0x00a329c0648769A73afAc7F9381E08FB43dBEA72); 50 | vm.warp(1655678279); 51 | marker.mint(100, sig); 52 | } 53 | 54 | // function testRoyaltyInfo() public { 55 | // (address dest, uint256 royalty) = marker.royaltyInfo(0, 150); 56 | // assertEq(dest, address(marker)); 57 | // assertEq(royalty, 15); 58 | // } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/recovery/TombRecoveryGovernor.t.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.17; 3 | 4 | import {Test} from "forge-std/Test.sol"; 5 | import {GovernorCountingSimple} from "openzeppelin/governance/extensions/GovernorCountingSimple.sol"; 6 | import {IGovernor} from "openzeppelin/governance/IGovernor.sol"; 7 | import {EIP712Upgradeable} from "openzeppelin-upgradeable/utils/cryptography/EIP712Upgradeable.sol"; 8 | import {ERC721PresetMinterPauserAutoId} from "openzeppelin/token/ERC721/presets/ERC721PresetMinterPauserAutoId.sol"; 9 | import {ERC1967Proxy} from "openzeppelin/proxy/ERC1967/ERC1967Proxy.sol"; 10 | import {RecoveryProxy} from "recovery-protocol/upgradeability/RecoveryProxy.sol"; 11 | import {RecoveryRegistry} from "recovery-protocol/RecoveryRegistry.sol"; 12 | import {RecoveryCollection} from "recovery-protocol/token/RecoveryCollection.sol"; 13 | import {RecoveryGovernor} from "recovery-protocol/governance/RecoveryGovernor.sol"; 14 | import {RecoveryTreasury} from "recovery-protocol/governance/RecoveryTreasury.sol"; 15 | 16 | import {MockOwnable721} from "../utils/MockOwnable721.sol"; 17 | import {TombRecoveryGovernor} from "../../recovery/TombRecoveryGovernor.sol"; 18 | import {RecoveryVoteAggregator} from "../../recovery/RecoveryVoteAggregator.sol"; 19 | import {IndexMarkerV2} from "../../IndexMarkerV2.sol"; 20 | 21 | contract TombRecoveryGovernorTest is Test, EIP712Upgradeable { 22 | IndexMarkerV2 indexMarker; 23 | RecoveryRegistry registry; 24 | MockOwnable721 aeon; 25 | MockOwnable721 tarot; 26 | TombRecoveryGovernor tombGovernorImplementation; 27 | 28 | event VoteCastWithParams( 29 | address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason, bytes params 30 | ); 31 | event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason); 32 | 33 | bytes32 public constant BALLOT_TYPEHASH = keccak256("Ballot(uint256 proposalId,uint8 support)"); 34 | 35 | address admin = address(0x1); 36 | address tombHolder = address(0x2); 37 | address voter = address(0x3); 38 | RecoveryVoteAggregator aggregator = new RecoveryVoteAggregator(); 39 | 40 | address[] tombContracts; 41 | 42 | function setUp() external { 43 | vm.startPrank(admin); 44 | 45 | indexMarker = IndexMarkerV2( 46 | address( 47 | new ERC1967Proxy( 48 | address(new IndexMarkerV2()), 49 | abi.encodeWithSignature( 50 | "initialize(address,address,address,address,address)", 51 | address(0), 52 | address(0), 53 | address(0), 54 | admin, 55 | address(0) 56 | ) 57 | ) 58 | ) 59 | ); 60 | 61 | address collectionImpl = address(new RecoveryCollection()); 62 | address governorImpl = address(new RecoveryGovernor()); 63 | address treasuryImpl = address(new RecoveryTreasury()); 64 | tombGovernorImplementation = new TombRecoveryGovernor(address(indexMarker), address(aggregator)); 65 | address registryImpl = address(new RecoveryRegistry(collectionImpl, governorImpl, treasuryImpl)); 66 | 67 | registry = RecoveryRegistry( 68 | address(new RecoveryProxy(registryImpl, abi.encodeWithSignature("__RecoveryRegistry_init()"))) 69 | ); 70 | 71 | aeon = new MockOwnable721("test", "test"); 72 | aeon.mint(tombHolder, 0); 73 | tarot = new MockOwnable721("test", "test"); 74 | tarot.mint(tombHolder, 1); 75 | 76 | tombContracts = new address[](2); 77 | tombContracts[0] = address(aeon); 78 | tombContracts[1] = address(tarot); 79 | bool[] memory isTombContract = new bool[](2); 80 | isTombContract[0] = true; 81 | isTombContract[1] = true; 82 | indexMarker.setTombContracts(tombContracts, isTombContract); 83 | 84 | uint256[] memory tokenIds = new uint256[](10); 85 | address[] memory recipients = new address[](10); 86 | for (uint256 i = 0; i < 10; i++) { 87 | tokenIds[i] = i + 1; 88 | recipients[i] = voter; 89 | } 90 | recipients[9] = tombHolder; 91 | indexMarker.adminMint(tokenIds, recipients); 92 | vm.stopPrank(); 93 | 94 | vm.prank(tombHolder); 95 | indexMarker.delegate(tombHolder); 96 | 97 | vm.prank(voter); 98 | indexMarker.delegate(voter); 99 | 100 | vm.roll(block.number + 1); 101 | } 102 | 103 | function test_Flow() external { 104 | vm.prank(admin); 105 | registry.registerParentCollection( 106 | address(aeon), 107 | address(indexMarker), 108 | address(tombGovernorImplementation), 109 | 1, 110 | 50400, 111 | 172800, 112 | 1, 113 | 0, 114 | false, 115 | true, 116 | 10 117 | ); 118 | 119 | vm.prank(tombHolder); 120 | registry.createRecoveryCollectionForParentToken(address(aeon), 0, address(indexMarker)); 121 | 122 | RecoveryRegistry.RecoveryCollectionAddresses memory addresses = 123 | registry.getRecoveryAddressesForParentToken(address(aeon), 0); 124 | RecoveryCollection collection = RecoveryCollection(addresses.collection); 125 | RecoveryGovernor governor = RecoveryGovernor(addresses.governor); 126 | RecoveryTreasury treasury = RecoveryTreasury(addresses.treasury); 127 | 128 | assertEq(governor.quorumDenominator(), 1000); 129 | 130 | address[] memory targets = new address[](1); 131 | targets[0] = address(collection); 132 | uint256[] memory values = new uint256[](1); 133 | bytes[] memory calldatas = new bytes[](1); 134 | calldatas[0] = abi.encodeWithSignature("safeMint(address,string)", tombHolder, "https://test.com"); 135 | vm.startPrank(tombHolder); 136 | uint256 proposalId = governor.propose(targets, values, calldatas, ""); 137 | vm.roll(block.number + 2); 138 | uint256[] memory tombTokenIds = new uint256[](2); 139 | tombTokenIds[0] = 0; 140 | tombTokenIds[1] = 1; 141 | uint256 parentOwnerWeight = governor.castVoteWithReasonAndParams( 142 | proposalId, uint8(GovernorCountingSimple.VoteType.For), "", abi.encode(tombContracts, tombTokenIds) 143 | ); 144 | assertEq(parentOwnerWeight, 12); // 10 from parent tomb + 1 other tomb + 1 index marker 145 | vm.stopPrank(); 146 | 147 | vm.prank(voter); 148 | uint256 voterWeight = governor.castVote(proposalId, uint8(GovernorCountingSimple.VoteType.For)); 149 | assertEq(voterWeight, 9); 150 | 151 | vm.roll(block.number + 50400); 152 | assertGt(block.number, governor.proposalDeadline(proposalId)); 153 | assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Succeeded)); 154 | 155 | vm.prank(admin); 156 | governor.queue(targets, values, calldatas, keccak256(bytes(""))); 157 | vm.warp(block.timestamp + 172800); 158 | governor.execute(targets, values, calldatas, keccak256(bytes(""))); 159 | 160 | assertEq(collection.balanceOf(tombHolder), 1); 161 | assertEq(collection.tokenURI(1), "https://test.com"); 162 | } 163 | 164 | function test_FlowAggregate() external { 165 | vm.prank(admin); 166 | registry.registerParentCollection( 167 | address(aeon), 168 | address(indexMarker), 169 | address(tombGovernorImplementation), 170 | 1, 171 | 50400, 172 | 172800, 173 | 1, 174 | 0, 175 | false, 176 | true, 177 | 10 178 | ); 179 | 180 | vm.prank(tombHolder); 181 | registry.createRecoveryCollectionForParentToken(address(aeon), 0, address(indexMarker)); 182 | 183 | RecoveryRegistry.RecoveryCollectionAddresses memory addresses = 184 | registry.getRecoveryAddressesForParentToken(address(aeon), 0); 185 | RecoveryCollection collection = RecoveryCollection(addresses.collection); 186 | RecoveryGovernor governor = RecoveryGovernor(addresses.governor); 187 | RecoveryTreasury treasury = RecoveryTreasury(addresses.treasury); 188 | 189 | address[] memory targets = new address[](1); 190 | targets[0] = address(collection); 191 | uint256[] memory values = new uint256[](1); 192 | bytes[] memory calldatas = new bytes[](1); 193 | calldatas[0] = abi.encodeWithSignature("safeMint(address,string)", tombHolder, "https://test.com"); 194 | vm.startPrank(tombHolder); 195 | uint256 proposalId = governor.propose(targets, values, calldatas, ""); 196 | vm.roll(block.number + 2); 197 | uint256[] memory tombTokenIds = new uint256[](2); 198 | tombTokenIds[0] = 0; 199 | tombTokenIds[1] = 1; 200 | 201 | address[] memory governors = new address[](1); 202 | governors[0] = address(governor); 203 | uint256[] memory proposalIds = new uint256[](1); 204 | proposalIds[0] = proposalId; 205 | uint8[] memory supportVals = new uint8[](1); 206 | supportVals[0] = uint8(GovernorCountingSimple.VoteType.For); 207 | string[] memory reasons = new string[](1); 208 | reasons[0] = ""; 209 | bytes[] memory paramVals = new bytes[](1); 210 | paramVals[0] = abi.encode(tombContracts, tombTokenIds); 211 | 212 | vm.expectEmit(true, false, false, false); 213 | emit VoteCastWithParams( 214 | tombHolder, 215 | proposalId, 216 | uint8(GovernorCountingSimple.VoteType.For), 217 | 12, 218 | "", 219 | abi.encode(tombContracts, tombTokenIds) 220 | ); 221 | aggregator.votesWithReasonAndParams(governors, proposalIds, supportVals, reasons, paramVals); 222 | vm.stopPrank(); 223 | 224 | vm.prank(voter); 225 | 226 | vm.expectEmit(true, false, false, false); 227 | emit VoteCast(voter, proposalId, uint8(GovernorCountingSimple.VoteType.For), 9, ""); 228 | aggregator.votes(governors, proposalIds, supportVals); 229 | 230 | vm.roll(block.number + 50400); 231 | assertGt(block.number, governor.proposalDeadline(proposalId)); 232 | assertEq(uint8(governor.state(proposalId)), uint8(IGovernor.ProposalState.Succeeded)); 233 | 234 | vm.prank(admin); 235 | governor.queue(targets, values, calldatas, keccak256(bytes(""))); 236 | vm.warp(block.timestamp + 172800); 237 | governor.execute(targets, values, calldatas, keccak256(bytes(""))); 238 | 239 | assertEq(collection.balanceOf(tombHolder), 1); 240 | assertEq(collection.tokenURI(1), "https://test.com"); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/test/utils/MockOwnable721.sol: -------------------------------------------------------------------------------- 1 | import {ERC721} from "openzeppelin/token/ERC721/ERC721.sol"; 2 | import {Ownable} from "openzeppelin/access/Ownable.sol"; 3 | 4 | contract MockOwnable721 is ERC721, Ownable { 5 | constructor(string memory name, string memory symbol) ERC721(name, symbol) {} 6 | 7 | function mint(address to, uint256 tokenId) public onlyOwner { 8 | _safeMint(to, tokenId); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/utils/Utilities.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Unlicense 2 | pragma solidity >=0.8.0; 3 | 4 | import {DSTest} from "ds-test/test.sol"; 5 | import {Vm} from "forge-std/Vm.sol"; 6 | 7 | //common utilities for forge tests 8 | contract Utilities is DSTest { 9 | Vm internal immutable vm = Vm(HEVM_ADDRESS); 10 | bytes32 internal nextUser = keccak256(abi.encodePacked("user address")); 11 | 12 | function getNextUserAddress() external returns (address payable) { 13 | //bytes32 to address conversion 14 | address payable user = payable(address(uint160(uint256(nextUser)))); 15 | nextUser = keccak256(abi.encodePacked(nextUser)); 16 | return user; 17 | } 18 | 19 | //create users with 100 ether balance 20 | function createUsers(uint256 userNum) external returns (address payable[] memory) { 21 | address payable[] memory users = new address payable[](userNum); 22 | for (uint256 i = 0; i < userNum; i++) { 23 | address payable user = this.getNextUserAddress(); 24 | vm.deal(user, 100 ether); 25 | users[i] = user; 26 | } 27 | return users; 28 | } 29 | 30 | //move block.number forward by a given number of blocks 31 | function mineBlocks(uint256 numBlocks) external { 32 | uint256 targetBlock = block.number + numBlocks; 33 | vm.roll(targetBlock); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/utils/IERC173.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | pragma solidity ^0.8.10; 3 | 4 | /// @title ERC-173 Contract Ownership Standard 5 | /// Note: the ERC-165 identifier for this interface is 0x7f5828d0 6 | interface IERC173 { 7 | /// @dev This emits when ownership of a contract changes. 8 | event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 9 | 10 | /// @notice Get the address of the owner 11 | /// @return The address of the owner. 12 | function owner() external view returns (address); 13 | 14 | /// @notice Set the address of the new owner of the contract 15 | /// @dev Set _newOwner to address(0) to renounce any ownership. 16 | /// @param _newOwner The address of the new owner of the contract 17 | function transferOwnership(address _newOwner) external; 18 | } 19 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.16.7" 7 | resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz" 8 | integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== 9 | dependencies: 10 | "@babel/highlight" "^7.16.7" 11 | 12 | "@babel/helper-validator-identifier@^7.16.7": 13 | version "7.16.7" 14 | resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz" 15 | integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== 16 | 17 | "@babel/highlight@^7.16.7": 18 | version "7.17.12" 19 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351" 20 | integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg== 21 | dependencies: 22 | "@babel/helper-validator-identifier" "^7.16.7" 23 | chalk "^2.0.0" 24 | js-tokens "^4.0.0" 25 | 26 | "@solidity-parser/parser@^0.14.0", "@solidity-parser/parser@^0.14.1": 27 | version "0.14.1" 28 | resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.1.tgz#179afb29f4e295a77cc141151f26b3848abc3c46" 29 | integrity sha512-eLjj2L6AuQjBB6s/ibwCAc0DwrR5Ge+ys+wgWo+bviU7fV2nTMQhU63CGaDKXg9iTmMxwhkyoggdIR7ZGRfMgw== 30 | dependencies: 31 | antlr4ts "^0.5.0-alpha.4" 32 | 33 | acorn-jsx@^5.0.0: 34 | version "5.3.2" 35 | resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" 36 | integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== 37 | 38 | acorn@^6.0.7: 39 | version "6.4.2" 40 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" 41 | integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== 42 | 43 | ajv@^6.10.2, ajv@^6.6.1, ajv@^6.9.1: 44 | version "6.12.6" 45 | resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" 46 | integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== 47 | dependencies: 48 | fast-deep-equal "^3.1.1" 49 | fast-json-stable-stringify "^2.0.0" 50 | json-schema-traverse "^0.4.1" 51 | uri-js "^4.2.2" 52 | 53 | ansi-escapes@^3.2.0: 54 | version "3.2.0" 55 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" 56 | integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== 57 | 58 | ansi-regex@^3.0.0: 59 | version "3.0.1" 60 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" 61 | integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== 62 | 63 | ansi-regex@^4.1.0: 64 | version "4.1.1" 65 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" 66 | integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== 67 | 68 | ansi-regex@^5.0.1: 69 | version "5.0.1" 70 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 71 | integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== 72 | 73 | ansi-styles@^3.2.0, ansi-styles@^3.2.1: 74 | version "3.2.1" 75 | resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" 76 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 77 | dependencies: 78 | color-convert "^1.9.0" 79 | 80 | antlr4@4.7.1: 81 | version "4.7.1" 82 | resolved "https://registry.yarnpkg.com/antlr4/-/antlr4-4.7.1.tgz#69984014f096e9e775f53dd9744bf994d8959773" 83 | integrity sha512-haHyTW7Y9joE5MVs37P2lNYfU2RWBLfcRDD8OWldcdZm5TiCE91B5Xl1oWSwiDUSd4rlExpt2pu1fksYQjRBYQ== 84 | 85 | antlr4ts@^0.5.0-alpha.4: 86 | version "0.5.0-alpha.4" 87 | resolved "https://registry.yarnpkg.com/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz#71702865a87478ed0b40c0709f422cf14d51652a" 88 | integrity sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ== 89 | 90 | argparse@^1.0.7: 91 | version "1.0.10" 92 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 93 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 94 | dependencies: 95 | sprintf-js "~1.0.2" 96 | 97 | ast-parents@0.0.1: 98 | version "0.0.1" 99 | resolved "https://registry.yarnpkg.com/ast-parents/-/ast-parents-0.0.1.tgz#508fd0f05d0c48775d9eccda2e174423261e8dd3" 100 | integrity sha1-UI/Q8F0MSHddnszaLhdEIyYejdM= 101 | 102 | astral-regex@^1.0.0: 103 | version "1.0.0" 104 | resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" 105 | integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== 106 | 107 | balanced-match@^1.0.0: 108 | version "1.0.2" 109 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" 110 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== 111 | 112 | brace-expansion@^1.1.7: 113 | version "1.1.11" 114 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 115 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 116 | dependencies: 117 | balanced-match "^1.0.0" 118 | concat-map "0.0.1" 119 | 120 | caller-callsite@^2.0.0: 121 | version "2.0.0" 122 | resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" 123 | integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= 124 | dependencies: 125 | callsites "^2.0.0" 126 | 127 | caller-path@^2.0.0: 128 | version "2.0.0" 129 | resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" 130 | integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= 131 | dependencies: 132 | caller-callsite "^2.0.0" 133 | 134 | callsites@^2.0.0: 135 | version "2.0.0" 136 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" 137 | integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= 138 | 139 | callsites@^3.0.0: 140 | version "3.1.0" 141 | resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" 142 | integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== 143 | 144 | chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.2: 145 | version "2.4.2" 146 | resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" 147 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 148 | dependencies: 149 | ansi-styles "^3.2.1" 150 | escape-string-regexp "^1.0.5" 151 | supports-color "^5.3.0" 152 | 153 | chardet@^0.7.0: 154 | version "0.7.0" 155 | resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" 156 | integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== 157 | 158 | cli-cursor@^2.1.0: 159 | version "2.1.0" 160 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" 161 | integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= 162 | dependencies: 163 | restore-cursor "^2.0.0" 164 | 165 | cli-width@^2.0.0: 166 | version "2.2.1" 167 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" 168 | integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== 169 | 170 | color-convert@^1.9.0: 171 | version "1.9.3" 172 | resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" 173 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 174 | dependencies: 175 | color-name "1.1.3" 176 | 177 | color-name@1.1.3: 178 | version "1.1.3" 179 | resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" 180 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 181 | 182 | commander@2.18.0: 183 | version "2.18.0" 184 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" 185 | integrity sha512-6CYPa+JP2ftfRU2qkDK+UTVeQYosOg/2GbcjIcKPHfinyOLPVGXu/ovN86RP49Re5ndJK1N0kuiidFFuepc4ZQ== 186 | 187 | concat-map@0.0.1: 188 | version "0.0.1" 189 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 190 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 191 | 192 | cosmiconfig@^5.0.7: 193 | version "5.2.1" 194 | resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" 195 | integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== 196 | dependencies: 197 | import-fresh "^2.0.0" 198 | is-directory "^0.3.1" 199 | js-yaml "^3.13.1" 200 | parse-json "^4.0.0" 201 | 202 | cross-spawn@^6.0.5: 203 | version "6.0.5" 204 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" 205 | integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== 206 | dependencies: 207 | nice-try "^1.0.4" 208 | path-key "^2.0.1" 209 | semver "^5.5.0" 210 | shebang-command "^1.2.0" 211 | which "^1.2.9" 212 | 213 | debug@^4.0.1: 214 | version "4.3.4" 215 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 216 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 217 | dependencies: 218 | ms "2.1.2" 219 | 220 | deep-is@~0.1.3: 221 | version "0.1.4" 222 | resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" 223 | integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== 224 | 225 | doctrine@^3.0.0: 226 | version "3.0.0" 227 | resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" 228 | integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== 229 | dependencies: 230 | esutils "^2.0.2" 231 | 232 | emoji-regex@^10.0.0: 233 | version "10.1.0" 234 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.1.0.tgz#d50e383743c0f7a5945c47087295afc112e3cf66" 235 | integrity sha512-xAEnNCT3w2Tg6MA7ly6QqYJvEoY1tm9iIjJ3yMKK9JPlWuRHAMoe5iETwQnx3M9TVbFMfsrBgWKR+IsmswwNjg== 236 | 237 | emoji-regex@^7.0.1: 238 | version "7.0.3" 239 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" 240 | integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== 241 | 242 | emoji-regex@^8.0.0: 243 | version "8.0.0" 244 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 245 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== 246 | 247 | error-ex@^1.3.1: 248 | version "1.3.2" 249 | resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz" 250 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 251 | dependencies: 252 | is-arrayish "^0.2.1" 253 | 254 | escape-string-regexp@^1.0.5: 255 | version "1.0.5" 256 | resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" 257 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 258 | 259 | escape-string-regexp@^4.0.0: 260 | version "4.0.0" 261 | resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" 262 | integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== 263 | 264 | eslint-scope@^4.0.3: 265 | version "4.0.3" 266 | resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" 267 | integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== 268 | dependencies: 269 | esrecurse "^4.1.0" 270 | estraverse "^4.1.1" 271 | 272 | eslint-utils@^1.3.1: 273 | version "1.4.3" 274 | resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" 275 | integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== 276 | dependencies: 277 | eslint-visitor-keys "^1.1.0" 278 | 279 | eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: 280 | version "1.3.0" 281 | resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" 282 | integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== 283 | 284 | eslint@^5.6.0: 285 | version "5.16.0" 286 | resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" 287 | integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== 288 | dependencies: 289 | "@babel/code-frame" "^7.0.0" 290 | ajv "^6.9.1" 291 | chalk "^2.1.0" 292 | cross-spawn "^6.0.5" 293 | debug "^4.0.1" 294 | doctrine "^3.0.0" 295 | eslint-scope "^4.0.3" 296 | eslint-utils "^1.3.1" 297 | eslint-visitor-keys "^1.0.0" 298 | espree "^5.0.1" 299 | esquery "^1.0.1" 300 | esutils "^2.0.2" 301 | file-entry-cache "^5.0.1" 302 | functional-red-black-tree "^1.0.1" 303 | glob "^7.1.2" 304 | globals "^11.7.0" 305 | ignore "^4.0.6" 306 | import-fresh "^3.0.0" 307 | imurmurhash "^0.1.4" 308 | inquirer "^6.2.2" 309 | js-yaml "^3.13.0" 310 | json-stable-stringify-without-jsonify "^1.0.1" 311 | levn "^0.3.0" 312 | lodash "^4.17.11" 313 | minimatch "^3.0.4" 314 | mkdirp "^0.5.1" 315 | natural-compare "^1.4.0" 316 | optionator "^0.8.2" 317 | path-is-inside "^1.0.2" 318 | progress "^2.0.0" 319 | regexpp "^2.0.1" 320 | semver "^5.5.1" 321 | strip-ansi "^4.0.0" 322 | strip-json-comments "^2.0.1" 323 | table "^5.2.3" 324 | text-table "^0.2.0" 325 | 326 | espree@^5.0.1: 327 | version "5.0.1" 328 | resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" 329 | integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== 330 | dependencies: 331 | acorn "^6.0.7" 332 | acorn-jsx "^5.0.0" 333 | eslint-visitor-keys "^1.0.0" 334 | 335 | esprima@^4.0.0: 336 | version "4.0.1" 337 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 338 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 339 | 340 | esquery@^1.0.1: 341 | version "1.4.0" 342 | resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" 343 | integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== 344 | dependencies: 345 | estraverse "^5.1.0" 346 | 347 | esrecurse@^4.1.0: 348 | version "4.3.0" 349 | resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" 350 | integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== 351 | dependencies: 352 | estraverse "^5.2.0" 353 | 354 | estraverse@^4.1.1: 355 | version "4.3.0" 356 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" 357 | integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== 358 | 359 | estraverse@^5.1.0, estraverse@^5.2.0: 360 | version "5.3.0" 361 | resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" 362 | integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== 363 | 364 | esutils@^2.0.2: 365 | version "2.0.3" 366 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" 367 | integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 368 | 369 | external-editor@^3.0.3: 370 | version "3.1.0" 371 | resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" 372 | integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== 373 | dependencies: 374 | chardet "^0.7.0" 375 | iconv-lite "^0.4.24" 376 | tmp "^0.0.33" 377 | 378 | fast-deep-equal@^3.1.1: 379 | version "3.1.3" 380 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 381 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== 382 | 383 | fast-diff@^1.1.2: 384 | version "1.2.0" 385 | resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" 386 | integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== 387 | 388 | fast-json-stable-stringify@^2.0.0: 389 | version "2.1.0" 390 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 391 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 392 | 393 | fast-levenshtein@~2.0.6: 394 | version "2.0.6" 395 | resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" 396 | integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= 397 | 398 | figures@^2.0.0: 399 | version "2.0.0" 400 | resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" 401 | integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= 402 | dependencies: 403 | escape-string-regexp "^1.0.5" 404 | 405 | file-entry-cache@^5.0.1: 406 | version "5.0.1" 407 | resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" 408 | integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== 409 | dependencies: 410 | flat-cache "^2.0.1" 411 | 412 | flat-cache@^2.0.1: 413 | version "2.0.1" 414 | resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" 415 | integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== 416 | dependencies: 417 | flatted "^2.0.0" 418 | rimraf "2.6.3" 419 | write "1.0.3" 420 | 421 | flatted@^2.0.0: 422 | version "2.0.2" 423 | resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" 424 | integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== 425 | 426 | fs.realpath@^1.0.0: 427 | version "1.0.0" 428 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 429 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 430 | 431 | functional-red-black-tree@^1.0.1: 432 | version "1.0.1" 433 | resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" 434 | integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= 435 | 436 | glob@^7.1.2, glob@^7.1.3: 437 | version "7.2.3" 438 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" 439 | integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== 440 | dependencies: 441 | fs.realpath "^1.0.0" 442 | inflight "^1.0.4" 443 | inherits "2" 444 | minimatch "^3.1.1" 445 | once "^1.3.0" 446 | path-is-absolute "^1.0.0" 447 | 448 | globals@^11.7.0: 449 | version "11.12.0" 450 | resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" 451 | integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== 452 | 453 | has-flag@^3.0.0: 454 | version "3.0.0" 455 | resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" 456 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 457 | 458 | iconv-lite@^0.4.24: 459 | version "0.4.24" 460 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" 461 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== 462 | dependencies: 463 | safer-buffer ">= 2.1.2 < 3" 464 | 465 | ignore@^4.0.6: 466 | version "4.0.6" 467 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" 468 | integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== 469 | 470 | import-fresh@^2.0.0: 471 | version "2.0.0" 472 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" 473 | integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= 474 | dependencies: 475 | caller-path "^2.0.0" 476 | resolve-from "^3.0.0" 477 | 478 | import-fresh@^3.0.0: 479 | version "3.3.0" 480 | resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" 481 | integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== 482 | dependencies: 483 | parent-module "^1.0.0" 484 | resolve-from "^4.0.0" 485 | 486 | imurmurhash@^0.1.4: 487 | version "0.1.4" 488 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 489 | integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= 490 | 491 | inflight@^1.0.4: 492 | version "1.0.6" 493 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 494 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 495 | dependencies: 496 | once "^1.3.0" 497 | wrappy "1" 498 | 499 | inherits@2: 500 | version "2.0.4" 501 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 502 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 503 | 504 | inquirer@^6.2.2: 505 | version "6.5.2" 506 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" 507 | integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== 508 | dependencies: 509 | ansi-escapes "^3.2.0" 510 | chalk "^2.4.2" 511 | cli-cursor "^2.1.0" 512 | cli-width "^2.0.0" 513 | external-editor "^3.0.3" 514 | figures "^2.0.0" 515 | lodash "^4.17.12" 516 | mute-stream "0.0.7" 517 | run-async "^2.2.0" 518 | rxjs "^6.4.0" 519 | string-width "^2.1.0" 520 | strip-ansi "^5.1.0" 521 | through "^2.3.6" 522 | 523 | is-arrayish@^0.2.1: 524 | version "0.2.1" 525 | resolved "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz" 526 | integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 527 | 528 | is-directory@^0.3.1: 529 | version "0.3.1" 530 | resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" 531 | integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= 532 | 533 | is-fullwidth-code-point@^2.0.0: 534 | version "2.0.0" 535 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 536 | integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= 537 | 538 | is-fullwidth-code-point@^3.0.0: 539 | version "3.0.0" 540 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 541 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== 542 | 543 | isexe@^2.0.0: 544 | version "2.0.0" 545 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 546 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 547 | 548 | js-tokens@^4.0.0: 549 | version "4.0.0" 550 | resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" 551 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 552 | 553 | js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: 554 | version "3.14.1" 555 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" 556 | integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== 557 | dependencies: 558 | argparse "^1.0.7" 559 | esprima "^4.0.0" 560 | 561 | json-parse-better-errors@^1.0.1: 562 | version "1.0.2" 563 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" 564 | integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== 565 | 566 | json-schema-traverse@^0.4.1: 567 | version "0.4.1" 568 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 569 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 570 | 571 | json-stable-stringify-without-jsonify@^1.0.1: 572 | version "1.0.1" 573 | resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" 574 | integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= 575 | 576 | levn@^0.3.0, levn@~0.3.0: 577 | version "0.3.0" 578 | resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" 579 | integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= 580 | dependencies: 581 | prelude-ls "~1.1.2" 582 | type-check "~0.3.2" 583 | 584 | lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14: 585 | version "4.17.21" 586 | resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" 587 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 588 | 589 | lru-cache@^6.0.0: 590 | version "6.0.0" 591 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" 592 | integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== 593 | dependencies: 594 | yallist "^4.0.0" 595 | 596 | mimic-fn@^1.0.0: 597 | version "1.2.0" 598 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" 599 | integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== 600 | 601 | minimatch@^3.0.4, minimatch@^3.1.1: 602 | version "3.1.2" 603 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" 604 | integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== 605 | dependencies: 606 | brace-expansion "^1.1.7" 607 | 608 | minimist@^1.2.6: 609 | version "1.2.6" 610 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" 611 | integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== 612 | 613 | mkdirp@^0.5.1: 614 | version "0.5.6" 615 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" 616 | integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== 617 | dependencies: 618 | minimist "^1.2.6" 619 | 620 | ms@2.1.2: 621 | version "2.1.2" 622 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 623 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 624 | 625 | mute-stream@0.0.7: 626 | version "0.0.7" 627 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" 628 | integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= 629 | 630 | natural-compare@^1.4.0: 631 | version "1.4.0" 632 | resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" 633 | integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= 634 | 635 | nice-try@^1.0.4: 636 | version "1.0.5" 637 | resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" 638 | integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== 639 | 640 | once@^1.3.0: 641 | version "1.4.0" 642 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 643 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 644 | dependencies: 645 | wrappy "1" 646 | 647 | onetime@^2.0.0: 648 | version "2.0.1" 649 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" 650 | integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= 651 | dependencies: 652 | mimic-fn "^1.0.0" 653 | 654 | optionator@^0.8.2: 655 | version "0.8.3" 656 | resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" 657 | integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== 658 | dependencies: 659 | deep-is "~0.1.3" 660 | fast-levenshtein "~2.0.6" 661 | levn "~0.3.0" 662 | prelude-ls "~1.1.2" 663 | type-check "~0.3.2" 664 | word-wrap "~1.2.3" 665 | 666 | os-tmpdir@~1.0.2: 667 | version "1.0.2" 668 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 669 | integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= 670 | 671 | parent-module@^1.0.0: 672 | version "1.0.1" 673 | resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" 674 | integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== 675 | dependencies: 676 | callsites "^3.0.0" 677 | 678 | parse-json@^4.0.0: 679 | version "4.0.0" 680 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" 681 | integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= 682 | dependencies: 683 | error-ex "^1.3.1" 684 | json-parse-better-errors "^1.0.1" 685 | 686 | path-is-absolute@^1.0.0: 687 | version "1.0.1" 688 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 689 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 690 | 691 | path-is-inside@^1.0.2: 692 | version "1.0.2" 693 | resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" 694 | integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= 695 | 696 | path-key@^2.0.1: 697 | version "2.0.1" 698 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 699 | integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= 700 | 701 | prelude-ls@~1.1.2: 702 | version "1.1.2" 703 | resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" 704 | integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= 705 | 706 | prettier-linter-helpers@^1.0.0: 707 | version "1.0.0" 708 | resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" 709 | integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== 710 | dependencies: 711 | fast-diff "^1.1.2" 712 | 713 | prettier-plugin-solidity@^1.0.0-beta.19: 714 | version "1.0.0-beta.19" 715 | resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.19.tgz#7c3607fc4028f5e6a425259ff03e45eedf733df3" 716 | integrity sha512-xxRQ5ZiiZyUoMFLE9h7HnUDXI/daf1tnmL1msEdcKmyh7ZGQ4YklkYLC71bfBpYU2WruTb5/SFLUaEb3RApg5g== 717 | dependencies: 718 | "@solidity-parser/parser" "^0.14.0" 719 | emoji-regex "^10.0.0" 720 | escape-string-regexp "^4.0.0" 721 | semver "^7.3.5" 722 | solidity-comments-extractor "^0.0.7" 723 | string-width "^4.2.3" 724 | 725 | prettier@^1.14.3: 726 | version "1.19.1" 727 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz" 728 | integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== 729 | 730 | prettier@^2.5.1: 731 | version "2.6.2" 732 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032" 733 | integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew== 734 | 735 | progress@^2.0.0: 736 | version "2.0.3" 737 | resolved "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz" 738 | integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== 739 | 740 | punycode@^2.1.0: 741 | version "2.1.1" 742 | resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" 743 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 744 | 745 | regexpp@^2.0.1: 746 | version "2.0.1" 747 | resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" 748 | integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== 749 | 750 | resolve-from@^3.0.0: 751 | version "3.0.0" 752 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" 753 | integrity sha1-six699nWiBvItuZTM17rywoYh0g= 754 | 755 | resolve-from@^4.0.0: 756 | version "4.0.0" 757 | resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" 758 | integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== 759 | 760 | restore-cursor@^2.0.0: 761 | version "2.0.0" 762 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" 763 | integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= 764 | dependencies: 765 | onetime "^2.0.0" 766 | signal-exit "^3.0.2" 767 | 768 | rimraf@2.6.3: 769 | version "2.6.3" 770 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" 771 | integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== 772 | dependencies: 773 | glob "^7.1.3" 774 | 775 | run-async@^2.2.0: 776 | version "2.4.1" 777 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" 778 | integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== 779 | 780 | rxjs@^6.4.0: 781 | version "6.6.7" 782 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" 783 | integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== 784 | dependencies: 785 | tslib "^1.9.0" 786 | 787 | "safer-buffer@>= 2.1.2 < 3": 788 | version "2.1.2" 789 | resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" 790 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 791 | 792 | semver@^5.5.0, semver@^5.5.1: 793 | version "5.7.1" 794 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 795 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 796 | 797 | semver@^6.3.0: 798 | version "6.3.0" 799 | resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" 800 | integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== 801 | 802 | semver@^7.3.5: 803 | version "7.3.7" 804 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" 805 | integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== 806 | dependencies: 807 | lru-cache "^6.0.0" 808 | 809 | shebang-command@^1.2.0: 810 | version "1.2.0" 811 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 812 | integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= 813 | dependencies: 814 | shebang-regex "^1.0.0" 815 | 816 | shebang-regex@^1.0.0: 817 | version "1.0.0" 818 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 819 | integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= 820 | 821 | signal-exit@^3.0.2: 822 | version "3.0.7" 823 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" 824 | integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== 825 | 826 | slice-ansi@^2.1.0: 827 | version "2.1.0" 828 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" 829 | integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== 830 | dependencies: 831 | ansi-styles "^3.2.0" 832 | astral-regex "^1.0.0" 833 | is-fullwidth-code-point "^2.0.0" 834 | 835 | solhint-plugin-prettier@^0.0.5: 836 | version "0.0.5" 837 | resolved "https://registry.yarnpkg.com/solhint-plugin-prettier/-/solhint-plugin-prettier-0.0.5.tgz#e3b22800ba435cd640a9eca805a7f8bc3e3e6a6b" 838 | integrity sha512-7jmWcnVshIrO2FFinIvDQmhQpfpS2rRRn3RejiYgnjIE68xO2bvrYvjqVNfrio4xH9ghOqn83tKuTzLjEbmGIA== 839 | dependencies: 840 | prettier-linter-helpers "^1.0.0" 841 | 842 | solhint@^3.3.6: 843 | version "3.3.7" 844 | resolved "https://registry.yarnpkg.com/solhint/-/solhint-3.3.7.tgz#b5da4fedf7a0fee954cb613b6c55a5a2b0063aa7" 845 | integrity sha512-NjjjVmXI3ehKkb3aNtRJWw55SUVJ8HMKKodwe0HnejA+k0d2kmhw7jvpa+MCTbcEgt8IWSwx0Hu6aCo/iYOZzQ== 846 | dependencies: 847 | "@solidity-parser/parser" "^0.14.1" 848 | ajv "^6.6.1" 849 | antlr4 "4.7.1" 850 | ast-parents "0.0.1" 851 | chalk "^2.4.2" 852 | commander "2.18.0" 853 | cosmiconfig "^5.0.7" 854 | eslint "^5.6.0" 855 | fast-diff "^1.1.2" 856 | glob "^7.1.3" 857 | ignore "^4.0.6" 858 | js-yaml "^3.12.0" 859 | lodash "^4.17.11" 860 | semver "^6.3.0" 861 | optionalDependencies: 862 | prettier "^1.14.3" 863 | 864 | solidity-comments-extractor@^0.0.7: 865 | version "0.0.7" 866 | resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19" 867 | integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw== 868 | 869 | sprintf-js@~1.0.2: 870 | version "1.0.3" 871 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 872 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 873 | 874 | string-width@^2.1.0: 875 | version "2.1.1" 876 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 877 | integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 878 | dependencies: 879 | is-fullwidth-code-point "^2.0.0" 880 | strip-ansi "^4.0.0" 881 | 882 | string-width@^3.0.0: 883 | version "3.1.0" 884 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" 885 | integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== 886 | dependencies: 887 | emoji-regex "^7.0.1" 888 | is-fullwidth-code-point "^2.0.0" 889 | strip-ansi "^5.1.0" 890 | 891 | string-width@^4.2.3: 892 | version "4.2.3" 893 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" 894 | integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== 895 | dependencies: 896 | emoji-regex "^8.0.0" 897 | is-fullwidth-code-point "^3.0.0" 898 | strip-ansi "^6.0.1" 899 | 900 | strip-ansi@^4.0.0: 901 | version "4.0.0" 902 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 903 | integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= 904 | dependencies: 905 | ansi-regex "^3.0.0" 906 | 907 | strip-ansi@^5.1.0: 908 | version "5.2.0" 909 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" 910 | integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== 911 | dependencies: 912 | ansi-regex "^4.1.0" 913 | 914 | strip-ansi@^6.0.1: 915 | version "6.0.1" 916 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" 917 | integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== 918 | dependencies: 919 | ansi-regex "^5.0.1" 920 | 921 | strip-json-comments@^2.0.1: 922 | version "2.0.1" 923 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 924 | integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= 925 | 926 | supports-color@^5.3.0: 927 | version "5.5.0" 928 | resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" 929 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 930 | dependencies: 931 | has-flag "^3.0.0" 932 | 933 | table@^5.2.3: 934 | version "5.4.6" 935 | resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" 936 | integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== 937 | dependencies: 938 | ajv "^6.10.2" 939 | lodash "^4.17.14" 940 | slice-ansi "^2.1.0" 941 | string-width "^3.0.0" 942 | 943 | text-table@^0.2.0: 944 | version "0.2.0" 945 | resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" 946 | integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= 947 | 948 | through@^2.3.6: 949 | version "2.3.8" 950 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 951 | integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= 952 | 953 | tmp@^0.0.33: 954 | version "0.0.33" 955 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" 956 | integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== 957 | dependencies: 958 | os-tmpdir "~1.0.2" 959 | 960 | tslib@^1.9.0: 961 | version "1.14.1" 962 | resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" 963 | integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== 964 | 965 | type-check@~0.3.2: 966 | version "0.3.2" 967 | resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" 968 | integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= 969 | dependencies: 970 | prelude-ls "~1.1.2" 971 | 972 | uri-js@^4.2.2: 973 | version "4.4.1" 974 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 975 | integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== 976 | dependencies: 977 | punycode "^2.1.0" 978 | 979 | which@^1.2.9: 980 | version "1.3.1" 981 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 982 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 983 | dependencies: 984 | isexe "^2.0.0" 985 | 986 | word-wrap@~1.2.3: 987 | version "1.2.3" 988 | resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" 989 | integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== 990 | 991 | wrappy@1: 992 | version "1.0.2" 993 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 994 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 995 | 996 | write@1.0.3: 997 | version "1.0.3" 998 | resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" 999 | integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== 1000 | dependencies: 1001 | mkdirp "^0.5.1" 1002 | 1003 | yallist@^4.0.0: 1004 | version "4.0.0" 1005 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 1006 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 1007 | --------------------------------------------------------------------------------